and*_*per 11 android root apk android-9.0-pie
到目前为止,我能够通过以下代码使用 root(在应用程序内)安装 APK 文件:
pm install -t -f fullPathToApkFile
Run Code Online (Sandbox Code Playgroud)
如果我想(尝试)安装到 SD 卡:
pm install -t -s fullPathToApkFile
Run Code Online (Sandbox Code Playgroud)
最近,不确定来自哪个 Android 版本(至少在 Android P beta 上存在问题),上述方法失败,向我显示此消息:
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)
Run Code Online (Sandbox Code Playgroud)
这似乎也影响了流行的应用程序,例如“钛备份(专业版)”,它无法恢复应用程序。
查看所写的内容,它似乎缺乏安装不在 .apk 中的 APK 文件的权限/data/local/tmp/。
所以我尝试了接下来的事情,看看我是否能克服它:
chmod 777)的访问权限- 没有帮助。/data/local/tmp/使用官方 API创建文件的符号链接,使其位于 中:
Os.symlink(fullPathToApkFile, symLinkFilePath)
Run Code Online (Sandbox Code Playgroud)
这没有任何作用。
使用此创建符号链接:
ln -sf $fullPathToApkFile $symLinkFilePath
Run Code Online (Sandbox Code Playgroud)
这部分奏效。该文件在那里,正如我在 Total Commander 应用程序中看到的那样,但是当我尝试检查它是否存在时,以及当我尝试从那里安装 APK 时,它失败了。
将文件复制/移动(使用cp或mv)到/data/local/tmp/路径,然后从那里安装。这有效,但它有缺点:移动有风险,因为它会暂时隐藏原始文件,并且会更改原始文件的时间戳。复制是不好的,因为使用额外的空间只是为了安装(即使是临时的),并且因为这样做会浪费时间。
使用以下命令(取自此处)复制 APK 文件,告诉它避免实际复制(即硬链接):
cp -p -r -l $fullPathToApkFile $tempFileParentPath"
Run Code Online (Sandbox Code Playgroud)
这没有用。它给了我这个错误:
cp: /data/local/tmp/test.apk: Cross-device link
Run Code Online (Sandbox Code Playgroud)检查在安装应用程序的其他情况下会发生什么。当您通过 IDE 安装时,它实际上会在此特殊路径中创建 APK 文件,但如果您通过 Play Store、简单 APK 安装(通过 Intent)或 adb(通过 PC)安装,则不会。
有没有办法克服在这个特殊路径上使用root安装APK的缺点?甚至可能完全避免处理这条路径?
为什么操作系统突然要求使用这条路径?为什么不使用原始路径,就像安装应用程序的其他方法一样?安装应用程序的其他方法有什么作用,以某种方式避免使用空间路径?
如果您不介意移动过程,一种解决方案是同时保存和恢复原始文件的时间戳,如下所示:
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()
Run Code Online (Sandbox Code Playgroud)
它仍然有点危险,但比复制文件好......
编辑:谷歌已经向我展示了一个很好的解决方法(这里):
我们不支持从设备上的随机目录安装 APK。它们要么需要使用“adb install”直接从主机安装,要么您必须流式传输内容才能安装——
$ cat foo.apk | pm install -S APK_SIZE
Run Code Online (Sandbox Code Playgroud)
虽然我认为这是不正确的,他们不支持从随机路径安装 APK 文件(以前一直有效),但解决方法似乎确实有效。我需要更改安装 APK 文件的代码如下:
val length = File(fullPathToApkFile ).length()
commands.add("cat $fullPathToApkFile | pm install -S $length")
Run Code Online (Sandbox Code Playgroud)
问题是,现在我还有其他一些问题: