アイコンにバッジをつける

#アイコンにバッジをつける
iPhoneのように、HOMEに表示されているアイコンにバッジをつけたい。

仕事で対応したので、一応メモとして書いておきます。

方法はありますが、すべてのHOMEアプリに適用できるわけではなく、一部のHOMEアプリでしか表示できないので注意です。

## 適用できるHOMEアプリ
確認したところ、以下のHOMEアプリでは動いてました。

- GalaxyのTouchWiz

それ以外のHOMEアプリはまだ未検証なので、あとあと検証してみます。
仕事では、XperiaHomeにも表示させましたが、その場合は実装がすこし異なるので、
それはまた後日追記します。。

## 表示方法
では実装です。
もう面倒なので、ざっくり作ったメソッド群をペタッと貼ときます。

[こちら](https://stackoverflow.com/questions/17565307/how-to-display-count-of-notifications-in-app-launcher-icon)を参考にしてます。（というかほぼそのままです。）

```
    /**
     * アイコンにバッジをクリアする。<br>
     * ※0を設定する
     * 
     * @param context コンテキスト
     */
    public static void clearIconBadge(final Context context) {
        setIconBadge(context, 0);
    }

    /**
     * アイコンにバッジを付ける。
     *
     * @param context コンテキスト
     * @param count バッジ表示する数字
     */
    public static void setIconBadge(final Context context, final int count) {
        if (context == null) {
            return;
        }
        final String launcherClassName = getLauncherClassName(context);
        if (TextUtils.isEmpty(launcherClassName)) {
            return;
        }
        final 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);
    }

    /**
     * 起動中のアプリのクラス名を取得する。
     *
     * @param context コンテキスト。
     * @return 起動中のアプリのクラス名<br>
     *     正常に取得できない場合はnull。
     */
    @Nullable
    private static String getLauncherClassName(@NonNull final Context context) {
        final PackageManager pm = context.getPackageManager();
        final Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        final List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(intent, 0);

        for (final ResolveInfo resolveInfo : resolveInfoList) {
            if (resolveInfo == null) {
                continue;
            }
            final String pkgName = resolveInfo.activityInfo.applicationInfo.packageName;
            if (pkgName.equalsIgnoreCase(context.getPackageName())) {
                return resolveInfo.activityInfo.name;
            }
        }

        return null;
    }
```

setIconBadge()を、バッジを表示させたいタイミングで呼び出します。
また、バッジを消したい場合は０を設定すれば良いので、↑で書いたコードだと
clearIconBadge()を呼び出せばOKです。

## Kotlinで書く
Kotlin言語の場合も一応貼っておきます。
作成したUtilityをそのままペタッと貼っておきます。

```
class Utility {
    companion object {

        /**
         * アイコンのバッジをクリアする。<br>
         * ※0を設定する
         * 
         * @param context コンテキスト
         */
        fun clearIconBadge(context: Context) {
            setIconBadge(context, 0)
        }

        /**
         * アイコンにバッジを付ける。

         * @param context コンテキスト
         *
         * @param count バッジ表示する数字
         */
        fun setIconBadge(context: Context?, count: Int) {
            if (context == null) {
                return
            }
            val launcherClassName = getLauncherClassName(context)
            if (TextUtils.isEmpty(launcherClassName)) {
                return
            }
            val intent = Intent("android.intent.action.BADGE_COUNT_UPDATE")
            intent.putExtra("badge_count", count)
            intent.putExtra("badge_count_package_name", context.packageName)
            intent.putExtra("badge_count_class_name", launcherClassName)

            context.sendBroadcast(intent)
        }

        /**
         * 起動中のアプリのクラス名を取得する。
         * 
         * @param context コンテキスト。
         * @return 起動中のアプリのクラス名<br></br>
         * *     正常に取得できない場合はnull。
         */
        private fun getLauncherClassName(context: Context): String? {
            val pm = context.packageManager
            val intent = Intent(Intent.ACTION_MAIN)
            intent.addCategory(Intent.CATEGORY_LAUNCHER)
            val resolveInfoList = pm.queryIntentActivities(intent, 0)

            for (resolveInfo in resolveInfoList) {
                if (resolveInfo == null) {
                    continue
                }
                val pkgName = resolveInfo.activityInfo.applicationInfo.packageName
                if (pkgName.equals(context.packageName, ignoreCase = true)) {
                    return resolveInfo.activityInfo.name
                }
            }

            return null
        }
    }
}
```