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

Flutter在Rooted Device复制文件遇Permission denied(errno=13)问题求助

问题

在已Root的Android设备上,使用Flutter 3.7.11、Android SDK 33.0.2开发应用,通过root_access和permission_handler包尝试将/data/file.txt复制到外部存储/storage/emulated/0/documents/file.txt时,尽管已申请并获取所有必要权限,仍报错:

OS Error: Permission denied, errno = 13

已在AndroidManifest.xml中添加对应权限,且普通存储间的复制操作正常。

引发错误的代码片段:

import 'dart:async';
import 'dart:io';
import 'package:permission_handler/permission_handler.dart';
import 'package:root_access/root_access.dart';

Future<void> copyrootfile() async {
    var status = await Permission.storage.status;
    var status2 = await Permission.accessMediaLocation.status;
    var status3 = await Permission.manageExternalStorage.status;
    if (!status.isGranted) {
      await Permission.storage.request();
    }
    if (!status2.isGranted) {
      await Permission.accessMediaLocation.request();
    }
    if (!status3.isGranted) {
      await Permission.manageExternalStorage.request();
    }
    await RootAccess.requestRootAccess;

    var rootFileText = "/data/file.txt";
    final rootFile = File(rootFileText);

    var copyTo = '/storage/emulated/0/documents/file.txt';
    if(rootFile.existsSync()){
        await rootFile.copy(copyTo);
    }
}

更新后的错误日志:

E/flutter (27371): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FileSystemException: Cannot copy file to '/storage/emulated/0/Documents/file.txt', path = '/data/file.txt' (OS Error: Permission denied, errno = 13)
E/flutter (27371): #0      _checkForErrorResponse (dart:io/common.dart:42:9)
E/flutter (27371): #1      _File.copy.<anonymous closure> (dart:io/file_impl.dart:339:7)
E/flutter (27371): <asynchronous suspension>
E/flutter (27371): #2      _MyHomePageState.copyrootfile (package:rootcopy/main.dart:90:7)
E/flutter (27371): <asynchronous suspension>
E/flutter (27371): #3      _MyHomePageState.build.<anonymous closure> (package:rootcopy/main.dart:130:17)
E/flutter (27371): <asynchronous suspension>
解决建议
  • 问题核心:Flutter原生的File.copy()是在应用自身进程权限下执行的,即便请求了Root权限,这个方法也不会自动以Root身份运行。/data属于系统级目录,普通应用进程无法直接访问,必须通过Root权限执行Shell命令才能操作。

  • 具体修复步骤:

    1. 替换File.copy()方法,改用RootAccess.executeCommand()执行系统cp命令完成复制。
    2. 修改后的代码示例:
      Future<void> copyrootfile() async {
          // 保留原有权限请求逻辑
          var status = await Permission.storage.status;
          var status2 = await Permission.accessMediaLocation.status;
          var status3 = await Permission.manageExternalStorage.status;
          if (!status.isGranted) await Permission.storage.request();
          if (!status2.isGranted) await Permission.accessMediaLocation.request();
          if (!status3.isGranted) await Permission.manageExternalStorage.request();
      
          // 确认Root权限获取成功
          bool hasRoot = await RootAccess.requestRootAccess;
          if (!hasRoot) {
              // 处理Root授权失败的情况,比如弹窗提示用户
              return;
          }
      
          final sourcePath = "/data/file.txt";
          final destPath = "/storage/emulated/0/Documents/file.txt";
      
          // 提前创建目标目录(防止目录不存在导致复制失败)
          Directory(destPath.split('/').sublist(0, -1).join('/')).createSync(recursive: true);
      
          // 执行Root级别的复制命令,部分设备需用完整路径:/system/bin/cp
          final result = await RootAccess.executeCommand("cp $sourcePath $destPath");
          // 可根据result判断命令执行是否成功,做后续处理
      }
      
    3. 额外注意点:
      • 部分设备的cp命令可能需要指定绝对路径(如/system/bin/cp),如果直接用cp失败,可尝试替换为完整路径。
      • 执行Shell命令后,可通过返回的result内容判断操作是否成功,针对性处理异常情况。

内容的提问来源于stack exchange,提问作者Ashok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:07:15