Android通知栏监听之NotificationListenerService

版权声明:转载请注明出处。 https://blog.csdn.net/rentee/article/details/54546514

NotificationListenerService的基础使用就不说了,可以阅读官方文档或者自行百度。这里参考个性通知App的功能做一些难点探究。


以下主要是对通知栏通知的跳转做探究。
当有通知弹出在通知栏时,NotificationListenerService的onNotificationPosted会回调,返回参数是StatusBarNotification的对象。
能拿到StatusBarNotfication对象跳转的方式很简单方便,通过获取它的PendingIntent,调用PendingIntent的send方法即可模拟发送此条通知的意图。代码如下:

//获取PendingItent
PendingIntent pendingIntent = sbn.getNotification().contentIntent;

pendingIntent.send();

难点一:通知栏通知的保存。
跳转的难点就在于,我们的通知栏监听应用退出或者被杀死时,我们将失去StatusBarNotification这个对象,继而没法通过PendingIntent的send方法进行跳转。
然后我们会想到,当收到onNotificationPosted方法回调时,就把StatusBarNotification存起来,但是你会发现这个对象虽然实现了Parcelable接口,但是没法进行实体化保存(就是像字符串那样存起来)。Parcel定位就是轻量级的高效的对象序列化和反序列化机制,专为Binder实现的一种序列化机制。
那保存PendingIntent呢?同样,也是不行的。
再往细想,保存PendingIntent中的Intent呢?嘿嘿嘿,可行,Intent有个toUri方法,可以将Intent转化为String,String肯定是可以存的了。代码如下:


        Intent intent = getIntentByPendingIntent(pendingIntent);

        //将Intent转换成String,可以存到数据库
        String serializeIntent = intent.toUri(0);

    /**
     * 通过反射从PendingIntent中拿到Intent
     *
     * @param pendingIntent
     * @return intent
     */
    public static Intent getIntentByPendingIntent(PendingIntent pendingIntent) {
        Intent intent = null;
        try {
            intent = (Intent) PendingIntent.class.getDeclaredMethod("getIntent", new Class[0]).invoke(pendingIntent, new Object[0]);
        } catch (Exception paramPendingIntent) {
            LogUtil.d("PendingIntent getIntent failure!!!");
        }
        return intent;
    }

注意:有博友反馈7.0以上系统会抛出java.lang.reflect.InvocationTargetException,详细信息为:
这里写图片描述
需要android.permission.GET_INTENT_SENDER_INTENT这个权限。
然后尝试申请这个权限,发现依旧报错,故猜测这个权限仅系统进程可用,暂未找到可解决方案!

难点二:通知栏Intent的跳转。
存了String的Intent,然后通过Intent的parseUri,可以将String后的Intent转化为Intent对象。然后我们知道,当初App建立Notification时,会通过getActivity、getService、getBroadcast方法传入Intent,从而点击通知栏时,系统会知道跳转到何种组件。而此时我们只有Intent,不知道应该是通过startActivity、startService、sendBroadcast进行跳转。故采用以下这种套路,每个试一下,哈哈哈:

        try {
            context.startActivity(intent);
            LogUtil.d("jumpAppByStartActivity");
        } catch (Exception e) {
            LogUtil.d("jumpAppByStartActivity Failure!!!");
        }

        try {
            context.startService(intent);
            LogUtil.d("jumpAppByStartService");
        } catch (Exception e) {
            LogUtil.d("jumpAppByStartService Failure!!!");
        }


        try {
            context.sendBroadcast(intent);
            LogUtil.d("jumpAppBySendBroadcast");
        } catch (Exception e) {
            LogUtil.d("jumpAppBySendBroadcast Failure!!!");

        }

附上Github的Demo:
https://github.com/OptimusPrimeRen/NotificationListenerDemo

猜你喜欢

转载自blog.csdn.net/rentee/article/details/54546514