【发布时间】:2021-02-18 07:22:14
【问题描述】:
我有以下代码,用于自动更新应用程序,它像系统应用程序一样安装在有根设备上。它从已下载新 apk 文件的 copyToPrivateApps 开始。它从协程范围附加到 IO 线程
fun copyToPrivateApps(context: Context, apkPath: String?) {
sudoForCommandAndResult("mount -o rw,remount /system")
sudoForCommandAndResult("mkdir $systemFolder")
sudoForCommandAndResult("cat $apkPath > $systemApkPath")
sudoForCommandAndResult("cp -R ${sudoForResult("find ./data/app -name ${context.packageName}*").drop(1) + "/lib"} $systemFolder")
sudoForCommandAndResult("chmod -R 755 $systemFolder")
sudoForCommandAndResult("chmod 644 $systemFngFolder")
sudoForCommandAndResult("chmod 644 $systemSilFolder")
sudoForCommandAndResult("chmod 644 $systemApkPath")
sudoForCommandAndResult("mount -o ro,remount /system")}
fun sudoForCommandAndResult(string: String): String {
var res = ""
var outputStream: DataOutputStream? = null
var response : InputStream? = null
var error : InputStream? = null
try {
val su = Runtime.getRuntime().exec("su")
outputStream = DataOutputStream(su.outputStream)
response = su.inputStream
error = su.errorStream
outputStream.writeBytes(string + "\n")
outputStream.flush()
outputStream.writeBytes("exit\n")
outputStream.flush()
try {
su.waitFor()
} catch (e: Throwable) {
e.printStackTrace()
}
val responseString = readFully(response!!).replace("su:main", "").trim()
val errorString = readFully(error!!).replace("su:main", "").trim()
res = logTimeFormat.format(Date()) + string + if(responseString.isNotBlank()) "\n" + logTimeFormat.format(Date()) + responseString else ""
res += if(errorString.isNotBlank()) "\n" + logTimeFormat.format(Date()) + errorString else ""
} catch (e: Throwable) {
res += logTimeFormat.format(Date()) + e.message?.trim()
e.printStackTrace()
} finally {
Closer.closeSilently(outputStream, response)
}
return res}
fun sudoForResult(string: String): String {
var res = ""
var outputStream: DataOutputStream? = null
var response : InputStream? = null
var error : InputStream? = null
try {
val su = Runtime.getRuntime().exec("su")
outputStream = DataOutputStream(su.outputStream)
response = su.inputStream
error = su.errorStream
outputStream.writeBytes(string + "\n")
outputStream.flush()
outputStream.writeBytes("exit\n")
outputStream.flush()
try {
su.waitFor()
} catch (e: Throwable) {
e.printStackTrace()
}
val responseString = readFully(response!!).replace("su:main", "").trim()
val errorString = readFully(error!!).replace("su:main", "").trim()
res = listOf(responseString, errorString).joinToString(separator = " ")
} catch (e: Throwable) {
res += e.message?.trim()
e.printStackTrace()
} finally {
Closer.closeSilently(outputStream, response)
}
return res.trim()}
尝试执行“cp”命令时,在 val su = Runtime.getRuntime().exec("su") 内 sudoForResult() 失败 出现以下错误: A/libc:致命信号 4 (SIGILL),代码 1,tid 6974 中的故障地址 0x7f6190fa24 (DefaultDispatch)
还有一些奇怪的警告
W/art: 失败的 execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime- arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m -j3 --instruction-set-variant=generic --instruction-set-features=默认 --dex-file=/system/priv-app/appName/appName.apk --oat-file=/data/dalvik-cache/arm64/system@priv-app@appName@appName.apk@classes.dex)因为非0退出状态
有时它甚至更早在“cat”命令上崩溃并出现类似错误
编辑:这在以前使用较小的更新 apk 文件时有效,现在它几乎大了 3 倍。
【问题讨论】: