-- 作者 謝恩銘 轉(zhuǎn)載請(qǐng)注明出處
內(nèi)容簡(jiǎn)介
- 需求簡(jiǎn)介
- Android角標(biāo)起源
- 不錯(cuò)的Github項(xiàng)目
- 清除角標(biāo)
- 小問題糾錯(cuò)
- 總結(jié)
1.需求簡(jiǎn)介
角標(biāo)是什么意思呢?
看下圖即可明了:
可以看到圖中的樂購(gòu)這個(gè)app右上角的紅色的圓圈,里面有10這個(gè)數(shù)字的涛菠,就是一種角標(biāo)赐稽。
角標(biāo)瞧哟,英語(yǔ)是badge并闲,也就是“徽章倚舀,像章叹哭,獎(jiǎng)?wù)拢?象征,標(biāo)記”的意思痕貌。
一般來說风罩,應(yīng)用的角標(biāo)是用來標(biāo)記有多少條提醒(Notification)沒讀(unread),一旦點(diǎn)擊提示進(jìn)應(yīng)用閱讀了舵稠,角標(biāo)也會(huì)消失超升。
2. Android角標(biāo)起源
角標(biāo)原本是蘋果的iOS中的東西入宦,Android原生并不支持角標(biāo),因?yàn)镚oogle的意思是讓大家用Notification(提示欄)即可室琢,角標(biāo)實(shí)在大有讓處女座“跳崖”的風(fēng)險(xiǎn)乾闰。幸好我不是...
最近公司的項(xiàng)目中,客戶的一個(gè)新需求是在我們的加密信息應(yīng)用上加上角標(biāo)功能盈滴,因?yàn)槲覀兊暮献骰锇槭侨牵梢詤⒖次业倪@篇文章:程序員在法國(guó) | 我被法國(guó)國(guó)防部盯上了!)涯肩,因此我就去網(wǎng)上找相關(guān)資料。
找的時(shí)候巢钓,才知道上面所說的Android原生不支持角標(biāo)一事病苗。不過無妨,厲害的Android第三方廠商可以通過在自定義的Launcher(啟動(dòng)器)中操作來實(shí)現(xiàn)添加角標(biāo)症汹。
我在第一時(shí)間當(dāng)然是去找三星的移動(dòng)設(shè)備如何添加角標(biāo)硫朦,不過卻有幸找到了Github上的比較普適的項(xiàng)目。
把我導(dǎo)向Github的自然是Stack Overflow背镇,而把我導(dǎo)向Stack Overflow的就是Google咬展,因此我會(huì)說:為什么程序員一定要會(huì)用Google和Stack Overflow? 芽世。
3. 不錯(cuò)的Github項(xiàng)目
-
一般來說,現(xiàn)在被引用最多的Android添加和去除角標(biāo)的Github項(xiàng)目是這位中國(guó)人寫的:https://github.com/leolin310148/ShortcutBadger
這個(gè)項(xiàng)目挺不錯(cuò)诡壁,雖然更新不是特別勤快济瓢,但最近一次更新是在2016年10月31日,也就是兩個(gè)月前妹卿,還可以接受旺矾。
《Android群英傳》和《Android群英傳:神兵利器》的作者 徐宜生 也在自己的Github上建了一個(gè)項(xiàng)目:https://github.com/xuyisheng/ShortcutHelper ,挺有意思夺克,里面還有號(hào)稱“瘋狂模式”的為所有在手機(jī)桌面上的應(yīng)用加上99的角標(biāo)數(shù)的功能箕宙,當(dāng)然了,去除的代碼也有铺纽,不然處女座豈不是要暈了~
添加角標(biāo)的原理就是發(fā)送一個(gè)Broadcast(廣播)柬帕,在廣播的Intent中指定需要被添加角標(biāo)的應(yīng)用的packageName(包名),className(類名)狡门,count(角標(biāo)數(shù)目)陷寝。當(dāng)然了,不同廠商的手機(jī)的角標(biāo)操作的Intent的action是不一樣的其馏。
因此凤跑,我們?nèi)绻o自己的手機(jī)里的應(yīng)用添加角標(biāo),只需要簡(jiǎn)單的利用上面兩個(gè)項(xiàng)目中的代碼即可叛复,一般不需要把全部項(xiàng)目搬過來仔引。當(dāng)然了扔仓,如果你要適配所有手機(jī),那么可以全盤引用項(xiàng)目咖耘。
比如我要給三星的手機(jī)的應(yīng)用添加角標(biāo)翘簇,那么我只需要做以下的幾步即可:
- 在AndroidManifest.xml中添加讀取和寫入角標(biāo)的權(quán)限:
<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />
- 自己寫一個(gè)類,隨便取名字鲤看,比如叫做 BadgeUtils缘揪,在類中添加如下內(nèi)容:
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);
}
}
-
使用上面的代碼時(shí),只需要傳入三個(gè)參數(shù)义桂,也就是:
- Context : 應(yīng)用的Context找筝。簡(jiǎn)單。
- ComponentName :組件名慷吊,略有點(diǎn)麻煩袖裕。可以這樣來獲雀绕俊(applicationContext就是應(yīng)用的Context) :
applicationContext.getPackageManager()
.getLaunchIntentForPackage(applicationContext.getPackageName())
.getComponent()
```
- badgeCount :角標(biāo)的數(shù)目急鳄,例如10。簡(jiǎn)單堰酿。
當(dāng)然了疾宏,如果你不想要傳入三個(gè)參數(shù)這么麻煩,你也可以再寫一個(gè)方法getLauncherClassName触创,就只需要傳入兩個(gè)參數(shù)即可坎藐。BadgeUtils中的代碼變?yōu)椋?/p>
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;
}
}
使用時(shí)傳入兩個(gè)參數(shù)即可:
- Context : 應(yīng)用的Context。
- badgeCount :角標(biāo)的數(shù)目哼绑,例如10岩馍。
4. 清除角標(biāo)
要清除應(yīng)用的角標(biāo)就很簡(jiǎn)單了,給badgeCount傳入0即可抖韩。
BadgeUtils.setBadgeCount(context,
context.getPackageManager()
.getLaunchIntentForPackage(context.getPackageName())
.getComponent(),
0);
或者
BadgeUtils.setBadgeCount(context, 0);
5. 小問題糾錯(cuò)
上面的 https://github.com/leolin310148/ShortcutBadger 這個(gè)項(xiàng)目中蛀恩,基本已經(jīng)包含了大多數(shù)可以定制角標(biāo)的Android生產(chǎn)廠商的添加角標(biāo)的代碼實(shí)現(xiàn),不過它也提到:
三星和LG(這兩個(gè)難兄難弟)的代碼有很多類似茂浮,連角標(biāo)處理的廣播的Intent中的action也是一樣的双谆,都是:
"android.intent.action.BADGE_COUNT_UPDATE"
但是作者在三星和LG的兩個(gè)角標(biāo)操作實(shí)現(xiàn)類中寫了注釋:
// Deprecated, Samsung devices will use DefaultBadger
// Deprecated, LG devices will use DefaultBadger
意思是“三星和LG的實(shí)現(xiàn)代碼已經(jīng)Deprecated(失效了),請(qǐng)用DefaultBadger類”席揽。
因此佃乘,這兩個(gè)需要用 https://github.com/leolin310148/ShortcutBadger/blob/master/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/DefaultBadger.java 中的實(shí)現(xiàn):
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());
}
}
不過上面的代碼有一個(gè)小問題,就是那句
if (BroadcastHelper.canResolveBroadcast(context, intent)) {
在有些設(shè)備(比如Samsung Galaxy S5)上會(huì)拋出異常(Exception)驹尼,找不到處理"android.intent.action.BADGE_COUNT_UPDATE"這個(gè)Intent的BroadcastReceiver趣避,很奇怪。
但有些設(shè)備(比如Samsung Galaxy A5)上又運(yùn)行正常新翎,沒有拋出異常程帕。
解決辦法是去除這一個(gè)檢測(cè)住练,把
if (BroadcastHelper.canResolveBroadcast(context, intent)) {
context.sendBroadcast(intent);
} else {
throw new ShortcutBadgeException("unable to resolve intent: " + intent.toString());
}
替換為簡(jiǎn)單的
context.sendBroadcast(intent);
就可以了。
也就是我上面自己實(shí)作時(shí)的代碼愁拭。
6. 總結(jié)
Android的角標(biāo)添加和移除畢竟是基于各大手機(jī)廠商的Launcher的定制讲逛,因此不是正統(tǒng)的Android技巧,隨著廠商的Launcher的改變岭埠,也許你的代碼未來就不一定有用了盏混,因此需要不斷修改,“推陳出新”惜论。
不過正所謂“生命在于折騰”许赃,而這也是我們喜歡Android系統(tǒng)的原因。這個(gè)萌萌的機(jī)器人可以經(jīng)得起我們隨意折騰馆类,在嵌入式領(lǐng)域的應(yīng)用前途也是很不錯(cuò)的混聊。
大家在平時(shí)學(xué)習(xí)編程的時(shí)候,也可以把自己的代碼或經(jīng)驗(yàn)匯總到Github項(xiàng)目乾巧,一來惠己利人句喜,二來提高自己的業(yè)界知名度。
- Git沟于,Github和Gitlab簡(jiǎn)介和基本使用
- Github | 如何貢獻(xiàn)Android開源項(xiàng)目和提交補(bǔ)丁
- Github改版+我的Github打怪升級(jí)之路
我是謝恩銘咳胃,在巴黎奮斗的軟件工程師。
熱愛生活旷太,喜歡游泳展懈,略懂烹飪。
人生格言:「向著標(biāo)桿直跑」