Android开发中如何用Kotlin添加并调用二进制命令行工具
在Android应用中通过Kotlin执行命令行工具并展示结果
一、可行性说明
Android基于Linux内核,完全支持执行Unix类命令行工具。需要注意两个核心点:
- 系统自带命令(如
ls)无需额外打包,Android系统本身已经内置 - 自定义命令行二进制文件才需要手动打包到APK中
二、命令二进制文件的存放位置
系统自带命令(以ls为例)
Android系统的ls二进制文件默认位于/system/bin/ls,直接调用即可,不需要你自行添加文件到应用包中。
自定义命令行工具
如果是你自己编译的二进制文件,需要放到APK的libs/目录下对应CPU架构的子文件夹中,比如:
libs/arm64-v8a/(适配64位ARM设备)libs/x86_64/(适配64位x86设备)
打包后,Android系统会自动将这些文件部署到应用私有目录/data/data/[你的包名]/lib/下,执行时通过该路径调用即可。
三、Kotlin执行命令行的实现代码
1. 通用命令执行工具函数
通过ProcessBuilder创建进程,读取命令输出结果:
fun executeCommand(command: String): List<String> { val output = mutableListOf<String>() try { // 拆分命令与参数,比如处理"ls -l /sdcard"这类带参数的命令 val cmdArray = command.split(" ").toTypedArray() val process = ProcessBuilder(cmdArray) .redirectErrorStream(true) // 将错误输出合并到标准输出,方便统一处理 .start() // 读取命令输出 process.inputStream.bufferedReader().useLines { lines -> lines.forEach { line -> output.add(line) } } process.waitFor() // 等待命令执行完成 } catch (e: Exception) { e.printStackTrace() output.add("执行失败: ${e.message ?: "未知错误"}") } return output }
2. 调用ls命令的示例
比如获取外部存储根目录的文件列表:
val fileList = executeCommand("ls /sdcard")
注意:访问外部存储需要申请权限——Android 13+需申请
READ_MEDIA_IMAGES等细分权限,Android 10-12需申请READ_EXTERNAL_STORAGE权限,必须完成动态权限申请后才能正常访问。
四、将结果展示到RecyclerView
1. 定义数据类与列表项布局
// 数据类 data class FileItem(val name: String)
创建item_file.xml布局文件(仅包含一个TextView展示文件名):
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_file_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:textSize="16sp"/>
2. 实现RecyclerView Adapter
class FileListAdapter(private val fileNames: List<String>) : RecyclerView.Adapter<FileListAdapter.ViewHolder>() { inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val fileNameTv: TextView = itemView.findViewById(R.id.tv_file_name) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_file, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.fileNameTv.text = fileNames[position] } override fun getItemCount() = fileNames.size }
3. 在Activity/Fragment中绑定数据
// 初始化RecyclerView val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) // 子线程执行命令,避免阻塞UI lifecycleScope.launch(Dispatchers.IO) { val fileList = executeCommand("ls /sdcard") // 切回主线程更新UI withContext(Dispatchers.Main) { recyclerView.adapter = FileListAdapter(fileList) } }
五、关键注意事项
- 权限限制:访问系统目录(如
/system/)通常需要root权限,普通应用不建议追求root,优先访问应用私有目录或外部存储的可访问区域 - 线程安全:命令执行属于耗时操作,必须在子线程中执行,更新UI时切回主线程
- 兼容性:不同Android版本的系统命令路径可能略有差异,优先依赖系统自带命令,减少自定义二进制的架构兼容问题
内容的提问来源于stack exchange,提问作者Ethan0456
相关产品推荐
相关产品推荐

