Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 无法使NotificationListenerService类工作_Android - Fatal编程技术网

Android 无法使NotificationListenerService类工作

Android 无法使NotificationListenerService类工作,android,Android,我有一个android应用程序,它试图使用api 18中的新NotificationListenerService类。我创建了自己的服务类,该类继承自该类,并覆盖onNotificationPosted和onNotificationRemoved事件,尽管我的服务似乎启动得很好,但在我获取或删除通知时,这两个事件似乎从未被调用 是否有人成功使用了该类,或者可能有任何源代码,他们将分享这些代码,以演示如何使用该类?在安装正确配置的应用程序后,您应该授予它 您可以在“设置>安全性>通知访问”中找到应

我有一个android应用程序,它试图使用api 18中的新NotificationListenerService类。我创建了自己的服务类,该类继承自该类,并覆盖onNotificationPosted和onNotificationRemoved事件,尽管我的服务似乎启动得很好,但在我获取或删除通知时,这两个事件似乎从未被调用


是否有人成功使用了该类,或者可能有任何源代码,他们将分享这些代码,以演示如何使用该类?

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


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

我刚刚看到一个很好的小例子,说明这门课在起作用:


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

我遇到了以下错误:


只有在我重新启动手机后,通知才会出现在我的服务中。

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


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

核心问题似乎发生在开发过程中;在开发代码时,当您在调试会话之间更新应用程序时,“通知访问”设置将停止使用

如果您的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);
    }

    ...
}
菜单\u my\u 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>
更新:

adb外壳转储系统通知

检查哪个服务正在使用

com.android.server.notification.ManagedServices#rebindServices


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

有时删除生成和重新生成源可能是问题所在

我为此奋斗了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>



导航到根目录>android,然后删除生成文件夹,允许项目重新生成。

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

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);
    }
}

这并不能解释为什么onNotificationPosted一开始就不被调用!我面临着同样的问题,我想知道为什么在依赖示例应用程序之前它不起作用……同意,这也困扰着我。我还想知道这些应用程序是否也需要持续的通知才能保持活动状态。代码可能无法工作的原因有很多,这就是为什么研究一个工作示例有利于调试的原因。使用上面的例子,我相信很快就会意识到你做错了什么。检查日志,我经常在NotificationManagerService中看到android.os.DeadObjectException,我的回调没有被调用。需要卸载/重新安装我的应用程序才能修复。此外,我可以发誓,我注意到在大约10-20次切换后,它会完全停止工作,直到你重新启动。冲洗,重复。我认为NotificationListenerService停止的问题是因为我怀疑操作系统在重新启动调试会话时没有调用onBind。我在onBind中添加了日志记录,我看到它在旧的调试会话结束后很快就会被调用,但是当新的调试会话开始时,onBind就不会被调用到新的进程中。我认为你答案的第一段应该是在官方文档中,因为我不得不努力学习,在你发布这篇文章将近2年后,我花了大约5个小时或更长的时间,让NotificationManagerService工作的唯一方法是重新启动手机。奇怪@aad编程即使在你发布这条评论将近两年后,我也必须这样做reboot@Ganesh即使在将近一年之后,你发表了这条评论,我也必须重新启动。谢谢@hugo这正是我想要的。不幸的是,通知侦听器服务有缺陷,但有了它,我们可以强制并重新加载。至少我可以确认这将关闭我的通知访问。@Jareddlc update:这如何回答原始海报的问题并不明显-也许您可以编辑您的答案以包含一些示例源代码?谢谢。我的2分钱给任何在安卓奥利奥面对它的人。以下是我对一个对我有效的解决方案的评论:
<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>
// 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);
    }
}