在上一篇博客 【Flutter】Flutter 混合开发 ( 简介 | Flutter 混合开发集成步骤 | 创建 Flutter Module ) 中 , 创建了 Flutter Module 工程 ;
本篇博客开始创建 Android 工程 , 并将两个工程进行关联 ;
Flutter 混合开发集成步骤 :
在 Android Studio 中 , 在菜单栏中 , 选择 " File -> New -> New Project … " 选项 ;
选择创建 " Empty Activity " ;
这里要特别注意路径的设置 ,
Flutter Module 工程的路径是 : D:\002_Project\002_Android_Learn\flutter_hybrid\flutter_module
Android 工程的路径是 : D:\002_Project\002_Android_Learn\flutter_hybrid\flutter_native
上面两个工程的路径都在 D:\002_Project\002_Android_Learn\flutter_hybrid 目录下 ;
Android 应用创建完成 :
Android 工程 与 Flutter Module 工程 , 都在同一个目录中 ;
Android 工程的路径 与 Flutter Module 工程路径 , 否符合如下要求 :
在 Android 工程的 settings.gradle 进行如下配置 : 这样配置后 , Flutter 工程就会被编译成一个 Android Library Module , 名称是 flutter ;
rootProject.name = "flutter_native"
include ':app'
setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir.parentFile,
'flutter_module/.android/include_flutter.groovy'
))
include ':flutter_module'
project(':flutter_module').projectDir = new File('../flutter_module')
在 Android Module 下的 build.gradle 中 :
① 配置最低支持版本 minSdkVersion 16+ , 因为 Flutter 最低支持版本是 16 ;
// Flutter 最低支持版本是 16
minSdkVersion 18
② 添加工程依赖 :
// 在 settings.gradle 中配置的脚本 , 会自动关联到 Flutter 模块
implementation project(':flutter')
完整的配置文件如下 :
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.flutter_native"
// Flutter 最低支持版本是 16
minSdkVersion 18
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
// 在 settings.gradle 中配置的脚本 , 会自动关联到 Flutter 模块
implementation project(':flutter')
}
将 io.flutter.embedding.android.FlutterActivity 配置到 AndroidManifest.xml 清单文件中 ;
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize" />
完整配置文件如下 :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.flutter_native">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Flutter_native">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize" />
</application>
</manifest>
在 Activity 中 , 将 Flutter 页面作为 Fragment , 嵌入到 Activity 中 ;
findViewById(R.id.flutter1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
// 创建 FlutterFragment
fragmentTransaction.replace(R.id.frame, FlutterFragment.createDefault());
fragmentTransaction.commit();
}
});
执行结果 :
将 Flutter 页面当做一个新的 Activity 启动 ;
findViewById(R.id.flutter2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = FlutterActivity
.withNewEngine()
.initialRoute("Android 启动 FlutterActivity")
.build(MainActivity.this);
//intent.putExtra("initParams", "Android 中 Activity 启动 Flutter");
startActivity(intent);
}
});
执行结果 : 点击 方式二 按钮 , 弹出 FlutterActivity ;
这里只贴出主界面完整代码 , 具体的配置参数 , 查看 GitHub 或者 CSDN 源码快照 ;
package com.example.flutter_native;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterFragment;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.flutter1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
// 创建 FlutterFragment
fragmentTransaction.replace(R.id.frame, FlutterFragment.createDefault());
fragmentTransaction.commit();
}
});
findViewById(R.id.flutter2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = FlutterActivity
.withNewEngine()
.initialRoute("Android 启动 FlutterActivity")
.build(MainActivity.this);
//intent.putExtra("initParams", "Android 中 Activity 启动 Flutter");
startActivity(intent);
}
});
}
}
import 'package:flutter/material.dart';
import 'dart:ui';
void main() => runApp(
/// 该构造方法中传入从 Android 中传递来的参数
MyApp(initParams: window.defaultRouteName,)
);
class MyApp extends StatelessWidget {
/// 这是从 Android 中传递来的参数
final String initParams;
/// 构造方法 , 获取从 Android 中传递来的参数
const MyApp({Key? key, required this.initParams}):super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: initParams),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
参考资料 :
重要的专题 :
博客源码下载 :