pubspec.yaml中增加so资源
flutter:
assets:
- p7zip/CPP/ANDROID/7zr/libs/arm64-v8a/lib7zr.so
- p7zip/CPP/ANDROID/7zr/libs/armeabi-v7a/lib7zr.so
新建p7zip.dart,由于压缩解压缩是阻塞式,所以我们要把指令执行任务放在isolate中
// 传入需要压缩的文件列表,以及压缩文件的路径
Future compress(List files, {String path}) async {
// 获取共享库路径
final soPath = await _checkSharedLibrary();
if (soPath == null) {
return null;
}
...
// 文件列表转化为字符串
String filesStr = "";
files.forEach((element) {
filesStr += " $element";
});
// 执行isolate任务
final receivePort = ReceivePort();
await Isolate.spawn(_shell, [ receivePort.sendPort, soPath, "7zr a $path $filesStr" ]);
// 等待任务完成,得到执行结果,0表示执行成功
final result = await receivePort.first;
print("[p7zip] compress: after first result = $result");
return result == 0 ? path : null;
}
isolate任务,调用p7zipShell函数
// dart <=> native函数原型定义
typedef _NativeP7zipShell = Int32 Function(Pointer);
typedef _DartP7zipShell = int Function(Pointer);
void _shell(List argv) {
// 传递进来的参数列表转化
final SendPort sendPort = argv[0];
final String soPath = argv[1];
final String cmd = argv[2];
// 打开动态链接库
final p7zip = DynamicLibrary.open(soPath);
if (p7zip == null) {
return null;
}
// 得到native中的p7zipShell函数
final _DartP7zipShell p7zipShell = p7zip.lookup>("p7zipShell")
.asFunction();
if (p7zipShell == null) {
return null;
}
// 把dart的String转化为c++中的char *
final cstr = _toNativeStr(cmd);
final result = p7zipShell.call(cstr);
// 通知主线程任务执行结果
sendPort.send(result);
}
核心的_checkSharedLibrary把动态链接库从assets中取出来,拷贝到cache目录下。
Future _checkSharedLibrary() async {
// 把so放在临时路径中
final dir = await getTemporaryDirectory();
if (dir == null) {
return null;
}
final libFile = File(dir.path + "/lib7zr.so");
final exist = await libFile.exists();
if (exist) {
return libFile.path;
}
// 获取系统
if (Platform.isAndroid) {
// 获取abi
final devicePlugin = DeviceInfoPlugin();
final deviceInfo = await devicePlugin.androidInfo;
if (deviceInfo == null) {
return null;
}
// 这里的soResource就是前面p7zip编译生成的库路径
String soResource = "p7zip/CPP/ANDROID/7zr/libs/armeabi-v7a/lib7zr.so";
final support64 = deviceInfo.supported64BitAbis;
if (support64 != null && support64.length > 0) {
soResource = "p7zip/CPP/ANDROID/7zr/libs/arm64-v8a/lib7zr.so";
}
// 从rootBundle加载出assets资源
final data = await rootBundle.load(soResource);
if (data == null) {
return null;
}
// 创建文件
final createFile = await libFile.create();
if (createFile == null) {
return null;
}
// 文件以写方式打开
final writeFile = await createFile.open(mode: FileMode.write);
if (writeFile == null) {
return null;
}
// 拷贝数据
await writeFile.writeFrom(Uint8List.view(data.buffer));
return libFile.path;
} else {
// ios平台的是用dylib
...
}
}
最后,在其他dart文件中使用
final path = await p7zip.compress(files, path: "/sdcard/Download/test.7z");
至于解压缩的的dart部分和compress是极为相似的,大家可自行编写。