Flutter插件開發例子分享到facebook和twitter

https://segmentfault.com/a/1190000018806329java

請看原文更詳細:http://tryenough.com/flutter-plugin-share

這個活生生的例子會教你開發flutter插件,功能是封裝Android和iOS端的分享到facebook和twitter的flutter接口。使用的分別是兩端的系統分享功能,不須要集成facebook和twitter 的 sdk。android

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

展現一下樣式:docker

ios 中分享到facebook:swift

android中分享到facebooksegmentfault

請看原文更詳細:http://tryenough.com/flutter-plugin-share

開始開發插件

步驟一:建立插件項目

這裏用的Android studio建立的項目,能夠直接建立flutter plugin項目,你也能夠用命令建立:xcode

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

將上面的「plugin_name」換成你的插件名字就好了,我這個插件名字叫flutter_share_go,因此命令就是:app

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

這裏沒有支持swift和kotlin,緣由是使用插件的不少項目可能並不支持,以避免形成沒必要要的麻煩,可是你仍然能夠選擇支持,命令以下:less

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

查看建立好的項目結構:async

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

相關文章
相關標籤/搜索