天道酬勤,学无止境

Android Nougat PhoneStateListener 未触发(Android Nougat PhoneStateListener is not triggered)

问题

在 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 上正常工作

回答1

这是由于 https://github.com/aosp-mirror/platform_frameworks_base/commit/f5d7c587e86c64e657a15a12ad70e75d47c48d99#diff-5af2ac899de823cf60597e50

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

回答2

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

因此,我没有注册电话管理器来侦听(服务的) onCreate方法,而是将其设置在onStartCommand 中,然后它就开始工作了。

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

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

所以这是我的代码也适用于 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
     } 
 }

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Android Nougat PhoneStateListener is not triggered
    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
  • android中的漫游检测(roaming detection in android)
    问题 我正在尝试检测何时发生漫游激活。 到目前为止,我已经使用了以下代码,但是由于无法测试,因此我不知道它的正确性。 TelephonyManager telephonyManager = TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); PhoneStateListener cellLocationListener = new PhoneStateListener() { public void onCellLocationChanged(CellLocation location) { if(telephonyManager.isNetworkRoaming() { Toast.makeText(getApplicationContext(),"in roaming",Toast.LENGTH_LONG).show(); } } }; telephonyManager.listen(cellLocationListener, PhoneStateListener.LISTEN_CELL_LOCATION); 我已经写了这篇文章,认为为了使漫游首先激活,信号单元必须改变。 请让我知道我的推论是否正确,如果不正确,我怎么能做到这一点。 回答1 如果您想知道是否存在语音漫游
  • 如何通过 NotificationListener 使用 Android Nougat 的直接回复功能?(How to utilize Android Nougat's Direct Reply feature with a NotificationListener?)
    问题 我的应用程序正在使用NotificationListener来读取来自各种 3rd 方应用程序(例如 WhatsApp)的消息。 到目前为止,如果只有一个聊天未读,我可以发送回复,代码如下。 但是,在 WhatsApp 的情况下,当两个以上的聊天未读时, getNotification().actions返回一个空对象,因为消息捆绑在一起。 正如你在下面的图片中看到的,如果通知被扩展,还有一个选项可以发送直接回复,因此我确信可以利用它,而且我认为像 PushBullet 这样的应用程序正在使用这种方法。 我如何访问该通知的 RemoteInput? public static ReplyIntentSender sendReply(StatusBarNotification statusBarNotification, String name) { Notification.Action actions[] = statusBarNotification.getNotification().actions; for (Notification.Action act : actions) { if (act != null && act.getRemoteInputs() != null) { if (act.title.toString().contains(name)) {
  • 结合使用BroadcastReceiver和PhoneStateListener的功能(Using BroadcastReceiver with functionality of PhoneStateListener)
    问题 我正在尝试制作一个MissCall应用程序,该应用程序会在收到未接来电时自动发送一条消息。 我已经完成了我的应用程序,并且运行良好! 这是完整的场景: 问题 : 该应用程序运行正常,但是当我重新启动设备时,该应用程序无法正常工作! 。 只有在我至少启动我的App一次之后,它才能正常工作,直到关闭为止。 这是我的代码: package com.example.misscallapp; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.preference.PreferenceActivity; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.widget.Toast; public class Pref_Main extends PreferenceActivity { int checkIt = 0; TelephonyManager tm; CallStateListener callStateListener = new CallStateListener()
  • Foreground notification service not working in one plus devices
    Below is the code for starting the foreground service. It is working fine for many devices like Samsung, moto, Vivo, Oppo and also with Android version nougat and oreo, but not working on One plus devices. Can anyone let me know if any extra changes or permission is required to run in One plus device or if any emulator supports one plus phones. public class ForegroundService extends Service { private Context ctx; private static final String PRIMARY_NOTIF_CHANNEL = "default"; @Override public void onCreate() { super.onCreate(); ctx = this; createNotificationService(); } private void
  • 在Android中获取信号强度(Get Signal Strength in Android)
    问题 我想在点击API调用时获得设备的信号强度。 我已经搜索了所有相关的线程,但还没有成功。 所以我想得到像 SignalStrength ss = null ; // some initialization int n = ss.getGsmSignalStrength(); 但是,在使用此功能时,很明显,由于将SignalStrength初始化为null,因此我将获得null指针异常。 但是我不知道该如何初始化。 另外,我也不想使用PhoneStateListener因为只有在信号发生更改时才会触发它。 我正在使用以下代码获取信号强度 TelephonyManager telephonyManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE); CellInfoGsm cellinfogsm = (CellInfoGsm)telephonyManager.getAllCellInfo().get(0); CellSignalStrengthGsm cellSignalStrengthGsm = cellinfogsm.getCellSignalStrength(); cellSignalStrengthGsm.getDbm()
  • 如何在Android中获得小区服务信号强度?(How to get cell service signal strength in Android?)
    问题 我正在尝试编写一个非常简单的Android应用程序,用于检查当前单元格的信号强度。 到目前为止,我只找到了一个名为getNeighboringCellInfo()东西,但是我不确定这是否包括当前单元格。 如何在Android中获取当前的细胞信号强度? getNeighborCellInfo()是否获取当前单元格? 基于我已经能够获得的结果,它似乎并不像它。 这是我当前的代码: List<NeighboringCellInfo> n = tm.getNeighboringCellInfo(); //Construct the string String s = ""; int rss = 0; int cid = 0; for (NeighboringCellInfo nci : n) { cid = nci.getCid(); rss = -113 + 2*nci.getRssi(); s += "Cell ID: " + Integer.toString(cid) + " Signal Power (dBm): " + Integer.toString(rss) + "\n"; } mainText.setText(s); 回答1 创建一个PhoneStateListener并处理onSignalStrengthChanged回调。 初始化您的应用后,它会给您一个初始通知。
  • 如何在android中拨打电话并完成通话后返回我的活动?(How to make a phone call in android and come back to my activity when the call is done?)
    问题 我正在启动一个活动来打电话,但是当我按下“结束通话”按钮时,它不会返回到我的活动。 您能告诉我如何启动按下“结束通话”按钮后又回到我身边的通话活动吗? 这是我拨打电话的方式: String url = "tel:3334444"; Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url)); 回答1 使用PhoneStateListener查看呼叫何时结束。 您很可能需要触发侦听器操作以等待调用开始(等待直到再次从PHONE_STATE_OFFHOOK更改为PHONE_STATE_IDLE),然后编写一些代码以使您的应用恢复到IDLE状态。 您可能需要在服务中运行侦听器,以确保侦听器保持运行状态并重新启动您的应用。 一些示例代码: EndCallListener callListener = new EndCallListener(); TelephonyManager mTM = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE); mTM.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE); 侦听器定义: private class
  • 图标未显示在 Android 牛轧糖的通知中(Icon is not getting displayed in notification in Android nougat)
    问题 我对此进行了研究,发现addAction (int icon, CharSequence title, PendingIntent intent)已被弃用,因此我使用了addAction (Notification.Action action) 。 在这两种情况下,都无法看到图标。 NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_share, "", pendingIntent).build(); notificationBuilder.addAction(action); 文本似乎正在工作,但我将其留空,因此主图像下方有一个空白空间,应该显示图标 回答1 这不是错误,而是 Android Nougat 的设计更改。 设备不再显示由addAction (Notification.Action action)定义的图标。 旧设备和 Android Wear 设备仍然需要它们! 引用 android 开发者 google 博客 您会注意到新通知中没有这些图标; 相反,在通知栏的受限空间中为标签本身提供了更多空间。 但是,通知操作图标仍然是必需的,并且会继续在旧版本的 Android 和 Android Wear 等设备上使用。 如果您一直使用
  • 在Android中检索当前传出电话号码时未获得正确的值(Not getting correct value when retrieving current outgoing phone number in android)
    问题 我正在使用以下广播接收器来检索传出的电话号码。 @Override public void onReceive(Context context, Intent intent) { mContext = context; mIntent = intent; TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); int events = PhoneStateListener.LISTEN_CALL_STATE; tm.listen(phoneStateListener, events); } private final PhoneStateListener phoneStateListener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_IDLE: break; case TelephonyManager.CALL_STATE_OFFHOOK: dialingNumber =
  • 即时信号强度(Instant signal strength)
    问题 我需要找到一种方法来测量Android手机的当前信号强度,而无需注册一个天知道什么时候返回实际asu的PhoneStateListener。 就像是: int signal = getPhoneSignal(); 有什么帮助吗? 谢谢! 回答1 如果您仔细查看 Android 源代码,您会发现在注册PhoneStateListener您将PhoneStateListener即时通知: public void listen(PhoneStateListener listener, int events) { String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>"; try { Boolean notifyNow = (getITelephony() != null); mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow); } catch (RemoteException ex) { // system process dead } } 因此,您可以创建自己的计时器并在计时器更新时注册新的侦听器,并在收到即时更新后通过传递相同的侦听器对象并将事件参数设置为LISTEN_NONE来删除它。 当然
  • 当应用程序在前台时检测 Android 7.0 Nougat 上的连接变化(Detect connectivity changes on Android 7.0 Nougat when app is in foreground)
    问题 Nougat 改变了它处理 CONNECTIVITY_CHANGED 意图的方式(基本上忽略它,迫使开发人员使用作业调度程序)所以这让我想知道: 如果我有一个应用程序正在检索一些数据(并且我检查了在我执行请求时手机是否在线,但用户正在移动并且手机连接到不同的 wifi 接入点,例如) 并且它失败了,我如何检测连接是否已恢复并重新尝试获取数据? 所以在这种情况下,我的应用程序在前台,我认为 Chrome(适用于 android)具有类似的功能。 我需要自己投票吗? 或者当时有什么活动是允许的? 回答1 如果正在运行的应用程序使用 BroadcastReceiver 请求通知,它们仍然可以在其主线程上侦听CONNECTIVITY_CHANGE 。 https://developer.android.com/about/versions/nougat/android-7.0-changes.html 回答2 虽然可以使用 Andromeda 的答案,但该解决方案不是 Google 的预期选择。 您的问题是当连接丢失时该怎么办,并且您需要在网络服务恢复时恢复操作。 虽然 CONNECTIVITY_CHANGE 从技术上讲是可行的,但对于这个特定的需求,它总是有点麻烦,一旦你的应用程序进入后台,它就会在 Nougat 中停止工作。 您真正应该使用的是作业调度程序 API。 Google
  • 添加PhoneStateListener(Add PhoneStateListener)
    问题 我正在尝试设置PhoneStateListener但是我无法将PhoneCallListener cannot be resolved to a type 。 public class ButtonView extends FrameLayout { PhoneCallListener phoneListener = new PhoneCallListener(); TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); telephonyManager.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE); } 在另一个示例中,我发现它是这样写的,并且可以正常工作 public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { // add PhoneStateListener PhoneCallListener phoneListener = new PhoneCallListener(); TelephonyManager
  • 当设备语言为 en_US 时,Android 7.0 Nougat 会选择默认字符串(Android 7.0 Nougat picks up default strings when device language is en_US)
    问题 根据语言和区域设置中的文档,Android 7.0(API 级别 24)对资源解析策略进行了改进,下表很容易理解:改进的资源解析策略 根据我的要求,我希望我的应用程序的默认语言为 en_US。 所以,我没有为 en_US 提供单独的资源。 我还单独提供了 en_GB 资源。 现在,根据解析策略,如果我的设备的语言是 en_US,那么它查找资源的顺序是 en_US -> en -> en_GB -> default 这意味着对于 en 的所有语言环境,在我的情况下将选择 en_GB因为我没有单独的“en”资源,但是存在子“en_GB”。 但是,当我将设备语言选择为 en_US 时,它会正确选择默认语言(在我的情况下为 en_US)而不是 en_GB,这正是我在设备语言为 en_US 的情况下所需要的。 When some other locale like en_IN or en_AU is selected, it picks up en_GB. 解决此问题的一种方法是我分别在 'en' 和 en_GB 中提供 en_US 字符串,这将导致我想要的行为。 但是,当我选择 en_US 作为我的设备语言时,我无法理解为什么会选择默认字符串。 是否 en_US 是 android 的默认语言,每当 en_US 被选为设备的语言时,如果 en_US 未单独提供,它会选择默认字符串?
  • PhoneStateListener在三星GT-S7562上不起作用(PhoneStateListener not working on Samsung GT-S7562)
    问题 我在Samsung GT-S7562(双SIM-4.0)上测试PhoneStateListener,那么STATE始终返回0,INCOMING NUMBER始终返回空。 虽然在我的另一台设备上可以正常使用SAMSUNG GT-S5570(单SIM-2.2)。 这是我的代码。 import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; public class IncomingCall extends BroadcastReceiver { Context pcontext; public void onReceive(Context context, Intent intent) { pcontext = context; try { TelephonyManager tmgr = (TelephonyManager) context
  • Using BroadcastReceiver with functionality of PhoneStateListener
    I am trying to make a MissCall App which sends a message automatically when a miss call is received.I had completed my app and it worked fine ! Here is the complete scenario : Problem : The app was working fine but when i restarted the device the app didn't work ! . It only worked when i started my App atleast once after that it worked fine till it is switched off . Here is my code : package com.example.misscallapp; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.preference.PreferenceActivity; import android.telephony.PhoneStateListener
  • 监听电话状态的变化 - Android(Listen to Change of Phone State State - Android)
    问题 我目前正在尝试创建一个简单的应用程序,该应用程序会记录您通话的时间,然后在您接近空闲时间时向您发出警告。 在这一点上,我创建了一个名为 CallService.java 的服务,每当用户呼叫人员时都会调用该服务。 该服务只是记录通话的开始时间和通话的结束时间。 该服务是使用名为 OutgoingCallReciever.Java 的类启动的。 此类只是等待用户呼叫某人,然后启动 CallService。 我现在试图在用户电话未呼叫某人时停止 CallService。 即(电话状态为空闲、摘机或其他人正在呼叫用户)但我不知道该怎么做(我是 Java/Android 新手)。 我是否使用 PhoneStateListener 的 onCallStateChanged 方法? (我不确定如何使用它..) 希望你能帮上忙! 课程如下: 主活动.java package com.fouadalnoor.callcounter; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.widget.CheckBox; import android.widget.CompoundButton
  • 在不更改SignalStrength的情况下使用PhoneStateListener的情况下获取SignalStrength(get SignalStrength without Using PhoneStateListener onSignalStrengthchanged)
    问题 有谁知道如何获取信号强度而不必调用onSignalStrengthChanged。 onSignalStrengthchanged的问题在于,当信号强度发生变化时需要调用它,而我需要根据不同的标准来获取signalstrength的值。 提前致谢。 回答1 仅在API级别17上,以下是一些可以在Activity (或任何其他Context子类)中使用的代码: import android.telephony.CellInfo; import android.telephony.CellInfoCdma; import android.telephony.CellInfoGsm; import android.telephony.CellInfoLte; import android.telephony.CellSignalStrengthCdma; import android.telephony.CellSignalStrengthGsm; import android.telephony.CellSignalStrengthLte; import android.telephony.TelephonyManager; try { final TelephonyManager tm = (TelephonyManager) this.getSystemService
  • PhoneStateListener not working on Samsung GT-S7562
    I am testing PhoneStateListener on Samsung GT-S7562(dual sim- 4.0) then STATE always returns 0 and INCOMING NUMBER always returns empty. While it works fine on my another device SAMSUNG GT-S5570(single sim- 2.2). Here is my code. import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; public class IncomingCall extends BroadcastReceiver { Context pcontext; public void onReceive(Context context, Intent
  • 无法检测何时在Android中接听去电(Cannot detect when outgoing call is answered in Android)
    问题 为了检测何时应答了去电,我尝试从该问题创建一个PhoneStateListener并侦听TelephonyManager的CALL_STATE_RINGING , CALL_STATE_OFFHOOK和CALL_STATE_IDLE ,但是它似乎不起作用,如下所述。 首先,我在清单中注册了以下权限: <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> 然后,称为OutCallLogger的BroadcastReceiver在每次拨出呼叫时捕获NEW_OUTGOING_CALL事件: <receiver android:name=".listener.OutCallLogger"> <intent-filter> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver> 接下来,我的OutCallLogger实现。 我设置了一个名为noCallListenerYet的布尔值,以避免在调用onReceive()时将新的PhoneStateListener到TelephonyManager 。 public class OutCallLogger