build.gradle.kts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import java.io.FileInputStream
  2. import java.util.Properties
  3. plugins {
  4. id("com.android.application")
  5. // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
  6. id("dev.flutter.flutter-gradle-plugin")
  7. }
  8. // 发布签名凭据放在 android/key.properties(和 mathtool2 同一套)。
  9. // 该文件和 key.jks 都已被 android/.gitignore 忽略,不会进仓库。
  10. val keystorePropertiesFile = rootProject.file("key.properties")
  11. val keystoreProperties = Properties()
  12. if (keystorePropertiesFile.exists()) {
  13. keystoreProperties.load(FileInputStream(keystorePropertiesFile))
  14. }
  15. android {
  16. namespace = "com.nonvioce.cal"
  17. compileSdk = flutter.compileSdkVersion
  18. compileOptions {
  19. sourceCompatibility = JavaVersion.VERSION_17
  20. targetCompatibility = JavaVersion.VERSION_17
  21. // Symja 使用 java.time(API 26 才有);minSdk 24 必须开 desugaring。
  22. // 注意:Ijs 在这一点上是错的(minSdk 24 却没开),这里顺手修掉。
  23. isCoreLibraryDesugaringEnabled = true
  24. }
  25. defaultConfig {
  26. applicationId = "com.nonvioce.cal"
  27. minSdk = 24
  28. targetSdk = flutter.targetSdkVersion
  29. versionCode = flutter.versionCode
  30. versionName = flutter.versionName
  31. // 光 Symja 就有约 42k 方法,必须 multiDex
  32. multiDexEnabled = true
  33. }
  34. signingConfigs {
  35. // 只有拿到凭据才建这个配置;否则下面的 release 退回调试签名,
  36. // 保证"没带 key.properties 的机器"上依然能构建。
  37. if (keystorePropertiesFile.exists()) {
  38. create("release") {
  39. keyAlias = keystoreProperties.getProperty("keyAlias")
  40. keyPassword = keystoreProperties.getProperty("keyPassword")
  41. storeFile = file(keystoreProperties.getProperty("storeFile"))
  42. storePassword = keystoreProperties.getProperty("storePassword")
  43. }
  44. }
  45. }
  46. buildTypes {
  47. release {
  48. signingConfig = if (keystorePropertiesFile.exists()) {
  49. signingConfigs.getByName("release")
  50. } else {
  51. signingConfigs.getByName("debug")
  52. }
  53. // 【真机实测的结论】不要对 Symja 开 R8 混淆。
  54. // Symja 及其依赖大量用「类名字符串」做反射创建,R8 看不到引用关系就会改名,
  55. // 运行时按原名找不到 -> 静态初始化直接炸。实测踩到两个:
  56. // 1. log4j2-android 的 com.celeral.android.logging.log4j.AndroidLoggerContextFactory
  57. // (由 system property "log4j2.loggerContextFactory" 指定)
  58. // 2. apfloat 的 org.apfloat.internal.LongBuilderFactory(由 "builderFactory" 属性指定)
  59. // -> F.<clinit> 抛 ExceptionInInitializerError
  60. // 官方的 Symja Android 参考工程 axkr/symja-example 同样不开 minify。
  61. // proguard-rules.pro 里的 -keep 规则保留着,将来若要重新开混淆可以从那里起步,
  62. // 但必须先在真机上回归。
  63. isMinifyEnabled = false
  64. isShrinkResources = false
  65. proguardFiles(
  66. getDefaultProguardFile("proguard-android-optimize.txt"),
  67. "proguard-rules.pro",
  68. )
  69. }
  70. }
  71. packaging {
  72. resources {
  73. excludes += setOf(
  74. "META-INF/DEPENDENCIES",
  75. "META-INF/LICENSE",
  76. "META-INF/LICENSE.txt",
  77. "META-INF/license.txt",
  78. "META-INF/NOTICE",
  79. "META-INF/NOTICE.txt",
  80. "META-INF/notice.txt",
  81. "META-INF/ASL2.0",
  82. "META-INF/*.kotlin_module",
  83. "Log4j2Plugins.dat",
  84. )
  85. pickFirsts += setOf(
  86. "**/*.xsd",
  87. )
  88. }
  89. // 只留 arm64-v8a 的原生库。
  90. //
  91. // 另外两条路都试过、都不行:
  92. // · defaultConfig 里写 ndk.abiFilters —— 实测三个 ABI 的 libflutter.so 照样全进包
  93. // · android/gradle.properties 里写 target-platform —— flutter_tools 会显式传
  94. // -Ptarget-platform=... (gradle.dart:581),命令行参数盖过 gradle.properties
  95. // 这里在 APK 组装阶段剔目录,Flutter 就管不着了。
  96. jniLibs {
  97. excludes += setOf(
  98. "lib/armeabi-v7a/**",
  99. "lib/x86/**",
  100. "lib/x86_64/**",
  101. )
  102. }
  103. }
  104. }
  105. kotlin {
  106. compilerOptions {
  107. jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
  108. }
  109. }
  110. dependencies {
  111. coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
  112. implementation("org.matheclipse:matheclipse-core:3.2.0")
  113. // log4j-api 在 Android 上需要一个实现,否则 Symja 的日志路径会抛错
  114. runtimeOnly("com.celeral:log4j2-android:1.0.0")
  115. // 用 Android 变体的 guava,避免 JRE 专属类(java.beans 等)
  116. implementation("com.google.guava:guava:33.5.0-android")
  117. // MCP 服务器用的内嵌 HTTP 服务器(JSON-RPC over HTTP)
  118. implementation("org.nanohttpd:nanohttpd:2.3.1")
  119. }
  120. configurations.all {
  121. resolutionStrategy {
  122. force("com.google.guava:guava:33.5.0-android")
  123. }
  124. }
  125. flutter {
  126. source = "../.."
  127. }