背景:

在Android原生系统中,众所周知不支持桌面图标显示未读消息提醒的数字,虽然第三方控件BadgeView可以实现应用内的数字提醒。但对于系统的图标,特别是app的logo图标很难实现数字标志,即使是绘图的方式不断修改,但这种方式天生弊端,实用性很差。但幸运的是,一些强大的手机厂商(小米,三星,索尼)提供了私有的API,但也带来了难度,API的不同就意味着代码量的增加和兼容性问题更加突出。

现在我们来看看他们是如何实现的:首先看张图片

实现原理:

首先我们要明白 并不是应用本身处理对启动图标进行修改、图标的动态修改的过程主要是在Launcher里面完成的.在应用安装,更新,卸载的时候,都会有广播发出,Launcher在LauncherApplication 中注册广播,在LauncherModel中处理接收到广播的消息,重新加载更新应用信息(如:应用图标、文字等)。但是原生的android系统是并不支持该特性的(及不能通过发送特定的系统广播 达到动态修改启动图标的效果),但是在强大的第三方Android手机厂商(如:三星、小米)的系统源码深度定制下、通过修改了Launcher源代码,增加/注册了新的广播接收器用来接收应用发送来的未读消息数广播,接收到广播后,系统将未读消息的数目显示事件交给Launcher去处理,调用相关方法去重绘应用的icon,最终达到动态更新应用图标的效果。

示例代码:

public class LauncherBadgeHelper {/*** Set badge count<br/>* 针对 Samsung / xiaomi / sony 手机有效** @param context The context of the application package.* @param count   Badge count to be set*/public static void setBadgeCount(Context context, int count) {if (count <= 0) {count = 0;} else {count = Math.max(0, Math.min(count, 99));}if (Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) {sendToXiaoMi(context, count);} else if (Build.MANUFACTURER.equalsIgnoreCase("sony")) {sendToSony(context, count);} else if (Build.MANUFACTURER.toLowerCase().contains("samsung")) {sendToSamsumg(context, count);} else {sendToSamsumg(context, count);}}/*** 向小米手机发送未读消息数广播** @param count*/private static void sendToXiaoMi(Context context, int count) {try {Class miuiNotificationClass = Class.forName("android.app.MiuiNotification");Object miuiNotification = miuiNotificationClass.newInstance();Field field = miuiNotification.getClass().getDeclaredField("messageCount");field.setAccessible(true);field.set(miuiNotification, String.valueOf(count == 0 ? "" : count));  // 设置信息数-->这种发送必须是miui 6才行} catch (Exception e) {LogController.e(e.toString());// miui 6之前的版本Intent localIntent = new Intent("android.intent.action.APPLICATION_MESSAGE_UPDATE");localIntent.putExtra("android.intent.extra.update_application_component_name",context.getPackageName() + "/" + getLauncherClassName(context));localIntent.putExtra("android.intent.extra.update_application_message_text", String.valueOf(count == 0 ? "" : count));context.sendBroadcast(localIntent);}}/*** 向索尼手机发送未读消息数广播<br/>* 据说:需添加权限:<uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE" /> [未验证]** @param count*/private static void sendToSony(Context context, int count) {String launcherClassName = getLauncherClassName(context);if (launcherClassName == null) {return;}boolean isShow = true;if (count == 0) {isShow = false;}Intent localIntent = new Intent();localIntent.setAction("com.sonyericsson.home.action.UPDATE_BADGE");localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", isShow);//是否显示localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME", launcherClassName);//启动页localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", String.valueOf(count));//数字localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", context.getPackageName());//包名context.sendBroadcast(localIntent);}/*** 向三星手机发送未读消息数广播** @param count*/private static void sendToSamsumg(Context context, int count) {String launcherClassName = getLauncherClassName(context);if (launcherClassName == null) {return;}Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");intent.putExtra("badge_count", count);intent.putExtra("badge_count_package_name", context.getPackageName());intent.putExtra("badge_count_class_name", launcherClassName);context.sendBroadcast(intent);}/*** 重置、清除Badge未读显示数<br/>** @param context*/public static void resetBadgeCount(Context context) {setBadgeCount(context, 0);}/*** Retrieve launcher activity name of the application from the context** @param context The context of the application package.* @return launcher activity name of this application. From the* "android:name" attribute.*/private static String getLauncherClassName(Context context) {PackageManager packageManager = context.getPackageManager();Intent intent = new Intent(Intent.ACTION_MAIN);// To limit the components this Intent will resolve to, by setting an// explicit package name.intent.setPackage(context.getPackageName());intent.addCategory(Intent.CATEGORY_LAUNCHER);// All Application must have 1 Activity at least.// Launcher activity must be found!ResolveInfo info = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);// get a ResolveInfo containing ACTION_MAIN, CATEGORY_LAUNCHER// if there is no Activity which has filtered by CATEGORY_DEFAULTif (info == null) {info = packageManager.resolveActivity(intent, 0);}return info.activityInfo.name;}}

可以看出小米,三星,索尼处理方式都是通过发送广播来实现的。

但是:小米MIUI6以后,改变了处理方式,弃用了发送广播的方式,改为通过发送通知。

一、基本介绍

1、默认的情况

当app 向通知栏发送了一条通知 (通知不带进度条并且用户可以删除的),那么桌面app icon角标就会显示1.此时app显示的角标数是和通知栏里app发送的通知数对应的,即向通知栏发送了多少通知就会显示多少角标

二、实现代码

第三方app需要用反射来调用,参考代码:

NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);Notification.Builder builder = new Notification.Builder(this).setContentTitle(“title”).setContentText(“text”).setSmallIcon(R.drawable.icon);Notification notification = builder.build();try {Field field = notification.getClass().getDeclaredField(“extraNotification”);Object extraNotification = field.get(notification);Method method = extraNotification.getClass().getDeclaredMethod(“setMessageCount”, int.class);method.invoke(extraNotification, mCount);} catch (Exception e) {e.printStackTrace();}mNotificationManager.notify(0,notification);

自己在之前的代码根据官方代码总结新的方法如下:

  /*** 向小米手机发送未读消息数广播miui6以后** @param count*/private static void sendToXiaoMi2(Context context, int count) {NotificationManager mNotificationManager = (NotificationManager) MyApplication.getContext().getSystemService(Context.NOTIFICATION_SERVICE);Notification.Builder builder = new Notification.Builder(MyApplication.getContext()).setContentTitle("title").setContentText("text").setSmallIcon(R.drawable.ico_haoyilogo);Notification notification = null;if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {notification = builder.build();}try {Field field = notification.getClass().getDeclaredField("extraNotification");Object extraNotification = field.get(notification);Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int.class);method.invoke(extraNotification, count);mNotificationManager.notify(10, notification);} catch (Exception e) {e.printStackTrace();LogController.e(e.toString());// miui 6之前的版本Intent localIntent = new Intent("android.intent.action.APPLICATION_MESSAGE_UPDATE");localIntent.putExtra("android.intent.extra.update_application_component_name",context.getPackageName() + "/" + getLauncherClassName(context));localIntent.putExtra("android.intent.extra.update_application_message_text", String.valueOf(count == 0 ? "" : count));context.sendBroadcast(localIntent);}}

这样既能兼容MIUI6之前的,还能实现MIUI6以后的。自己在开发的时候经过测试,发现MIUI内部对于相同的消息数字是不显示的,由于我测试的时候用的是写死的数字,导致走了很多弯路。还有,自己在查找资料的时候发现有许多朋友都遇到过这样的问题,未读消息数字只有在第一次安装的时候才显示,进入后再设置就没有了,我估计都是因为数字相同造成的。

细想一下,MIUI这种做法也挺好的,消息数字和通知绑定,当来通知时触发事件,从而桌面图标数字动态改变。当我们清楚通知时,清空数字。自己也调研了iOS的做法,他们只是通过调用系统的一个方法将消息数字传进去即可,做法类似于Android 通过发送广播方式,和三星一样。

那么,小米是如何做到累加的呢。

我们只需定义全局变量count,初始值设置为1,然后发送通知后,手动改变count值,count=count+1。

友情链接:

https://github.com/lixiangers/BadgeUtil

Android 桌面图标右上角显示未读消息数字相关推荐

  1. android 应用图标 角标 显示未读消息

    Android桌面角标的适配确实是非常坑爹的需求.原生系统根本就没有这个功能,国内很多厂家效仿ios都自己定义了该功能.Android程序员就很苦逼,要适配很多机型.建议万不得已情况下还是不要进行这项 ...

  2. 图标显示未读消息数量

    最近做的项目,要求图标的右上角能显示未读消息的数量,也就像微信的未读消息一样的效果. 没有做过,之前一直这样的效果好是申请,怎么图标的右上角会出现一个圆圈,然后圆圈里面有数字呢. 只有经历,才能懂得. ...

  3. android底部导航栏带消息数的框架,GitHub - BarkSheep/Android-NavMenuLayout: 一个底部导航栏, 实现了显示未读消息数, 显示红点等效果的封装...

    Android-NavMenu-master 一个底部导航栏, 实现了显示未读消息数, 显示红点等效果的封装. 添加依赖 1. 在项目根目录的 build.gradle 中添加 allprojects ...

  4. Android实现小圆点显示未读功能

    代码地址如下: http://www.demodashi.com/demo/13541.html ####前言 以前我们实现这个功能都是用 BadgeView.java,大体就是将这个java类复制到 ...

  5. android 小白点代码,Android实现小圆点显示未读功能

    ####前言 以前我们实现这个功能都是用 BadgeView.java,大体就是将这个java类复制到自己的项目中,然后在项目中使用,今天讲的也是一款BadgeView,我将其封装称工具类Badget ...

  6. 安卓微信 返回显示未读条数_Android仿微信底部菜单栏功能显示未读消息数量

    底部菜单栏很重要,我看了一下很多应用软件都是用了底部菜单栏,这里使用了tabhost做了一种通用的(就是可以像微信那样显示未读消息数量的,虽然之前也做过但是layout下的xml写的太臃肿,这里去掉了 ...

  7. 微信小程序定时器获取消息并在tabber按钮显示未读消息

    微信小程序定时器获取消息并在tabber按钮显示未读消息 onShow() {let that = this;this.getUserToken();wxService.setPageTitle(&q ...

  8. 设置App桌面图标上显示的角标数字

    原文 手机微信搜索公众号 酒酒酒酒,公共号内搜索标题 设置App桌面图标上显示的角标数字 扫描公共号查看原文: 设置App桌面图标上显示的角标数字 原文 前言: 新的前置条件: 正文: 代码: 文档地 ...

  9. Android系统 应用图标显示未读消息数(BadgeNumber) 桌面app图标的角标显示

    转载请标明出处:http://blog.csdn.net/xx326664162/article/details/51082574 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定的 ...

最新文章

  1. 论文《一种金融市场预测的深度学习模型:FEPA》(3)--EMD+PCA
  2. 问题二:相关性怎么引入?
  3. 雷军做程序员时写的博客,太牛了!
  4. 批量恢复加密图像,联邦学习真的危了? | CVPR 2021
  5. Asp.Net Core 第02局:Program
  6. hutool中的threadutil_Hutool - 好用的Java工具类库
  7. Promise读取多个文件
  8. cus.crm.notes.Component.extend(cus.crm.notes.ext.Component, {
  9. shared_ptr简介以及常见问题
  10. java des对称加密_JAVA加密解密DES对称加密算法
  11. Linux环境下Mysql的安装教程及安装过程常见问题的解决方法
  12. [Editor][002][Emacs] 从零到高级的进阶 - 实践开发 - 帮助菜单主页
  13. phpcms v9 在当前栏目下获取父栏目与当前栏目的名称与连接
  14. 在浏览器中进行深度学习:TensorFlow.js (二)第一个模型,线性回归
  15. 用户故事与敏捷方法—用户故事的优势
  16. java程序cpu突然飚高_简单排查java应用CPU飙高的线程问题
  17. 2019中兴笔试选择题
  18. Python Turtle画奥运标志
  19. xp提示计算机内存不足,xp系统提示配额不足的解决方法
  20. 结节性硬化症会一直病变吗?结节性硬化最晚多大发病?

热门文章

  1. RIA技术之争 谁将胜出?(转)
  2. Linux系统编程(十)--高级IO-异步IO
  3. 原生JAVASCRIPT操作cookie方法
  4. SQL函数和存储过程的区别
  5. javascript用车牌号码判断所属城市
  6. 安装pyqt5及软件打包
  7. Tor Browser(洋葱浏览器)——一款使你匿名上网的浏览器
  8. 《流畅的python》学习笔记
  9. rsync搭建和错误解决
  10. Uber上市第二日股价继续大跌 市值缩水至622亿美元