Flutter中如何在Android/obb目录创建文件夹并复制文件?
Flutter中如何在Android/obb目录创建文件夹并复制文件?
我完全懂你现在的困惑——明明已经拿到了MANAGE_EXTERNAL_STORAGE权限,却还是没法在Android/obb目录下创建文件夹,而第三方应用商店却能轻松搞定APP+OBB的安装,这确实让人摸不着头脑。下面我分两种场景给你拆解解决方案:
场景1:操作自身应用的OBB目录
这是最常规的需求,Android系统本身就给应用提供了合法访问自身OBB目录的API,根本不需要依赖MANAGE_EXTERNAL_STORAGE这种宽泛的权限。你可以通过Flutter的MethodChannel调用Android原生代码来实现:
Flutter端代码
import 'package:flutter/services.dart'; class ObbManager { static const MethodChannel _channel = MethodChannel('obb_manager'); // 创建自身应用的OBB子目录 static Future<bool> createObbFolder(String folderName) async { try { return await _channel.invokeMethod('createObbFolder', {'folderName': folderName}); } on PlatformException catch (e) { print('创建目录失败:${e.message}'); return false; } } // 复制文件到OBB目录 static Future<bool> copyFileToObb(String sourcePath, String destFileName) async { try { return await _channel.invokeMethod('copyFileToObb', { 'sourcePath': sourcePath, 'destFileName': destFileName, }); } on PlatformException catch (e) { print('复制文件失败:${e.message}'); return false; } } }
Android端Kotlin代码
在MainActivity.kt中注册MethodChannel并实现逻辑:
import android.content.Context import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.nio.channels.FileChannel class MainActivity : FlutterActivity() { private val CHANNEL = "obb_manager" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> when (call.method) { "createObbFolder" -> { val folderName = call.argument<String>("folderName") ?: "" val success = createObbFolder(folderName) result.success(success) } "copyFileToObb" -> { val sourcePath = call.argument<String>("sourcePath") ?: "" val destFileName = call.argument<String>("destFileName") ?: "" val success = copyFileToObb(sourcePath, destFileName) result.success(success) } else -> result.notImplemented() } } } // 创建自身应用的OBB子目录 private fun createObbFolder(folderName: String): Boolean { // 获取自身应用的OBB根目录 val obbDir = getObbDir() ?: return false val targetFolder = File(obbDir, folderName) return if (!targetFolder.exists()) { targetFolder.mkdirs() } else { true } } // 复制文件到OBB目录 private fun copyFileToObb(sourcePath: String, destFileName: String): Boolean { val sourceFile = File(sourcePath) if (!sourceFile.exists()) return false val obbDir = getObbDir() ?: return false val destFile = File(obbDir, destFileName) return try { FileInputStream(sourceFile).channel.use { sourceChannel -> FileOutputStream(destFile).channel.use { destChannel -> destChannel.transferFrom(sourceChannel, 0, sourceChannel.size()) } } true } catch (e: Exception) { e.printStackTrace() false } } }
场景2:操作其他应用的OBB目录
这就是你疑惑第三方应用商店能做到的原因——它们拥有系统级的特殊权限(比如INSTALL_PACKAGES、WRITE_MEDIA_STORAGE),或者是通过系统签名认证的,普通开发者的应用根本无法获取这些权限。
对于普通应用来说,有几个折衷的方案:
- 引导用户手动操作:提示用户打开系统文件管理器,手动将OBB文件复制到目标应用的OBB目录下(路径一般是
Android/obb/[目标应用包名]); - 使用系统文件选择器:通过Intent调用系统文件选择器,让用户选择要复制的文件,再尝试写入,但这种方式在Android 11+上依然会受到Scoped Storage的限制,不一定能成功写入其他应用的OBB目录;
- Root设备:如果用户的设备已经Root,你可以通过Root权限执行Shell命令来创建目录和复制文件,但这只适用于小众Root用户群体。
关键注意事项
- 不要依赖
MANAGE_EXTERNAL_STORAGE来操作OBB目录:这个权限主要是用于访问共享存储的其他区域,对系统预留的OBB目录的限制依然存在; - 自身应用的OBB目录是沙箱化的:其他应用无法访问你的应用的OBB目录,反之亦然,这是Android的安全机制;
- 测试时注意OBB目录的实际路径:不同设备的OBB目录可能略有差异,但
getObbDir()会自动返回正确的路径,不要硬编码路径。
备注:内容来源于stack exchange,提问作者Mojtaba Mahamed
相关产品推荐
相关产品推荐

