zoukankan      html  css  js  c++  java
  • MessageListActivity has leaked IntentReceiver

    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);
        }
    }

  • 相关阅读:
    Android之Wifi使用
    Android之浮动小窗口
    Android之Socket的基于UDP传输
    Android之基本常见知识(持续更新)
    Android之打开闪光灯关键代码
    Android之Oauth验证(一)
    Android之WebView简易应用
    Android之短信广播接收内容
    Google HTML/CSS 代码风格指南
    几个 HTML 标签的用法
  • 原文地址:https://www.cnblogs.com/fengzhblog/p/3192267.html
Copyright © 2011-2022 走看看