如何确保广播接收器已断开连接

时间:2014-03-21 15:25:19

标签: android broadcastreceiver telephonymanager disconnect phone-state-listener

我写了一个简单的广播接收器,它接听来电并用来电号码开始活动:

package com.example.nrsearch;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class CallReceiver extends BroadcastReceiver {
public CallReceiver() {
}

public Context context;

@Override
public void onReceive(Context context, Intent intent) {
    Log.i("CallReceiverBroadcast", "onReceive() is called. ");
    this.context = context;
    TelephonyManager teleMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    PhoneStateListener psl = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            Log.i("CallReceiverBroadcast", "onCallStateChanged() is called. ");
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                Log.i("CallReceiverBroadcast", "Incoming call caught. Caller's number is " + incomingNumber + ".");
                startNumberDisplayActivity(incomingNumber);
            }
        }
    };
    teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
    teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
}

public void startNumberDisplayActivity(String incomingNumber) {
    Intent i = new Intent(context, MainActivity.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    i.putExtra("incomingNumber", incomingNumber);
    context.startActivity(i);
}
}

然而,在第一个来电后,我觉得我的设备电池开始很快耗尽。我担心某些进程仍会阻止我的广播接收器断开连接(我的意思是我的广播接收器可能永远在运行)。那么,我的代码中是否存在可能导致此类行为的内容,并且此行确实会阻止TelephonyManager监听调用状态更改:teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);还是应该以其他方式执行此操作?

编辑:我几乎可以肯定这个类导致电池耗尽,因为现在我正在测试我的应用程序已卸载的电池续航时间,并且它远低于之前安装此应用程序并调用广播接收器的时间。我不能发誓,这个级别是排水的原因,但无论有没有这个应用程序,电池消耗差异清晰可见。有人可以看看这段代码并说出什么可能导致电池耗尽?提前致谢!

1 个答案:

答案 0 :(得分:1)

方法

@Override 
public void onPause() {

super.onPause();
mActivity.unregisterReceiver(myReceiver);

}

你可以放置其他地方,但那是一个好地方。请在onResume注册。

另请阅读broadcastreceiver docs,他们不会按照您认为他们的方式工作:

http://developer.android.com/reference/android/content/BroadcastReceiver.html

接收器生命周期基本上是:

  

接收器生命周期

     

BroadcastReceiver对象仅在通话期间有效   to onReceive(Context,Intent)。一旦你的代码从此返回   功能,系统认为要完成的对象不再   活性

     

这对你能做些什么有重要的影响   onReceive(Context,Intent)实现:需要的任何东西   异步操作不可用,因为您需要   从函数返回来处理异步操作,但是在   那一点,BroadcastReceiver不再是活动的,因此   系统可以在异步操作之前自由地终止其进程   完成。

     

特别是,您可能无法显示对话框或绑定到服务   在BroadcastReceiver中。对于前者,你应该使用   NotificationManager API。对于后者,你可以使用   Context.startService()将命令发送到服务。

编辑:

根据您的意见 - 关于BroadcastReceiver吃电池寿命的担忧并不现实。接收器只持续运行接收器方法中的代码所需的时间。在那时,Android会在它认为必要的时候清理它。如果你的代码中的任何内容破坏了它,那就是:

this.context = context;

/// these three lines
    TelephonyManager teleMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
   .....
    teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);

因为您创建了一个对象,然后尝试监听它。

但是你应该真正阅读文档:

  

任何需要的东西   异步操作不可用,

您在代码中正在做什么 - 附加到服务并等待其异步响应。这在BroadcastReceiver中是不可接受的,此时在文档中明确指出:

  

特别是,您可能无法显示对话框或绑定到服务   在BroadcastReceiver中。