- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用 root,我知道对于单个 APK 文件,我们可以使用“libsu”库( here )进行安装:
val installResult = Shell.su("pm install -t \"$filePath\"").exec()
如果失败(在新的 Android 版本上失败,不确定是哪个版本),如下(关于此 here ):
val installResult = Shell.su("cat \"$filePath\" | pm install -t -S ${apkSource.fileSize}").exec()
我还知道,在安装拆分 APK 文件时,事情会变得非常困惑(如 here 所示)。首先,您需要使用“pm install-create”命令创建一个 session :
var sessionId: Int? = null
run {
val sessionIdResult =
Shell.su("pm install-create -r -t").exec().out
val sessionIdPattern = Pattern.compile("(\\d+)")
val sessionIdMatcher = sessionIdPattern.matcher(sessionIdResult[0])
sessionIdMatcher.find()
sessionId = Integer.parseInt(sessionIdMatcher.group(1)!!)
Log.d("AppLog", "sessionId:$sessionId")
}
然后您必须“推送”每个 APK 文件,如下所示:
for (apkSource in fileInfoList) {
val filePath = File(apkSource.parentFilePath, apkSource.fileName).absolutePath
Log.d("AppLog", "installing APK : $filePath ${apkSource.fileSize} ")
val result = Shell.su("pm install-write -S ${apkSource.fileSize} $sessionId \"${apkSource.fileName}\" \"$filePath\"").exec()
Log.d("AppLog", "success pushing apk:${apkSource.fileName} ? ${result.isSuccess}")
}
然后使用 pm install-commit
提交更改:
val installResult = Shell.su("pm install-commit $sessionId").exec()
有关这一切的文档:
install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]
[-p INHERIT_PACKAGE] [--install-location 0/1/2]
[--install-reason 0/1/2/3/4] [--originating-uri URI]
[--referrer URI] [--abi ABI_NAME] [--force-sdk]
[--preload] [--instantapp] [--full] [--dont-kill]
[--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]
[--multi-package] [--staged]
Like "install", but starts an install session. Use "install-write"
to push data into the session, and "install-commit" to finish.
install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]
Write an apk into the given install session. If the path is '-', data
will be read from stdin. Options are:
-S: size in bytes of package, required for stdin
install-commit SESSION_ID
Commit the given active install session, installing the app.
这一切在 Android P 之前都工作得很好,但由于某种原因,它在 Q beta 6 上失败了,向我显示了这个错误:
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/split/base.apk, context u:r:system_server:s0)
Error: Unable to open file: /storage/emulated/0/Download/split/base.apk
Consider using a file under /data/local/tmp/
这与我发现的单个 APK here 的情况类似。 ,所以我想也许类似的解决方案也可以应用在这里:
val result = Shell.su("cat $filePath | pm install-write -S ${apkSource.fileSize} $sessionId \"${apkSource.fileName}\" \"$filePath\"").exec()
这仍然仅适用于 Android P 及更低版本。
因此,看到我查看的原始代码有效,它使用了 InputStream,正如文档所暗示的那样,这是可能的。这是他们拥有的:
while (apkSource.nextApk())
ensureCommandSucceeded(Root.exec(String.format("pm install-write -S %d %d \"%s\"", apkSource.getApkLength(), sessionId, apkSource.getApkName()), apkSource.openApkInputStream()));
所以我尝试的是这样的:
val result = Shell.su("pm install-write -S ${apkSource.fileSize} $sessionId \"${apkSource.fileName}\" -")
.add(SuFileInputStream(filePath)).exec()
遗憾的是这也不起作用。
我知道我可以复制相同的代码,但是仍然有办法使用该库(因为它会更短、更优雅)?如果是这样,我该怎么做?
最佳答案
这很困惑,但是试试这个代码。它使用 SuFileInputStream 读取 apk 文件内容,然后将其传输到 install-write 命令中。理论上这应该可以解决问题。
// getting session id
val createSessionResult = Shell.su("pm install-create -S $size").
val sessionIdRegex = "\\[([0-9]+)]".toRegex()
var sessionId: Int? = null
for (line in createSessionResult.out) {
val result = sessionIdRegex.find(line)?.groupValues?.get(1)?.toInt()
if (result != null) {
sessionId = result
break
}
}
// writing apks, you might want to extract this to another function
val writeShellInStream = PipedInputStream()
PipedOutputStream(writeShellInStream).use { writeShellInOutputStream ->
PrintWriter(writeShellInOutputStream).use { writeShellInWriter ->
writeShellInWriter.println("pm install-write -S $size $sessionId base") // eventually replace base with split apk name
writeShellInWriter.flush()
Shell.su(writeShellInStream).submit { writeResult ->
if (writeResult.isSuccess) {
Shell.su("pm install-commit $sessionId").submit { commitResult ->
// commitResult.isSuccess to check if worked
}
}
}
apkInputStream.copyTo(writeShellInOutputStream)
writeShellInWriter.println()
}
}
编辑:如果您不需要安装,您可能需要先尝试命令“cat [您的 apk 文件] | pm install-write -S [大小] [sessionId] [基本/拆分 apk 名称]”溪流。如果 cat 不起作用,请尝试“dd if=[apk file]”。
关于android - 如何使用 "libsu"库(或 adb)在 Android Q 上安装拆分 APK 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57468292/
使用 http://developer.android.com/training/basics/firstapp/running-app.html 上的指南,我使用 adb 将示例 Hello, Wo
如何修复 - 无法创建调试桥:无法启动 adb 服务器:无法检测 adb 版本,adb 输出:/home/dilip/Downloads/sdk/platform-tools/adb: 1:/home
我在 UBUNTU 18.x 操作系统上练习 REACT NATIVE,一切运行顺利,昨天我更新了我的 React native、react 和 android gradle 版本然后我收到一些错误,
这个问题在这里已经有了答案: android studio adb Syntax error: ")" unexpected (4 个答案) 关闭 5 年前。 我确实将我的工作室更新到 Linux
这是我的步骤: adb connect 'my android IP address' connected adb reboot //in this step my phone is rebootin
我有一个应用程序可以监听接收通知。安装后,我应该从设置 -> 安全 -> 通知访问启用通知访问 我在模拟器上安装这个应用程序并使用 ADB 运行它。但我不知道如何使用 ADB 中的命令行为其启用通知访
ADB全称Android Debug Bridge, 是android sdk里的一个工具, 用这个工具可以直接操作管理android模拟器或者真实的andriod设备(如G1手机). 它的主要功能
我知道这个问题被问了多次,也有一些替代答案。所以请不要关闭其他链接,因为我在下面添加了该链接。 [2014-01-23 16:19:44 - adb] ADB server didn't ACK [2
我在 adb 中观察到了这种新行为v1.0.39。命令: adb shell getevent -l 给出以下输出: 观察到最后一行是不完整的。这发生在许多不同的设备上。相同的命令在 adb 中无需缓
我正在尝试通过 adb shell am 和 adb shell service call 发送短信。我都收到错误消息。 a) 我正在尝试按照 adb shell am 命令发送短信 adb shel
由于某些原因,我的手机无法使用电缆。 我在 Internet 上看到可以通过 Wifi 将 adb 连接到 Wifi,但是我试了一下,结果是这样的: adb devices List of devic
尝试通过 expo 在模拟器上运行 react-native 应用程序时出现此错误。 Couldn't start project on Android: Error running adb: adb
这个问题在这里已经有了答案: adb server version doesn't match this client (41 个回答) 关闭4年前。 在启动 genymotion 模拟器后尝试从终
adb server version (39) doesn't match this client (40); killing... could not read ok from ADB Server
我已经创建了一个虚拟 Android 模拟器 (Nexus_5X_API25),我需要获得根访问权限。但是当我输入 adb remount 命令时,它总是告诉我 adb 没有以 root 身份运行。我
这个问题在这里已经有了答案: ADB - Android - Getting the name of the current activity (13 个答案) 关闭 4 年前。 我正在使用 adb
我只是想运行 adb shell,这样我就可以终止进程以进行测试。我在目录 platform-tools 中,adb 可执行文件就在那里。当我尝试运行 shell 时,它说找不到 adb 命令。我正在
我刚刚安装了 android studio 和平台工具,但我无法调用 adb,即使它们显然位于同一目录中。我收到此错误: zsh: command not found: adb 我是 android
以下命令用于使用 Android SDK 工具版本 24.4.1 退出模拟器。将工具版本更新到 25.1.6 后,它在 Mac 上停止工作。 adb -s emulator-5554 emu kill
我正在尝试 root 第 8 代 Kindle HD Fire (Fire OS 6.3.0.1)我已经打开了 Developer options,但是 Enable ADB 没有列在它下面。还有其他
我是一名优秀的程序员,十分优秀!