Разработка Android RecoverySystem.installPackage() не может выполнить запись в /cache/recovery/, команда запрещена
Меня попросили написать небольшое простое приложение для продукта на базе Android. Устройство поставляется с двумя образами системы Android с различными функциями. Приложение, которое я пишу, является лишь подтверждением концепции, где, когда вы нажимаете кнопку, оно использует систему восстановления, чтобы заменить текущую ОС одним из образов.
Устройство рутировано, и приложение запускается как системное приложение.
я использую
RecoverySystem.installPackage(context, packageFile);
( см. здесь для справки) заменить ОС на один из образов. Это должно перезагрузить систему и инициализировать систему восстановления для установки образа.
Проблема, которая у меня есть, заключается в том, что этот вызов не удается, потому что RecoverySystem.installPackage
Кажется, что метод не может получить доступ к / cache / recovery / command file. Я думаю, что он пытается написать некоторые команды для системы восстановления, которые будут выполняться при перезагрузке, но не удается. Вот исключение, которое я получаю:
02-27 16:44:39.463: E/BroadSign Resolution Switcher(4439): java.io.FileNotFoundException: /cache/recovery/command: open failed: EACCES (Permission denied)
02-27 16:44:39.463: E/BroadSign Resolution Switcher(4439): at libcore.io.IoBridge.open(IoBridge.java:416)
02-27 16:44:39.463: E/BroadSign Resolution Switcher(4439): at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
02-27 16:44:39.463: E/BroadSign Resolution Switcher(4439): at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
02-27 16:44:39.463: E/BroadSign Resolution Switcher(4439): at java.io.FileWriter.<init>(FileWriter.java:42)
02-27 16:44:39.463: E/BroadSign Resolution Switcher(4439): at android.os.RecoverySystem.bootCommand(RecoverySystem.java:381)
02-27 16:44:39.463: E/BroadSign Resolution Switcher(4439): at android.os.RecoverySystem.installPackage(RecoverySystem.java:330)
Итак, я предполагаю, что у меня нет необходимых прав доступа к этому файлу. Хотя вот разрешение, которое я установил в своем манифесте:
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
Я знаю, что мне нужно разрешение REBOOT для RecoverySystem
, Тем не менее, я не знаю, актуальны ли другие два. Я даже не знаю, нужно ли мне какое-то другое разрешение для создания / записи в файлы в разделе / cache.
Кто-нибудь знает, чего мне не хватает?
ОБНОВИТЬ:
Ну, похоже, я понял это. Разрешения были правильными в конце концов. Все было правильно.
Когда я настраивал приложение как системное приложение, перемещая файл apk в / system / app, я еще не добавил все разрешения. Когда я запустил последний код на моем устройстве, он установил его в / data / app и распознал как обновление системного приложения. По этой причине распознавались только разрешения исходного системного приложения.
После того, как я заново настроил мой последний код для непосредственного запуска из / system / app, он заработал.
Теперь единственная проблема, с которой я столкнулся, это то, что когда он перезагружается, он не устанавливает образ, и я получаю мертвого зеленого робота с восклицательным знаком. Я буду продолжать расследование.
Я надеюсь, что этот пост поможет любому с той же проблемой. Я также буду рад ответить на любые вопросы.
3 ответа
До того, как мое приложение было установлено в /system/app, я получал сообщение об ошибке ниже:
07-20 10:52:46.512 933-951/? W/RecoverySystem﹕ !!! REBOOTING TO INSTALL /storage/emulated/legacy/Download/Update.zip !!!
07-20 10:52:46.512 933-951/? W/System.err﹕ java.io.FileNotFoundException: /cache/recovery/command: open failed: EACCES (Permission denied)
07-20 10:52:46.512 933-951/? W/System.err﹕ at libcore.io.IoBridge.open(IoBridge.java:409)
07-20 10:52:46.512 933-951/? W/System.err﹕ at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
07-20 10:52:46.512 933-951/? W/System.err﹕ at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
07-20 10:52:46.512 933-951/? W/System.err﹕ at java.io.FileWriter.<init>(FileWriter.java:42)
07-20 10:52:46.512 933-951/? W/System.err﹕ at android.os.RecoverySystem.bootCommand(RecoverySystem.java:389)
07-20 10:52:46.522 933-951/? W/System.err﹕ at android.os.RecoverySystem.installPackage(RecoverySystem.java:337)
Я перепробовал все необходимые разрешения, но не смог продолжить.
Итак, так как я использовал API выше 4.2, я попытался поместить свое приложение в/system/priv-app
и это сработало для меня.
Системные приложения (приложения с общим идентификатором пользователя, установленным на android.uid.system
) не может устанавливать системные обновления на Android 5 и новее - это запрещено политикой SELinux. Конкретно писать в /cache
запрещено для системных приложений. Другими словами:
/cache
принадлежитsystem
пользователь, так что ваше приложение работает подsystem
UID может написать в него. Но только если SELinux отключен / разрешен.- Если у вас есть
android.permission.ACCESS_CACHE_FILESYSTEM
разрешение подписи платформы, вы можете написать/cache
,
Вам нужно будет удалить общий идентификатор пользователя. Вы все еще должны подписать приложение подписью платформы и убедиться, что у вас есть следующие разрешения:
android.permission.REBOOT
android.permission.ACCESS_CACHE_FILESYSTEM
- написать/cache
android.permission.RECOVERY
- требуется API 21 для перезагрузки для восстановления
Это будет работать как на Kitkat, так и на Lollipop+.
У меня такая же проблема с вами, когда вы создаете пользовательское приложение OtaUpdate в Android 5.0.2, и я решил ее. Я поделюсь с вами 2 шагами ниже:
- Добавить Android:sharedUserId="com.google.uid.shared" в AndroidManifest.xml
- Вставьте свой apk в систему / приложение или систему /priv-app
Для Android 4.1.2:
- Добавьте android:sharedUserId="android.uid.system" в AndroidManifest.xml
- Вставьте свой апк в систему / приложение
Для Android 5.1.0
- добавлять
android:sharedUserId="android.uid.system"
в AndroidManifest.xml - Нажмите на свой апк
system/priv-app
а потом
adb root adb shell setenforce 0
Я встретил ту же проблему в Android 8.
Если вы добавите android:sharedUserId="android.uid.system"
в AndroidManifest.xml
, он должен работать.