Flutter与Android原生代码交互

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/S43565442/article/details/86016442

一、概述

Flutter正式版已经出了一段时间了,作为刚入门的一个菜鸟而言,我还需要更多的学习。
最近开始的flutter项目用到了分享功能,但是到目前为止,微信,QQ等还没有出对flutter分享的SDK,这就需要用到flutter与Android和ios的原生交互。下面仅关于flutter与Android原生的交互,希望能给像我一样的菜鸟们些微的帮助(只有Android是因为ios我还没开始写哈哈哈)。

二、开始编码(以分享功能为例)

  1. 首先在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;
  }
}    
  1. 然后在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;
    }
}
  1. 在继承了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"));
   }
}
  1. 在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原生代码就一下四点

  1. flutter端创建一个MethodChannel,名字要和Android端的相同,并使用MethodChannel通过唯一方法名对应调用Android原生方法。
  2. Android端同样生成一个MethodChannel,名字要和上步骤Flutter中创建的相同。继承MethodCallHandler方法后实现onMethodCall(MethodCall call, Result result)方法,通过call拿到上步骤调用的唯一方法名实现不同的方法。
  3. 在继承了FlutterActivity的Activity中注册步骤2中实现了MethodCallHandler的通道。
  4. 开始在flutter的控件中调用原生方法。

写的比较简单,是以完成项目目前的功能为前提下匆匆记录的,希望能帮助到一些人。

猜你喜欢

转载自blog.csdn.net/S43565442/article/details/86016442