Системное приложение с android: persistent = true сбой после обновления

У меня есть системно-привилегированное приложение с android: persistent = true в < Приложение > . Когда я обновляю его (через ADB или любым другим способом), он не может корректно обновляться и сбой.

Что я вижу, так это то, что система устанавливает обновление, пока текущая (системная) версия все еще работает. Во время обновления система не останавливает процесс (либо пытается остановиться, либо не работает, либо вообще не пытается). После завершения обновления приложение, похоже, подвергнется "перезагрузке" - я вижу инициализацию компонентов, таких как Application:: onCreate(). Но это происходит в том же процессе, что и до обновления!

Следовательно (при запуске некоторой активности приложения) приложение вылетает с "странными" исключениями, такими как отказ от использования класса для себя:

Вызвано: java.lang.ClassCastException: com.XX.YY.ZZ.ClassName не может быть добавлено в com.XX.YY.ZZ.ClassName

Во время исследования я увидел, что ClassLoader, используемый после обновления, не ссылается на путь обновленного APK, но остается указывать на путь исходной версии:

Ожидаемый загрузчик классов:

dalvik.system.PathClassLoader [DexPathList [[zip файл]/data/app/com.app.package-1/base.apk"],nativeLibraryDirectories=[/data/app/com.app.package-1/lib/x86_64,/data/app/com.app.package-1/base.apk!/lib/x86_64,/system/lib64,/vendor/lib64]]]

Фактический загрузчик классов:

dalvik.system.PathClassLoader [DexPathList [[zip файл]/system/priv-app/Appname.apk"],nativeLibraryDirectories=[/system/lib64/Start,/system/priv-app/Appname.apk!/lib/x86_64,/system/lib64,/vendor/lib64,/system/lib64,/vendor/lib64]]]

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

Есть ли способ обновить приложение с помощью persistent = true? Или это ожидаемое поведение, такое приложение не может быть обновлено общей процедурой обновления (например, публикация более новой версии в Google Play)?

Ответ 1

Вы не можете использовать adb install при работе с приложениями в образе системы, а постоянные приложения должны быть в образе системы. Для какой версии Android вы разрабатываете? На последних версиях андроида я использую один из способов, описанных ниже. Перед каждым вы должны запустить adb remount хотя бы один раз.

Метод 1: работает только для изменений кода, не работает для изменений ресурсов или манифеста

Временно добавьте это на свой Android.mk:

LOCAL_DEX_PREOPT := false # Do not commit

Затем выполните сборку с помощью mm или т.п.

Запустите соответствующую команду push следующим образом:

adb push $OUT/system/priv-app/MyApp/MyApp.apk /system/priv-app/MyApp/

Поскольку приложение является постоянным, вы должны прервать процесс приложения с помощью следующей команды, чтобы оно приняло изменения:

adb shell ps | grep com.my.app | awk '{print $2}' | xargs adb shell kill

Не забудьте удалить или закомментировать изменения, внесенные в Android.mk до совершения или создания полной сборки.

Метод 2: Необходим для всего, кроме простых изменений кода Java

Выполните сборку с помощью mm или тому подобное.

Запустите следующие команды:

adb sync
adb shell stop
adb shell start

Способ 3

Просто для полноты вы можете просто построить все дерево и либо прошить систему, либо применить OTA из результата.

Ответ 2

Вы можете использовать простой хак и зарегистрироваться, чтобы получить намерение "android.intent.action.PACKAGE_ADDED" для каждого приложения, установленного на устройстве. В случае, если добавленное приложение имеет идентификатор вашего пакета (с указанием того, что ваше приложение было обновлено), вы можете попытаться заставить его закончить и ждать, пока механизм "persist" повторно переучет в качестве нового процесса.

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

Ответ 3

Нашел обходной путь для проблемы. Обновление выполнится успешно, если новая версия изменит свое имя процесса