原生Android项目添加Flutter Module
公司原先iOS和Android都用原生开发,效率低成本高。 于是和team中的App开发小伙伴讨论了一下,决定用Flutter改进。 又不能一下子把整个原生App废弃,于是决定把一个相对独立的模块用Flutter实现后,导入到原生项目中。
这里记录下用Flutter实现一个module并导入Android原生项目的过程。
1: 安装Android Studio,新建一个Android原生项目
2:下载Flutter SDK,添加环境变量,参考:https://flutter.cn/docs/get-started/install
运行Flutter doctor,查看安装情况。 如遇以下异常
可通过Android Studio安装以下组件解决
为Android Studio安装Flutter插件
3:通过Android Studio新建Flutter Module, new flutter project ->
选择Flutter SDK地址
注意Project Type选择Module
4:配置原生Android项目
根目录下的settings.gradle 文件尾部加入以下配置。 其中的FlutterModule为路径,假设Flutter Module和Native Android项目在同一级目录
setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir.parentFile,
'FlutterModule/.android/include_flutter.groovy'
))
以下配置为了解决Error:repository 'maven' was added by plugin class 'FlutterPlugin', 参考:https://github.com/flutter/flutter/issues/85014
根目录下的build.gradle增加
allprojects {
repositories {
google()
jcenter()
}
}
根目录下的settings.gradle,dependencyResolutionManagement -> repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
替换为repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
在使用flutter module的Android module下的build.gradle中dependencies添加
implementation project(path: ':flutter')
5:build项目
6:
AndroidManifest.xml中增加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:theme="@style/Theme.NativeApp.NoActionBar"
android:windowSoftInputMode="adjustResize" >
</activity>
参考:https://docs.flutter.dev/development/add-to-app/android/project-setup
但是
实测下来,自己写配置导入的方式不work,运行项目的时候会报错。 所以尝试用Android Studio自带的导入
导入后可在导航栏中见到
并且可以运行
!注意,必须全程在VPN环境下安装,否则会出现某些依赖,如io.flutter.embedding.android.FlutterActivity
添加FlutterActivity
参考:https://blog.csdn.net/mengks1987/article/details/109321951
修改MainActivity.kt, 代码如下
package com.example.myapplication
import android.content.Intent
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import android.view.Menu
import android.view.MenuItem
import com.example.myapplication.databinding.ActivityMainBinding
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnNext.setOnClickListener {
startActivity(Intent(this,SecondFlutterActivity::class.java))
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
}
修改res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Theme.MyApplication.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="226dp"
android:background="?attr/colorPrimary"
app:popupTheme="@style/Theme.MyApplication.PopupOverlay" />
<Button
android:id="@+id/btnNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Go to page 2" />
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
添加SecondFlutterActivity.kt
package com.example.myapplication
import io.flutter.embedding.android.FlutterActivity
class SecondFlutterActivity:FlutterActivity() {
}
res/layout/下添加second_flutter_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondFlutterActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Theme.MyApplication.AppBarOverlay">
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
运行后效果如下
单击"go to page 2"