Android 无法使NotificationListenerService类工作
我有一个android应用程序,它试图使用api 18中的新NotificationListenerService类。我创建了自己的服务类,该类继承自该类,并覆盖onNotificationPosted和onNotificationRemoved事件,尽管我的服务似乎启动得很好,但在我获取或删除通知时,这两个事件似乎从未被调用Android 无法使NotificationListenerService类工作,android,Android,我有一个android应用程序,它试图使用api 18中的新NotificationListenerService类。我创建了自己的服务类,该类继承自该类,并覆盖onNotificationPosted和onNotificationRemoved事件,尽管我的服务似乎启动得很好,但在我获取或删除通知时,这两个事件似乎从未被调用 是否有人成功使用了该类,或者可能有任何源代码,他们将分享这些代码,以演示如何使用该类?在安装正确配置的应用程序后,您应该授予它 您可以在“设置>安全性>通知访问”中找到应
是否有人成功使用了该类,或者可能有任何源代码,他们将分享这些代码,以演示如何使用该类?在安装正确配置的应用程序后,您应该授予它
您可以在“设置>安全性>通知访问”中找到应用程序的名称,然后确保复选框已填充。:) 我刚刚看到一个很好的小例子,说明这门课在起作用:
我从下面的示例中学到的一点是,当通过新通知访问屏幕授予权限时,我创建的通知服务会自动启动,这意味着我的应用程序不必手动启动服务。我遇到了以下错误:
只有在我重新启动手机后,通知才会出现在我的服务中。经过几个小时的研究,我终于找到了实际有效的示例代码:
根据我的经验,几乎所有这些答案都非常接近正确的解决方案 核心问题似乎发生在开发过程中;在开发代码时,当您在调试会话之间更新应用程序时,“通知访问”设置将停止使用 如果您的APK/二进制文件发生更改并且NotificationListenerService停止:
- 重新启动修复了它
- 返回到“通知访问”,禁用并重新启用应用程序,它会修复它
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);
}
}