未触发Android Nougat PhoneStateListener

时间:2017-02-13 20:47:43

标签: android telephonymanager android-7.0-nougat android-7.1-nougat android-doze

在Android(目标25)中,我有一个后台服务,在onCreate函数中,我初始化了一个手机状态监听器。它适用于Nougat之前的Android版本,但在Nougat中它不起作用,即使权限被授予。

public class Service extends IntentService
{
    class PhoneListener extends PhoneStateListener
    {
       String TAG = getClass().getName();
       @Override
       public void onCallStateChanged(int state, String incomingNumber) 
       {
           super.onCallStateChanged(state, incomingNumber);
           switch (state)
           {
               case TelephonyManager.CALL_STATE_IDLE:
                Log.d(TAG,"IDLE" );
               break;
               case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.d(TAG,"OFFHOOK");
               break;
               case TelephonyManager.CALL_STATE_RINGING:
                Log.d(TAG,"RINGING");
               break;
           }
       }
   }

   public Service ()
   {
       super("ChatService");
   }
   public Service(String name)
   {
       super(name);
   }

   @Override
   public void onCreate()
   {
       super.onCreate();
       TelephonyManager tm = (TelephonyManager)getApplicationContext().getSystemService(TELEPHONY_SERVICE);
       PhoneListener listener = new PhoneListener();
       tm.listen(listener,PhoneStateListener.LISTEN_CALL_STATE);
   }
}

我不知道是什么问题,看起来电话管理器没有注册,因此没有触发onCallStateChanged。 我的猜测之一是在Android M上引入的Doze功能,但仍然......即使手机未找到“工作中”,此代码在Android 6上运行良好

2 个答案:

答案 0 :(得分:5)

这是由于https://github.com/aosp-mirror/platform_frameworks_base/commit/f5d7c587e86c64e657a15a12ad70e75d47c48d99#diff-5af2ac899de823cf60597e554bf67fe0引入的PhoneStateListener发生了变化。

对PhoneStateListener的本地引用仅在内部通过弱引用进行跟踪。这使得它有资格在函数退出时进行垃圾收集,一旦监听器完成,应用程序将不会收到任何进一步的更新。解决方案是通过类成员变量保持对PhoneStateListener的引用。

答案 1 :(得分:3)

因此,对于那些遇到同样问题的人,我找到了解决方案。 您无需为 PhoneState 注册 BroadcastReceiver

因此,我没有注册电话管理员在 onCreate 方法(服务)中进行监听,而是将其设置在 onStartCommand 中,然后开始工作。

但请注意,在任何情况下都会触发 onStartCommand ,它会注册电话管理器,因此请务必只注​​册一次。

在我的情况下,因为在服务类内部我有内部类 PhoneListener 我创建了一个类成员并将其初始化为null,并且在onStartCommand中我检查了它是否为null然后创建了注册了电话管理员,但你可以使用singelton方式。

所以这是我的代码,也适用于Android Nougat:

public class Service extends IntentService
{
    class PhoneListener extends PhoneStateListener
    {
       String TAG = getClass().getName();
       @Override
       public void onCallStateChanged(int state, String incomingNumber) 
       {
           super.onCallStateChanged(state, incomingNumber);
           switch (state)
           {
               case TelephonyManager.CALL_STATE_IDLE:
                  Log.d(TAG,"IDLE" );
               break;
               case TelephonyManager.CALL_STATE_OFFHOOK:
                   Log.d(TAG,"OFFHOOK");
               break;
               case TelephonyManager.CALL_STATE_RINGING:
                   Log.d(TAG,"RINGING");
               break;
           }
     }
     PhoneListener phoneListener = null;

     public Service ()
     {
       super("ChatService");
     }

     @Override
     public void onCreate()
     {
        super.onCreate();
        // do what you need here
     }

     @Override
     public int onStartCommand (Intent intent, int flags, int startId)
     {
        if (phoneListener == null)
        {
          TelephonyManager tm = (TelephonyManager)getApplicationContext().getSystemService(TELEPHONY_SERVICE);
          phoneListener = new PhoneListener();
          tm.listen(listener,PhoneStateListener.LISTEN_CALL_STATE);
        }
        // do what you need to do here

        return START_STICKY; // you can set it as you want
     } 
 }