问题
In Android (target 25) I have a background service and in onCreate function I have initialized a phone state listener. It works fine on Android versions that are before Nougat but in Nougat it doesn't work, even though the permissions are granted.
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);
}
}
I don't know what is the problem, it looks like the telephony manager is not registered and therefore the onCallStateChanged is not triggered. One of my guesses is the Doze feature that was introduced on Android M, but still.. this code works fine on Android 6 even when the phone is not found "in work"
回答1:
This was due to a change in PhoneStateListener introduced by https://github.com/aosp-mirror/platform_frameworks_base/commit/f5d7c587e86c64e657a15a12ad70e75d47c48d99#diff-5af2ac899de823cf60597e554bf67fe0.
Local reference to PhoneStateListener is kept track internally only by a weak reference. This makes it eligible for garbage collection upon function exit and once the listener is finalized, apps will not receive any further updates. Solution is to keep a reference to PhoneStateListener via class member variable.
回答2:
So for those who encountered the same problem I found a solution. You don't need to register a BroadcastReceiver for PhoneState.
So instead of registere the telephony manager to listen inside the onCreate method (of the service), I set it in onStartCommand and it started to work.
but notice that in any case that onStartCommand will be triggered it will register the telephony manager, so be sure to register it only once.
In my case, since inside the service class I have the Inner class PhoneListener I created a class member and initialized it to null, and In the onStartCommand I have checked if it's null and then created and registered the telephony manager, but you can use the singelton way.
So this is my code that worked also in 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
}
}
来源:https://stackoverflow.com/questions/42213250/android-nougat-phonestatelistener-is-not-triggered