Ответ 1
DEPRECATED; KEPT SOLELY ДЛЯ ИСТОРИЧЕСКИХ ЦЕЛЕЙ
Этот ответ был опубликован в 2014 году, когда описанный метод опирался на функциональность, существующую на большинстве Android-устройств. Однако, как упоминалось Adrian-Costin Ţundrea, эта функциональность была удалено пару лет назад из Launcher3, который является пусковой установкой AOSP, на которой находится Google Now Launcher, 1. Сообщение фиксации сказало:
Удаление поддержки из-за ее неряшливого дизайна. Удаление ярлыка вызывает полную перезагрузку. Также у нас нет понятия владельца, поэтому любое приложение может удалить любой ярлык.
По состоянию на март 2017 года эта пусковая установка постепенно прекращается в пользу "Службы Google Search Launcher Services", что означает, что производители могут интегрировать определенную библиотеку Google в свои собственные пусковые установки вместо того, чтобы полагаться на стандартную пусковую установку, предоставляемую Google.
Учитывая, что каждый производитель может свободно реализовать свою пусковую установку, какой бы они ни хотели, и предполагая, что некоторые из них основаны на Launcher3, трудно определить, на каких устройствах будет работать метод ниже, поскольку Launcher3 был запущен даже на некоторых Android 4.1, которые относятся к старым устройствам, которые все еще используются.
Привет!
Я только что рассмотрел ту же самую проблему и хотел бы поделиться своим опытом после успешного ее решения. tl; dr - перейдите к разделу "В заключение" ниже.
Некоторая предыстория:
Во время работы над "следующей версией" приложения возникла необходимость изменить точку входа по умолчанию (т.е. переименовать "Основная активность" ). Это неодобрительно, потому что пользователи, которые будут обновляться со старой версии, по-прежнему будут иметь старый ярлык, указывая на неправильное место. Чтобы избежать проблем, насколько это возможно, при первом запуске, без ведома им, старый ярлык должен был быть заменен новым.
Шаг 1: Настройка новой точки входа
Это самая легкая часть. Чтобы объявить точку входа , необходимо сделать только <action ...>
тег <action ...>
в соответствующем объявлении активности внутри вашего манифеста:
<activity
android:name="YOUR_PACKAGE_NAME.YOUR_ACTIVITY_NAME"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
То, что делает точку входа по умолчанию в некотором смысле, заключается в том, что на нее указывает ярлык запуска. Вот почему разработчики обычно также включают это в <intent-filter>
:
<category android:name="android.intent.category.LAUNCHER"/>
Следует отметить, что каждое действие, которое имеет это в <intent-filter>
, будет создавать элемент в вашем ящике приложения - вот почему для большинства случаев вам нужен только один экземпляр.
Шаг 2. Выяснение того, как работает старый ярлык
Имея корневое устройство, я мог получить доступ к таблице базы данных, где хранятся элементы запуска/рабочего стола/рабочего стола (см. изображение того, как выглядят записи SQLite ), который находится в:
/data/data/com.android.launcher/databases/launcher.db -> SELECT * FROM favorites`
Здесь более читаемая версия выделенной записи из изображения:
#Intent;
action=android.intent.action.MAIN;
category=android.intent.category.LAUNCHER;
launchFlags=0x10200000;
package=gidutz.soft.bluecard;
component=gidutz.soft.bluecard/.LoadingScreen;
end
Обратите внимание на 0x10200000
- это объясняется в Шаг 4 - Попытка 1 ниже.
Шаг 3: Выясните, что ожидает Uninstaller Shortcut
Строки 38-42 в UninstallShortcutReceiver.java
говорят нам, что:
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
if (intent != null && name != null) { ... }
Значение "намерение удаления" должно иметь как Intent.EXTRA_SHORTCUT_INTENT
, так и Intent.EXTRA_SHORTCUT_NAME
, иначе он даже не рассмотрит выполнение.
Шаг 4: Поиск правильного синтаксиса
Это случай пробной ошибки со счастливым концом.
Попытка 1: Реконструкция намерения
Intent oldShortcutIntent = new Intent();
oldShortcutIntent.setAction(Intent.ACTION_MAIN);
oldShortcutIntent.addCategory(Intent.CATEGORY_LAUNCHER);
oldShortcutIntent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED +
Intent.FLAG_ACTIVITY_NEW_TASK);
oldShortcutIntent.setPackage("gidutz.soft.bluecard");
oldShortcutIntent.setComponent(new ComponentName("gidutz.soft.bluecard",
".LoadingScreen"));
// The above line is equivalent to:
Intent oldShortcutIntent = new Intent(getApplicationContext(),LoadingScreen.class);
Intent uninstaller = new Intent();
uninstaller.putExtra(Intent.EXTRA_SHORTCUT_INTENT, oldShortcutIntent);
uninstaller.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Blue Card");
uninstaller.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
getApplicationContext().sendBroadcast(uninstaller);
Результат: Значок не удален.
0x10200000
на самом деле представляет собой сумму двух аргументов, как описано здесь.
Попытка 2: Использование кода as-is из viralpatel
Intent shortcutIntent = new Intent(getApplicationContext(),LoadingScreen.class);
shortcutIntent.setAction(Intent.ACTION_MAIN);
Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Blue Card");
addIntent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
getApplicationContext().sendBroadcast(addIntent);
Результат: Иконка не удалена.
Попытка 3: "Грубая сила"
Попытка скопировать-вставить намерение точно так же, как оно появляется в файле launcher.db:
Intent intent = new Intent();
String oldShortcutUri = "#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;package=gidutz.soft.bluecard;component=gidutz.soft.bluecard/.LoadingScreen;end";
try {
Intent altShortcutIntent = Intent.parseUri(oldShortcutUri,0);
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, altShortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Blue Card");
} catch (URISyntaxException e) {
}
intent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
getApplicationContext().sendBroadcast(intent);
Результат: Удалена Icon!
Заключение
- Убедитесь, что ваш намерение "Иконки Uninstaller" использует тот же URI, который используется для создания значка, который вы пытаетесь удалить, либо сохраняя URI, который использовался для его создания, либо, получив его из
launcher.db
. - Подождите около 2-3 секунд, пока не появится значок "icon removed".
Источники
1) Это руководство на viralpatel.net
2) Реализация Google UninstallShortcutReceiver.java
P.S.
Чтобы смоделировать и отладить обновление Google Play (которое хранит старый ярлык), я сделал следующее:
- Установлена старая версия приложения из магазина - значок со старым ярлыком был автоматически помещен на мой экран.
- Резервное копирование my launcher.db с помощью Total Commander.
- Установил новую версию через мою IDE (для этого также можно использовать .apk) - теперь "старый ярлык" исчез.
- Открыл Total Commander и минимизировал его (чтобы в меню "ALT-TAB" был доступен ярлык).
- Пошел на Настройки устройства → Приложения → ALL, нашел мою пусковую установку (для меня это было "Trebuchet", так как я на CM11), и Force остановила его.
- ALT-TAB в Total Commander и восстановил DB.
- Нажмите кнопку "home" для перезапуска запуска.
- Viola! Теперь был восстановлен старый ярлык.
Примечание1. В ретроспективе было бы проще создать старый ярлык вручную, используя URI, полученный из базы данных, вместо того, чтобы проходить все испытания на резервное копирование и принудительное прекращение.
Примечание2: Я не пробовал удалять иконки, принадлежащие другим приложениям, используя этот метод, но это может быть просто безумно достаточно для работы.