Flutter分享处理插件zikzak_share_handler的使用
Flutter分享处理插件zikzak_share_handler的使用
zikzak_share_handler
是一个用于Flutter的插件,支持iOS和Android平台,能够处理接收到的共享文本/媒体,并允许将共享内容添加到建议/快捷方式中。本文将详细介绍如何安装和配置该插件,并提供一个完整的示例Demo。
1. 安装
首先,在 pubspec.yaml
文件中添加 zikzak_share_handler
作为依赖:
dependencies:
zikzak_share_handler: ^latest_version
2. iOS配置
2.1 修改 Info.plist
在 <project root>/ios/Runner/Info.plist
文件中添加以下内容,以注册应用通过深度链接启动,并请求访问照片库的权限:
<!-- Add for zikzak_share_handler start -->
<!-- 如果你计划使用 recordSentMessage API,使对话显示为直接分享建议,则需要以下键 -->
<key>NSUserActivityTypes</key>
<array>
<string>INSendMessageIntent</string>
</array>
<!-- 如果你想使用自定义组ID而不是默认值,请取消注释以下行,并在Build Settings -> User-Defined中设置 -->
<!-- <key>AppGroupId</key>
<string>$(CUSTOM_GROUP_ID)</string> -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<key>NSPhotoLibraryUsageDescription</key>
<string>照片可以被分享并在此应用中使用</string>
<!-- 可选:添加或自定义以支持AirDrop -->
<key>LSSupportsOpeningDocumentsInPlace</key>
<string>No</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>ShareHandler</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.file-url</string>
<string>public.image</string>
<string>public.text</string>
<string>public.movie</string>
<string>public.url</string>
<string>public.data</string>
</array>
</dict>
</array>
<!-- Add for zikzak_share_handler end -->
2.2 创建Share Extension
- 在Xcode中,选择
File -> New -> Target
,然后选择 “Share Extension”。 - 将其命名为
ShareExtension
并保存。
2.3 修改 ShareExtension/Info.plist
编辑 <project root>/ios/ShareExtension/Info.plist
文件,添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- 如果你想使用自定义组ID而不是默认值,请取消注释以下行,并在Build Settings -> User-Defined中设置 -->
<!-- <key>AppGroupId</key>
<string>$(CUSTOM_GROUP_ID)</string> -->
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<!-- 如果你支持分享到特定对话,请添加支持的消息意图 -->
<key>IntentsSupported</key>
<array>
<string>INSendMessageIntent</string>
</array>
<!-- 删除仅在开发模式下工作的 TRUEPREDICATE NSExtensionActivationRule -->
<!-- <string>TRUEPREDICATE</string> -->
<!-- 添加新的 NSExtensionActivationRule,允许分享一个或多个任意类型的文件、URL 或文本内容 -->
<string>SUBQUERY (
extensionItems,
$extensionItem,
SUBQUERY (
$extensionItem.attachments,
$attachment,
(
ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.file-url"
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.image"
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.text"
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.movie"
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.url"
)
).@count > 0
).@count > 0
</string>
<key>PHSupportedMediaTypes</key>
<array>
<string>Video</string>
<string>Image</string>
</array>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
</dict>
</plist>
2.4 添加App Group
- 在Xcode中,选择
Runner -> Targets -> Runner -> Signing & Capabilities
。 - 点击
+
按钮并选择App Groups
。 - 添加一个新的组(默认是你的bundle identifier前缀为
group.
,例如group.wtf.zikzak
)。 - 对
ShareExtension
目标重复上述步骤,选择相同的组ID。
2.5 (可选) 自定义组ID
如果你使用了自定义组ID而不是默认的 group.<bundle_identifier>
,请确保在 ShareExtension
的 info.plist
文件中引用自定义构建设置变量:
- 进入
Targets -> ShareExtension -> Build Settings
。 - 点击
+
图标并选择Add User-Defined Setting
。 - 给它设置键
CUSTOM_GROUP_ID
,值为你给两个目标的组ID。 - 对
Runner
目标重复上述步骤。
2.6 修改 Podfile
在 <project root>/ios/Podfile
文件中,在 target 'Runner' do
块内添加以下代码,然后运行 pod install
:
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
# zikzak_share_handler addition start
target 'ShareExtension' do
inherit! :search_paths
pod "zikzak_share_handler_ios_models", :path => ".symlinks/plugins/zikzak_share_handler_ios/ios/Models"
end
# zikzak_share_handler addition end
end
2.7 替换 ShareViewController.swift
将 <project root>/ios/ShareExtension/ShareViewController.swift
文件的内容替换为以下代码:
import zikzak_share_handler_ios_models
class ShareViewController: ShareHandlerIosViewController {}
2.8 Xcode 16 和 iOS 故障排除
-
将Share Extension转换为Group:
-
将Thin Library移动到构建阶段的底部:
-
更新
ios/Runner/Release.xcconfig
文件:
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"
#include "Generated.xcconfig"
- 更新
ios/Runner/Debug.xcconfig
文件:
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"
#include "Generated.xcconfig"
-
如果遇到警告:
更新
ShareExtension
的构建设置CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER
为$(inherited)
,并将其值设置为No
。
3. Android配置
3.1 修改 AndroidManifest.xml
编辑 <project root>/android/app/src/main/AndroidManifest.xml
文件,添加或取消注释你想要支持的 intent 过滤器和元数据:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:name="io.flutter.app.FlutterApplication"
...>
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- 如果你想处理共享文本,请添加此过滤器 -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>
<!-- 如果你想处理共享图片,请添加此过滤器 -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<!-- 如果你想处理共享视频,请添加此过滤器 -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
</intent-filter>
<!-- 如果你想处理任何类型的文件,请添加此过滤器 -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<!-- (可选) 如果你想支持分享到特定目标/对话/快捷方式,请添加这些元数据标签 -->
<meta-data
android:name="android.service.chooser.chooser_target_service"
android:value="androidx.sharetarget.ChooserTargetServiceCompat" />
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/share_targets" />
</activity>
</application>
</manifest>
3.2 (可选) 防止每次共享时打开新Activity
如果你想防止每次共享时打开新的Activity,可以在 MainActivity
的 intent 中添加 android:launchMode="singleTask"
属性。
3.3 (可选) 添加共享建议/快捷方式支持
创建文件 <project root>/android/app/src/main/res/xml/share_targets.xml
,并添加以下内容,将 {your.package.identifier}
替换为你的包标识符(例如 wtf.zikzak.zikzak_share_handler_android_example
):
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<share-target android:targetClass="{your.package.identifier}.MainActivity">
<data android:mimeType="*/*" />
<category android:name="{your.package.identifier}.dynamic_share_target" />
</share-target>
</shortcuts>
4. 示例代码
以下是一个完整的示例代码,展示了如何使用 zikzak_share_handler
插件来处理共享内容:
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:zikzak_share_handler/zikzak_share_handler.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
[@override](/user/override)
void initState() {
super.initState();
initPlatformState();
}
SharedMedia? media;
// 平台消息是异步的,因此我们在异步方法中初始化
Future<void> initPlatformState() async {
final handler = ShareHandler.instance;
media = await handler.getInitialSharedMedia();
handler.sharedMediaStream.listen((SharedMedia sharedMedia) {
if (!mounted) return;
setState(() {
this.media = sharedMedia;
});
});
if (!mounted) return;
setState(() {
// _platformVersion = platformVersion;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Share Handler'),
),
body: Center(
child: ListView(
children: <Widget>[
Text("共享到对话标识符: ${media?.conversationIdentifier}"),
const SizedBox(height: 10),
Text("共享文本: ${media?.content}"),
const SizedBox(height: 10),
Text("共享文件数量: ${media?.attachments?.length}"),
...(media?.attachments ?? []).map((attachment) {
final path = attachment?.path;
if (path != null && attachment?.type == SharedAttachmentType.image) {
return Column(
children: [
ElevatedButton(
onPressed: () {
ShareHandlerPlatform.instance.recordSentMessage(
conversationIdentifier: "custom-conversation-identifier",
conversationName: "John Doe",
conversationImageFilePath: path,
serviceName: "custom-service-name",
);
},
child: const Text("记录消息"),
),
const SizedBox(height: 10),
Image.file(File(path)),
],
);
} else {
return Text("${attachment?.type} 附件: ${attachment?.path}");
}
}).toList(),
],
),
),
),
);
}
}
更多关于Flutter分享处理插件zikzak_share_handler的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter分享处理插件zikzak_share_handler的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 zikzak_share_handler
Flutter 插件的代码示例。zikzak_share_handler
是一个用于处理应用内分享功能的 Flutter 插件,它能够监听并处理来自其他应用的分享意图。
首先,确保你已经在 pubspec.yaml
文件中添加了 zikzak_share_handler
依赖:
dependencies:
flutter:
sdk: flutter
zikzak_share_handler: ^最新版本号 # 请替换为实际最新版本号
然后运行 flutter pub get
来获取依赖。
接下来,在你的 Flutter 应用中实现分享处理功能。以下是一个简单的示例,展示如何设置和使用 zikzak_share_handler
。
主文件 main.dart
import 'package:flutter/material.dart';
import 'package:zikzak_share_handler/zikzak_share_handler.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Share Handler Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ShareHandlerScreen(),
);
}
}
class ShareHandlerScreen extends StatefulWidget {
@override
_ShareHandlerScreenState createState() => _ShareHandlerScreenState();
}
class _ShareHandlerScreenState extends State<ShareHandlerScreen> {
@override
void initState() {
super.initState();
// 初始化并监听分享事件
ZikzakShareHandler.instance.initialize().then((_) {
ZikzakShareHandler.instance.onShareReceived.listen((ShareData data) {
// 处理接收到的分享数据
setState(() {
_handleShareData(data);
});
});
});
}
void _handleShareData(ShareData data) {
// 显示接收到的分享内容
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Received share: ${data.text ?? 'No text provided'}'),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Share Handler Example'),
),
body: Center(
child: Text('Waiting for share...'),
),
);
}
}
Android 配置
在 android/app/src/main/AndroidManifest.xml
文件中,确保你的应用能够接收 ACTION_SEND 意图:
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- 添加以下 intent-filter 以接收分享意图 -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
iOS 配置
对于 iOS,你需要在 Info.plist
文件中添加相应的配置以允许应用接收分享。不过,zikzak_share_handler
插件在 iOS 上的配置相对简单,通常不需要手动修改 Info.plist
,除非你有特殊需求。
运行应用
现在你可以运行你的 Flutter 应用,并从其他应用分享文本到你的应用。一旦分享成功,你的应用将显示一个 SnackBar,包含接收到的分享内容。
这个示例展示了如何使用 zikzak_share_handler
来处理应用内分享功能。根据实际需求,你可以进一步扩展和处理不同类型的分享数据(如图片、链接等)。