See the article for more details:Tryenough.com/flutter-plu…
This is a real life example of how to develop a Flutter plugin that encapsulates the Android and iOS shared flutter interface to Facebook and Twitter. It uses system sharing at both ends of the spectrum and doesn’t need to integrate facebook and Twitter SDKS.
The example plug-in url: pub.dartlang.org/packages/fl…
To show the style:
Share to Facebook on ios:
Share on Android to Facebook
See the original for more details: tryenough.com/flutter-plu…
Start developing plug-ins
Step 1: Create the plug-in project
You can create the Flutter Plugin project directly by using Android Studio. You can also create the Flutter plugin project with commands:
flutter create --org com.example --template=plugin "plugin_name"
Copy the code
Replace “plugin_name” with the name of your plugin. My plugin is called Flutter_share_go, so the command is:
flutter create --org com.example --template=plugin flutter_share_go
Copy the code
Swift and Kotlin are not supported here, as many projects using the plugin may not support swift and kotlin, so as not to cause unnecessary trouble, but you can still choose to support them, using the following command:
flutter create --template=plugin -i swift -a kotlin flutter_share_go
Copy the code
View the created project structure:
** The plugin encapsulates the native interface, which is called directly in the Dart code
Edit Android and iOS code in Android Studio and XCode, respectively
Start by writing the Android part in Android Studio
Open the Android folder in your project with Android Studio. Because the Flutter library dependencies are missing, you need to configure them:
Create a folder called Libs in your project root directory to store the Flutter libraries. The Flutter libraries can be found in the Flutter SDK path on your computer:
/bin/cache/artifacts/engine
Copy the code
There are many android libraries in the engine directory. Copy any of the android libraries to the libs folder, right-click the flutter. Jar folder, and select Add As Library… . Don’t worry about that, we’ll just set it up so that it’s only compile-time, it’s not packaged.
Then click on the menu File/Project Structure… In flutter_text_plugin Dependencies, change the Scope of flutter library from Implementation to Compile Only.
Start adding Android code add the following two files:
PackageUtils. Java tools
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);
returninfo ! =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); }}}Copy the code
ShareHelper. Java tools
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); }}/ * * *@paramDlgTitle Selects the title * of the pop-up box@paramSubject shares the subject *@paramShareText Share content */
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); }// Set the title of the pop-up
if (TextUtils.isEmpty(dlgTitle)) { // Customize the title
Intent chooser = Intent.createChooser(intent, dlgTitle);
chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(chooser);
} else { // System default titleactivity.startActivity(intent); }}}Copy the code
Then in FlutterShareGoPlugin. Add call logic Java file. This file is the Java side call interface to the DART side. Let’s take a look at the code and parse it:
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; A / / analysis
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")) { 2 / / analysis
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(); }}}Copy the code
See the original for more details: tryenough.com/flutter-plu…
-
Analysis 1 We add a constructor that stores activities
-
Analysis two calls different code logic on the Java side in the method onMethodCall based on the method name passed by dart
This is the end of the Android code.
IOS side development, development in Xcode
As shown in the picture, when we open an iOS file in Android Studio, there will be a button to open it with Xcode in the upper right corner. Click open to edit it with Xcode.
Open the project and add the file shown above:
FlutterShareGoPlugin. M file
#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
Copy the code
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
Copy the code
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
Copy the code
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
Copy the code
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) { } }; } @endCopy the code
See the original for more details: tryenough.com/flutter-plu…
Add a whitelist to the plist file for iOS9 adaptation to check whether facebook and twitter are installed:
This is the end of some of the iOS code.
Add a FLUTTER interface to be called by dart code
Open the flutter_share_go file in the lib folder of the project
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); }}Copy the code
The code for the flutter side ends.
Test plug-in:
Dart: Open main.dart under example in the project:
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("Share to Facebook button"),
color: Colors.red,
onPressed: () {
FlutterShareGo.shareToFBPlatform("test share to fb content"."http://tryenough.com"); },)],),),); }}Copy the code
Run and you will see the effect at the top of the article. Good luck.
For final release, you can refer to the following steps:
Run the command and resolve any problems that arise:
flutter packages pub publish --dry-run
Copy the code
When the problem is resolved, you can issue the command:
flutter packages pub publish
Copy the code
See the original for more details: tryenough.com/flutter-plu…