Ответ 1
Хорошо. Я много раз изучал эту проблему с двух дней и, наконец, нашел "дикий путь", чтобы решить эту проблему, не укореняя устройство:)
Во-первых, вот основные моменты для достижения решения:
1. Всякий раз, когда пользователь переходит в Настройки → Управление приложениями → Выбирает конкретное приложение мы получаем широковещательный файл android.intent.action.QUERY_PACKAGE_RESTART с именем пакета приложения в качестве дополнительных функций.
2.. После этого, когда мы нажимаем кнопку Удалить (с установщиком пакетов), она открывает действие с именем - com.android.packageinstaller.UninstallerActivity
Управляющий поток будет выглядеть следующим образом:
В разделе "Настройки приложения" кнопка "Нажимает кнопку на кнопку" Удалить "--- > Мы получаем контроль, чтобы показать диалог/запустить другое действие /etc --- > Закончить задачу" Предварительная деинсталляция "--- > Пользователь возвращается обратно на экран подтверждения удаления --- > Пользователь подтверждает и удаляет приложение
Используемый метод:
Мы будем использовать BroadcastReceiver в нашем приложении для прослушивания действия " android.intent.action.QUERY_PACKAGE_RESTART" и соответствия имени нашего пакета внутри метода onReceive(). Если трансляция была получена для выбора нашего желаемого пакета приложений, мы инициируем фоновый поток, который будет отслеживать действия, выполняемые переднего плана, с помощью ActivityManager.
Как только мы увидим, что переднего плана " com.android.packageinstaller.UninstallerActivity", он будет подтверждать, что пользователь хочет удалить наше приложение. На этом этапе мы выполним требуемые задачи (либо отобразим диалог, либо запустим другое действие, перекрывающее окно удаления и т.д.), Которые должны быть выполнены перед деинсталляцией. После выполнения нашей задачи мы разрешим пользователю продолжить подтверждение процесса удаления.
Реализация/Исходный код:
В manifest.xml
добавить разрешение:
<uses-permission android:name="android.permission.GET_TASKS"/>
и широковещательный приемник:
<receiver android:name=".UninstallIntentReceiver">
<intent-filter android:priority="0">
<action android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
<data android:scheme="package" />
</intent-filter>
</receiver>
UninstallIntentReceiver.java (класс вещательного приемника)
public class UninstallIntentReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// fetching package names from extras
String[] packageNames = intent.getStringArrayExtra("android.intent.extra.PACKAGES");
if(packageNames!=null){
for(String packageName: packageNames){
if(packageName!=null && packageName.equals("YOUR_APPLICATION_PACKAGE_NAME")){
// User has selected our application under the Manage Apps settings
// now initiating background thread to watch for activity
new ListenActivities(context).start();
}
}
}
}
}
Класс ListenActivities - для мониторинга действий переднего плана
class ListenActivities extends Thread{
boolean exit = false;
ActivityManager am = null;
Context context = null;
public ListenActivities(Context con){
context = con;
am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
}
public void run(){
Looper.prepare();
while(!exit){
// get the info from the currently running task
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(MAX_PRIORITY);
String activityName = taskInfo.get(0).topActivity.getClassName();
Log.d("topActivity", "CURRENT Activity ::"
+ activityName);
if (activityName.equals("com.android.packageinstaller.UninstallerActivity")) {
// User has clicked on the Uninstall button under the Manage Apps settings
//do whatever pre-uninstallation task you want to perform here
// show dialogue or start another activity or database operations etc..etc..
// context.startActivity(new Intent(context, MyPreUninstallationMsgActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
exit = true;
Toast.makeText(context, "Done with preuninstallation tasks... Exiting Now", Toast.LENGTH_SHORT).show();
} else if(activityName.equals("com.android.settings.ManageApplications")) {
// back button was pressed and the user has been taken back to Manage Applications window
// we should close the activity monitoring now
exit=true;
}
}
Looper.loop();
}
}
Известные ограничения:
Когда пользователь нажимает кнопку Удалить в настройках "Управление приложениями", мы выполним наши задачи перед удалением, а затем предложим пользователю окно подтверждения, в котором пользователь может подтвердить или удалить Отмените операцию.
Подход, описанный выше, теперь не распространяется на случай, если пользователь нажимает кнопку Отмена после выполнения нашей задачи. Но с этим можно легко справиться с некоторыми изменениями.
Например: мы можем реализовать логику, чтобы вернуть изменения, которые мы сделали, если трансляция " android.intent.action.PACKAGE_REMOVED" в конце не была получена.
Я надеюсь, что этот подход будет вам полезен:) Поскольку это единственный способ, на мой взгляд, мы можем решить вашу проблему, не укореняя устройство!
[Обновить 1]: Рекомендуемый подход, чтобы проверить, была ли задача удаления Отменена:
Его смешно, что раньше у меня была совершенно другая и сложная идея (с участием трансляций, ActivityManager и т.д. и т.д.), но, написав здесь, просто мне пришла в голову другая идея, которая сравнительно проста:)
Когда пользователь нажимает кнопку "Удалить" в настройках "Управление приложениями" и после выполнения задач предварительной деинсталляции, вы просто устанавливаете некоторые параметры SharedPreference в своем приложении, которые выполняли задачи перед удалением, и готовы к удалению. После этого вам не нужно ничего волноваться.
Если пользователь продолжает деинсталлировать → хорошо и хорошо, как вы уже выполнили требуемые задачи.
Пока пользователь, наконец, нажимает кнопку Отменить и уходит → не беспокойтесь. Пока пользователь не запустит ваше приложение и не запустит его. Теперь внутри "onStart()" / "onResume()" основного действия вашего приложения вы можете проверить значение SharedPreference, и если оно было установлено для удаления, это будет означать, что пользователь не завершил деинсталляцию. И теперь вы можете отменить сделанные ранее изменения (реверсирование выполняемых задач перед удалением), чтобы убедиться, что приложение работает отлично!