前言
Flutter版本:1.9.1
FlutterBoost版本:1.9.1
测试使用的iamge_picker版本:0.6.2+2
2
3
Flutter Boost 目前算是 Flutter 混合开发的一个旗帜了,不过也由于 Flutter 技术本身就较新,Flutter Boost 也才开源一年多时间,里面还是会存在较多 bug。我们公司使用的就是 Flutter Boost 集成的混合开发项目,这几天集成选择相册的功能,本地开发没问题,通过 Flutter Boost 集成到原生后 Android 端第一次跳转后返回接收不到参数,由于接收不到参数,第二次点击就没响应了,报错Unhandled Exception: PlatformException(already_active, Image picker is already active, null)
,iOS 就根本跳转不了。我也花了点时间 debug,发现了其中的问题。
Android 端解决方案
问题原因
- 集成 flutter_boost 之后,很多插件会使用栈底的 Activity,也就是 app 启动的时候的 MainActivity()(app 启动的时候会注册插件,插件通过 registrar.activity()获取到的)
- Android 使用底层 Activity 跳转没问题,但是调用 startActivityForResult 的时候,需要使用在栈顶的 Activity(onResume 状态的 Activity)才会在拉起的界面 finish 的时候拿到回调,这就会导致我们使用的插件中的 Activity 拿不到回调
我的解决方案
- 修改插件源码,在插件里面注册 Activity 的生命周期回调,并修改 Activity 指向
在android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java
中本身就有 Activity 生命周期注册:
70- public void onActivityResumed(Activity activity) {}
70+ public void onActivityResumed(Activity activity) {
71+ delegate.changeActivity(activity);
72+}
2
3
4
5
2.在android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java
中需要把原来 final 的 activity 改为动态的
80- private final Activity activity;
80+ private Activity activity;
2
然后添加更新函数
public void changeActivity(Activity activity) {
this.activity=activity;
}
2
3
4
ok,这个时候在调用 startActivityForResult 的时候会使用这个改过的 Activity 的实例,在拉起的 Activity finish 的时候,就能顺利拿到回调了。
iOS 端解决方案
问题原因
iOS 其实跟 Android 端的问题大同小异,注册的时候是使用的底层的 controller,所以我们在 FlutterController 中使用这个底层的 controller 无法跳转
我的解决方案
- 添加一个能拿到顶层 controller 的方法
ios/Classes/ImagePickerPlugin.m
- (UIViewController *)getCurrentVC
{
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
return currentVC;
}
- (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
{
UIViewController *currentVC;
if ([rootVC presentedViewController]) {
// 视图是被presented出来的
rootVC = [rootVC presentedViewController];
}
if ([rootVC isKindOfClass:[UITabBarController class]]) {
// 根视图为UITabBarController
currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];
} else if ([rootVC isKindOfClass:[UINavigationController class]]){
// 根视图为UINavigationController
currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];
} else {
// 根视图为非导航类
currentVC = rootVC;
}
return currentVC;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- 在我们点击 image_picker 发送通道消息的时候更改本地已缓存的 controller
57+ UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
58+ _viewController = [self getCurrentVCFrom:rootViewController];
2
3
问题解决
总结
我这里这两种方案不会是最好的解决方案,因为涉及到改插件源码,这样以后插件更新会比较麻烦,但是从目前看来是解决了我开发的问题,如果你们有好的解决方案,或者新版本已经解决了这个问题,请留言告知。