一、概述
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的控件中调用原生方法。
写的比较简单,是以完成项目目前的功能为前提下匆匆记录的,希望能帮助到一些人。