1. 在MessagelistActivity中出现has leaked IntentReceiver的异常。异常日志如下。

07-15 08:09:53.211: E/ActivityThread(15491): Activity com.txrj.sms.activity.MessageListActivity has leaked IntentReceiver com.txrj.sms.activity.MessageListActivity$6@41e189d0 that was originally registered here. Are you missing a call to unregisterReceiver()?
07-15 08:09:53.211: E/ActivityThread(15491): android.app.IntentReceiverLeaked: Activity com.txrj.sms.activity.MessageListActivity has leaked IntentReceiver com.txrj.sms.activity.MessageListActivity$6@41e189d0 that was originally registered here. Are you missing a call to unregisterReceiver()?
07-15 08:09:53.211: E/ActivityThread(15491):     at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:763)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:567)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1167)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.app.ContextImpl.registerReceiver(ContextImpl.java:1154)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.app.ContextImpl.registerReceiver(ContextImpl.java:1148)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:348)
07-15 08:09:53.211: E/ActivityThread(15491):     at com.txrj.sms.activity.MessageListActivity.getDeliveryIntent(MessageListActivity.java:247)
07-15 08:09:53.211: E/ActivityThread(15491):     at com.txrj.sms.activity.MessageListActivity.sendMessage(MessageListActivity.java:196)
07-15 08:09:53.211: E/ActivityThread(15491):     at com.txrj.sms.activity.MessageListActivity.access$14(MessageListActivity.java:190)
07-15 08:09:53.211: E/ActivityThread(15491):     at com.txrj.sms.activity.MessageListActivity$2.onClick(MessageListActivity.java:120)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.view.View.performClick(View.java:3567)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.view.View$PerformClick.run(View.java:14224)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.os.Handler.handleCallback(Handler.java:605)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.os.Handler.dispatchMessage(Handler.java:92)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.os.Looper.loop(Looper.java:137)
07-15 08:09:53.211: E/ActivityThread(15491):     at android.app.ActivityThread.main(ActivityThread.java:4517)
07-15 08:09:53.211: E/ActivityThread(15491):     at java.lang.reflect.Method.invokeNative(Native Method)
07-15 08:09:53.211: E/ActivityThread(15491):     at java.lang.reflect.Method.invoke(Method.java:511)
07-15 08:09:53.211: E/ActivityThread(15491):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
07-15 08:09:53.211: E/ActivityThread(15491):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
07-15 08:09:53.211: E/ActivityThread(15491):     at dalvik.system.NativeStart.main(Native Method)
07-15 08:09:53.221: E/ActivityThread(15491): Activity com.txrj.sms.activity.MessageListActivity has leaked IntentReceiver com.txrj.sms.activity.MessageListActivity$5@41df9b80 that was originally registered here. Are you missing a call to unregisterReceiver()?
07-15 08:09:53.221: E/ActivityThread(15491): android.app.IntentReceiverLeaked: Activity com.txrj.sms.activity.MessageListActivity has leaked IntentReceiver com.txrj.sms.activity.MessageListActivity$5@41df9b80 that was originally registered here. Are you missing a call to unregisterReceiver()?
07-15 08:09:53.221: E/ActivityThread(15491):     at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:763)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:567)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1167)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.app.ContextImpl.registerReceiver(ContextImpl.java:1154)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.app.ContextImpl.registerReceiver(ContextImpl.java:1148)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:348)
07-15 08:09:53.221: E/ActivityThread(15491):     at com.txrj.sms.activity.MessageListActivity.getSentIntent(MessageListActivity.java:232)
07-15 08:09:53.221: E/ActivityThread(15491):     at com.txrj.sms.activity.MessageListActivity.sendMessage(MessageListActivity.java:195)
07-15 08:09:53.221: E/ActivityThread(15491):     at com.txrj.sms.activity.MessageListActivity.access$14(MessageListActivity.java:190)
07-15 08:09:53.221: E/ActivityThread(15491):     at com.txrj.sms.activity.MessageListActivity$2.onClick(MessageListActivity.java:120)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.view.View.performClick(View.java:3567)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.view.View$PerformClick.run(View.java:14224)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.os.Handler.handleCallback(Handler.java:605)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.os.Handler.dispatchMessage(Handler.java:92)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.os.Looper.loop(Looper.java:137)
07-15 08:09:53.221: E/ActivityThread(15491):     at android.app.ActivityThread.main(ActivityThread.java:4517)
07-15 08:09:53.221: E/ActivityThread(15491):     at java.lang.reflect.Method.invokeNative(Native Method)
07-15 08:09:53.221: E/ActivityThread(15491):     at java.lang.reflect.Method.invoke(Method.java:511)
07-15 08:09:53.221: E/ActivityThread(15491):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
07-15 08:09:53.221: E/ActivityThread(15491):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
07-15 08:09:53.221: E/ActivityThread(15491):     at dalvik.system.NativeStart.main(Native Method)

2. 出现异常原因分析。在发送信息时,创建了两个PendingIntent,它们是调用方法getBroadcast来发送广播。在此之前调用registerBroadcast注册广播,查看代码找不到注销广播的语句,所以导致出现leaked IntentReceiver的异常。以下是改正之后的代码。

private PendingIntent getSentIntent(final Uri uri) {
    BroadcastReceiver receiver = new BroadcastReceiver(){

        @Override
        public void onReceive(Context context, Intent intent) {
            mContext.unregisterReceiver(this);
            int resultCode = getResultCode();
            if(resultCode == RESULT_OK) {
                Toast.makeText(context, "send message success.", Toast.LENGTH_SHORT).show();
                //Log.i("txrjsms", "send message success.");
                updateMsgType(uri, Sms.MESSAGE_TYPE_SENT);
            } else if(resultCode == SmsManager.RESULT_ERROR_GENERIC_FAILURE) {
                Toast.makeText(context, "Generic failure.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
            } else if(resultCode == SmsManager.RESULT_ERROR_NO_SERVICE) {
                Toast.makeText(context, "service is currently unavailable.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
            } else if(resultCode == SmsManager.RESULT_ERROR_NULL_PDU) {
                Toast.makeText(context, "no pdu provided.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
            } else if(resultCode == SmsManager.RESULT_ERROR_RADIO_OFF) {
                Toast.makeText(context, "radio was explicitly turned off.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
            }
        }
    };
    IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_SEND_SMS);
    mContext.registerReceiver(receiver, filter);
    Intent sentIntent = new Intent(TxrjConstant.ACTION_SEND_SMS);
    return PendingIntent.getBroadcast(mContext, 0, sentIntent, 0);
}

 

private PendingIntent getDeliveryIntent() {
    BroadcastReceiver receiver = new BroadcastReceiver(){

        @Override
        public void onReceive(Context context, Intent intent) {
            mContext.unregisterReceiver(this);
            Toast.makeText(context, "message arrived.", Toast.LENGTH_SHORT).show();
            //Log.i("txrjsms", "message arrived.");
        }
    };
    IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_DELIVERY_SMS);
    mContext.registerReceiver(receiver, filter);
    Intent deliveryIntent = new Intent(TxrjConstant.ACTION_DELIVERY_SMS);
    return PendingIntent.getBroadcast(mContext, 0, deliveryIntent, 0);
}

3. 添加了注销广播接收器的语句之后还会有问题。比如,发出信息之后,对方有信息回复时,在MessageListActivity界面中无法将刚收到的信息显示出来。优化注册和注销Receiver的代码。以下是优化过的代码,将receiver作为实例变量来定义,在第一次获取sentIntert和deliveryIntent时创建并注册它们。在onDestroy方法中注销它们。

在sentReceiver中需要传递表示发送信息的uri。在调用getBroadcast时通过intent.putExtra放入Uri。在onReceive方法中通过intent.getParcelableExtra取出Uri。

private void createAndRegisterSentReceiver() {
    sentReceiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {
            Uri uri = intent.getParcelableExtra(TxrjConstant.EXTRA_SENT_URI);
            int resultCode = getResultCode();
            if(resultCode == RESULT_OK) {
                Toast.makeText(context, "send message success.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_SENT);
            } else if(resultCode == SmsManager.RESULT_ERROR_GENERIC_FAILURE) {
                Toast.makeText(context, "Generic failure.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
            } else if(resultCode == SmsManager.RESULT_ERROR_NO_SERVICE) {
                Toast.makeText(context, "service is currently unavailable.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
            } else if(resultCode == SmsManager.RESULT_ERROR_NULL_PDU) {
                Toast.makeText(context, "no pdu provided.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
            } else if(resultCode == SmsManager.RESULT_ERROR_RADIO_OFF) {
                Toast.makeText(context, "radio was explicitly turned off.", Toast.LENGTH_SHORT).show();
                updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
            }
        }
    };
    IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_SEND_SMS);
   mContext.registerReceiver(sentReceiver, filter);
}

private PendingIntent getSentIntent(final Uri uri) {
    if(sentReceiver == null) {
        createAndRegisterSentReceiver();
    }
    Intent sentIntent = new Intent(TxrjConstant.ACTION_SEND_SMS);
    sentIntent.putExtra(TxrjConstant.EXTRA_SENT_URI, uri);
    return PendingIntent.getBroadcast(mContext, 0, sentIntent, 0);
}

deliveryReceiver使用类似的处理方法。代码如下所示。

private void createAndRegisterDeliveryIntent() {
    deliveryReceiver = new BroadcastReceiver(){

        @Override
        public void onReceive(Context context, Intent intent) {
            mContext.unregisterReceiver(this);
            Toast.makeText(context, "message arrived.", Toast.LENGTH_SHORT).show();
        }
    };
    IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_DELIVERY_SMS);
    mContext.registerReceiver(deliveryReceiver, filter);
}

private PendingIntent getDeliveryIntent() {
    if(deliveryReceiver == null) {
        createAndRegisterDeliveryIntent();
    }
    Intent deliveryIntent = new Intent(TxrjConstant.ACTION_DELIVERY_SMS);
    return PendingIntent.getBroadcast(mContext, 0, deliveryIntent, 0);
}

在onDestroy()方法中注销sentReceiver和deliveryReceiver。

protected void onDestroy() {
    super.onDestroy();
    getContentResolver().unregisterContentObserver(mInboxObserver);
    if(sentReceiver != null) {
        unregisterReceiver(sentReceiver);
    }
    if(deliveryReceiver != null) {
        unregisterReceiver(deliveryReceiver);
    }
}

MessageListActivity has leaked IntentReceiver的更多相关文章

  1. Android学习系列(37)--App调试内存泄露之Context篇(下)

    接着<Android学习系列(36)--App调试内存泄露之Context篇(上)>继续分析. 5. AsyncTask对象 我N年前去盛大面过一次试,当时面试官极力推荐我使用AsyncT ...

  2. [Android Memory] App调试内存泄露之Context篇(下)

    转载地址:http://www.cnblogs.com/qianxudetianxia/p/3655475.html 5. AsyncTask对象 我N年前去盛大面过一次试,当时面试官极力推荐我使用A ...

  3. Android 之 WebView

    1:在AndroidManifest.xml中添加允许android访问网络权限. <uses-permission android:name="android.permission. ...

  4. WebView全面学习(二)-- Native与js双方通信

    WebView全面学习(二)-- Native与js双方通信 Native与js通信的本质 Native与js通信的核心在于WebView. 两端的通信主要还是单向的.假如要完成js->Nati ...

  5. android中常见的内存泄漏和解决的方法

    android中的内存溢出预计大多数人在写代码的时候都出现过,事实上突然认为工作一年和工作三年的差别是什么呢.事实上干的工作或许都一样,产品汪看到的结果也都一样,那差别就是速度和质量了. 写在前面的一 ...

  6. StrictMode 详解

    StrictMode类是Android 2.3 (API 9)引入的一个工具类,可以用来帮助开发者发现代码中的一些不规范的问题.比如,如果你在UI线程中进行了网络或者磁盘操作,StrictMode就会 ...

  7. Activity has leaked window that was originally added

    错误: E/WindowManager: android.view.WindowLeaked: Activity com.x.x.x has leaked window com.android.int ...

  8. 数据库内存泄漏——A SQLiteConnection object for database '/data/data/.../databases/....db' was leaked!

      详细异常: A SQLiteConnection object for database '/data/data/.../database/....db' was leaked!  Please ...

  9. has leaked ServiceConnection com.baidu.location.LocationClient

    02-06 05:01:52.806: E/ActivityThread(1120): Activity com.project.xxxActivity $1@45fc5af8 that was or ...

随机推荐

  1. Ubuntu sh命令无法正确执行 (修改默认sh为bash)

    新安装的ubuntu,执行shell命令,都怀疑自己的shell水平了. 原来, ubuntu默认的是dash, 需要手动执行命令将dash改为bash. 命令: sudo dpkg-reconfig ...

  2. 【LeetCode】Number of Islands

    Number of Islands 问题描写叙述 Given a 2d grid map of '1's (land) and '0's (water), count the number of is ...

  3. 如何三招帮你排查Linux中的硬件问题

    下列贴士帮助你更快速更轻松地为Linux中的硬件排查故障.许多不同的因素可能导致Linux硬件出现问题:在你开始尝试诊断之前,了解最常见的问题以及最有可能找到原因的环节是明智之举. Linux服务器在 ...

  4. 设置py文件的路径

    想在IDLE中打开py文件,需要设置PYTHONPATH环境变量: 设置后,就能在IDLE的Path Browser中看到sys.path了: 然后,就可以用import了

  5. Direct2D教程II——绘制基本图形和线型(StrokeStyle)的设置详解

    目前,在博客园上,相对写得比较好的两个关于Direct2D的教程系列,分别是万一的Direct2D系列和zdd的Direct2D系列.有兴趣的网友可以去看看.本系列也是介绍Direct2D的教程,是基 ...

  6. 彻底解决 Intellij IDEA 卡顿 优化笔记,重要的快捷键

    由于工作中经常出现分支各种切换,使用Eclipse便不再像以前那么舒服了,不停的修改工作空间,每次修改完工作空间又是一堆一堆的个性化设置,来回的切换,真的很累.我们做软件的,怎么能不去尝试新鲜的呢,毕 ...

  7. AS打开速度慢,AS项目导入慢,新建项目导入慢

    1.AS打开速度慢 在Android Studio的bin目录里,打开idea.prooperties文件,添加disable.android.first.run=true 再次打开时,启动加快 2. ...

  8. 【转】web.xml不同版本的头

    web.xml v2.3 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web- ...

  9. 微信小程序 - 接口更新记录以及解决方案(2018/12/26)

    2018/8/17 - 背景音频需要在app.json添加requireBackGroundModes 2018/9/12 - 微信更改获取用户信息接口/获取位置等接口 - button 2018/1 ...

  10. Go语言使用PostgreSQL数据库

    Go语言使用PostgreSQL数据库 PostgreSQL和MySQL比较,它更加庞大一点,因为它是用来替代Oracle而设计的.所以在企业应用中采用PostgreSQL是一个明智的选择. 现在My ...