这几天在做安卓的推送对接,因为内网的使用场景以及费用问题,公司使用RabbitMQ的框架进行消息推送,但是在完成了简单的推送以及接受代码之后。APP消息通知遇到了两个问题:1.没有类似于微信的锁屏通知,2.没有类似于微信收到消息之后的顶部通知。在经过两天的摸索之后有了答案,先看下实际的实现效果图吧(部分通知内容因为隐私问题进行了模糊处理):

  

 

  哈哈,这个不知道是不是你想要的效果,如果是的话,请继续往下看:

  起初,我以为顶部通知以及锁屏通知都是开发自定义做的,所以在网上百度了一波。结果呢,网上五花八门,大多数都是自定义Toast实现,但是效果和微信、qq收到消息的效果大相径庭,所以抱着试试看的态度,我打开了应用的通知权限管理页面。

  上图是已经代码设置好之后的状态,具体的代码实现下面再说。起初,悬浮通知开关是关闭的,经过百度,了解到需要假如如下权限:

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />

  我习惯使用AndPermission框架申请权限,一顿查询之后发现没有上述两个权限的申请代码,所以我直接加上权限配置,run了下app,还是不行,最终经过一天的折腾,结论是这里需要用户自己去打开!(安卓O以上才需要进行处理)跳转代码是:

var isFirstOpen = Acache.get(this).getAsString(AppContentValue.AppAcacheKey.IsFirstOpen);
        if (isEmpty(isFirstOpen)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, this.packageName);
                startActivity(intent);
                showToast(this, "请允许通知的相关权限,否则可能导致无法接收消息!")

            }
//            else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
//                val localIntent = Intent()
//                localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//                localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
//                localIntent.setData(Uri.fromParts("package", this.packageName, null));
//                this.startActivity(localIntent);
//            }

        }

        Acache.get(this).put(AppContentValue.AppAcacheKey.IsFirstOpen, "no");

  接着继续顺藤摸瓜,点开上图最下面消息通知按钮(这里要注意,app在收到任意一次通知之后才会展示),“消息通知”这个名称是在NotificationChannel中设置的。

  

  下面关键来了,要想实现通知来了之后,顶部通知,就需要设置重要程度为“紧急”,这样Notification就会自动去匹配了,哈哈!就是这么简单,不知道为何网上有那么多误导人的博客文章。。。

  接下来贴出所有的展示通知的代码:

  

/**
 * 展示通知
 */
@SuppressLint("WrongConstant")
fun showNotification(context: Activity, sb: String, content: String) {
    context.runOnUiThread {
        var id = Acache.get(context).getAsString("notifyNum").toInt();
        id++;
        Acache.get(context).put("notifyNum", id.toString());
        //1.获取通知管理器类
        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        /**
         * 兼容Android版本8.0系统
         */
        val channeId = "1"
        val channelName = "消息通知"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(channeId, channelName, NotificationManager.IMPORTANCE_MAX)
            channel.enableLights(true) // 开启指示灯,如果设备有的话
            channel.lightColor = Color.RED // 设置指示灯颜色
//            channel.setShowBadge(true) // 检测是否显示角标
            // 设置通知出现时的震动(如果 android 设备支持的话)
            channel.enableVibration(true);
            // 设置通知出现时声音,默认通知是有声音的
//            channel.setSound(null, null);
            notificationManager.createNotificationChannel(channel)
        }
        //2.构建通知类
        val builder: NotificationCompat.Builder = NotificationCompat.Builder(context, id.toString())
        builder.setSmallIcon(R.mipmap.ic_launcher_trans) //设置小图标
        builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher_notify))//设置大图标
        builder.setContentTitle("消息通知") //标题
        builder.setColor(Color.parseColor("#00000000"))
        builder.setContentText(sb) //内容
        builder.setWhen(System.currentTimeMillis()) //时间
        builder.setDefaults(Notification.DEFAULT_SOUND)
        val intent = Intent(context, NotificationClickReceiver::class.java)
        val bundle = Bundle()
        bundle.putString("notifyNum", id.toString())
        intent.action = "MessageHandleService"
        intent.putExtra("bundle", bundle)
        val pendingIntent = PendingIntent.getBroadcast(context, id, intent, 0)
        builder.setContentIntent(pendingIntent)
        builder.setPriority(NotificationCompat.PRIORITY_MAX)

        //3.获取通知
        val notification: Notification = builder.build()
        // 4. 发送通知
        notificationManager.notify(id, notification)

        //收到信息刷新通知
        val info = MessageEventInfo("refresh", false)
        EventBus.getDefault().post(info)
    }
}

  其中的Acache是一个工具类,类似于SharedPreference,大家可以参考下,主要的作用是来区分channelID,保证每个消息都会在通知栏出现。如果不动态去加1的话,会导致最后一条通知覆盖第一条通知。(这里的坑还真不少,哈哈!)

  锁屏通知的话,重点就在通知权限的配置,我这里的处理是跳到设置页面,让用户手动打开相关权限:

var isFirstOpen = Acache.get(this).getAsString(AppContentValue.AppAcacheKey.IsFirstOpen);
        if (isEmpty(isFirstOpen)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, this.packageName);
                startActivity(intent);
                showToast(this, "请允许通知的相关权限,否则可能导致无法接收消息!")

            }
//            else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
//                val localIntent = Intent()
//                localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//                localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
//                localIntent.setData(Uri.fromParts("package", this.packageName, null));
//                this.startActivity(localIntent);
//            }

        }

        Acache.get(this).put(AppContentValue.AppAcacheKey.IsFirstOpen, "no");

 

  设置成默认,系统回去自己处理,哈哈!

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐