-- 做者 谢恩铭 转载请注明出处javascript
角标是什么意思呢?java
看下图便可明了:android
能够看到图中的乐购这个app右上角的红色的圆圈,里面有10这个数字的,就是一种角标。git
角标,英语是badge,也就是“徽章,像章,奖章; 象征,标记”的意思。程序员
通常来讲,应用的角标是用来标记有多少条提醒(Notification)没读(unread),一旦点击提示进应用阅读了,角标也会消失。github
角标本来是苹果的iOS中的东西,Android原生并不支持角标,由于Google的意思是让你们用Notification(提示栏)便可,角标实在大有让处女座“跳崖”的风险。幸亏我不是...编程
最近公司的项目中,客户的一个新需求是在咱们的加密信息应用上加上角标功能,由于咱们的合做伙伴是三星(能够参看个人这篇文章:程序员在法国 | 我被法国国防部盯上了!),所以我就去网上找相关资料。微信
找的时候,才知道上面所说的Android原生不支持角标一事。不过无妨,厉害的Android第三方厂商能够经过在自定义的Launcher(启动器)中操做来实现添加角标。app
我在第一时间固然是去找三星的移动设备如何添加角标,不过却有幸找到了Github上的比较普适的项目。ide
把我导向Github的天然是Stack Overflow,而把我导向Stack Overflow的就是Google,所以我会说:为何程序员必定要会用Google和Stack Overflow? 。
通常来讲,如今被引用最多的Android添加和去除角标的Github项目是这位中国人写的:github.com/leolin31014…
这个项目挺不错,虽然更新不是特别勤快,但最近一次更新是在2016年10月31日,也就是两个月前,还能够接受。
《Android群英传》和《Android群英传:神兵利器》的做者 徐宜生 也在本身的Github上建了一个项目:github.com/xuyisheng/S… ,挺有意思,里面还有号称“疯狂模式”的为全部在手机桌面上的应用加上99的角标数的功能,固然了,去除的代码也有,否则处女座岂不是要晕了~
添加角标的原理就是发送一个Broadcast(广播),在广播的Intent中指定须要被添加角标的应用的packageName(包名),className(类名),count(角标数目)。固然了,不一样厂商的手机的角标操做的Intent的action是不同的。
所以,咱们若是要给本身的手机里的应用添加角标,只须要简单的利用上面两个项目中的代码便可,通常不须要把所有项目搬过来。固然了,若是你要适配全部手机,那么能够全盘引用项目。
好比我要给三星的手机的应用添加角标,那么我只须要作如下的几步便可:
<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />复制代码
public class BadgeUtils {
private static final String INTENT_ACTION = "android.intent.action.BADGE_COUNT_UPDATE";
private static final String INTENT_EXTRA_BADGE_COUNT = "badge_count";
private static final String INTENT_EXTRA_PACKAGENAME = "badge_count_package_name";
private static final String INTENT_EXTRA_ACTIVITY_NAME = "badge_count_class_name";
public static void setBadgeCount(Context context, ComponentName componentName, int badgeCount) {
Intent intent = new Intent(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);
}
}复制代码
使用上面的代码时,只须要传入三个参数,也就是:
applicationContext.getPackageManager()
.getLaunchIntentForPackage(applicationContext.getPackageName())
.getComponent()复制代码
固然了,若是你不想要传入三个参数这么麻烦,你也能够再写一个方法getLauncherClassName,就只须要传入两个参数便可。BadgeUtils中的代码变为:
public class BadgeUtils {
private static final String INTENT_ACTION = "android.intent.action.BADGE_COUNT_UPDATE";
private static final String INTENT_EXTRA_BADGE_COUNT = "badge_count";
private static final String INTENT_EXTRA_PACKAGENAME = "badge_count_package_name";
private static final String INTENT_EXTRA_ACTIVITY_NAME = "badge_count_class_name";
public static void setBadgeCount(Context context, int badgeCount) {
String launcherClassName = getLauncherClassName(context);
if (launcherClassName == null) {
return;
}
Intent intent = new Intent(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);
}
private static String getLauncherClassName(Context context) {
PackageManager pm = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : resolveInfos) {
String pkgName = resolveInfo.activityInfo.applicationInfo.packageName;
if (pkgName.equalsIgnoreCase(context.getPackageName())) {
String className = resolveInfo.activityInfo.name;
return className;
}
}
return null;
}
}复制代码
使用时传入两个参数便可:
要清除应用的角标就很简单了,给badgeCount传入0便可。
BadgeUtils.setBadgeCount(context,
context.getPackageManager()
.getLaunchIntentForPackage(context.getPackageName())
.getComponent(),
0);复制代码
或者
BadgeUtils.setBadgeCount(context, 0);复制代码
上面的 github.com/leolin31014… 这个项目中,基本已经包含了大多数能够定制角标的Android生产厂商的添加角标的代码实现,不过它也提到:
三星和LG(这两个难兄难弟)的代码有不少相似,连角标处理的广播的Intent中的action也是同样的,都是:
"android.intent.action.BADGE_COUNT_UPDATE"复制代码
可是做者在三星和LG的两个角标操做实现类中写了注释:
// Deprecated, Samsung devices will use DefaultBadger
// Deprecated, LG devices will use DefaultBadger复制代码
意思是“三星和LG的实现代码已经Deprecated(失效了),请用DefaultBadger类”。
所以,这两个须要用 github.com/leolin31014… 中的实现:
private static final String INTENT_ACTION = "android.intent.action.BADGE_COUNT_UPDATE";
private static final String INTENT_EXTRA_BADGE_COUNT = "badge_count";
private static final String INTENT_EXTRA_PACKAGENAME = "badge_count_package_name";
private static final String INTENT_EXTRA_ACTIVITY_NAME = "badge_count_class_name";
@Override
public void executeBadge(Context context, ComponentName componentName, int badgeCount) throws ShortcutBadgeException {
Intent intent = new Intent(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 {
throw new ShortcutBadgeException("unable to resolve intent: " + intent.toString());
}
}复制代码
不过上面的代码有一个小问题,就是那句
if (BroadcastHelper.canResolveBroadcast(context, intent)) {复制代码
在有些设备(好比Samsung Galaxy S5)上会抛出异常(Exception),找不处处理"android.intent.action.BADGE_COUNT_UPDATE"这个Intent的BroadcastReceiver,很奇怪。
但有些设备(好比Samsung Galaxy A5)上又运行正常,没有抛出异常。
解决办法是去除这一个检测,把
if (BroadcastHelper.canResolveBroadcast(context, intent)) {
context.sendBroadcast(intent);
} else {
throw new ShortcutBadgeException("unable to resolve intent: " + intent.toString());
}复制代码
替换为简单的
context.sendBroadcast(intent);复制代码
就能够了。
也就是我上面本身实做时的代码。
Android的角标添加和移除毕竟是基于各大手机厂商的Launcher的定制,所以不是正统的Android技巧,随着厂商的Launcher的改变,也许你的代码将来就不必定有用了,所以须要不断修改,“推陈出新”。
不过正所谓“生命在于折腾”,而这也是咱们喜欢Android系统的缘由。这个萌萌的机器人能够经得起咱们随意折腾,在嵌入式领域的应用前途也是很不错的。
你们在平时学习编程的时候,也能够把本身的代码或经验汇总到Github项目,一来惠己利人,二来提升本身的业界知名度。
人世间,
万千情感皆有温度,
千万代码似有性格。
这里有原创教程,IT丛林......
和你一块儿探索程序人生。
微信公众号「程序员联盟」ProgrammerLeague
我是谢恩铭,在巴黎奋斗的嵌入式软件工程师。
我的简介热爱生活,喜欢游泳,略懂烹饪。人生格言:“向着标杆直跑”