【问题标题】:Cannot get the NotificationListenerService class to work无法让 NotificationListenerService 类工作
【发布时间】:2013-07-28 19:14:29
【问题描述】:

我有一个 android 应用程序正在尝试使用 api 18 中的新 NotificationListenerService 类。我创建了自己的服务类,它继承自此类并覆盖了 onNotificationPosted 和 onNotificationRemoved 事件,尽管我的服务似乎可以正常启动这些当我收到或删除通知时,似乎从未调用 2 个事件。

有没有人在这个类上取得过任何成功,或者他们愿意分享的任何源代码来展示如何使用这个类?

【问题讨论】:

标签: android


【解决方案1】:

根据我的经验,几乎所有这些答案都非常接近正确的解决方案!

CORE问题似乎是在开发过程中出现的;在您开发代码时,当您在调试会话之间更新您的应用时,“通知访问”设置将不再有效。

如果您的 APK/二进制文件发生更改并且 NotificationListenerService 停止:

  • 重新启动修复它。
  • 返回“通知访问”并禁用和重新启用您的应用,它可以修复它。

希望在通过 Google Play 更新您的应用时这不是问题。

作为最佳实践,我为我的应用添加了一个溢出菜单选项,该选项仅显示在非发布版本中,让我可以轻松访问设置:

NotificationListener.java:

public class NotificationListener
    extends NotificationListenerService
    implements RemoteController.OnClientUpdateListener
{
    private static final int VERSION_SDK_INT = VERSION.SDK_INT;

    public static boolean supportsNotificationListenerSettings()
    {
        return VERSION_SDK_INT >= 19;
    }

    @SuppressLint("InlinedApi")
    @TargetApi(19)
    public static Intent getIntentNotificationListenerSettings()
    {
        final String ACTION_NOTIFICATION_LISTENER_SETTINGS;
        if (VERSION_SDK_INT >= 22)
        {
            ACTION_NOTIFICATION_LISTENER_SETTINGS = Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS;
        }
        else
        {
            ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
        }

        return new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS);
    }

    ...
}

menu_my_activity.xml:

<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MyActivity"
    >

    <item
        android:id="@+id/action_application_info"
        android:title="@string/action_application_info"
        app:showAsAction="never"
        />

    <item
        android:id="@+id/action_notification_settings"
        android:title="Notification Settings"
        app:showAsAction="never"
        />

</menu>

MyActivity.java:

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    getMenuInflater().inflate(R.menu.menu_my_activity, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onPrepareOptionsMenu(Menu menu)
{
    MenuItem menuItem;
    menuItem = menu.findItem(R.id.action_application_info);
    if (menuItem != null)
    {
        menuItem.setVisible(BuildConfig.DEBUG);
    }
    menuItem = menu.findItem(R.id.action_notification_settings);
    if (menuItem != null)
    {
        menuItem.setVisible(BuildConfig.DEBUG && NotificationListener.supportsNotificationListenerSettings());
    }
    return super.onPrepareOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    switch (item.getItemId())
    {
        case R.id.action_application_info:
            startActivity(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName())));
            return true;
        case R.id.action_notification_settings:
            startActivity(NotificationListener.getIntentNotificationListenerSettings());
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

【讨论】:

  • 另外,我可以发誓我注意到在大约 10-20 次切换后,它会完全停止工作,直到您重新启动。冲洗,重复。
  • 我认为 NotificationListenerService 停止的问题是由于groups.google.com/forum/#!msg/android-developers/2IegSgtGxyE/… 我怀疑操作系统在重新启动调试会话时没有调用 onBind。我在 onBind 中添加了日志记录,我发现它在旧调试会话结束后不久就被调用了,但是当新的调试会话启动时,新进程永远不会调用 onBind。
  • 我认为你的答案的第一段应该在官方文档中,因为我必须努力学习它并且失去了大约 5 个小时左右
【解决方案2】:

安装正确配置的应用程序后,您应该授予它。

您可以在“设置 > 安全 > 通知访问”中找到应用程序的名称,然后确保选中该复选框。 :)

【讨论】:

  • 查看日志,我经常从 NotificationManagerService 中看到 android.os.DeadObjectException 并且我的回调没有被调用。需要卸载/重新安装我的应用才能修复。
【解决方案3】:

更新:https://gist.github.com/xinghui/b2ddd8cffe55c4b62f5d8846d5545bf9

private void toggleNotificationListenerService() {
    PackageManager pm = getPackageManager();
    pm.setComponentEnabledSetting(new ComponentName(this, com.xinghui.notificationlistenerservicedemo.NotificationListenerServiceImpl.class),
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

    pm.setComponentEnabledSetting(new ComponentName(this, com.xinghui.notificationlistenerservicedemo.NotificationListenerServiceImpl.class),
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);

}

adb shell dumpsys 通知

检查正在使用的服务。

com.android.server.notification.ManagedServices#rebindServices

toggleNotificationListenerService()触发系统调用此方法。

【讨论】:

【解决方案4】:

我遇到了这个错误:

https://code.google.com/p/android/issues/detail?id=59044

只有在我重新启动手机后,我的服务才开始收到通知。

【讨论】:

  • 即使在您发布此内容将近 2 年后,获得NotificationManagerService 工作的唯一方法是重新启动电话。奇怪!!
  • @AADProgramming 即使在您发布此评论将近两年后,我也必须重新启动
  • @Ganesh 即使在将近 1 年之后,您发布了此评论,我也必须重新启动。
【解决方案5】:

经过几个小时的研究,我终于找到了真正有效的示例代码:

https://github.com/yihongyuelan/NotificationListenerServiceDemo

【讨论】:

    【解决方案6】:

    在对设备进行多次调试后,重命名 NotificationListener 类有助于解决问题。将其重命名为什么并不重要,只需将其更改为与以前名称不同的名称即可。我总是不得不一遍又一遍地这样做。

    【讨论】:

    • 这如何回答原始发帖人的问题并不明显 - 也许您可以编辑您的答案以包含一些示例源代码?谢谢。
    【解决方案7】:

    有时删除构建和重建源可能是问题。

    我挣扎了 3 天,这就是我所做的:

    AndroidManifest.xml

    仅从类示例更改服务名称:

    <service
              android:name=".NotificationListener"
              android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
              <intent-filter>
                  <action android:name="android.service.notification.NotificationListenerService" />
              </intent-filter>
          </service>
    

     <service
              android:name="com.mypackage.example.NotificationListener"
              android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
              <intent-filter>
                  <action android:name="android.service.notification.NotificationListenerService" />
              </intent-filter>
          </service>
    

    导航到你的根目录 > android ,然后删除 build 文件夹,让你的项目重新构建。

    【讨论】:

      【解决方案8】:

      NLService 将根据 android 文档一直工作,但在某些情况下,它将与您的特定应用解除绑定,并且可能重新启动您的手机,它会再次绑定。但在更安全的方面,您可以在开始时进行此检查,

      // check NLsettings
      private void checkNLSettings() {
          //check notification access
          if (!NotificationUtils.isNotificationServiceEnabled(this)) {
              //start NLsetting activity
              Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
              startActivityForResult(intent, REQUEST_ACCESSIBLITYCODE);
              finish();
          }
          //check isNLservice running
          if (!isNLServiceRunning()) {
              enableNotificationListenerService(this);
          }
      
          Toast.makeText(this, "NLS == " + isNLServiceRunning(), Toast.LENGTH_SHORT).show();
      }
      
      private boolean isNLServiceRunning() {
          ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
          for (ActivityManager.RunningServiceInfo service :
                  manager.getRunningServices(Integer.MAX_VALUE)) {
              if (NLService.class.getName().equals(service.service.getClassName())) {
                  return true;
              }
          }
          return false;
      }
      
      /**
       * enable notification service.
       *
       * @param context context
       */
      public static void enableNotificationListenerService(Context context) {
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
              NotificationListenerService.requestRebind(new ComponentName(context.getPackageName(),
                      COMPONENT_NLSERVICE));
          } else {
              PackageManager pm = context.getPackageManager();
              pm.setComponentEnabledSetting(new ComponentName(context.getPackageName(),
                              COMPONENT_NLSERVICE),
                      PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                      PackageManager.DONT_KILL_APP);
          }
      }
      

      【讨论】:

        【解决方案9】:

        我刚刚遇到了这个类的一个很好的小例子:

        http://www.kpbird.com/2013/07/android-notificationlistenerservice.html

        我从这个示例中学到的一点是,当通过新的通知访问屏幕授予权限时,我创建的通知服务会自动启动,这意味着我的应用程序不必手动启动该服务。

        【讨论】:

        • 这并不能解释为什么 onNotificationPosted 一开始就没有被调用!我面临同样的问题,我想知道为什么它在依赖示例应用程序之前不起作用......
        • 同意,这也困扰着我。我也很好奇这些应用程序是否需要持续通知才能保持活动状态。
        • 您的代码可能无法正常工作的原因有很多,这就是为什么研究一个工作示例有利于调试的原因。使用上面的例子,我相信很快就会意识到你做错了什么。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-10
        • 1970-01-01
        • 2020-02-23
        • 2014-12-26
        • 2017-12-22
        • 2012-02-28
        • 2015-12-01
        相关资源
        最近更新 更多