开始
大家经常看见在小米或者三星系统上,应用会把应用的消息数量想苹果手机一样显示在右上角,其实这种消息提示的方法在原生Android上是不支持的,原生的launcher在图标上没有显示徽标的view。
但是小米、三星、华为、联想、索尼等手机厂商都没有使用原生的launcher,他们使用的桌面都是自己重写的。所以他们都已经实现了在桌面图标上显示消息数量徽标的方法,我们只要进行调用就行了。
先上图(设备有限,只有小米和三星):
小米实现的源码:
/*** 在小米手机上显示桌面徽标** @param context* @param num*/private static void xiaoMiShortCut(Context context, int num) {boolean isMiUIV6 = true;try {Class miuiNotificationClass = Class.forName("android.app.MiuiNotification");Object miuiNotification = miuiNotificationClass.newInstance();Field field = miuiNotification.getClass().getDeclaredField("messageCount");field.setAccessible(true);field.set(miuiNotification, num);// 设置信息数field = notification.getClass().getField("extraNotification");field.setAccessible(true);field.set(notification, miuiNotification);} catch (Exception e) {e.printStackTrace();//miui 6之前的版本isMiUIV6 = false;Intent localIntent = new Intent("android.intent.action.APPLICATION_MESSAGE_UPDATE");localIntent.putExtra("android.intent.extra.update_application_component_name", context.getPackageName() + "/.login.WelcomeActivity");localIntent.putExtra("android.intent.extra.update_application_message_text", num);context.sendBroadcast(localIntent);} finally {if (notification != null && isMiUIV6) {//miui6以上版本需要使用通知发送nm.notify(10201, notification);}}}
三星上实现的源码:
/*** 在三星手机上显示桌面徽标** @param context 上下文* @param num 显示的消息数量,整数*/private static void samsungShortCut(Context context, int num) {String launcherClassName = getLaunchActivityName(context);if (launcherClassName == null) {return;}Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");intent.putExtra("badge_count", num);intent.putExtra("badge_count_package_name", context.getPackageName());intent.putExtra("badge_count_class_name", launcherClassName);context.sendBroadcast(intent);
// Toast.makeText(context, "三星手机," + "广播已经发送", Toast.LENGTH_LONG).show();}
关于MIUI的一点看法
1.大家应该已经看出,小米在MIUI6以后和三星的实现方式不一样了,小米将系统的Notification改写成了自己的MiuiNotification,增加了messageCount字段,用于存储消息数量,通过反射将消息数量设置到了messageCount里。此处的num一定要是整数~
2.MIUI6以下,通过发送广播即可完成徽标设置~
3.通过上面可以发现,MIUI6以上系统,在显示桌面徽标数量的时候是通过统计在系统通知栏中的所有该应用的notification的messageCount的总和,如果你清除了那条通知,那么桌面徽标也就跟随去掉。
4.我个人觉得这样的实现方式比较好,也方便进行管理,毕竟显示的徽标也是一种notification,那么就应该和系统通知同步进行管理。
关于三星的一点看法
1.在三星的实现方式上,系统通知和桌面徽标数量是没有联系的,三星的桌面应用是TouchWiz.apk,通过反编译可以看到,在launcher类中定义了action为“android.intent.action.BADGE_COUNT_UPDATE”的广播接收者,
我之前在网上查找到的资料,在设置消息条数的时候设置的都是String类型的,导致我一直不能显示徽标,人家广播接收者里面只接受int类型的。。。
2.三星在设置完徽标数量后,是将徽标数量持久化了的,也就是如果你需要去掉徽标,得重新发送广播,将数量设置为0即可。个人觉得没有小米的管理方便~
关于其他类型手机的徽标设置
通过反编译麻花腾的产品看到,他还判断联想、华为、索尼等产品,附上一些代码(下面代码除华为外,其他没有进行测试#华为的测试结果是跑不通):
/*** 创建索尼桌面徽标** @param context* @param num*/private static void setSonyBadge(Context context, int num) {Intent localIntent = new Intent();String str1 = getLaunchActivityName(context);if (str1 == null)return;boolean isShow = false;if (num < 1) {isShow = false;} else if (num > 99) {isShow = true;}localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", isShow);localIntent.setAction("com.sonyericsson.home.action.UPDATE_BADGE");localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME", str1);localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", "");localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", context.getPackageName());context.sendBroadcast(localIntent);}
/*** 判断是否是联想手机** @param context* @param paramString* @return*/private static boolean islenovoLanucher(Context context, String paramString) {try {if (null == packmag)packmag = context.getPackageManager();float f = Float.valueOf(Float.parseFloat(packmag.getPackageInfo(paramString, 0).versionName.substring(0, 3))).floatValue();if (f >= 6.7F)return true;} catch (Exception localException) {return false;}return false;}
2017年12月27日更新-华为参见华为桌面未读角标
以下华为相关代码不再使用
/*** 在华为手机上显示桌面徽标** @param context* @param num*/private static void setHuaweiBadge(Context context, int num) {String launcherClassName = getLaunchActivityName(context);if (launcherClassName == null) {return;}Bundle localBundle = new Bundle();localBundle.putString("package", context.getPackageName());localBundle.putString("class", launcherClassName);localBundle.putInt("badgenumber", num);context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, localBundle);}
理论上,设置华为徽标需要以下权限:
<uses - permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE" />
<uses-permission android:name="com.huawei.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.android.launcher.permission.WRITE_SETTINGS" />
但是,结果是以上权限在普通应用中并不适用,尽管你在应用中添加了这些权限,在设置徽标的时候华为的机子还是会抛异常,说没有com.huawei.android.launcher.permission.WRITE_SETTINGS权限(报这个错,说明上面的设置办法应该是正确的),可能这个权限华为自己的应用使用吧,后面有空再研究吧~
以上内容仅个人观点,能力有限,如有不足,欢迎指导,勿喷~谢谢