Android 项目集成 Flutter Module
分类于 Flutter
发表于 2020-11-13
作者: 灼灼团队
本文字数: 4346
阅读时长 ≈ 14.5 分钟

# Flutter Module 集成说明

# 术语说明:

  • 宿主项目: 即安卓原生项目(Java/Kotlin)
  • Flutter Module: 即 Flutter 代码,是 Flutter 实现的代码模块,可以做为一个模块集成到宿主项目当中,可放在一个单独的代码仓库中

# 首先,参考 Flutter 官网文档(flutter.dev) 安装 Flutter 环境;

如果外网条件不好的话,可以访问国内中文网:https://flutter.cn/docs

# 0. 在Flutter 项目目录下运行命令对 Flutter Module 进行初始化:

flutter pub get
1

# 1. 修改宿主项目根目录下的 /settings.gradle

include ':app', ':mvvmhabit', ':pictureselector'
include ':timepicker',':kepler'

setBinding(new Binding([gradle: this]))

// 下面这个目录,换成你本机 Flutter Module 项目所在的目录, 可以不和宿主项目同目录
evaluate(new File(
        settingsDir,
        '../../your_flutter_module/.android/include_flutter.groovy'
))

rootProject.name = 'YourAndroidProjectName'


include ':your_flutter_module'
// 下面这个目录,换成你本机 Flutter Module 的项目目录
project(':your_flutter_module').projectDir = new File('../../your_flutter_module')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2. 修改宿主项目中 /app/build.gradle,添加 Flutter 依赖:

dependencies {
    // ...
    // 添加 Flutter 依赖
    implementation project(path: ':flutter')
}

1
2
3
4
5
6

# 3. 将 MyFlutterActivity.java 文件,拷贝至宿主项目中的目录: /app/src/main/java/com/your-domain/projectName/

package com.ysst.feixuan.ui.activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.ysst.feixuan.base.Constant;
import com.ysst.feixuan.bean.User;
import com.ysst.feixuan.data.AppDatabase;
import com.ysst.feixuan.utils.GsonUtil;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import me.goldze.mvvmhabit.utils.SPUtils;

/**
 * 飞选 Flutter Activity
 */
public class FeiFlutterActivity extends FlutterActivity {
    public static final String PAGE_COLLECTION = "collection";
    public static final String PAGE_FOOTPRINT = "footprint";

    private static final String CHANNEL = "flutter.channel";

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        System.out.println("configureFlutterEngine");
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler(((call, result) -> {
                    // Note: this method is invoked on the main thread.
                    if (call.method.equals("getUser")) {
                        User user = getUserData();
                        if(user != null){
                            result.success(GsonUtil.toJsonStr(user));
                        }else{
                            result.success(null);
                        }
                    }else{
                        result.notImplemented();
                    }
                }));

    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        System.out.println("onFlutterActivityCreate");

//        // 据说可以解决 flutter module 白屏的问题, 待验证
//        getIntent().putExtra("enable-software-rendering", true);

//        // 设置 Flutter Activity 状态栏透明
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0及以上
//            View decorView = getWindow().getDecorView();
//            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
//                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
//            decorView.setSystemUiVisibility(option);
//            getWindow().setStatusBarColor(Color.TRANSPARENT);
//        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4到5.0
//            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
//            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
//        }
    }

    /**
     * 父类的这个方法写死了,会导致本类不会被实例化
     * 需重写此方法,使用 FeiFlutterActivity.class
     * @param cachedEngineId
     * @return
     */
    public static CachedEngineIntentBuilder withCachedEngine(@NonNull String cachedEngineId) {
        return new CachedEngineIntentBuilder(FeiFlutterActivity.class, cachedEngineId);
    }

    /**
     * 同上
     * @return
     */
    @NonNull
    public static NewEngineIntentBuilder withNewEngine() {
        return new NewEngineIntentBuilder(FeiFlutterActivity.class);
    }

    /**
     * 获取用户数据
     * @return
     */
    private static User getUserData() {
        // TODO: 自行实现获取当前登录用户的代码
        return user;
    }

    /**
     * 打开 Flutter 页面
     * @param activity
     * @param page
     */
    public static void openPage(Activity activity, String page) {
//        Intent i = FeiFlutterActivity
//                .withCachedEngine(page)
//                .build(activity);
        // TIP: 不需要使用缓存引擎,黑屏 or 白屏问题只在 debug 模式下存在,release 下无此问题

        Intent i = FeiFlutterActivity.withNewEngine().initialRoute(page).build(activity);
        activity.startActivity(i);
    }
}

1
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

# 4. 在宿主项目的 /app/src/main/AndroidManifest.xml 中,添加 Flutter Activity 的声明:

<application>
  <!-- 省略  -->
  <activity
            android:name=".ui.activity.FeiFlutterActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize" />

</application>
1
2
3
4
5
6
7
8
9

# 5. 在宿主项目的相应位置调用类似如下代码可打开 Flutter 页面:

// 打开收藏夹页面
public void onClick(View view) {
    FeiFlutterActivity.openPage(getActivity(), FeiFlutterActivity.PAGE_COLLECTION);
}

// 打开浏览足迹页面
public void onClick(View view) {
    FeiFlutterActivity.openPage(getActivity(), FeiFlutterActivity.PAGE_FOOTPRINT);
}
1
2
3
4
5
6
7
8
9

# 常见问题:

  1. 运行时打开 flutter activity 失败,日志显示 can not open "libflutter.so" 时,可能原因是编译的 架构没有配置好: 打开宿主项目的 /app/build.gradle,找到并修改以下相应配置:
     defaultConfig {
       // ...
       ndk {
           // 设置支持的SO库架构
           abiFilters 'armeabi' , 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
       }
       // ...
     }
    
    1
    2
    3
    4
    5
    6
    7
    8
联系我们
联系电话:17681177133
联系邮箱:admin@zhuo-zhuo.com
公司地址:合肥市高新区习友路2666号 (习友路和石莲南路交叉口西北角)二期304室
官网
博客
皖ICP备20009670号-2
合肥灼灼信息技术有限公司 | Copyright © 2020-present zhuo-zhuo.com