安卓APP开启锁屏通知&微信、qq顶部消息通知

    技术2022-07-10  191

      这几天在做安卓的推送对接,因为内网的使用场景以及费用问题,公司使用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");

     

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

    Processed: 0.011, SQL: 9