使用root安装APK,处理“/data/local/tmp/"的新限制;文件夹 [英] Install APK using root, handling new limitations of "/data/local/tmp/" folder

查看:43
本文介绍了使用root安装APK,处理“/data/local/tmp/"的新限制;文件夹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

到目前为止,我能够通过以下代码使用 root(在应用程序内)安装 APK 文件:

pm install -t -f fullPathToApkFile

如果我想(尝试)安装到 SD 卡:

pm install -t -s fullPathToApkFile

问题

最近,不确定来自哪个 Android 版本(至少在 Android P beta 上存在问题),上述方法失败,向我显示此消息:

avc: denied { read } for scontext=u:r:system_server:s0 tcontext=u:object_r:sdcardfs:s0 tclass=file permissive=0系统服务器无权读取文件上下文 u:object_r:sdcardfs:s0(来自路径/storage/emulated/0/Download/FDroid.apk,上下文 u:r:system_server:s0)错误:无法打开文件:/storage/emulated/0/Download/FDroid.apk考虑使用/data/local/tmp/下的文件错误:无法打开文件:/storage/emulated/0/Download/FDroid.apk执行时发生异常:java.lang.IllegalArgumentException:错误:无法打开文件:/storage/emulated/0/Download/FDroid.apk在 com.android.server.pm.PackageManagerShellCommand.setParamsSize(PackageManagerShellCommand.java:306)在 com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:884)在 com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:138)在 android.os.ShellCommand.exec(ShellCommand.java:103)在 com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21125)在 android.os.Binder.shellCommand(Binder.java:634)在 android.os.Binder.onTransact(Binder.java:532)在 android.content.pm.IPPackageManager$Stub.onTransact(IPPackageManager.java:2806)在 com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3841)在 android.os.Binder.execTransact(Binder.java:731)

这似乎也会影响流行的应用程序,例如Titanium 备份 (pro)",无法恢复应用.

我的尝试

看看写的内容,它似乎没有权限安装不在 /data/local/tmp/ 中的 APK 文件.

所以我尝试了接下来的事情,看看我能不能克服它:

  1. 设置对文件的访问权限 (chmod 777) - 没有帮助.
  2. 向我的应用授予存储和 REQUEST_INSTALL_PACKAGES 的权限(使用ACTION_MANAGE_UNKNOWN_APP_SOURCES 意图) - 没有帮助.
  3. 创建文件的符号链接,使其位于/data/local/tmp/中,使用官方API:

     Os.symlink(fullPathToApkFile, symLinkFilePath)

    这没有任何作用.

  4. 使用这个创建一个符号链接:

     ln -sf $fullPathToApkFile $symLinkFilePath

    这部分奏效了.该文件在那里,正如我在 Total Commander 应用程序中看到的那样,但是当我尝试检查它是否存在时,以及当我尝试从那里安装 APK 时,它失败了.

  5. 将文件复制/移动(使用cpmv)到/data/local/tmp/ 路径,然后然后从那里安装.这有效,但它有缺点:移动有风险,因为它会暂时隐藏原始文件,并且会更改原始文件的时间戳.复制是不好的,因为使用额外的空间来安装(即使是临时的)并且因为这样做会浪费时间.

  6. 复制 APK 文件,告诉它避免实际复制(即硬链接),使用此命令(取自 <强>这里) :

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

    这没有用.它给了我这个错误:

     cp:/data/local/tmp/test.apk: 跨设备链接

  7. 检查在安装应用程序的其他情况下会发生什么.当您通过 IDE 安装时,它实际上会在此特殊路径中创建 APK 文件,但如果您通过 Play Store、简单 APK 安装(通过 Intent)或 adb(通过 PC)安装,则不会.

  8. 在这里也写过这个:https://issuetracker.google.com/issues/80270303

问题

  1. 有没有办法克服在这个特殊路径上使用root安装APK的缺点?甚至可能完全避免处理这条路径?

  2. 为什么操作系统突然要求使用这个路径?为什么不使用原始路径,就像安装应用程序的其他方法一样?安装应用程序的其他方法有什么作用,以某种方式避免使用空间路径?

解决方案

一个解决方案,如果你不介意移动过程,也是保存和恢复原始文件的时间戳,这样:

 val tempFileParentPath = "/data/local/tmp/"val tempFilePath = tempFileParentPath + File(fullPathToApkFile).nameval 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 |下午安装 -S APK_SIZE

虽然我认为他们不支持从随机路径安装 APK 文件是不正确的(以前一直有效),但解决方法似乎确实有效.我需要更改安装 APK 文件的代码如下:

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

问题是,现在我还有一些其他问题:

  1. 此变通方法是否可以避免将 APK 移动/复制到存储中,并且不会影响原始文件?- 似乎确实如此
  2. 这是否支持任何 APK 文件,甚至是大文件?- 对于一个需要 433MB 的 APK,它似乎成功地做到了,所以我认为它可以安全地用于所有大小.
  3. 这仅在 Android P 中需要,对吗?- 目前看来是这样.
  4. 为什么需要文件大小作为参数?- 不知道,但如果我删除它,它将不起作用

Background

So far, I was able to install APK files using root (within the app), via this code:

pm install -t -f fullPathToApkFile

and if I want to (try to) install to sd-card :

pm install -t -s fullPathToApkFile

The problem

Recently, not sure from which Android version (issue exists on Android P beta, at least), the above method fails, showing me this message:

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)

This seems to also affect popular apps such as "Titanium backup (pro)", which fails to restore apps.

What I've tried

Looking at what's written, it appears it lacks permission to install APK files that are not in /data/local/tmp/.

So I tried the next things, to see if I can overcome it:

  1. set the access to the file (chmod 777) - didn't help.
  2. grant permissions to my app, of both storage and REQUEST_INSTALL_PACKAGES (using ACTION_MANAGE_UNKNOWN_APP_SOURCES Intent) - didn't help.
  3. create a symlink to the file, so that it will be inside the /data/local/tmp/, using official API:

     Os.symlink(fullPathToApkFile, symLinkFilePath)
    

    This didn't do anything.

  4. create a symlink using this :

     ln -sf $fullPathToApkFile $symLinkFilePath
    

    This partially worked. The file is there, as I can see it in Total Commander app, but when I try to check if it exists there, and when I try to install the APK from there, it fails.

  5. Copy/move (using cp or mv) the file to the /data/local/tmp/ path, and then install from there. This worked, but it has disadvantages: moving is risky because it temporarily hides the original file, and it changes the timestamp of the original file. Copying is bad because of using extra space just for installing (even temporarily) and because it wastes time in doing so.

  6. Copy the APK file, telling it to avoid actual copy (meaning hard link), using this command (taken from here) :

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

    This didn't work. It got me this error:

     cp: /data/local/tmp/test.apk: Cross-device link
    

  7. Checking what happens in other cases of installing apps. When you install via via the IDE, it actually does create the APK file in this special path, but if you install via the Play Store, simple APK install (via Intent) or adb (via PC), it doesn't.

  8. Wrote about this here too: https://issuetracker.google.com/issues/80270303

The questions

  1. Is there any way to overcome the disadvantages of installing the APK using root on this special path? Maybe even avoid handling this path at all?

  2. Why does the OS suddenly require to use this path? Why not use the original path instead, just like in the other methods of installing apps? What do the other methods of installing apps do, that somehow avoids using the spacial path?

解决方案

One solution, in case you don't mind the moving procedure, is to also save&restore the timestamp of the original file, as such:

    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()

It's still a bit dangerous, but better than copying files...


EDIT: Google has shown me a nice workaround for this (here) :

We don't support installation of APKs from random directories on the device. They either need to be installed directly from the host using 'adb install' or you have to stream the contents to install --

$ cat foo.apk | pm install -S APK_SIZE

While I think this is incorrect that they don't support installing of APK files from random paths (always worked before), the workaround does seem to work. All I needed to change in the code of installing an APK file is as such:

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

Thing is, now I have some other questions about it :

  1. Does this workaround avoid the moving/copying of the APK into storage, and without affecting the original file ? - seems it does
  2. Will this support any APK file, even large ones? - seems it succeeds in doing it for an APK that takes 433MB, so I think it's safe to use for all sizes.
  3. This is needed only from Android P, right? - so far seems so.
  4. Why does it need the file size as a parameter ? - No idea, but if I remove it, it won't work

这篇关于使用root安装APK,处理“/data/local/tmp/"的新限制;文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆