Android 角標適配

角標是從 iOS 那邊 copy 過來的一個功能,目前 Android 沒有提供系統 API 對此做支持。如果需要適配這個功能需要遵循主流的 Android 手機廠商的適配規範,文章列舉的 華爲 三星 vivo  HTC 的適配方式。

 

一 判斷機型

if (Build.MANUFACTURER.equalsIgnoreCase("HUAWEI")) {
            // luncherPackageName : com.huawei.android.internal.app
            badgeHandler = new HuaweiBadgeHandler(context);
            return;
        }
        if (Build.MANUFACTURER.equalsIgnoreCase("vivo")) {
            badgeHandler = new VivoBadgeHandler(context);
            return;
        }
        if (Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
            badgeHandler = new SamsungBadgeHandler(context);
            return;
        }
        if (Build.MANUFACTURER.equalsIgnoreCase("HTC")) {
            badgeHandler = new HtcBadgeHandler(context);
            return;
        }

二 各機型適配規則:

1 華爲:

public class HuaweiBadgeHandler implements IBadgeHandler {

    private static final String TAG = HuaweiBadgeHandler.class.getSimpleName();

    private Context context;
    private boolean isSupportedBade = false;
    private String packageName;
    private String launchClassName;
    private ExecutorService executorService = Executors.newSingleThreadExecutor();

    HuaweiBadgeHandler(Context context) {
        this.context = context;
        try {
            packageName = context.getPackageName();
            launchClassName = context.getPackageManager()
                    .getLaunchIntentForPackage(packageName)
                    .getComponent().getClassName();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void updateBadgeCount(int count) {
        checkIsSupportedByVersion();
        if (isSupportedBade) {
            ChangeBadgeRunnable runnable = new ChangeBadgeRunnable(count);
            executorService.submit(runnable);
        }
    }

    private void checkIsSupportedByVersion() {
        if (launchClassName == null) {
            isSupportedBade = false;
            return;
        }
        try {
            PackageManager manager = context.getPackageManager();
            PackageInfo info = manager.getPackageInfo("com.huawei.android.launcher",
                    0);
            if (info.versionCode >= 63025) {
                isSupportedBade = true;
            }
            RLog.d(TAG, "checkIsSupportedByVersion versionCode " + info.versionCode + " isSupportedBade: " + isSupportedBade);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class ChangeBadgeRunnable implements Runnable {

        private int count;

        ChangeBadgeRunnable(int count) {
            this.count = count;
        }

        @Override
        public void run() {
            try {
                Bundle bundle = new Bundle();//需要存儲的數據
                bundle.putString("package", packageName);//包名
                bundle.putString("class", launchClassName);//啓動的Activity完整名稱
                bundle.putInt("badgenumber", count);//未讀信息條數
                context.getContentResolver().call(
                        Uri.parse("content://com.huawei.android.launcher.settings/badge/"),
                        "change_badge", null, bundle);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2 Htc:

public class HtcBadgeHandler implements IBadgeHandler {

    private Context context;

    private static final String EXTRA_COMPONENT = "com.htc.launcher.extra.COMPONENT";
    private static final String EXTRA_COUNT = "com.htc.launcher.extra.COUNT";
    private static final String INTENT_SET_NOTIFICATION = "com.htc.launcher.action.SET_NOTIFICATION";
    private static final String INTENT_UPDATE_SHORTCUT = "com.htc.launcher.action.UPDATE_SHORTCUT";
    private static final String COUNT = "count";
    private static final String PACKAGENAME = "packagename";
    private ComponentName componentName;

    public HtcBadgeHandler(Context context) {
        this.context = context;
        componentName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent();
    }

    @Override
    public void updateBadgeCount(int count) {
        Intent intent = new Intent(INTENT_SET_NOTIFICATION);
        intent.putExtra(EXTRA_COMPONENT, componentName.flattenToShortString());
        intent.putExtra(EXTRA_COUNT, count);

        Intent intent1 = new Intent(INTENT_UPDATE_SHORTCUT);
        intent1.putExtra(PACKAGENAME, context.getPackageName());
        intent1.putExtra(COUNT, count);

        if (canResolveBroadcast(intent) || canResolveBroadcast(intent1)) {
            context.sendBroadcast(intent);
            context.sendBroadcast(intent1);
        }
    }

    private boolean canResolveBroadcast(Intent intent) {
        PackageManager packageManager = context.getPackageManager();
        List<ResolveInfo> receivers = packageManager.queryBroadcastReceivers(intent, 0);
        return receivers != null && receivers.size() > 0;
    }
}

 

3 三星:

 

public class SamsungBadgeHandler implements IBadgeHandler {

    private Context context;

    public SamsungBadgeHandler(Context context) {
        this.context = context;
    }

    @Override
    public void updateBadgeCount(int count) {
        String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();
        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", launchClassName);
        context.sendBroadcast(intent);
    }
}

4 Vivo:

 

public class VivoBadgeHandler implements IBadgeHandler {

    private Context context;

    public VivoBadgeHandler(Context context) {
        this.context = context;
    }

    @Override
    public void updateBadgeCount(int count) {
        Intent intent = new Intent("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM");
        intent.putExtra("packageName", context.getPackageName());
        String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();
        intent.putExtra("className", launchClassName);
        intent.putExtra("notificationNum", count);
        context.sendBroadcast(intent);
    }
}

角標適配的複雜在於機型廠商多樣,以及如何更好的跟自身業務結合,例如一些需要殺死主進程還需要提醒角標的場景。

希望後續 google 可以在某個版本出系統級別的 API 接口來規範 Android 角標的問題。

 

推薦參考項目 : https://github.com/leolin310148/ShortcutBadger

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