美文网首页Flutter圈子FlutterFlutter
Flutter插件开发例子分享到facebook和twitter

Flutter插件开发例子分享到facebook和twitter

作者: TryEnough | 来源:发表于2019-04-09 16:10 被阅读13次

    请看原文更详细:http://tryenough.com/flutter-plugin-share

    这个活生生的例子会教你开发flutter插件,功能是封装Android和iOS端的分享到facebook和twitter的flutter接口。使用的分别是两端的系统分享功能,不需要集成facebook和twitter 的 sdk。

    例子插件网址:https://pub.dartlang.org/packages/flutter_share_go#-readme-tab-

    展示一下样式:

    ios 中分享到facebook:

    android中分享到facebook

    请看原文更详细:http://tryenough.com/flutter-plugin-share

    开始开发插件

    步骤一:创建插件项目

    这里用的Android studio创建的项目,可以直接创建flutter plugin项目,你也可以用命令创建:

    flutter create --org com.example --template=plugin "plugin_name"
    

    将上面的“plugin_name”换成你的插件名字就行了,我这个插件名字叫flutter_share_go,所以命令就是:

    flutter create --org com.example --template=plugin flutter_share_go
    

    这里没有支持swift和kotlin,原因是使用插件的很多项目可能并不支持,以免造成不必要的麻烦,但是你仍然可以选择支持,命令如下:

    flutter create --template=plugin -i swift -a kotlin flutter_share_go
    

    查看创建好的项目结构:

    Android文件夹中:Android端原生的代码
    iOS文件夹中:iOS端原生的代码
    example文件:是方便测试你的插件的例子代码
    lib文件:插件对原生接口的封装,也就是直接在dart代码中调用的接口

    分别在Android studio和xcode中编辑Android和iOS代码

    先在Android studio中编写Android部分代码

    用Android studio打开项目中的android文件夹,因为此时缺少flutter库依赖,需要配置一下:

    在项目根目录建立一个libs文件夹,用来存放flutter库,flutter库可以到你电脑的flutter sdk路径中寻找:

    /bin/cache/artifacts/engine
    

    在engine路径下有很多的android支持库,随便拷贝一个Android平台的库到libs文件夹下,右键flutter.jar,弹出菜单选择Add As Library...。这里不用担心,我们等下设置一下让它只是编译时使用,不会打包进来。

    然后点击菜单File/Project Structure...,找到flutter_text_plugin的Dependencies中,将flutter库的Scope从Implementation改成Compile Only。

    开始添加Android代码
    添加如下两个文件:

    PackageUtils.java 工具类

    package com.doglobal.flutter_share_go;
    
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    
    public class PackageUtils {
    
        public static boolean isPkgInstalled(Context context, String packageName) {
            if (packageName == null || "".equals(packageName))
                return false;
            android.content.pm.ApplicationInfo info = null;
            try {
                info = context.getPackageManager().getApplicationInfo(packageName, 0);
                return info != null;
            } catch (PackageManager.NameNotFoundException e) {
                return false;
            }
        }
    
        public static void goDownloadPage(Context context, String pkgName) {
            Context app = context.getApplicationContext();
            try {
                Intent intent = new Intent(Intent.ACTION_VIEW,
                        Uri.parse("market://details?id=" + pkgName));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                app.startActivity(intent);
            } catch (android.content.ActivityNotFoundException anfe) {
                Intent intent = new Intent(Intent.ACTION_VIEW,
                        Uri.parse("https://play.google.com/store/apps/details?id=" + pkgName));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                app.startActivity(intent);
            }
        }
    }
    
    

    ShareHelper.java 工具类

    package com.doglobal.flutter_share_go;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.text.TextUtils;
    
    public class ShareHelper {
    
        public static final String CHANNEL_FACEBOOK_PKG_NAME = "com.facebook.katana";
        public static final String CHANNEL_TWITTER_PKG_NAME = "com.twitter.android";
    
        public static void shareMain(Activity activity, String shareText) {
            shareText(activity, null, null, shareText, null, "");
        }
    
        public static void shareTextToChannel(Activity activity,String pkgName, String shareText,
                                              String shareUrl) {
            if (PackageUtils.isPkgInstalled(activity, pkgName)) {
                shareText(activity, null, null, shareText, pkgName, shareUrl);
            } else {
                PackageUtils.goDownloadPage(activity, pkgName);
            }
        }
    
        /**
         * @param dlgTitle 选择弹框标题
         * @param subject  分享主题
         * @param shareText  分享内容
         */
        public static void shareText(Activity activity, String dlgTitle, String subject,
                                     String shareText, String pkgName, String shareUrl) {
            if (shareText == null || "".equals(shareText)) {
                return;
            }
            String content = shareText + ": " + shareUrl + " .";
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setType("text/plain");
            if (!TextUtils.isEmpty(subject)) {
                intent.putExtra(Intent.EXTRA_SUBJECT, subject);
            }
    
            intent.putExtra(Intent.EXTRA_TEXT, content);
    
            if (!TextUtils.isEmpty(pkgName)) {
                intent.setPackage(pkgName);
            }
    
            // 设置弹出框标题
            if (TextUtils.isEmpty(dlgTitle)) { // 自定义标题
                Intent chooser = Intent.createChooser(intent, dlgTitle);
                chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                activity.startActivity(chooser);
            } else { // 系统默认标题
                activity.startActivity(intent);
            }
        }
    }
    
    

    然后在FlutterShareGoPlugin.java文件中添加调用逻辑。
    这个文件就是java端对dart端的调用接口。我们先来看下代码,再进行解析:

    package com.doglobal.flutter_share_go;
    
    import android.app.Activity;
    
    import io.flutter.plugin.common.MethodCall;
    import io.flutter.plugin.common.MethodChannel;
    import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
    import io.flutter.plugin.common.MethodChannel.Result;
    import io.flutter.plugin.common.PluginRegistry.Registrar;
    
    /** FlutterShareGoPlugin */
    public class FlutterShareGoPlugin implements MethodCallHandler {
    
      private Activity mActivity; //分析一
      private FlutterShareGoPlugin(Activity context) {
        mActivity = context;
      }
    
      /** Plugin registration. */
      public static void registerWith(Registrar registrar) {
        final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_share_go");
        channel.setMethodCallHandler(new FlutterShareGoPlugin(registrar.activity()));
      }
    
      @Override
      public void onMethodCall(MethodCall call, Result result) {
        if (call.method.equals("getPlatformVersion")) {
          result.success("Android " + android.os.Build.VERSION.RELEASE);
        } else if (call.method.equals("shareToFBPlatform")) {  //分析二
          String content = call.argument("shareContent");
          String shareUrl = call.argument("shareUrl");
          ShareHelper.shareTextToChannel(mActivity, ShareHelper.CHANNEL_FACEBOOK_PKG_NAME, content, shareUrl);
        } else if (call.method.equals("shareToTwitterPlatform")) {
          String content = call.argument("shareContent");
          String shareUrl = call.argument("shareUrl");
          ShareHelper.shareTextToChannel(mActivity, ShareHelper.CHANNEL_TWITTER_PKG_NAME, content, shareUrl);
        }
        else {
          result.notImplemented();
        }
      }
    
    }
    
    

    请看原文更详细:http://tryenough.com/flutter-plugin-share

    • 分析一
      我们添加一个构造方法,用来存储activity

    • 分析二
      在方法onMethodCall中根据dart传递过来的方法名调用java端不同的代码逻辑

    至此,Android端代码就告一段落了。

    iOS端开发,在xcode中开发

    如图,我们在Android studio中打开一个iOS文件,在右上角会有用xcode打开的按钮,我们点击打开就可以用xcode编辑了。

    打开项目添加上图中的文件:

    FlutterShareGoPlugin.m文件

    #import "FlutterShareGoPlugin.h"
    #import "ShareHelper.h"
    #import <Social/Social.h>
    
    
    @interface FlutterShareGoPlugin()
    @property (nonatomic, strong)UIViewController * rootViewController;
    @end
    
    @implementation FlutterShareGoPlugin
    + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
      FlutterMethodChannel* channel = [FlutterMethodChannel
          methodChannelWithName:@"flutter_share_go"
                binaryMessenger:[registrar messenger]];
      FlutterShareGoPlugin* instance = [[FlutterShareGoPlugin alloc] init];
      [registrar addMethodCallDelegate:instance channel:channel];
    }
    
    - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    
      if ([@"getPlatformVersion" isEqualToString:call.method]) {
        result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
      }
      else if ([@"shareToFBPlatform" isEqualToString:call.method]) {
          NSDictionary *arguments = [call arguments];
          NSString * shareContent = arguments[@"shareContent"];
          NSString * shareUrl = arguments[@"shareUrl"];
          [ShareHelper shareToPlatformType:SLServiceTypeFacebook withContent:shareContent withShareUrl:shareUrl];
          result(nil);
      }
      else if ([@"shareToTwitterPlatform" isEqualToString:call.method]) {
          NSDictionary *arguments = [call arguments];
          NSString * shareContent = arguments[@"shareContent"];
          NSString * shareUrl = arguments[@"shareUrl"];
          [ShareHelper shareToPlatformType:SLServiceTypeTwitter withContent:shareContent withShareUrl:shareUrl];
          result(nil);
      }
      else {
        result(FlutterMethodNotImplemented);
      }
    }
    @end
    
    

    PackageUtil.h

    
    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface PackageUtil : NSObject
    
    // Is intalled specific app or not
    + (BOOL)isInstalledWithUrlScheme:(NSString *)urlScheme;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    PackageUtil.m

    #import "PackageUtil.h"
    
    @implementation PackageUtil
    
    + (BOOL)isInstalledWithUrlScheme:(NSString *)urlScheme {
        if (urlScheme == nil || urlScheme.length == 0) {
            return false;
        }
        return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlScheme]];
    }
    
    
    @end
    
    

    ShareHelper.h

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface ShareHelper : NSObject
    +(void)shareToPlatformType:(NSString *)platformType withContent:(NSString *)content withShareUrl:(NSString*)url;
    @end
    
    NS_ASSUME_NONNULL_END
    
    

    ShareHelper.m

    
    #import "ShareHelper.h"
    #import <Social/Social.h>
    #import "PackageUtil.h"
    
    @implementation ShareHelper
    
    /*
     SOCIAL_EXTERN NSString *const SLServiceTypeTwitter NS_AVAILABLE(10_8, 6_0);//Twitter
     SOCIAL_EXTERN NSString *const SLServiceTypeFacebook NS_AVAILABLE(10_8, 6_0);//Facebook
     SOCIAL_EXTERN NSString *const SLServiceTypeSinaWeibo NS_AVAILABLE(10_8, 6_0);
     SOCIAL_EXTERN NSString *const SLServiceTypeTencentWeibo NS_AVAILABLE(10_9, 7_0);
     SOCIAL_EXTERN NSString *const SLServiceTypeLinkedIn NS_AVAILABLE(10_9, NA);
     */
    +(void)shareToPlatformType:(NSString *)platformType withContent:(NSString *)content withShareUrl:(NSString*)url{
        if (platformType == nil || platformType.length == 0) {
            NSLog(@"unspecified platform");
            return;
        }
        if([platformType isEqualToString:SLServiceTypeFacebook] && ![[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"fb://"]]) {
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/app/id284882215"]];
            NSLog(@"UnInstall facebook");
            return;
        }
        if([platformType isEqualToString:SLServiceTypeTwitter] && ![[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"twitter://"]]) {
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/app/id333903271"]];
            NSLog(@"UnInstall twitter");
            return;
        }
        // create controller for ServiceType
        SLComposeViewController *composeVC = [SLComposeViewController composeViewControllerForServiceType:platformType];
        // image
        // [composeVC addImage:[UIImage imageNamed:@"Nameless"]];
        // content
        [composeVC setInitialText:content];
        // share url
        [composeVC addURL:[NSURL URLWithString:url]];
        // share controller
        if([[[UIApplication sharedApplication] keyWindow].rootViewController isKindOfClass:[UINavigationController class]]) {
            UINavigationController *vc = (UINavigationController *)[[UIApplication sharedApplication] keyWindow].rootViewController;
            [vc pushViewController:composeVC animated:YES];
        } else {
            UINavigationController *vc = (UINavigationController *)[[UIApplication sharedApplication] keyWindow].rootViewController;
            [vc presentViewController:composeVC animated:YES completion:nil];
        }
        // callback user hanlder
        composeVC.completionHandler = ^(SLComposeViewControllerResult result){
            if (result == SLComposeViewControllerResultDone) {
            }
            else if (result == SLComposeViewControllerResultCancelled) {
            }
        };
    }
    
    @end
    

    请看原文更详细:http://tryenough.com/flutter-plugin-share

    最后需要我们在plist文件中添加白名单,用于iOS9适配,查看是否安装了facebook和twitter:

    iOS 部分代码到此也告一段落了。

    添加flutter接口,供dart代码调用

    打开项目中lib文件夹下的flutter_share_go文件

    FlutterShareGo.dart

    import 'dart:async';
    
    import 'package:flutter/services.dart';
    
    class FlutterShareGo {
      static const MethodChannel _channel =
          const MethodChannel('flutter_share_go');
    
      static Future<String> get platformVersion async {
        final String version = await _channel.invokeMethod('getPlatformVersion');
        return version;
      }
    
      static Future<void> shareToFBPlatform(String shareContent, String shareUrl) async {
        assert(shareContent != null);
        assert(shareContent.isNotEmpty);
        final Map<String, dynamic> params = <String, dynamic> {
          'shareContent': shareContent,
          'shareUrl':shareUrl,
        };
        await _channel.invokeMethod("shareToFBPlatform", params);
      }
    
      static Future<void> shareToTwitterPlatform(String shareContent, String shareUrl) async {
        assert(shareContent != null);
        assert(shareContent.isNotEmpty);
        final Map<String, dynamic> params = <String, dynamic> {
          'shareContent': shareContent,
          'shareUrl':shareUrl,
        };
        await _channel.invokeMethod("shareToTwitterPlatform", params);
      }
    }
    
    

    flutter端代码就告一段落了。

    测试插件:

    打开项目中example文件下的main.dart:

    main.dart

    import 'package:flutter/material.dart';
    import 'dart:async';
    
    import 'package:flutter/services.dart';
    import 'package:flutter_share_go/flutter_share_go.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      String _platformVersion = 'Unknown';
    
      @override
      void initState() {
        super.initState();
        initPlatformState();
      }
    
      // Platform messages are asynchronous, so we initialize in an async method.
      Future<void> initPlatformState() async {
        String platformVersion;
        // Platform messages may fail, so we use a try/catch PlatformException.
        try {
          platformVersion = await FlutterShareGo.platformVersion;
        } on PlatformException {
          platformVersion = 'Failed to get platform version.';
        }
    
        // If the widget was removed from the tree while the asynchronous platform
        // message was in flight, we want to discard the reply rather than calling
        // setState to update our non-existent appearance.
        if (!mounted) return;
    
        setState(() {
          _platformVersion = platformVersion;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Plugin example app'),
            ),
            body: Column(
              children: <Widget>[
                Text('Running on: $_platformVersion\n'),
                RaisedButton(
                  child: Text("分享到facebook按钮"),
                  color: Colors.red,
                  onPressed: () {
                    FlutterShareGo.shareToFBPlatform("test share to fb content", "http://tryenough.com");
                  },
                )
              ],
            ),
          ),
        );
      }
    }
    
    

    运行就会出现文章最上面的效果了。祝你顺利。

    最后发布可以参照如下步骤:

    运行命令,并解决所有出现的问题:

     flutter packages pub publish --dry-run
    

    问题解决完就可以发布了,命令:

     flutter packages pub publish 
    

    请看原文更详细:http://tryenough.com/flutter-plugin-share

    相关文章

      网友评论

        本文标题:Flutter插件开发例子分享到facebook和twitter

        本文链接:https://www.haomeiwen.com/subject/biwuiqtx.html