1. 程式人生 > >Badge分析&如何逼死處女座

Badge分析&如何逼死處女座

Badge分析

所謂Badge,原本是iOS上的一個效果,但是被Android抄的多了,也就成了Android的標配。圖就不上了,大家都懂的。

應用icon顯示角標實際上是在Launcher中實現的,其實不管是角標還是其他對快捷方式的增刪改查,都是需要Launcher支援的,應用在增刪改查快捷方式和安裝、解除安裝時,都會發出相應的廣播,通過這個廣播,Launcher會對快捷方式進行修改。

很慶幸,Android原生ROM的Launcher並不具有給icon新增角標的功能,因為Android的設計思想是把所有訊息中心都放置在Notification通知欄中,只有iOS這種通知欄半殘廢的,才會使用角標。這玩意兒,讓強迫症患者,完全不能自理,每日陷落在清除小紅點的生活中。

很悲劇,Android的AOSP程式碼被國內各大ROM廠商改的不能自理。很多被修改的ROM都可以支援這種角標的功能,甚至是很多第三方Launcher,也提供了這種功能。其基本原理也是天下一大抄,都是監聽發出的廣播來進行快捷方式的修改,但是,關鍵是沒有Google親爹的支援,所有的實現都不統一,大家自己做自己的,沒有統一的介面,導致各種碎片化非常嚴重。

現在原理很清晰了,關鍵就是要儘可能多的找到這些ROM、Launcher的修改icon的廣播。

在調查該問題時,我找到了https://github.com/leolin310148/ShortcutBadger 這個庫,很多地方參考了這個庫,但是該庫由於很久沒有維護了,所以我提取了裡面收集的一些Badge的方法,並做了完善,這裡對作者表示感謝。

各種ROM角標分析

MIUI6&7 Badge

以下內容來自MUI開發者平臺:

一、基本介紹

1、預設的情況

當app 向通知欄傳送了一條通知 (通知不帶進度條並且使用者可以刪除的),那麼桌面app icon角標就會顯示1.此時app顯示的角標數是和通知欄裡app傳送的通知數對應的,即向通知欄傳送了多少通知就會顯示多少角標。

2、通知可以定義角標數

例如 有5封未讀郵件,通知欄裡只會顯示一條通知,但是想讓角標顯示5. 可以在發通知時加個標示。

修改MIUI的原理是通過反射拿到Notification的私有屬性extraNotification,但是這個extraNotification在MIUI系統中重定義了,這個類就是MIUI系統中的android.app.MiuiNotification這個類,這個類裡面有個私有屬性messageCount,我們只要改變這個messageCount

值就能顯示的改變app icon的角標數了。

二、實現程式碼

第三方app需要用反射來呼叫,參考程式碼:

/**
 * 設定MIUI的Badge
 *
 * @param context context
 * @param count   count
 */
private static void setBadgeOfMIUI(Context context, int count) {
    Log.d("xys", "Launcher : MIUI");
    NotificationManager mNotificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);
    Notification.Builder builder = new Notification.Builder(context)
            .setContentTitle("title").setContentText("text").setSmallIcon(R.mipmap.ic_launcher);
    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, count);
    } catch (Exception e) {
        e.printStackTrace();
    }
    mNotificationManager.notify(0, notification);
}

Sony Badge

Samsung Badge

方法一

通過三星Launcher自己的廣播,來給應用新增角標:

/**
 * 設定三星的Badge
 *
 * @param context context
 * @param count   count
 */
private static void setBadgeOfSumsung(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);
}

此方法不需要任何許可權,只需要知道App的包名和類名。因此,你當然可以在程式裡面給其它任意一個App設定任意數量的角標,而且沒有任何提示,是的,很流氓,誰說不是呢,當然別說是我告訴你的,你就所你是百度的。例如:

intent.putExtra("badge_count_package_name", "com.tencent.mobileqq");
    intent.putExtra("badge_count_class_name", "com.tencent.mobileqq.activity.SplashActivity");

將包名和類名用QQ的替換下,然後你就可以隨心所欲、為所欲為了。

方法二

LG Badge

Samsung好基友,三星能用的,LG幾乎都可以用,連Bug都一樣。

華為EMUI Badge

目前華為的ROM只支援給內建的App新增角標,華為本身沒有給出相應的介面。

酷派 Badge

簡單粗暴,不支援。我喜歡,類原生。

ZUK ZUI Badge

ZUK作為一個非常小眾的手機廠商,居然在網上官方給出了詳細的開發者文件,就這一點,很多大廠都該好好打打自己的耳光。

由於實在找不到ZUK的測試機,所以這裡給出ZUK的開發者文件,有需要的自己看看吧:

HTC Badge

HTC雖然沒落了,但好歹是第一隻Android的寄生獸,好歹也支援下。

Intent intentNotification = new Intent("com.htc.launcher.action.SET_NOTIFICATION");
ComponentName localComponentName = new ComponentName(context.getPackageName(),
        AppInfoUtil.getLauncherClassName(context));
intentNotification.putExtra("com.htc.launcher.extra.COMPONENT", localComponentName.flattenToShortString());
intentNotification.putExtra("com.htc.launcher.extra.COUNT", count);
context.sendBroadcast(intentNotification);

Intent intentShortcut = new Intent("com.htc.launcher.action.UPDATE_SHORTCUT");
intentShortcut.putExtra("packagename", context.getPackageName());
intentShortcut.putExtra("count", count);
context.sendBroadcast(intentShortcut);

其原理同樣是使用廣播,不解釋了。

錘子

錘子很遺憾,使用的是原生Launcher進行的修改,只有System App具有獲得角標的許可權。

Nova Badge

Nova是一款非常讚的Launcher,作為第三方Launcher,它的使用率非常高(當然是在國外)。該Launcher作為業界良心,提供了content provider供外界呼叫。與ZUK手機一樣,良心大大的好,程式碼如下:

ContentValues contentValues = new ContentValues();
contentValues.put("tag", context.getPackageName() + "/" +
        AppInfoUtil.getLauncherClassName(context));
contentValues.put("count", count);
context.getContentResolver().insert(Uri.parse("content://com.teslacoilsw.notifier/unread_count"),
        contentValues);

一些好玩的

在知道了一些ROM的生成角標的原理,我們可以做一些好玩的東西。前面在說LG三星Sony的ROM的時候,已經提到了,廣播只需要傳人包名和啟動Activity名就可以給任意一個icon新增角標,因此。。。直接看程式碼吧:

/**
 * Bug利用測試,請勿濫用
 *
 * @param view view
 */
public void madMode(View view) {
    madMode(99);
}

/**
 * 清除Bug角標
 *
 * @param view view
 */
public void cleanMadMode(View view) {
    madMode(0);
}

/**
 * 獲取所有App的包名和啟動類名
 *
 * @param count count
 */
private void madMode(int count) {
    Intent intent = new Intent(Intent.ACTION_MAIN, null);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    List<ResolveInfo> list = getPackageManager().queryIntentActivities(
            intent, PackageManager.GET_ACTIVITIES);
    for (int i = 0; i < list.size(); i++) {
        ActivityInfo activityInfo = list.get(i).activityInfo;
        String activityName = activityInfo.name;
        String packageName = activityInfo.applicationInfo.packageName;
        BadgeUtil.setBadgeOfMadMode(getApplicationContext(), count, packageName, activityName);
    }
}

非常簡單的程式碼,就是通過PM找出具有啟動Intent的Activity,再取出其包名,通過設定來新增角標。效果如圖:

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述
OK,喪心病狂,逼死強迫症處女座。

請勿濫用,由此引起的一切問題,不要找我

請不要提桌面背景!!!

Github