–简书作者谢恩铭转载,转载请注明出处。徽章是什么意思?看下图:可以看到Tesco这个app右上角的红圈,里面有数字10,是一种角标。角标,英文为badge,意为“徽章、徽章、勋章;符号、标记”。一般来说,app的badge是用来标记有多少条通知(Notification)没有被阅读(unread)。一旦点击通知进入应用阅读,徽章就会消失。安卓徽章的由来,本来是苹果iOS里面的东西。Android本身并不支持徽章,因为谷歌意味着每个人都可以使用Notification(提示栏),而徽章确实让处女座“跳下悬崖”。”的风险。幸好我不是。。。公司最近的一个项目,客户的一个新需求是给我们的加密消息应用增加一个角标功能,因为我们的合作伙伴是三星(可以参考这个我的一篇文章:法国的程序员|我被法国国防部盯上了!),于是上网找相关资料,找的时候发现上面说的Android原生不支持corner不过没关系,强大的第三方安卓厂商可以在自定义的Launcher(启动器)中操作来添加角标。当然我第一时间在找三星的移动设备如何添加角标,但我有幸在Github上找到了一个比较常见的项目,自然是StackOverflow把我引向了Github,又是Google把我引向了StackOverflow,所以我想说:为什么程序员一定要用Google和StackOverflow?.好的github项目一般来说g、Android加删角标引用最多的Github项目是这个中文写的:https://github.com/leolin310148/ShortcutBadger这个项目还不错,虽然更新不是特别勤快,但是最后更新了是2016年10月31日,也就是两个月前,还是可以接受的。《Android群英传》和《Android群英传:神兵利器》的作者徐玄生也在他的Github上建了一个项目:https://github.com/xuyisheng/ShortcutHelper。上面的应用添加了下标号为99的功能,当然也有去掉的代码,不然处女座会晕的~添加下标的原理是发送一个Broadcast(广播),在广播Intent中指定需要be添加标记的应用程序的packageName(包名)、className(类名)和count(角标记数)。当然,不同厂商的手机上角标操作的Intent的动作是不一样的。所以,如果我们想在手机中的应用中添加角标,只需要简单的使用上面两个工程中的代码即可,一般不需要把所有的工程都搬过来。当然,如果你想适配所有手机,完全可以引用该项目。比如我想给三星手机的应用添加徽章,那么我只需要执行以下步骤:在AndroidManifest.xml中添加读写徽章的权限:自己写一个类,随便起个名字,suchasBadgeUtils,在类中添加如下内容:publicclassBadgeUtils{privatestaticfinalStringINTENT_ACTION="android.intent.action.BADGE_COUNT_UPDATE";privatestaticfinalStringINTENT_EXTRA_BADGE_COUNT="badge_count";privatestaticfinalStringINTENT_EXTRA_PACKAGENAME="badge_count_package_name";privatestaticfinalStringINTENT_EXTRA_ACTIVITY_NAME="badge_count_class_name";publicstaticvoidsetBadgeCount(Contextcontext,ComponentNamecomponentName,intbadgeCount){Intentintent=newIntent(INTENT_ACTION);intent.putExtra(INTENT_EXTRA_BADGE_COUNT,badgeCount);intent.putExtra(INTENT_EXTRA_PACKAGENAME,componentName.getPackageName());intent.putExtra(INTENT_EXTRA_ACTIVITY_NAME,componentName.getClassName());context.sendBroadcast(intent);}}使用上述代码时,只需要传入三个参数,即:Context:应用的Context,很简单。ComponentName:组件的名称,有点繁琐。可以这样获取(applicationContext就是应用的Context):applicationContext.getPackageManager().getLaunchIntentForPackage(applicationContext.getPackageName()).getComponent()badgeCount:徽章的个数,比如10个。简单。当然,如果不想传入三个参数的麻烦,也可以写另外一个方法getLauncherClassName,只需要传入两个参数即可。BadgeUtils中的代码变为:publicclassBadgeUtils{privatestaticfinalStringINTENT_ACTION="android.intent.action.BADGE_COUNT_UPDATE";privatestaticfinalStringINTENT_EXTRA_BADGE_COUNT="badge_count";privatestaticfinalStringINTENT_EXTRA_PACKAGENAME="badge_count_package_name";privatestaticfinalStringINTENT_EXTRA_ACTIVITY_NAME="badge_count_class_name";publicstaticvoidsetBadgeCount(Contextcontext,intbadgeCount){StringlauncherClassName=getLauncherClassName(context);if(launcherClassName==null){return;}Intentintent=newIntent(INTENT_ACTION);intent.putExtra(INTENT_EXTRA_BADGE_COUNT,badgeCount);intent.putExtra(INTENT_EXTRA_PACKAGENAME,context.getPackageName());intent.putExtra(INTENT_EXTRA_ACTIVITY_NAME,launcherClassName);context.sendBroadcast(intent);}privatestaticStringgetLauncherClassName(Contextcontext){PackageManagerpm=context.getPackageManager();Intentintent=newIntent(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_LAUNCHER);列表resolveInfos=pm.queryIntentActivities(intent,0);for(ResolveInforesolveInfo:resolveInfos){StringpkgName=resolveInfo.activityInfo.applicationInfo.packageName;if(pkgName.equalsIgnoreCase(context.getPackageName())){StringclassName=resolveInfo.activityInfo.name;returnclassName;}}returnnull;}}使用的时候传入两个参数即可:Context:应用的上下文badgeCount:徽章的个数,比如10个clearbadges清除徽章很简单应用程序的徽章,只需将0传递给badgeCount。BadgeUtils.setBadgeCount(context,context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent(),0);或BadgeUtils.setBadgeCount(context,0);https://github上面的小问题修正。com/leolin310148/ShortcutBadger这个项目已经基本收录了大部分安卓厂商可以自定义角标的代码实现,但是也提到了三星和LG(这两兄弟)的代码非常相似。连下标处理的广播Intent中的action也是一样的,都是:“android.intent.action.BADGE_COUNT_UPDATE”,但是作者在Samsung和LG的两个下标操作实现类中写了注释://Deprecated,SamsungdeviceswilluseDefaultBadger//Deprecated,LGdeviceswilluseDefaultBadger的意思是“三星和LG的实现代码已经被Deprecated(无效),请使用DefaultBadger类”。因此,这两个需要使用https://github.com/leolin310148/ShortcutBadger/blob/master/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/DefaultBadger.java中的现实:privatestaticfinalStringINTENT_ACTION="android.intent.action.BADGE_COUNT_UPDATE";privatestaticfinalStringINTENT_EXTRA_BADGE_COUNT="badge_count";privatestaticfinalStringINTENT_EXTRA_PACKAGENAME="badge_count_package_name";privatestaticfinalStringINTENT_EXTRA_ACTIVITY_NAME="badge_count_class_name";@OverridepublicvoidexecuteBadge(Contextcontext,ComponentNamecomponentName,intbadgeCount)throwsShortcutBadgeException{Intentintent=newIntent(INTENT_ACTION);intent.putExtra(INTENT_EXTRA_BADGE_COUNT,badgeCount);intent.putExtra(INTENT_EXTRA_PACKAGENAME,componentName.getPackageName());intent.putExtra(INTENT_EXTRA_ACTIVITY_NAME,componentName.getClassName());if(BroadcastHelper.canResolveBroadcast(context,intent)){context.sendBroadcast(intent);}else{thrownewShortcutBadgeException("unabletoresolveintent:"+intent.toString());}}不过上面的代码有个小问题,就是这句if(BroadcastHelper.canResolveBroadcast(context,intent)){在某些设备上(比如SamsungGalaxyS5)会抛出异常(Exception),无法找到处理Intent"android.intent.action.BADGE_COUNT_UPDATE"的BroadcastReceiver。很奇怪,但有些设备(如三星GalaxyA5)运行正常,没有抛出异常。解决方案是删除此检测并用简单的上下文替换if(BroadcastHelper.canResolveBroadcast(context,intent)){context.sendBroadcast(intent);}else{thrownewShortcutBadgeException("unabletoresolveintent:"+intent.toString());}.sendBroadcast(意图);会做。那是我自己上面实现的代码。综上所述,Android角标的增减毕竟是基于各大手机厂商Launcher的定制,并不是正统的Android技术。随着厂商发射器的变化,你的代码以后可能用不上了,所以你需要继续修改,“推陈出新”。不过俗话说“人生在于折腾”,这也是我们喜欢安卓系统的原因。这个可爱的机器人经得起我们的随意折腾,在嵌入式领域的应用前景也很好。大家在平时学习编程的时候,也可以把自己的代码或者经验总结到Github项目中,既造福自己也造福他人,增加自己在业界的知名度。Git、Github和Gitlab介绍及Github基本使用|如何为Android开源项目做贡献并提交补丁Github修订+我的Github升级路径