我有一个 android 应用程序正在尝试使用 api 18 中的新 NotificationListenerService 类。我创建了自己的服务类,该类继承自该类并覆盖了 onNotificationPosted 和 onNotificationRemoved 事件,尽管我的服务似乎启动得很好,但这两个事件从来没有当我收到或删除通知时似乎被调用。
有没有人在这个类上取得了任何成功,或者他们可能会分享任何源代码来准确地展示如何使用这个类?
我有一个 android 应用程序正在尝试使用 api 18 中的新 NotificationListenerService 类。我创建了自己的服务类,该类继承自该类并覆盖了 onNotificationPosted 和 onNotificationRemoved 事件,尽管我的服务似乎启动得很好,但这两个事件从来没有当我收到或删除通知时似乎被调用。
有没有人在这个类上取得了任何成功,或者他们可能会分享任何源代码来准确地展示如何使用这个类?
根据我的经验,几乎所有这些答案都非常接近正确的解决方案!
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>
我的活动.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);
}
}
安装正确配置的应用程序后,您应该授予它。
您可以在“设置 > 安全 > 通知访问”中找到应用程序的名称,然后确保选中该复选框。:)
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()触发系统调用此方法。
经过数小时的研究,我终于找到了实际有效的示例代码:
https://github.com/yihongyuelan/NotificationListenerServiceDemo
在对设备进行多次调试后,重命名 NotificationListener 类有助于解决问题。将其重命名为什么并不重要,只需将其更改为与以前名称不同的名称即可。我总是不得不一遍又一遍地这样做。
NLService will be working all the time as per android docs but in some cases it will be unbind from your specific app and may restarting your phone it will bind again . But in safer side you can have this check whenever your starts ,
// 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);
}
}
有时删除构建和重建源可能是问题。
我挣扎了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 ,然后删除构建文件夹,让您的项目重新构建。
我刚刚遇到了这个类的一个很好的小例子:
http://www.kpbird.com/2013/07/android-notificationlistenerservice.html
我从这个示例中学到的一件事是,当通过新的通知访问屏幕授予权限时,我创建的通知服务会自动启动,这意味着我的应用程序不必手动启动该服务。