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

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

问题描述

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

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

pm install -t -f fullPathToApkFile

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

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

pm install -t -s fullPathToApkFile

问题

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

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.

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

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. 设置对文件(chmod 777)的访问权限-并没有帮助.
  2. 为我的应用授予存储和 的权限REQUEST_INSTALL_PACKAGES (使用 ACTION_MANAGE_UNKNOWN_APP_SOURCES > 意向)-没有帮助.
  3. 创建指向文件的符号链接,以便使用官方API将其放置在/data/local/tmp/中:

  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)

这没做.

使用以下命令创建符号链接:

create a symlink using this :

 ln -sf $fullPathToApkFile $symLinkFilePath

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

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.

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

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.

使用此命令(取自 这里 ):

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

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

  • 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.

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

    问题

    1. 有什么方法可以克服在此特殊路径上使用root安装APK的弊端?甚至可以根本避免处理此路径?

    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?

    为什么OS突然需要使用此路径?与其他安装应用程序的方法一样,为什么不使用原始路径呢?可以避免使用空间路径的其他安装应用程序的方法有什么用呢?

    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...

    Google向我展示了一个很好的解决方法( 此处 ):

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

    我们不支持从设备上的随机目录安装APK.它们要么需要使用"adb install"直接从主机安装,要么必须流式传输内容才能安装-

    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
    

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

    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. 此解决方法是否避免将APK移动/复制到存储中,并且不影响原始文件? -好像有
    2. 这将支持任何APK文件,甚至大文件吗? -似乎它成功完成了一个需要433MB的APK的操作,因此我认为所有尺寸的APK都可以安全使用.
    3. 仅Android P需要此功能,对吗? -到目前为止看来还是这样.
    4. 为什么它需要文件大小作为参数? -不知道,但是如果我删除它,将无法正常工作

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

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