根据 https://www.it1352.com/752040.html 这篇文章整理而来
Android exe native
Android10以下,可以直接把二进制文件拷贝到data/data/包名下/xxx文件,使用Runtime.getInstance().exec就可以了,但是Android10和11会报
java.io.IOException: Cannot run program "data/data/包名/xxx文件": error=13, Permission denied
猜测原因是存储分区权限改变导致的问题
我们的.so文件也是二进制文件,放在data/data/包名下/lib路径下面,有权限去运行,那我们把二进制文件放在.so文件的地方,android打包即可自动把我们的二进制文件打到该路径下,我们就可以有权限去运行二进制文件了。
我们把我们要用的二进制文件,名字改成so文件名字的格式,libxxx.so这种形式,放在app/libs/armeabi路径下。这样我们运行后,就可以发现我们的二进制文件在data/data/包名下/lib路径下面。如果不改成这种形式,系统不会把该文件打包过去,估计做判断了
我们把原文件hello的文件名字改成libhello.so
程序运行后,这个假的so文件就自动被存到这里了
后续就直接
Process process = runtime.exec(“data/data/包名/lib/libtest.so”);
就可以无Root权限执行且兼容Android低版本,也不需要拷贝二进制文件到制定目录,系统会自动把我们要运行的二进制文件放到可执行的地方。
class MainActivity : AppCompatActivity() {
private var LOCAL = "/data/data/com.example.myapplication/lib/libhello.so"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val thread = Thread {
val output = exec(LOCAL)
}
thread.start()
}
private fun exec(command: String): String? {
return try {
val process = Runtime.getRuntime().exec(command)
val reader = BufferedReader(
InputStreamReader(process.inputStream)
)
var read: Int
val buffer = CharArray(4096)
val output = StringBuffer()
while (reader.read(buffer).also { read = it } > 0) {
output.append(buffer, 0, read)
}
reader.close()
process.waitFor()
output.toString()
} catch (e: IOException) {
throw RuntimeException(e)
} catch (e: InterruptedException) {
throw RuntimeException(e)
}
}
}
app/build.gradle
sourceSets {
main{
jniLibs.srcDirs = ['libs']
}
}