DEPRECATED; ХРАНИТСЯ ТОЛЬКО ДЛЯ ИСТОРИЧЕСКИХ ЦЕЛЕЙ
Этот ответ был опубликован в 2014 году, когда описанный метод основывался на функциональности, существовавшей в большинстве устройств Android. Однако, как упомянул Adrian-Costin Țundrea , эта функция была удалена пару лет назад из Launcher3, который является средством запуска AOSP, на котором Google Now Launcher основан 1 . Сообщение коммита говорит:
Снятие опоры из-за ее ворсистой конструкции. Удаление ярлыка
вызывает полную перезагрузку. Также у нас нет никакой концепции владельца, поэтому
любое приложение может удалить любой ярлык.
По состоянию на март 2017 года эта программа запуска тоже постепенно прекращается в пользу «Служб Google Search Launcher», что означает, что производители могут вместо этого интегрировать определенную библиотеку Google в свои собственные собственные программы запуска полагаться на стандартный лаунчер, предоставленный Google.
Учитывая, что каждый производитель может свободно внедрять свои средства запуска, в зависимости от того, что они хотят, и предполагая, что некоторые из них основаны на Launcher3, трудно сказать, на каких устройствах будет работать метод, описанный ниже, поскольку Launcher3 был запущен даже на некоторых Android 4.1 устройства, которые являются одними из старейших устройств, все еще используемых .
Привет!
Я только что столкнулся с той же самой проблемой и хотел бы поделиться своим опытом после успешного ее решения. tl; dr - перейти к разделу «В заключение» ниже.
Некоторый фон:
Во время работы над «следующей версией» приложения возникла необходимость изменить точку входа по умолчанию (т.е. переименовать «Основное действие»). Это нахмурилось , потому что пользователи, которые будут обновляться со старой версии, все равно будут иметь старый ярлык, указывающий на неправильное место. Чтобы максимально избежать проблем, при первом запуске, без их ведома, старый ярлык должен был быть заменен новым.
Шаг 1: Настройка новой точки входа
Это самая простая часть. Чтобы объявить точку входа , единственное существенное, что нужно сделать , - это вставить следующий тег <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>
, будет создавать элемент в вашем ящике приложения - вот почему в большинстве случаев 1 экземпляр - это все, что вам нужно.
Шаг 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: Выяснение того, что ожидает программа удаления ярлыков
Строки 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: использование кода как есть от 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);
Результат: Значок удален !!
В заключение
- Убедитесь, что ваше намерение «Удаление значков» использует тот же URI, который использовался для создания значка, который вы пытаетесь удалить, либо сохраняя URI, использованный для его создания, либо получая его из
launcher.db
.
- Подождите примерно 2-3 секунды, пока не появится тост "Значок удален".
Источники
1) Это руководство на viralpatel.net
2) Реализация Google UninstallShortcutReceiver.java
3) Эта тема на xdadevelopers
приписка
Чтобы смоделировать и отладить обновление Google Play (которое сохраняет старый ярлык), я сделал следующее:
- Установил старую версию приложения из магазина - на моем экране автоматически появилась иконка со «старым ярлыком».
- Создайте резервную копию моего launcher.db с помощью Total Commander.
- Установил новую версию через мою IDE (вы также можете использовать .apk для этого) - теперь "старый ярлык" исчез.
- Открыл Total Commander и свернул его (чтобы ярлык был доступен в меню «ALT-TAB»).
- Зашел в Настройки устройства >> Приложения >> ВСЕ, нашел мой лаунчер (для меня это был "Требушет", так как я на CM11) и Force остановил it.
- ALT-TAB в Total Commander и восстановил БД.
- Нажал аппаратную кнопку «домой», чтобы перезапустить модуль запуска.
- Viola! Старый ярлык теперь восстановлен.
Примечание 1. В ретроспективе, возможно, было бы проще создать старый ярлык вручную, используя URI, полученный из базы данных, вместо того, чтобы проходить через все операции резервного копирования и принудительного останова.
Примечание 2: Я не пробовал удалять значки, принадлежащие другим приложениям, используя этот метод, но он может быть достаточно сумасшедшим, чтобы работать.