Flutter与Android原生代码交互
16lz
2021-01-23
一、概述
Flutter正式版已经出了一段时间了,作为刚入门的一个菜鸟而言,我还需要更多的学习。
最近开始的flutter项目用到了分享功能,但是到目前为止,微信,QQ等还没有出对flutter分享的SDK,这就需要用到flutter与Android和ios的原生交互。下面仅关于flutter与Android原生的交互,希望能给像我一样的菜鸟们些微的帮助(只有Android是因为ios我还没开始写哈哈哈)。
二、开始编码(以分享功能为例)
- 首先在Flutter端创建一个方法调用工具类,便于方法调用管理:
class ShareUtil { ///私有构造方法 ShareUtil._(); ///其中com.example/share用于唯一识别通道名称, /// 这个名字后边会在Android端使用到,必须跟Android端对应调用方法中的通道名称保持一致,否则无法调用 static const MethodChannel _channel = const MethodChannel('com.example/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.example/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.example/share")); }}
- 在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的控件中调用原生方法。
写的比较简单,是以完成项目目前的功能为前提下匆匆记录的,希望能帮助到一些人。
更多相关文章
- Android中Calendar与Date的区别以及消除时区对日期操作影响的方
- 使用千千静听或手动创建Android播放列表的方法
- Android日志打印类LogUtils,能够定位到类名,方法名以及出现错误的
- Android操作SQLite数据库(增、删、改、查、分页等)及ListView显
- Android退出应用的方法总结
- 改进Android语音对讲系统的方法
- Android内存泄漏的轻松解决方法