Установите APK, используя root, обрабатывая новые ограничения папки "/ data / local / tmp /" - PullRequest
0 голосов
/ 26 мая 2018

Фон

До сих пор я смог установить APK-файлы, используя root (в приложении), с помощью этого кода:

pm install -t -f fullPathToApkFile

и, если я хочу (попытаться)установить на SD-карту:

pm install -t -s fullPathToApkFile

Проблема

В последнее время, не уверен, с какой версии Android (по крайней мере, проблема существует в бета-версии Android P), вышеуказанный метод не работает, показывая мнеэто сообщение:

avc:  denied  { read } for  scontext=u:r:system_server:s0 tcontext=u:object_r:sdcardfs:s0 tclass=file permissive=0
System server has no access to read file context u:object_r:sdcardfs:s0 (from path /storage/emulated/0/Download/FDroid.apk, context u:r:system_server:s0)
Error: Unable to open file: /storage/emulated/0/Download/FDroid.apk
Consider using a file under /data/local/tmp/
Error: Can't open file: /storage/emulated/0/Download/FDroid.apk
Exception occurred while executing:
java.lang.IllegalArgumentException: Error: Can't open file: /storage/emulated/0/Download/FDroid.apk
    at com.android.server.pm.PackageManagerShellCommand.setParamsSize(PackageManagerShellCommand.java:306)
    at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:884)
    at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:138)
    at android.os.ShellCommand.exec(ShellCommand.java:103)
    at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21125)
    at android.os.Binder.shellCommand(Binder.java:634)
    at android.os.Binder.onTransact(Binder.java:532)
    at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2806)
    at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3841)
    at android.os.Binder.execTransact(Binder.java:731)

Похоже, это также влияет на популярные приложения, такие как " Резервная копия Titanium (pro)", которая не может восстановить приложения.

То, что я пробовал

Глядя на то, что написано, кажется, что у него нет разрешения на установку файлов APK, которых нет в /data/local/tmp/.

Поэтому я попробовал следующее, чтобыпосмотрите, смогу ли я преодолеть это:

  1. установить доступ к файлу (chmod 777) - не помогло.
  2. предоставить разрешения для моего приложения, как хранилища, так и REQUEST_INSTALL_PACKAGES (с использованием ACTION_MANAGE_UNKNOWN_APP_SOURCES Intent) - не помогло.
  3. создайте символическую ссылку на файл, чтобы он находился внутри /data/local/tmp/, используя официальный API:

     Os.symlink(fullPathToApkFile, symLinkFilePath)
    

    Это ничего не делало.

  4. создать символическую ссылку, используя это:

     ln -sf $fullPathToApkFile $symLinkFilePath
    

    Это частично сработало.Файл там, как я вижу в приложении Total Commander, но когда я пытаюсь проверить, существует ли он там, и когда я пытаюсь установить APK оттуда, он терпит неудачу.

  5. Скопируйте / переместите (используя cp или mv) файл в путь /data/local/tmp/, а затем установите его оттуда.Это сработало, но у него есть недостатки: перемещение сопряжено с риском, поскольку временно скрывает исходный файл и изменяет временную метку исходного файла.Копирование является плохим из-за использования дополнительного места только для установки (даже временно) и из-за того, что оно тратит на это время.

  6. Скопируйте файл APK, сказав, чтобы он не копировался (то есть трудноссылка), используя эту команду (взято из здесь ):

     cp -p -r -l $fullPathToApkFile $tempFileParentPath"
    

    Это не сработало.Он получил мне эту ошибку:

     cp: /data/local/tmp/test.apk: Cross-device link
    
  7. Проверка того, что происходит в других случаях установки приложений.Когда вы устанавливаете через IDE, он на самом деле создает файл APK по этому специальному пути, но если вы устанавливаете через Play Store, простой APK-установщик (через Intent) или adb (через ПК), это не так.

  8. Написал об этом и здесь: https://issuetracker.google.com/issues/80270303

Вопросы

  1. Есть ли способ преодолеть недостаткиустановить APK с помощью root по этому специальному пути?Может быть, вообще избегать обработки этого пути?

  2. Почему ОС внезапно требует использовать этот путь?Почему бы вместо этого не использовать исходный путь, как в других методах установки приложений?Что делают другие методы установки приложений, которые каким-то образом избегают использования пространственного пути?

1 Ответ

0 голосов
/ 26 мая 2018

Одним из решений, если вы не возражаете против процедуры перемещения, является также сохранение и восстановление метки времени исходного файла, например:

    val tempFileParentPath = "/data/local/tmp/"
    val tempFilePath = tempFileParentPath + File(fullPathToApkFile).name
    val apkTimestampTempFile = File(context.cacheDir, "apkTimestamp")
    apkTimestampTempFile.delete()
    apkTimestampTempFile.mkdirs()
    apkTimestampTempFile.createNewFile()
    root.runCommands("touch -r $fullPathToApkFile ${apkTimestampTempFile.absolutePath}")
    root.runCommands("mv $fullPathToApkFile $tempFileParentPath")
    root.runCommands("pm install -t -f $tempFilePath")
    root.runCommands("mv $tempFilePath $fullPathToApkFile")
    root.runCommands("touch -r ${apkTimestampTempFile.absolutePath} $fullPathToApkFile")
    apkTimestampTempFile.delete()

Это все еще немного опасно, но лучше, чем копированиефайлы ...


РЕДАКТИРОВАТЬ: Google показал мне хороший обходной путь для этого ( здесь ):

Мыне поддерживает установку APK из случайных каталогов на устройстве.Они либо должны быть установлены непосредственно с хоста с помощью 'adb install', либо вам необходимо передать содержимое для установки -

$ cat foo.apk | pm install -S APK_SIZE

Хотя я считаю, что это неверно, поскольку они не поддерживаютустановка APK-файлов по случайным путям (всегда работавшим раньше), обходной путь, похоже, работает.Все, что мне нужно было изменить в коде установки APK-файла:

val length = File(fullPathToApkFile ).length()
commands.add("cat $fullPathToApkFile | pm install -S $length")

Дело в том, что теперь у меня есть еще несколько вопросов по этому поводу:

  1. Есть ли обходной путь?избегать перемещения / копирования APK в хранилище и не затрагивать оригинальный файл?- кажется, это
  2. Будет ли это поддерживать какой-либо файл APK, даже большие?- кажется, ему удается сделать это для APK, который занимает 433 МБ, поэтому я думаю, что это безопасно использовать для всех размеров.
  3. Это нужно только от Android P, верно?- пока что так кажется.
  4. Зачем ему нужен размер файла в качестве параметра?- Понятия не имею, но если я уберу его, он не будет работать
...