在小米、三星等系統應用圖標上顯示badge

開始

大家經常看見在小米或者三星系統上,應用會把應用的消息數量想蘋果手機一樣顯示在右上角,其實這種消息提示的方法在原生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”的廣播接收者,TouchWiz的launcher類
我之前在網上查找到的資料,在設置消息條數的時候設置的都是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權限(報這個錯,說明上面的設置辦法應該是正確的),可能這個權限華爲自己的應用使用吧,後面有空再研究吧~

以上內容僅個人觀點,能力有限,如有不足,歡迎指導,勿噴~謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章