Flutter與Android原生程式碼互動
阿新 • • 發佈:2019-01-08
一、概述
Flutter正式版已經出了一段時間了,作為剛入門的一個菜鳥而言,我還需要更多的學習。
最近開始的flutter專案用到了分享功能,但是到目前為止,微信,QQ等還沒有出對flutter分享的SDK,這就需要用到flutter與Android和ios的原生互動。下面僅關於flutter與Android原生的互動,希望能給像我一樣的菜鳥們些微的幫助(只有Android是因為ios我還沒開始寫哈哈哈)。
二、開始編碼(以分享功能為例)
- 首先在Flutter端建立一個方法呼叫工具類,便於方法呼叫管理:
class ShareUtil {
///私有構造方法
ShareUtil._();
///其中com.dislux.yshangflutter/UMengShare用於唯一識別通道名稱,
/// 這個名字後邊會在Android端使用到,必須跟Android端對應呼叫方法中的通道名稱保持一致,否則無法呼叫
static const MethodChannel _channel =
const MethodChannel('com.secoo.yshangflutter/share');
///shareTextWithMenu對應的是Android端可以通過這個名字呼叫對應的方法,如果Flutter端呼叫方法需要傳遞引數,可以用map傳遞,
///如下傳遞了一個map,其中儲存text:text
static Future<dynamic> shareTextWithMenu(String text) async {
Map<dynamic, dynamic> result =
await _channel.invokeMethod('shareTextWithMenu', {"text": text});
return result;
}
///Flutter呼叫是否安裝了微信QQ等,需要Android端返回是否安裝,用於flutter端呼叫方法時得到返回值。
///這個地方我使用了回撥方法onResult
static Future<dynamic> checkInstall(String platform,
{Function onResult(bool isInstall)}) async {
bool result =
await _channel.invokeMethod('checkInstall', {"platform": platform});
print("是否安裝了${platform} =$result");
if (onResult != null) onResult(result);
return result;
}
///Flutter呼叫三方登入,需要Android端返回是否登入成功,以及使用者資訊。
///onResult中儲存了是否呼叫成功,以及成功之後獲取到的使用者資訊
static Future<dynamic> login(int platform,
{Function onResult(Map<String, String> userInfo)}) async {
Map<String, String> result =
await _channel.invokeMethod('login', {"platform": platform});
if (onResult != null) onResult(result);
return result;
}
}
- 然後在Android端對應方法:
public class SharePlugin implements MethodCallHandler, ActivityResultListener {
private final Registrar registrar;
private ShareAction mShareAction;
// 用於Activity中註冊,com.secoo.yshangflutter/share和剛flutter端要相同
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.secoo.yshangflutter/share");
channel.setMethodCallHandler(new SharePlugin(registrar));
}
private SharePlugin(Registrar registrar) {
this.registrar = registrar;
}
/// 分享sdk初始化
private void init(Context context) {
UMConfigure.init(context, "5c2f5016b465f54424000446", "umengshare", UMConfigure.DEVICE_TYPE_PHONE, "");//58edcfeb310c93091c000be2 5965ee00734be40b580001a0
PlatformConfig.setWeixin("wxdc1e388c3822c80b", "3baf1193c85774b3fd9d18447d76cab0");
PlatformConfig.setQQZone("100424468", "c7394704798a158208a74ab60104f0ba");
mShareAction = new ShareAction(registrar.activity()).setDisplayList(SHARE_MEDIA.WEIXIN, SHARE_MEDIA.WEIXIN_CIRCLE, SHARE_MEDIA.WEIXIN_FAVORITE, SHARE_MEDIA.QQ, SHARE_MEDIA.QZONE, SHARE_MEDIA.SINA);
}
///方法呼叫,對應上邊呼叫時使用的名字
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("shareTextWithMenu")) {
String text = call.argument("text");
shareText(text, result);
} else if (call.method.equals("login")) {
int platform = call.argument("platform");
login(sharePlatForm(platform), result);
} else if (call.method.equals("checkInstall")) {
int platform = call.argument("platform");
boolean flag = UMShareAPI.get(registrar.context()).isInstall(registrar.activity(), sharePlatForm(platform));
result.success(flag);
} else {
result.notImplemented();
}
}
///返回值都存在result中,Flutter中呼叫方法_channel.invokeMethod()返回值就是result中的值
private void shareText(final String text, final Result result) {
mShareAction.setShareboardclickCallback(new ShareBoardlistener() {
@Override
public void onclick(SnsPlatform snsPlatform, SHARE_MEDIA share_media) {
new ShareAction(registrar.activity()).setPlatform(share_media)
.withText(text)
.setCallback(new UMShareListener() {
@Override
public void onStart(SHARE_MEDIA share_media) {
LoadingDialog.showLoading(registrar.activity());
}
@Override
public void onResult(SHARE_MEDIA share_media) {
LoadingDialog.hideLoading();
Map<String, Object> map = new HashMap<>();
map.put("code", "000000");
result.success(map);
}
@Override
public void onError(SHARE_MEDIA share_media, Throwable throwable) {
LoadingDialog.hideLoading();
Toast.makeText(registrar.activity(), throwable.getMessage(), Toast.LENGTH_LONG).show();
Map<String, Object> map = new HashMap<>();
map.put("code", "100000");
map.put("msg", throwable.getMessage());
result.success(map);
}
@Override
public void onCancel(SHARE_MEDIA share_media) {
LoadingDialog.hideLoading();
Toast.makeText(registrar.activity(), "已取消", Toast.LENGTH_LONG).show();
Map<String, Object> map = new HashMap<>();
map.put("status", "200000");
result.success(map);
}
});
}
}).open();
}
private void login(SHARE_MEDIA platform, final Result result) {
UMShareAPI.get(registrar.activity()).getPlatformInfo(registrar.activity(), platform, new UMAuthListener() {
@Override
public void onStart(SHARE_MEDIA share_media) {
Log.e("login", "onStart");
}
@Override
public void onComplete(SHARE_MEDIA share_media, int i, Map<String, String> map) {
map.put("code", "000000");
result.success(map);
}
@Override
public void onError(SHARE_MEDIA share_media, int i, Throwable throwable) {
Map<String, Object> map = new HashMap<>();
map.put("code", "100000");
map.put("msg", throwable.getMessage());
result.success(map);
}
@Override
public void onCancel(SHARE_MEDIA share_media, int i) {
Map<String, Object> map = new HashMap<>();
map.put("code", "200000");
result.success(map);
}
});
}
private SHARE_MEDIA sharePlatForm(int index) {
final SHARE_MEDIA platform;
switch (index) {
case 0:
platform = SHARE_MEDIA.WEIXIN;
break;
case 1:
platform = SHARE_MEDIA.QQ;
break;
default:
platform = SHARE_MEDIA.QQ;
break;
}
return platform;
}
@Override
public boolean onActivityResult(int i, int i1, Intent intent) {
UMShareAPI.get(registrar.activity()).onActivityResult(i, i1, intent);
return false;
}
}
- 在繼承了FlutterActivity的Activity中註冊:
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
registerCustomPlugin(this);
}
///註冊剛剛寫的原生方法通道
private static void registerCustomPlugin(PluginRegistry registrar) {
UmengsharePlugin.registerWith(registrar.registrarFor("com.dislux.yshangflutter/UMengShare"));
}
}
- 在flutter控制元件中呼叫方法,並獲取返回值:
//分享按鈕
Widget _shareButton() {
return GestureDetector(
onTap: () {
Share.shareTextWithMenu("分享分享測試");
Share.checkInstall(Platform.QQ, onResult: (bool isInstall) {
print("是否安裝了QQ =$isInstall");
});
Share.login(Platform.QQ, onResult: (Map<String, String> userInfo) {
print("登入使用者資訊=${userInfo.toString()}");
});
},
child: ...
);
三、總結
其實總結下來,flutter呼叫Android原生程式碼就一下四點
- flutter端建立一個MethodChannel,名字要和Android端的相同,並使用MethodChannel通過唯一方法名對應呼叫Android原生方法。
- Android端同樣生成一個MethodChannel,名字要和上步驟Flutter中建立的相同。繼承MethodCallHandler方法後實現onMethodCall(MethodCall call, Result result)方法,通過call拿到上步驟呼叫的唯一方法名實現不同的方法。
- 在繼承了FlutterActivity的Activity中註冊步驟2中實現了MethodCallHandler的通道。
- 開始在flutter的控制元件中呼叫原生方法。
寫的比較簡單,是以完成專案目前的功能為前提下匆匆記錄的,希望能幫助到一些人。