Есть ли способ добавить значок к значку приложения в Android?

На iPhone вы можете добавить пронумерованный значок к значку приложения. На BlackBerry я успешно нарисовал изображение на иконке приложения в то время как в программе. Я хочу сделать это и для Android. Я не хочу использовать панель уведомлений, так как это не то, что нужно немедленно уведомлять. Вместо этого я просто хочу, чтобы пользователь мог видеть, сколько новых сообщений находится в приложении, просто взглянув на значок приложения.

5 ответов

Решение

К сожалению, Android не позволяет менять значок приложения, потому что он запечатан в APK после компиляции программы. Нет никакого способа программно изменить его на "рисуемый".

Вы можете достичь своей цели, используя виджет вместо значка. Виджеты легко настраиваются и могут делать то, что вы хотите.

Здесь кратко обсуждается разница между уведомлением о значке iPhone и использованием виджетов:

http://www.cnet.com/8301-19736_1-10278814-251.html

Как вы заметите, между использованием виджета или иконки практически нет разницы, поскольку они могут быть одинакового размера и выглядеть одинаково.

Это также можно сделать для Sony Xperia Home. Я писал об этом здесь, но важные части приведены ниже. Устройства Sony используют класс с именем BadgeReciever,

  1. Объявить com.sonyericsson.home.permission.BROADCAST_BADGE разрешение в вашем файле манифеста:

  2. Трансляция Intent к BadgeReceiver:

    Intent intent = new Intent();
    
    intent.setAction("com.sonyericsson.home.action.UPDATE_BADGE");
    intent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME", "com.yourdomain.yourapp.MainActivity");
    intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", true);
    intent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", "99");
    intent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", "com.yourdomain.yourapp");
    
    sendBroadcast(intent);
    
  3. Готово. Однажды это Intent При запуске программы запуска должен отображаться значок на значке вашего приложения.

  4. Чтобы снова удалить значок, просто отправьте новую трансляцию, на этот раз с SHOW_MESSAGE установить в ложь:

    intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", false);
    

Я исключил детали того, как я нашел это, чтобы краткий ответ, но все это доступно в блоге. Может быть, интересное чтение для кого-то.

Я также разместил отдельный ТАК вопрос об этом здесь и добавлю полный ответ, как только мне позволят (мне нужно 10 репутаций, чтобы ответить на мой собственный вопрос в течение 8 часов).

Библиотека ShortcutBadger делает это возможным и работает с LG, Sony, Samsung, HTC и другими кастомными программами запуска.

У этого даже есть способ показать Счетчик Жетонов на рабочем столе Чистых устройств Android.

Обновление счетчика значков на значке приложения так же просто, как вызов:

int badgeCount = 1;
ShortcutBadger.setBadge(getApplicationContext(), badgeCount);

Он включает в себя демонстрационное приложение, которое позволяет вам проверить его поведение.

ИЛИ ЖЕ

Вы также можете попробовать использовать псевдоним активности для этого, но в этом случае вам нужно создать разные значки со значениями значков, это будет отлично работать в случае - вам нужно переключаться между двумя разными значками приложения (необходимо создать разные псевдонимы активности для отображения другой значок, т.е. больше значков = больше псевдонимов активности).

Устройства Asus:

public static class AsusHomeBadger implements Badger {

    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(int badgeCount) {
        final 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());
        intent.putExtra("badge_vip_count", 0);
        if (canResolveBroadcast(intent)) {
            AndroidUtilities.runOnUIThread(new Runnable() {
                @Override
                public void run() {
                    ApplicationLoader.applicationContext.sendBroadcast(intent);
                }
            });
        }
    }

    @Override
    public List<String> getSupportLaunchers() {
        return Arrays.asList("com.asus.launcher");
    }
}

Устройства Huawei:

public static class HuaweiHomeBadger implements Badger {

    @Override
    public void executeBadge(int badgeCount) {
        final Bundle localBundle = new Bundle();
        localBundle.putString("package", ApplicationLoader.applicationContext.getPackageName());
        localBundle.putString("class", componentName.getClassName());
        localBundle.putInt("badgenumber", badgeCount);
        AndroidUtilities.runOnUIThread(new Runnable() {
            @Override
            public void run() {
                try {
                    ApplicationLoader.applicationContext.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, localBundle);
                } catch (Exception e) {
                    FileLog.e(e);
                }
            }
        });
    }

    @Override
    public List<String> getSupportLaunchers() {
        return Arrays.asList(
                "com.huawei.android.launcher"
        );
    }
}

Устройства HTC:

public static class NewHtcHomeBadger implements Badger {

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

    @Override
    public void executeBadge(int badgeCount) {

        final Intent intent1 = new Intent(INTENT_SET_NOTIFICATION);
        intent1.putExtra(EXTRA_COMPONENT, componentName.flattenToShortString());
        intent1.putExtra(EXTRA_COUNT, badgeCount);

        final Intent intent = new Intent(INTENT_UPDATE_SHORTCUT);
        intent.putExtra(PACKAGENAME, componentName.getPackageName());
        intent.putExtra(COUNT, badgeCount);

        if (canResolveBroadcast(intent1) || canResolveBroadcast(intent)) {
            AndroidUtilities.runOnUIThread(new Runnable() {
                @Override
                public void run() {
                    ApplicationLoader.applicationContext.sendBroadcast(intent1);
                    ApplicationLoader.applicationContext.sendBroadcast(intent);
                }
            });
        }
    }

    @Override
    public List<String> getSupportLaunchers() {
        return Arrays.asList("com.htc.launcher");
    }
}

Устройства Samsung:

public static class SamsungHomeBadger implements Badger {
    private static final String CONTENT_URI = "content://com.sec.badge/apps?notify=true";
    private static final String[] CONTENT_PROJECTION = new String[]{"_id","class"};

    private static DefaultBadger defaultBadger;

    @Override
    public void executeBadge(int badgeCount) {
        try {
            if (defaultBadger == null) {
                defaultBadger = new DefaultBadger();
            }
            defaultBadger.executeBadge(badgeCount);
        } catch (Exception ignore) {

        }

        Uri mUri = Uri.parse(CONTENT_URI);
        ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver();
        Cursor cursor = null;
        try {
            cursor = contentResolver.query(mUri, CONTENT_PROJECTION, "package=?", new String[]{componentName.getPackageName()}, null);
            if (cursor != null) {
                String entryActivityName = componentName.getClassName();
                boolean entryActivityExist = false;
                while (cursor.moveToNext()) {
                    int id = cursor.getInt(0);
                    ContentValues contentValues = getContentValues(componentName, badgeCount, false);
                    contentResolver.update(mUri, contentValues, "_id=?", new String[]{String.valueOf(id)});
                    if (entryActivityName.equals(cursor.getString(cursor.getColumnIndex("class")))) {
                        entryActivityExist = true;
                    }
                }

                if (!entryActivityExist) {
                    ContentValues contentValues = getContentValues(componentName, badgeCount, true);
                    contentResolver.insert(mUri, contentValues);
                }
            }
        } finally {
            close(cursor);
        }
    }

    private ContentValues getContentValues(ComponentName componentName, int badgeCount, boolean isInsert) {
        ContentValues contentValues = new ContentValues();
        if (isInsert) {
            contentValues.put("package", componentName.getPackageName());
            contentValues.put("class", componentName.getClassName());
        }

        contentValues.put("badgecount", badgeCount);

        return contentValues;
    }

    @Override
    public List<String> getSupportLaunchers() {
        return Arrays.asList(
                "com.sec.android.app.launcher",
                "com.sec.android.app.twlauncher"
        );
    }
}

Устройства Sony:

public static class SonyHomeBadger implements Badger {

    private static final String INTENT_ACTION = "com.sonyericsson.home.action.UPDATE_BADGE";
    private static final String INTENT_EXTRA_PACKAGE_NAME = "com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME";
    private static final String INTENT_EXTRA_ACTIVITY_NAME = "com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME";
    private static final String INTENT_EXTRA_MESSAGE = "com.sonyericsson.home.intent.extra.badge.MESSAGE";
    private static final String INTENT_EXTRA_SHOW_MESSAGE = "com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE";

    private static final String PROVIDER_CONTENT_URI = "content://com.sonymobile.home.resourceprovider/badge";
    private static final String PROVIDER_COLUMNS_BADGE_COUNT = "badge_count";
    private static final String PROVIDER_COLUMNS_PACKAGE_NAME = "package_name";
    private static final String PROVIDER_COLUMNS_ACTIVITY_NAME = "activity_name";
    private static final String SONY_HOME_PROVIDER_NAME = "com.sonymobile.home.resourceprovider";
    private final Uri BADGE_CONTENT_URI = Uri.parse(PROVIDER_CONTENT_URI);

    private static AsyncQueryHandler mQueryHandler;

    @Override
    public void executeBadge(int badgeCount) {
        if (sonyBadgeContentProviderExists()) {
            executeBadgeByContentProvider(badgeCount);
        } else {
            executeBadgeByBroadcast(badgeCount);
        }
    }

    @Override
    public List<String> getSupportLaunchers() {
        return Arrays.asList("com.sonyericsson.home", "com.sonymobile.home");
    }

    private static void executeBadgeByBroadcast(int badgeCount) {
        final Intent intent = new Intent(INTENT_ACTION);
        intent.putExtra(INTENT_EXTRA_PACKAGE_NAME, componentName.getPackageName());
        intent.putExtra(INTENT_EXTRA_ACTIVITY_NAME, componentName.getClassName());
        intent.putExtra(INTENT_EXTRA_MESSAGE, String.valueOf(badgeCount));
        intent.putExtra(INTENT_EXTRA_SHOW_MESSAGE, badgeCount > 0);
        AndroidUtilities.runOnUIThread(new Runnable() {
            @Override
            public void run() {
                ApplicationLoader.applicationContext.sendBroadcast(intent);
            }
        });
    }

    private void executeBadgeByContentProvider(int badgeCount) {
        if (badgeCount < 0) {
            return;
        }

        if (mQueryHandler == null) {
            mQueryHandler = new AsyncQueryHandler(ApplicationLoader.applicationContext.getApplicationContext().getContentResolver()) {

                @Override
                public void handleMessage(Message msg) {
                    try {
                        super.handleMessage(msg);
                    } catch (Throwable ignore) {

                    }
                }
            };
        }
        insertBadgeAsync(badgeCount, componentName.getPackageName(), componentName.getClassName());
    }

    private void insertBadgeAsync(int badgeCount, String packageName, String activityName) {
        final ContentValues contentValues = new ContentValues();
        contentValues.put(PROVIDER_COLUMNS_BADGE_COUNT, badgeCount);
        contentValues.put(PROVIDER_COLUMNS_PACKAGE_NAME, packageName);
        contentValues.put(PROVIDER_COLUMNS_ACTIVITY_NAME, activityName);
        mQueryHandler.startInsert(0, null, BADGE_CONTENT_URI, contentValues);
    }

    private static boolean sonyBadgeContentProviderExists() {
        boolean exists = false;
        ProviderInfo info = ApplicationLoader.applicationContext.getPackageManager().resolveContentProvider(SONY_HOME_PROVIDER_NAME, 0);
        if (info != null) {
            exists = true;
        }
        return exists;
    }
}

Устройства Xiaomi:

public static class XiaomiHomeBadger implements Badger {

    public static final String INTENT_ACTION = "android.intent.action.APPLICATION_MESSAGE_UPDATE";
    public static final String EXTRA_UPDATE_APP_COMPONENT_NAME = "android.intent.extra.update_application_component_name";
    public static final String EXTRA_UPDATE_APP_MSG_TEXT = "android.intent.extra.update_application_message_text";

    @Override
    public void executeBadge(int badgeCount) {
        try {
            Class miuiNotificationClass = Class.forName("android.app.MiuiNotification");
            Object miuiNotification = miuiNotificationClass.newInstance();
            Field field = miuiNotification.getClass().getDeclaredField("messageCount");
            field.setAccessible(true);
            field.set(miuiNotification, String.valueOf(badgeCount == 0 ? "" : badgeCount));
        } catch (Throwable e) {
            final Intent localIntent = new Intent(INTENT_ACTION);
            localIntent.putExtra(EXTRA_UPDATE_APP_COMPONENT_NAME, componentName.getPackageName() + "/" + componentName.getClassName());
            localIntent.putExtra(EXTRA_UPDATE_APP_MSG_TEXT, String.valueOf(badgeCount == 0 ? "" : badgeCount));
            if (canResolveBroadcast(localIntent)) {
                AndroidUtilities.runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        ApplicationLoader.applicationContext.sendBroadcast(localIntent);
                    }
                });
            }
        }
    }

    @Override
    public List<String> getSupportLaunchers() {
        return Arrays.asList(
                "com.miui.miuilite",
                "com.miui.home",
                "com.miui.miuihome",
                "com.miui.miuihome2",
                "com.miui.mihome",
                "com.miui.mihome2"
        );
    }
}

Начиная с API 28, теперь официально поддерживается:

Начиная с версии 8.0 (уровень API 26), значки уведомлений (также известные как точки уведомлений) отображаются на значке средства запуска, когда у связанного приложения есть активное уведомление. Пользователи могут долго нажимать на значок приложения, чтобы отобразить уведомления (вместе с ярлыками приложений), как показано на рисунке 1.

Эти точки появляются по умолчанию в приложениях запуска, которые их поддерживают, и вашему приложению ничего не нужно делать. Однако могут возникнуть ситуации, когда вы не хотите, чтобы точка уведомления появлялась или вы хотите контролировать, какие именно уведомления будут там отображаться.

Чтобы установить собственный номер, вызовите setNumber () в уведомлении:

mNotification.setNumber(messageCount)

Вот как это сделать:

Я думаю, что есть и способ сделать это на LG Launcher, но пока не выяснил, как это сделать.

Другие вопросы по тегам