最近开发的Flutter APP iOS端需要用到一个从其他应用分享上传附件的功能,这里记录一下实现的过程
配置
要让系统分享的列表里出现我们自己的APP,首先是需要小小的配置一下。打开项目/ios/Runner/Info.plist
文件
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Text</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.text</string>
<string>public.plain-text</string>
<string>public.utf8-plain-text</string>
<string>public.utf16-external-plain-text</string>
<string>public.utf16-plain-text</string>
<string>com.apple.traditional-mac-plain-text</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>PDF</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.adobe.pdf</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Microsoft Word</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.microsoft.word.docx</string>
<string>com.microsoft.word.doc</string>
<string>com.microsoft.word.wordml</string>
<string>org.openxmlformats.wordprocessingml.document</string>
</array>
</dict>
</array>
这样的话就配置完成了。顺便解释下每个字段的意思
CFBundleDocumentTypes
:指的是可以接收文件的类型,比如图片、文档、压缩包等等
LSItemContentTypes
: 指的是具体可以接收的类型,比如txt
、jpg
、doc
、pdf
等,这个key对应的是一个Array,Array中是支持字段的类型。支持的字段类型参考这里
应用内处理
分享过来的文件会存储在沙盒文件夹Documents/Inbox
下,所以我们这边需要在AppDelegate
中重写openURL
方法。
swift
我们在项目目录ios/
下,双击Runner.xcworkspace
文件,就会在xcode中打开工程目录,我们编辑AppDelegate.swift
文件。
如下
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
// new add
// 文件沙盒路径
var lastFilePath = String.init("");
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// new add
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let yizhipinToolsChannel = FlutterMethodChannel.init(name: "zrong.life/tools", binaryMessenger: controller as! FlutterBinaryMessenger)
yizhipinToolsChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: FlutterResult) -> Void in
if (call.method == "getLastShareFilePath") {
self.getLastShareFilePath(result: result)
} else if (call.method == "clearLastShareFilePath") {
self.clearLastShareFilePath(result: result)
}
})
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// new add
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if url.scheme == "file" {
let path = url.absoluteString
lastFilePath = path
return true
}
return super.application(app, open: url, options: options)
}
// new add
private func getLastShareFilePath(result: FlutterResult) {
result(lastFilePath)
}
// new add
private func clearLastShareFilePath(result: FlutterResult) {
lastFilePath = ""
result(true)
}
}
在上面,我们重写了openURL
的方法,并且创建了一个FlutterMethodChannel
,并且创建了两个方法getLastShareFilePath
、clearLastShareFilePath
。这两个方法的作用是:获取最后分享文件的路径,清除最后分享文件的路径。
Flutter处理
在上面我们实现了FlutterMethodChannel
。这样还不够,我们需要在flutter中来建一个通道来调用。
我们新建一个文件tools.dart
import 'package:flutter/services.dart';
class Tools {
static const MethodChannel _channel = MethodChannel('yzp.cn/tools');
Future<String> get lastShareFilePath async {
String path = await _channel.invokeMethod('getLastShareFilePath');
return path;
}
Future<bool> get clearLastShareFilePath async {
bool status = await _channel.invokeMethod('clearLastShareFilePath');
return status;
}
}
然后,我们就能在项目中使用这个方法了
main.dart
中
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
// 当APP打开时我们去获取分享文件的链接
getLastShareFilePath();
}
}
getLastShareFilePath () async {
String path = await Tools().getLastShareFilePath;
print(path);
// 这里记得将最后一次分享的文件链接清空
await Tools().clearLastShareFilePath;
}
}
这样的话,我们就可以实现在ios系统分享中加上自己的应用啦。并且可以在Flutter中操作这样文件啦
结尾
如果在使用途中遇到什么问题或者BUG,请在下方留言反馈