如何在Flutter Android应用中免Root运行Unix Shell程序?
解决Flutter应用运行Unix可执行文件的Permission Denied问题(无需Root)
核心原因
Android应用私有目录下的文件默认没有执行权限,即便成功将可执行文件从Asset写入目录,系统也不允许直接运行;此外,可执行文件的CPU架构与设备不匹配,也会触发类似权限错误的提示。
解决方案
1. 为提取的文件添加执行权限
这是解决问题的关键步骤:在将Asset中的可执行文件写入磁盘后,必须通过chmod命令赋予其执行权限。修改你的代码如下:
Future<void> extractCliFromAsset() async { var content = await rootBundle.load("assets/cli-test"); await file.writeAsBytes(content.buffer.asUint8List(), mode: FileMode.writeOnly); // 赋予文件可执行权限 await Process.run('chmod', ['+x', file.path]); }
如果文件已存在,建议在运行前再次确认权限:
if (!file.existsSync()) { await extractCliFromAsset(); } else { await Process.run('chmod', ['+x', file.path]); }
2. 确认可执行文件的架构匹配
确保你打包到Asset中的cli-test是针对目标设备CPU架构编译的:
- 主流Android架构:
arm64-v8a(64位设备)、armeabi-v7a(32位旧设备)、x86/x86_64(模拟器) - 若架构不匹配,即便权限设置正确,也会出现无法执行的错误(表现可能类似Permission Denied)
- 可编译包含多架构的Fat Binary,或根据设备架构动态选择对应版本的可执行文件
3. 无需额外存储权限
你使用的getApplicationDocumentsDirectory()是应用的私有目录,Android系统默认允许应用在此目录下读写、执行文件,无需申请外部存储权限——之前尝试的外部存储方案反而可能引入更多权限问题,建议保留私有目录方案。
修改后的完整代码
import 'dart:io'; import 'package:flutter/services.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; // 你的函数内代码 Directory directory_app = await getApplicationDocumentsDirectory(); File file = File(path.join(directory_app.path, "cli-test")); Future<void> extractCliFromAsset() async { var content = await rootBundle.load("assets/cli-test"); await file.writeAsBytes(content.buffer.asUint8List(), mode: FileMode.writeOnly); // 添加执行权限 await Process.run('chmod', ['+x', file.path]); } if (!file.existsSync()) { await extractCliFromAsset(); } else { // 确保文件保持可执行权限 await Process.run('chmod', ['+x', file.path]); } Process shell = await Process.start( file.path, ["run"], workingDirectory: directory_app.path, runInShell: false, ); shell.stderr.listen((event) { stderr.add(event); }); shell.stdout.listen((event) { stdout.add(event); });
内容的提问来源于stack exchange,提问作者Aleta Nob Dev
相关产品推荐
相关产品推荐

