1

美好的一天,我动态构建了 android 短信发送和交付接收器,我收到泄漏错误,因为我需要在切换活动之前取消注册接收器。我想在收到响应时注销接收器。

此外,我无法覆盖 onPause 和 resume,因为此类是一个库并扩展了对话框,并且必须在代码中构造接收器。

这是代码:

private void sendSMS(String msg, String msisdn, String func) { 

   String SENT = "SMS_SENT";
   String DELIVERED = "SMS_DELIVERED";
   log("SMS FUNCTION: RUN");


    PendingIntent sentPI = PendingIntent.getBroadcast(mContext, 0,
           new Intent(SENT), 0);

    PendingIntent deliveredPI = PendingIntent.getBroadcast(mContext, 0,
           new Intent(DELIVERED), 0);

    BroadcastReceiver smsReceiverD=new BroadcastReceiver(){

        @Override
        public void onReceive(Context arg0, Intent arg1) {
            log("SMS FUNCTION: SMS DELIVER CHECK");
            switch (getResultCode())
            {
                case Activity.RESULT_OK:
                    break;
                case Activity.RESULT_CANCELED:
                    sendEventLog("Failed(SMS not delivered)"); 
                    break;
            }
        }

    };

    BroadcastReceiver smsReceiverS=new BroadcastReceiver(){

        @Override
        public void onReceive(Context arg0, Intent arg1) {
            log("SMS FUNCTION: SEND CHECK");

            switch (getResultCode())
            {
                case Activity.RESULT_OK:
                    break;
                case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                    log("Failed(Generic failure)");
                    sendEventLog("moFailed(Generic failure)");  
                    break;
                case SmsManager.RESULT_ERROR_NO_SERVICE:
                    sendEventLog("Failed(No service)");     
                    break;
                case SmsManager.RESULT_ERROR_NULL_PDU:
                    sendEventLog("Failed(Null PDU)");   
                    break;
                case SmsManager.RESULT_ERROR_RADIO_OFF:
                    sendEventLog("Failed(Radio off)");  
                    break;
            }
        }

    };

   SmsManager MySmsManager = SmsManager.getDefault();
   sendEventLog("Send("+keyword+":"+msisdn+")");         

   if (msg != null) {
    log("SMS FUNCTION: SMS SEND");
       MySmsManager.sendTextMessage(msisdn, null, keyword, sentPI, deliveredPI);
       mContext.registerReceiver(smsReceiverD,new IntentFilter(DELIVERED));
       mContext.registerReceiver(smsReceiverS,new IntentFilter(SENT));
    }
   }

我想添加

mContext.unregisterReceiver(smsReceiverS);

在 smsReciverS.

它说

Cannot refer to a non-final variable smsReceiverS inside an inner class defined in a different method

如果我确实做到了:

The local variable smsReceiverS may not have been initialized

请有人帮忙。

4

3 回答 3

0

在你的方法中使用arg0.unregister(this);where arg0is instanceofContextonReceive(Context arg0, Intent arg1)smsReceiverS

于 2013-01-30T07:48:12.010 回答
0

我认为在这种情况下,您可以使用HandlerRunnable任务来取消注册您的接收器:

private Handler mHandler = new Handler();

....

private Runnable unregisterIt = new Runnable() {

    @Override
    public void run() {
        mContext.unregisterReceiver(smsReceiverS);
    }
};

...
//to unregister just call this
mHanler.post(unregisterIt);
于 2013-01-30T07:50:03.627 回答
0

虽然 Waqas 的解决方案绝对是可能的(onReceive() 将在接收器运行的上下文中调用),而 Evos 的解决方案对我来说毫无意义(代码通过调用假设Handler()它在它所在的确切上下文中运行然后稍后应该运行),两个答案都没有解决原始问题,即关于最终变量的错误。

关键是您需要使 mContext 成为最终的,这样它就不会为您的即时广播接收器更改,因为它是一个匿名内部类,它将携带对它的隐式引用。但是,限制适用于最终变量;它们必须只初始化一次。

强制执行的分析是在编译时运行的,并且对 Android 机制没有更深入的了解,所以重要的是声明、构造函数和未来的进一步使用。

大概,你在声明

Activity mContext = null;

这会导致稍后出现错误,因为您会再次分配一个值?

虽然 Waqas 的解决方案会起作用,但如果您想了解final. 并且我的假设是错误的,您将不得不使用有关使用mContext.

于 2013-01-30T08:00:27.580 回答