Cannot get the NotificationListenerService class to work

前端 未结 9 1842
梦如初夏
梦如初夏 2020-12-03 01:35

I have a android application that is trying to use the new NotificationListenerService class from api 18. I have created my own service class that inherits from this class a

相关标签:
9条回答
  • 2020-12-03 02:09

    I have encountered this bug:

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

    And notifications started coming to my service only after I rebooted my phone.

    0 讨论(0)
  • 2020-12-03 02:16

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-03 02:19

    update: https://gist.github.com/xinghui/b2ffffd8cffe55c4b62f5d8846d5545bf9

    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 notification

    check which service is living.

    com.android.server.notification.ManagedServices#rebindServices

    toggleNotificationListenerService() trigger system invoke this method.

    0 讨论(0)
  • 2020-12-03 02:19

    Sometimes deleting build and rebuilding source might be the issue.

    I Struggled with it for 3 days, and here is what I have done:

    AndroidManifest.xml

    Changes service name from just class example:

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

    to

     <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>
    

    Navigate to your root directory > android , then delete build folder, allow your project to rebuild.

    0 讨论(0)
  • 2020-12-03 02:22

    I have just come accross a great little example of this class in action:

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

    One thing I learned from following this example is that the notification service I created starts automatically when permission is granted via the new notification access screen, meaning my application doesn't have to start the service manually.

    0 讨论(0)
  • 2020-12-03 02:25

    In my experience, almost all of these answers are so damn close to the right solution!

    The CORE problem seems to happen during development; as you are developing your code the "Notification access" settings stop being honored when you update your app between debug sessions.

    If your APK/binary changes and your NotificationListenerService stops:

    • Rebooting fixes it.
    • Going back in to "Notification access" and disabling and re-enabling your app it fixes it.

    Hopefully this isn't a problem when updating your app through Google Play.

    As a best practice, for my app I add an overflow menu option that only shows up in non-release builds that allows me easy access to the settings:

    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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题