前言

我们在写 flutter 项目时每次执行 pub clean.android 项目同样会重新创建,在我们项目中遇到minSdkVersion 默认(17)kotlin 默认 (1.3.50) 版本低,相信大家都遇到过,每次都需要手动设置,考虑这种手动操作繁琐让我团队成员不胜其扰。通过 py 脚本一键处理这个问题,大家也就能愉快开发了~😆

minSdkVersion 版本问题

iShot2022-03-07 22.25.13.png

kotlin 版本问题

iShot2022-03-07 22.45.30.png

思考

之前我们手动修改 flutter 自动生成的 build.gradle 的模板文件,具体可以看这里 传送门。但每次都需要自己去手动去修改模板文,文件路径打开比较麻烦,并且我们更新 flutter 版本后这里也会重置掉。既然如此我想通过 Python 脚本自动去生成对应的模板文件覆盖即可。

使用

方式一

  • 配置好 ssh 工具 shuttle 一键执行,其实 shuttle 的命令是用 json 来设置,可以结合 [jsonnet](https://github.com/google/jsonnet) 去动态生成,这样就可以复用给别人

image.png

  • 当然我们也可以直接终端执行,不过需要自己写好对应的路径相对麻烦些如下, 所以我更推荐使用 ssh 工具 shuttle 一键执行。
    1. cd /Users/zhengzeqin/Desktop/GitLab/TWHouseScript; python flutter_android_build_gradle_set.py -p '/Users/addcn/flutter/packages/flutter_tools/templates/module/android/gradle/build.gradle.tmpl' -a /Users/addcn/flutter/packages/flutter_tools/templates/module/android/host_app_common/app.tmpl/build.gradle.tmpl

方式二

路径我们也可以写在脚本里,定义好需要修改的 flutter sdk 的目标模板路径即可,具体如下

  1. # 定义 flutter 目标 android project build_gradle 配置的路径
  2. _project_build_gradle_set_file = "/Users/zhengzeqin/flutter/packages/flutter_tools/templates/module/android/gradle/build.gradle.tmpl"
  3. # 定义 flutter 目标 android app build_gradle 配置的路径
  4. _app_build_gradle_set_file = "/Users/zhengzeqin/flutter/packages/flutter_tools/templates/module/android/host_app_common/app.tmpl/build.gradle.tmpl"
  5. # 定义需要写入的 android project 根目录的 build_gradle 配置
  6. _build_gradle_tmpl_for_project = "/build_gradle_tmpl_for_project.txt"
  7. # 定义需要写入的 android app 目录的 build_gradle 配置
  8. _build_gradle_tmpl_for_app = "/build_gradle_tmpl_for_app.txt"
  9. # ...
  10. if __name__ == "__main__":
  11. # 执行脚本路径修改 Android build gradle 的目标模板
  12. set_android_build_gradle_params_files()
  13. pass

完整脚本代码

自定义 Android Project 的 build gradle 模板

  1. def flutterPluginVersion = 'managed'
  2. apply plugin: 'com.android.application'
  3. android {
  4. compileSdkVersion 31
  5. compileOptions {
  6. sourceCompatibility JavaVersion.VERSION_1_8
  7. targetCompatibility JavaVersion.VERSION_1_8
  8. }
  9. defaultConfig {
  10. applicationId "{{androidIdentifier}}.host"
  11. minSdkVersion 21
  12. targetSdkVersion 31
  13. versionCode 1
  14. versionName "1.0"
  15. }
  16. buildTypes {
  17. profile {
  18. initWith debug
  19. }
  20. release {
  21. // TODO: Add your own signing config for the release build.
  22. // Signing with the debug keys for now, so `flutter run --release` works.
  23. signingConfig signingConfigs.debug
  24. }
  25. }
  26. }
  27. buildDir = new File(rootProject.projectDir, "../build/host")
  28. dependencies {
  29. implementation project(':flutter')
  30. implementation fileTree(dir: 'libs', include: ['*.jar'])
  31. implementation 'androidx.appcompat:appcompat:1.0.2'
  32. implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
  33. }

自定义 Android App 的 build gradle 模板

  1. // Generated file. Do not edit.
  2. buildscript {
  3. ext.kotlin_version = '1.6.10'
  4. repositories {
  5. google()
  6. mavenCentral()
  7. }
  8. dependencies {
  9. classpath 'com.android.tools.build:gradle:{{agpVersion}}'
  10. classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
  11. classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
  12. }
  13. }
  14. allprojects {
  15. repositories {
  16. google()
  17. mavenCentral()
  18. }
  19. }
  20. task clean(type: Delete) {
  21. delete rootProject.buildDir
  22. }

需要修改的 Flutter 目标模板

image.png

脚本代码

  1. # -*- coding: utf-8 -*-
  2. # -*- author: zhengzeqin -*-
  3. # -*- date: 2022-03-07 -*-
  4. """
  5. Flutter 修改默认生成的 minSdkVersion 问题
  6. flutter pub get 会自动生成 android 目录,但是如果要修改 build.gradle 文件里面的内容,需要每次都要手动改一下,很麻烦
  7. 解决办法
  8. 修改 flutter 自动生成的 build.gradle 的模板文件
  9. 模板文件路径: flutter_sdk/packages/flutter_tools/templates/module/android/host_app_common/app.tmpl/build.gradle.tmpl
  10. py 解决思路: 通过脚本一键复制修改 flutter 配置模板
  11. """
  12. import os
  13. import sys
  14. import getopt
  15. # 定义 flutter 目标 android project build_gradle 配置的路径
  16. _project_build_gradle_set_file = "/Users/zhengzeqin/flutter/packages/flutter_tools/templates/module/android/gradle/build.gradle.tmpl"
  17. # 定义 flutter 目标 android app build_gradle 配置的路径
  18. _app_build_gradle_set_file = "/Users/zhengzeqin/flutter/packages/flutter_tools/templates/module/android/host_app_common/app.tmpl/build.gradle.tmpl"
  19. # 定义需要写入的 android project 根目录的 build_gradle 配置
  20. _build_gradle_tmpl_for_project = "/build_gradle_tmpl_for_project.txt"
  21. # 定义需要写入的 android app 目录的 build_gradle 配置
  22. _build_gradle_tmpl_for_app = "/build_gradle_tmpl_for_app.txt"
  23. # 读取文件内容
  24. def readfile(file_name):
  25. file2 = open(file_name)
  26. str = file2.read()
  27. file2.close()
  28. return str
  29. # 设置 build_gradle 的内容
  30. def android_gradle_set():
  31. # 获取当前文件路径
  32. concurrent = os.path.abspath(os.path.dirname(__file__))
  33. read_file_path = concurrent + '/build_gradle_tmpl_for_project.txt'
  34. write_file_path = concurrent + '/build.gradle.tmpl'
  35. read_file = open(read_file_path, 'r')
  36. write_file = open(write_file_path, "w")
  37. s = read_file.read()
  38. w = write_file.write(s)
  39. read_file.close()
  40. write_file.close()
  41. # 从文件路径中写入到目标文件
  42. def set_build_gradle_file(read_file_path, write_file):
  43. read_file = open(read_file_path, 'r')
  44. write_file = open(write_file, "w")
  45. s = read_file.read()
  46. write_file.write(s)
  47. read_file.close()
  48. write_file.close()
  49. # 获取当前文件夹的路径
  50. def get_current_path():
  51. return os.path.abspath(os.path.dirname(__file__))
  52. # 设置 app 的 file
  53. def set_app_build_gradle_file():
  54. read_file_path = get_build_gradle_file(_build_gradle_tmpl_for_app)
  55. set_build_gradle_file(read_file_path, _app_build_gradle_set_file)
  56. # 设置 project 根目录的 file
  57. def set_pro_build_gradle_file():
  58. read_file_path = get_build_gradle_file(_build_gradle_tmpl_for_project)
  59. set_build_gradle_file(read_file_path, _project_build_gradle_set_file)
  60. # 读取本地配置文件
  61. def get_build_gradle_file(build_gradle_tmpl):
  62. concurrent = os.path.abspath(os.path.dirname(__file__))
  63. read_file_path = concurrent + build_gradle_tmpl
  64. return read_file_path
  65. # 通过本地文件配置路径修改 Android 项目的 build_gradle 配置
  66. def set_android_build_gradle_params_files():
  67. set_pro_build_gradle_file()
  68. set_app_build_gradle_file()
  69. # 通过参数配置路径修改 Android 项目的 build_gradle 配置
  70. def set_android_build_gradle_argv_files():
  71. argv = sys.argv[1:]
  72. # android project build_gradle 配置的路径
  73. project_path = ""
  74. # android app build_gradle 配置的路径
  75. app_path = ""
  76. # 默认关闭
  77. is_close_bitcode = True
  78. try:
  79. opts, args = getopt.getopt(argv, "p:a:", ["project=", "app="])
  80. except getopt.GetoptError:
  81. print('flutter_android_gradle_set.py -p "项目路径"')
  82. sys.exit(2)
  83. print("opts ===>", opts)
  84. for opt, arg in opts:
  85. if opt in ["-p", "--project"]:
  86. project_path = arg
  87. if opt in ["-a", "--app"]:
  88. app_path = arg
  89. # 设置 project build gradle
  90. read_pro_file_path = get_build_gradle_file(_build_gradle_tmpl_for_project)
  91. set_build_gradle_file(read_pro_file_path, project_path)
  92. # 设置 app build gradle
  93. read_app_file_path = get_build_gradle_file(_build_gradle_tmpl_for_app)
  94. set_build_gradle_file(read_app_file_path, app_path)
  95. if __name__ == "__main__":
  96. # set_android_build_gradle_params_files()
  97. set_android_build_gradle_argv_files()
  98. pass

脚本地址