6

在 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 上引入的打盹功能,但仍然......即使没有找到“工作中”的手机,此代码在 Android 6 上也能正常工作

4

2 回答 2

11

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

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

于 2018-04-20T03:43:34.527 回答
4

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

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

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

就我而言,由于在服务类中我有内部类PhoneListener我创建了一个类成员并将其初始化为 null,并且在 onStartCommand 我检查了它是否为 null 然后创建并注册了电话管理器,但是您可以使用辛格尔顿方式。

所以这是我在 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
     } 
 }
于 2017-02-14T21:42:03.103 回答