使用场景:android原生页面直接跳转flutter功能页面
实现方式:
1. 将flutter代码打包成aar引入android项目,flutter代码对原生不可见
2. 将flutter代码引入android项目,flutter代码对原生可见
flutter module项目是可以单独运行的,项目结构同flutter Application类似,只不过这里是.android和.ios。
按如下路径对module进行打包,打包完成后会生成系统的aar集成提示。
其中:
①aar生成的路径,如下图
②③④原生项目需要相应添加的代码
①:直接拷贝过来,repo文件是aar生成的路径
②:maven直接引用你本地的aar文件夹路径,这里是放在了app目录下。
代码:
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
}
}
allprojects {
String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
repositories {
google()
jcenter()
maven {
url 'repo' //这里引用你本地的aar文件夹路径
}
maven {
url "$storageUrl/download.flutter.io"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
③④:引用aar依赖
plugins {
id 'com.android.application'
}
android {
compileSdk 30
defaultConfig {
//compileSdk 30编译失败解决
configurations.all {
resolutionStrategy { force 'androidx.media2:media2-session:1.1.3' }
resolutionStrategy { force 'androidx.media2:media2-common:1.1.3' }
resolutionStrategy { force 'androidx.core:core:1.6.0' }
resolutionStrategy { force 'androidx.core:core-ktx:1.6.0' }
}
applicationId "com.example.aar_local"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
multiDexEnabled true
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
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//aar依赖
debugImplementation 'com.example.flutter_module:flutter_debug:1.0'
releaseImplementation 'com.example.flutter_module:flutter_release:1.0'
}
另外settings.gradle:
rootProject.name = "aar_local"
include ':app'
同实现方式一。
settings.gradle添加:
//引入flutter_module
//使用方式
//startActivity(FlutterActivity.withNewEngine().build(MainActivity.this));
rootProject.name = "shukuang_jiangning"
include ':app'
setBinding(new Binding([gradle: this]))
//这里是当前flutter_module的位置,最好是把flutter module放在和当前android项目平级的文件夹里面
evaluate(new File(
settingsDir.parentFile,
'flutter_module/.android/include_flutter.groovy'
))
include ':flutter_module'
project(':flutter_module').projectDir = new File('../flutter_module')
app/build.gradle添加:
dependencies {
//flutter引用
implementation project(':flutter')
}
AndroidManifest.xml添加:
flutter main.dart:
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:jk_framework/jk_framework.dart';
import 'package:module_alarm_record/ui/alarm_record_page.dart';
import 'package:module_monitor_new/ui/monitor_page.dart';
import 'package:module_inspection/ui/task/station/show/home/task_list_page.dart';
import 'package:module_video/ui/video_home_page.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
//初始化存储管理
await StorageManager.initSP();
EventbusManager.init();
config();
runApp(MyApp(initParams: window.defaultRouteName));
}
///配置主机地址
void config() {
// 海康环境配置
CacheManager.put('videoBaseUrl', 'xxx');
CacheManager.put('videoAppKey', 'xxx');
CacheManager.put('videoAppSecret', 'xxx');
//接口地址
CacheManager.put('baseUrl', 'xxx');
//配置图片前缀
CacheManager.put('baseImageUrl', 'xxx');
// 配置待办流程为h5时的ip地址
CacheManager.put('baseWebUrl', 'xxx');
}
class MyApp extends StatefulWidget {
final String? initParams;
const MyApp({Key? key, this.initParams}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'flutter_module',
home: _createJumpPage(),
);
}
//配置不同的跳转页面,这里接收原生token
Widget _createJumpPage() {
Map initParams = {};
try {
initParams = json.decode(widget.initParams ?? '');
} catch (e) {
return MyHomePage(title: 'Flutter Demo Home Page');
}
Map params = initParams;
String route = params['route'];
String token = params['token'];
CacheManager.put(CacheManager.token, token);
if (route.contains('module_video')) {
return DMVideoPage();
} else if (route.contains('module_inspection')) {
return TaskListPage();
} else if (route.contains('module_monitor')) {
return DMMonitorPage();
} else if (route.contains('module_alarm')) {
return AlarmRecordPage();
} else {
return MyHomePage(title: 'Flutter Demo Home Page');
}
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
int _counter = 0;
@override
void initState() {
super.initState();
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
leading: BackButton(
onPressed: () {
SystemNavigator.pop();
},
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
android MainActivity.java:
package com.example.aar_local;
import androidx.appcompat.app.AppCompatActivity;
import io.flutter.embedding.android.FlutterActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
//模拟跳转
String token = "xxx";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startActivity(
FlutterActivity
.withNewEngine()
.initialRoute("{\"route\":\"module_video\", \"token\": \"" + token + "\"}")
// .initialRoute("{\"route\":\"module_monitor\", \"token\": \"" + token + "\"}")
// .initialRoute("{\"route\":\"module_inspection\", \"token\": \"" + token + "\"}")
.build(MainActivity.this)
);
}
}
android AndroidManifest.xml: