在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上运行良好
答案 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
}
}