Flutter接收分享意图插件receive_sharing_intent的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter接收分享意图插件receive_sharing_intent的使用

插件简介

receive_sharing_intent 是一个Flutter插件,它使得Flutter应用能够从其他应用接收到分享的照片、视频、文本、网址或任何其他文件类型。该插件还支持iOS的Share扩展,并能自动启动宿主应用。

支持平台版本

平台 版本要求
Android SDK 19+ (Kotlin 1.9.22)
iOS 12.0+ (Swift 5.0)

使用方法

添加依赖

pubspec.yaml文件中添加receive_sharing_intent作为依赖项:

dependencies:
  receive_sharing_intent: ^latest

配置Android项目

修改AndroidManifest.xml

根据需求向android/app/src/main/AndroidManifest.xml添加相应的intent-filter,例如支持分享文本到应用:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <application
        android:name="io.flutter.app.FlutterApplication"
        ...
        >
        <!--Set activity launchMode to singleTask, if you want to prevent creating new activity instance everytime there is a new intent.-->

        <activity
            android:name=".MainActivity"
            android:launchMode="singleTask"
            ...>
            
            <!--TODO: Add this filter, if you want support opening urls into your app-->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data
                    android:scheme="https"
                    android:host="example.com"
                    android:pathPrefix="/invite"/>
            </intent-filter>

            <!--TODO: Add this filter, if you want support opening files into your app-->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:mimeType="*/*"
                    android:scheme="content" />
            </intent-filter>

            <!--TODO: Add this filter, if you want to support sharing text into your app-->
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/*" />
            </intent-filter>

            <!--TODO: Add this filter, if you want to support sharing images into your app-->
            <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>

            <!--TODO: Add this filter, if you want to support sharing videos into your app-->
            <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>

            <!--TODO: Add this filter, if you want to support sharing any type of files-->
            <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>
        </activity>

    </application>
</manifest>

配置iOS项目

创建Share Extension

  • 使用Xcode创建一个新的Target选择"Share Extension"。
  • 确保Runner.app和Share Extension的部署目标相同。

替换Info.plist文件

ios/Share Extension/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>
    <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>PHSupportedMediaTypes</key>
        <array>
          <string>Video</string>
          <string>Image</string>
        </array>
        <key>NSExtensionActivationRule</key>
        <dict>
          <key>NSExtensionActivationSupportsText</key>
          <true/>
          <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
          <integer>1</integer>
          <key>NSExtensionActivationSupportsImageWithMaxCount</key>
          <integer>100</integer>
          <key>NSExtensionActivationSupportsMovieWithMaxCount</key>
          <integer>100</integer>
          <key>NSExtensionActivationSupportsFileWithMaxCount</key>
          <integer>1</integer>
        </dict>
      </dict>
      <key>NSExtensionMainStoryboard</key>
      <string>MainInterface</string>
      <key>NSExtensionPointIdentifier</key>
      <string>com.apple.share-services</string>
    </dict>
  </dict>
</plist>

修改Runner的Info.plist

ios/Runner/Info.plist添加如下配置:

...
<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>To upload photos, please allow permission to access your photo library.</string>
...

修改Runner.entitlements

ios/Runner/Runner.entitlements添加如下配置:

...
<!--TODO:  Add this tag, if you want support opening urls into your app-->
<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:example.com</string>
</array>
...

修改Podfile

ios/Podfile添加如下配置:

...
target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

  # Share Extension is name of Extension which you created which is in this case 'Share Extension'
  target 'Share Extension' do
    inherit! :search_paths
  end
end
...

其他设置

  • Signing & Capabilities选项卡中,为两个目标(Runner和Share Extension)添加App Groups能力,并创建新的容器如group.MyContainer
  • 添加自定义构建设置CUSTOM_GROUP_ID,并设置为上述创建的组ID。
  • Embed Foundation Extension移动到Build Phases中的Thin Binary顶部。
  • 修改ShareViewController.swift继承自RSIShareViewController

完整示例代码

import 'package:flutter/material.dart';
import 'dart:async';

import 'package:receive_sharing_intent/receive_sharing_intent.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late StreamSubscription _intentSub;
  final _sharedFiles = <SharedMediaFile>[];

  @override
  void initState() {
    super.initState();

    // Listen to media sharing coming from outside the app while the app is in the memory.
    _intentSub = ReceiveSharingIntent.instance.getMediaStream().listen((value) {
      setState(() {
        _sharedFiles.clear();
        _sharedFiles.addAll(value);

        print(_sharedFiles.map((f) => f.toMap()));
      });
    }, onError: (err) {
      print("getIntentDataStream error: $err");
    });

    // Get the media sharing coming from outside the app while the app is closed.
    ReceiveSharingIntent.instance.getInitialMedia().then((value) {
      setState(() {
        _sharedFiles.clear();
        _sharedFiles.addAll(value);
        print(_sharedFiles.map((f) => f.toMap()));

        // Tell the library that we are done processing the intent.
        ReceiveSharingIntent.instance.reset();
      });
    });
  }

  @override
  void dispose() {
    _intentSub.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    const textStyleBold = const TextStyle(fontWeight: FontWeight.bold);
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Column(
            children: <Widget>[
              Text("Shared files:", style: textStyleBold),
              Text(_sharedFiles
                  .map((f) => f.toMap())
                  .join(",\n****************\n")),
            ],
          ),
        ),
      ),
    );
  }
}

通过以上步骤,您可以成功地在Flutter项目中集成receive_sharing_intent插件,实现接收来自其他应用的分享内容功能。如果您遇到编译问题,请参考官方文档中的解决办法。


更多关于Flutter接收分享意图插件receive_sharing_intent的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter接收分享意图插件receive_sharing_intent的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter中使用receive_sharing_intent插件来接收分享意图的示例代码。这个插件允许你的Flutter应用接收来自其他应用的分享内容,比如文本、图片或链接。

首先,确保你的Flutter项目已经创建,并在pubspec.yaml文件中添加receive_sharing_intent依赖:

dependencies:
  flutter:
    sdk: flutter
  receive_sharing_intent: ^1.5.0  # 请检查最新版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的main.dart文件中,设置插件以监听分享意图。以下是一个完整的示例:

import 'package:flutter/material.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化ReceiveSharingIntent
  ReceiveSharingIntent.configure()
      .then((Map<String, dynamic> intentData) {
    // 在这里处理接收到的分享数据
    runApp(MyApp(intentData: intentData));
  }).catchError((e) {
    // 处理错误
    print('Error in receiving sharing intent: $e');
    runApp(MyApp(intentData: null));
  });
}

class MyApp extends StatelessWidget {
  final Map<String, dynamic>? intentData;

  MyApp({this.intentData});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Share Intent Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Share Intent Demo'),
        ),
        body: Center(
          child: intentData != null
              ? ShareContentWidget(intentData!)
              : NoSharedContentWidget(),
        ),
      ),
    );
  }
}

class ShareContentWidget extends StatelessWidget {
  final Map<String, dynamic> intentData;

  ShareContentWidget({required this.intentData});

  @override
  Widget build(BuildContext context) {
    // 根据intentData的类型和内容展示不同的UI
    String textContent = intentData['text'] ?? '';
    String? urlContent = intentData['text/plain'] ?? intentData['url'] ?? '';
    List<dynamic>? imageContent = intentData['image']?.cast<Map<String, dynamic>>();

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        if (textContent.isNotEmpty)
          Text('Text: $textContent'),
        if (urlContent != null)
          Text('URL: $urlContent'),
        if (imageContent != null && imageContent.isNotEmpty)
          Image.network(imageContent.first['url'] as String),
      ],
    );
  }
}

class NoSharedContentWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('No shared content received.');
  }
}

在这个示例中,我们首先初始化ReceiveSharingIntent,并在配置完成后运行应用。如果成功接收到分享数据,我们将数据传递给MyApp小部件,并在UI中展示这些数据。ShareContentWidget负责根据接收到的数据类型(文本、URL、图片等)来展示相应的内容。

请注意,实际开发中可能需要根据具体的应用需求对代码进行调整,比如处理更多类型的数据、优化UI布局等。同时,确保在Android和iOS平台上都进行了必要的配置,以便应用能够正确接收分享意图。

回到顶部