You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 22:40:40