最近遇到了这个问题,其实这个问题在源生开发中算是一个很常见的问题。有很多场景都需要通过其他APP或者H5来打开APP并且有时候会携带参数。
所以在这里我说一下我的做法(大神勿喷,有更好的办法请评论区留言,不胜感激)。
我的思路就是:1.APP接收第三方平台的请求方式与源生处理方式不变,然后存储好请求的参数;2.利用平台提供的Flutter与源生交互的通道MethodChannel(android)以及FlutterMethodChannel(iOS),在双端分别创建一个可以访问到存储的请求数据的通道,通过判断存储的数据,来响应第三方平台的请求。
1.首先在AndroidManifest.xml中修改入口Activity的配置:
android:name=".MainActivity"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:exported="true"
android:windowSoftInputMode="adjustResize">
其中 android:launchMode=“singleTask” android:exported=“true” 是新增的
以及
2.在MainActivity中接收并保存第三方传递过来的参数信息:
private void getOpenData(){
try {
Uri uri = getIntent().getData();
if (uri==null){
return;
}
String query = uri.getQuery();
String openpage = uri.getQueryParameter("openpage");
String data = uri.getQueryParameter("data");
Log.d("scheme-", "openpage: " + openpage + ", data: " + data + ", query: " + query);
JSONObject jsonObject=new JSONObject();
jsonObject.put("openpage",openpage);
jsonObject.put("data",data);
CampusBarApplication.schemeInfo=jsonObject;
} catch (Exception e) {
Log.e("scheme-", e.getMessage(), e);
}
}
我这里用了一个静态变量保存 CampusBarApplication.schemeInfo=jsonObject; 用数据库、SP,文件等都可以,这里为了方便就用了个静态变量。
3.定义一个Flutter与源生交互的通道:
什么是通道?https://book.flutterchina.club/chapter12/platform-channel.html
private void initOpenPage() {
// new MethodChannel()
new MethodChannel(getFlutterView(), openpage_chanel).setMethodCallHandler(
(methodCall, result) -> {
if (methodCall.method.equals(checkOpenPage)) {
Map map=new HashMap<>();
if (CampusBarApplication.schemeInfo==null){
map.put("code","201");
}else {
map.put("code","200");
map.put("openpage",CampusBarApplication.schemeInfo.getString("openpage"));
map.put("data",CampusBarApplication.schemeInfo.getString("data"));
CampusBarApplication.schemeInfo=null;//记得在每次相应完清空保存的数据
}
result.success(map);
}
}
);
}
4.在flutter代码使用:
var platform = MethodChannel(NetUrlConstant.OPENPAGE_CHANEL);
platform.invokeMethod(NetUrlConstant.CHECK_OPEN_PAGE).then((onValue){
if(onValue["code"]=="200"){
println(onValue["data"]+"aassddffgg-----------------------------");
//TODO
}else if(onValue["code"]=="201"){
}
});
这样就可以在flutter响应到第三方的请求。
1.首先开始跟源生开发一样去配置URL Scheme 或者使用universal link,我在这就不讲怎么配置了。
2.在AppDelegate.m中接收并保存第三方传递过来的参数信息:
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options
{
NSLog(@"URL scheme:%@", [url scheme]);
NSLog(@"URL query: %@", [url query]);
NSMutableDictionary * dic=[NSMutableDictionary dictionary];
[dic setObject:[url scheme] forKey:@"openpage"];
[dic setObject:[url query] forKey:@"data"];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:dic forKey:@"openinfo"];
//这里建议同步存储到磁盘中,但是不是必须的
[userDefaults synchronize];
return YES;
}
3.在AppDelegate.m 中同样是定义一个通道:
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"openpage_chanel"
binaryMessenger:controller];
[channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
// TODO
if ([@"checkOpenPage" isEqualToString:call.method]) {
NSUserDefaults *userDefaultes = [NSUserDefaults standardUserDefaults];
//读取字典类型NSDictionary类型的数据
NSMutableDictionary *dic = [userDefaultes dictionaryForKey:@"openinfo"];
if (dic) {
[dic setObject:@"200" forKey:@"code"];
//记得清除保存的信息
}else{
dic=[NSMutableDictionary dictionary];
[dic setObject:@"201" forKey:@"code"];
}
result(dic);
}
}];
注意:Android跟iOS要协商好,将通道返回的信息格式保持一致,这样在Flutter就不用判断平台,用一套代码就可以完成双端的操作。