记录一个ios开发者使用flutter开发者运行安卓模拟器的痛苦经历

使用安卓模拟器启动flutter项目或者执行build apk --release --no-pub始终报了一个错误,百度了各大网页,对于安卓0经验开发的人来说还是一脸的迷茫,所以今天记录一下,便于帮助其他遇到同样问题的IOS开发者走出困境:

Execution failed for task ':app:processDebugMainManifest'.Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not "opens java.io" to unnamed module @ffea291

一、报错内容

android studio点击debug main.dart爬虫按钮:

报错内容如下:

vbnet 复制代码
Launching lib/main.dart on sdk gphone64 arm64 in debug mode...
Running Gradle task 'assembleDebug'...

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:processDebugMainManifest'.
> Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not "opens java.io" to unnamed module @ffea291

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 3s
Exception: Gradle task assembleDebug failed with exit code 1

二、flutter tools调试

通过使用flutter_tools调试

方法为: /packages/flutter_tools/lib/src/android/gradle.dart

dart 复制代码
Future<void> buildGradleApp({
  required FlutterProject project,
  required AndroidBuildInfo androidBuildInfo,
  required String target,
  required bool isBuildingBundle,
  required List<GradleHandledError> localGradleErrors,
  required bool configOnly,
  bool validateDeferredComponents = true,
  bool deferredComponentsEnabled = false,
  int retry = 0,
  @visibleForTesting int? maxRetries,
})

主要执行的功能为:

yaml 复制代码
final String? javaHome = globals.androidSdk?.javaHome;
 exitCode = await _processUtils.stream(
   command,
   workingDirectory: project.android.hostAppGradleRoot.path,
   allowReentrantFlutter: true,
   environment: <String, String>{
     if (javaHome != null)
       AndroidSdk.javaHomeEnvironmentVariable: javaHome,
   },
   mapFunction: consumeLog,
 );

打印command 命令为

三、gradlew 命令解析

意思就是说执行flutter android工程下的 gradlew 命令 查看一下gradle是一个shell 脚本

在这个文件最后倒数第二行添加日志打印:

bash 复制代码
echo "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

重新执行 flutter run --debug

可以看到 通过flutter run --debug 运行安卓模拟器,本质上是需要执行gradle打包app命令 gradlew,格式化看的清楚一些:

ini 复制代码
/Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java

 -Xdock:name=Gradle 

 -Xdock:icon=/Users/axx/Desktop/carrier_project_name/android/media/gradle.icns 

 -Dorg.gradle.appname=gradlew 


 -classpath /Users/axx/Desktop/carrier_project_name/android/gradle/wrapper/gradle-wrapper.jar 

 org.gradle.wrapper.GradleWrapperMain 

 -q 

 -Ptarget-platform=android-arm64 

 -Ptarget=/Users/axx/Desktop/carrier_project_name/lib/main.dart 

 -Pbase-application-name=android.app.Application 

 -Pdart-defines=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9jZGJlZGE3ODhhMjkzZmEyOTY2NWRjM2ZhM2Q2ZTYzYmQyMjFjYjBkLw== 

 -Pdart-obfuscation=false 

 -Ptrack-widget-creation=true 

 -Ptree-shake-icons=false 

 -Pfilesystem-scheme=org-dartlang-root 

 assembleDebug

意思就是通过java 来驱动启动app

四、错误分析

4.1 Android SDK & ndk 版本下载

cmd + ,打开android studio 设置,下载Android sdk版本, ndk版本

android sdk 30,31,33版本 以及 ndk 21.1.6352462都是为了能尝试解决问题下载的版本

4.2 Project Structure设置

打开android studio菜单,file 菜单,下面选择Project Structure,打开Project Structure设置窗框:

当前Module SDK版本设置: 选择Module SDK设置为 API 33版本:

点击edit 选择 android api 版本:

把不要的都删了, 这里只留了 API 33的版本。

API language 没有改,默认啥样子就还是什么样

4.3 android 模拟器设备管理Device Manager

从菜单选择tools,点击 Device Manager

点击添加设备

选择手机,选择一个合适尺寸的模拟器:

这里我下载了 api Level 33的 image镜像:

点击API33,完成设备添加:

点击启动按钮

这样就把安卓模拟器 模拟器启动好了

4.4 修改 build.gradle中的 kotlin_version 和 gradle版本

回到开始的报错:

FAILURE: Build failed with an exception.

  • What went wrong: Execution failed for task ':app:processDebugMainManifest'.

Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not "opens java.io" to unnamed module @ffea291

通过上面分析,是java执行命令出错了

bash 复制代码
which java

输出如下:

bash 复制代码
/usr/bin/java

执行 gradlew

java 命令为 Android Studio.app目录下的java 命令。

gradlew脚本内容如下:

bash 复制代码
echo "JAVA_HOME=$JAVA_HOME"

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

通过添加echo "JAVA_HOME=$JAVA_HOME"日志

JAVA_HOME=/Applications/Android Studio.app/Contents/jbr/Contents/Home

这个JAVA_HOME 在什么时候赋值了呢?

回到上面flutter tools启动命令的过程

yaml 复制代码
final String? javaHome = globals.androidSdk?.javaHome;
exitCode = await _processUtils.stream(
  command,
  workingDirectory: project.android.hostAppGradleRoot.path,
  allowReentrantFlutter: true,
  environment: <String, String>{
    if (javaHome != null)
      AndroidSdk.javaHomeEnvironmentVariable: javaHome,
  },
  mapFunction: consumeLog,
);

则是在flutter tools执行时,通过android studio 的安装目录,自动动态获取的路径:

arduino 复制代码
static const String javaHomeEnvironmentVariable = 'JAVA_HOME';

那么看看java 版本是多少:

bash 复制代码
/Applications/Android\ Studio.app/Contents/jbr/Contents/Home/bin/java --version

输出:

java 复制代码
openjdk 17.0.6 2023-01-17

OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

OpenJDK 64-Bit Server VM (build 17.0.6+0-17.0.6b829.9-10027231, mixed mode)

到此,我们知道我们的 flutter run --debug的启动过程时通过java 执行gradlew 打包的过程

并且或者我们的java 版本是17

参考一下文章 www.kuazhi.com/post/425519...

最后 通过 修改 android/build.gradle 文件:

bash 复制代码
buildscript {
    ext.kotlin_version = '1.9.0'
    repositories {
        google()
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:7.2.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

旧的配置: ext.kotlin_version = '1.6.10' classpath 'com.android.tools.build:gradle:4.1.0'

修改为新的配置: ext.kotlin_version = '1.9.0' classpath 'com.android.tools.build:gradle:7.2.0'

这里如果不修改 kotlin版本,则会报错:

vbnet 复制代码
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugKotlin'.
> Compilation error. See log for more details

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 10s

┌─ Flutter Fix ──────────────────────────────────────────────────────────────────────────────┐
│ [!] Your project requires a newer version of the Kotlin Gradle plugin.                     │
│ Find the latest version on https://kotlinlang.org/docs/releases.html#release-details, then │
│ update /Users/axx/Desktop/carrier_project_name/android/build.gradle:                       │
│ ext.kotlin_version = '<latest-version>'                                                    │
└────────────────────────────────────────────────────────────────────────────────────────────┘
Exception: Gradle task assembleDebug failed with exit code 1

通过访问 kotlinlang.org

看到Kotlin 当前 最新版本为1.9.0 ,所以修改为此配置。

重新运行,终于OK了。

总结

  • 安卓项目的启动是通过flutter tools找到 java_home 环境,即使用android studio app 程序下的java环境启动 gradlew 编译app。
  • flutter tools java bin path AndroidSdk.javaHomeEnvironmentVariable是通过本机安装的androd studio应用程序安装目录。为
yaml 复制代码
 _processUtils.stream(
command,
workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true,
environment: <String, String>{
  if (javaHome != null)
    AndroidSdk.javaHomeEnvironmentVariable: javaHome,
},
mapFunction: consumeLog,
);
  • gradlew 为一个shell程序,启动命令为JAVA_HOME=/Applications/Android Studio.app/Contents/jbr/Contents/Home /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java -Xdock:name=Gradle -Xdock:icon=/Users/axx/Desktop/carrier_project_name/android/media/gradle.icns -Dorg.gradle.appname=gradlew -classpath /Users/axx/Desktop/carrier_project_name/android/gradle/wrapper/gradle-wrapper.jar org.gradle.wrapper.GradleWrapperMain -q -Ptarget-platform=android-arm64 -Ptarget=/Users/axx/Desktop/carrier_project_name/lib/main.dart -Pbase-application-name=android.app.Application -Pdart-defines=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9jZGJlZGE3ODhhMjkzZmEyOTY2NWRjM2ZhM2Q2ZTYzYmQyMjFjYjBkLw== -Pdart-obfuscation=false -Ptrack-widget-creation=true -Ptree-shake-icons=false -Pfilesystem-scheme=org-dartlang-root assembleDebug

  • 我的安卓stuio版本是Android Studio Giraffe | 2022.3.1则通过修改build.gradle配置文件的com.android.tools.build:gradle版本和kotlin_version版本解决 java 版本不匹配问题,即可成功运行项目或者打包apk

相关推荐
️ 邪神12 小时前
【Android、IOS、Flutter、鸿蒙、ReactNative 】文本点击事件
flutter·ios·鸿蒙·reactnative·anroid
️ 邪神13 小时前
【Android、IOS、Flutter、鸿蒙、ReactNative 】文本Text显示
flutter·ios·鸿蒙·reactnative·anroid
袁代码14 小时前
Swift 开发教程系列 - 第11章:内存管理和 ARC(Automatic Reference Counting)
开发语言·ios·swift·ios开发
海绵不是宝宝81714 小时前
IOS开发之MapKit定位国内不准的问题
ios
iFlyCai14 小时前
Flutter中有趣的级联语法
flutter
恋猫de小郭14 小时前
Flutter 小技巧之 Shader 实现酷炫的粒子动画
flutter
那就可爱多一点点16 小时前
如何处理 iOS 客户端内 Webview H5 中后台播放的音视频问题
ios·音视频
crasowas16 小时前
iOS问题记录 - 503 Service Temporarily Unavailable
ios·fastlane
货拉拉技术18 小时前
货拉拉是如何实现symbolic demangle?
ios·性能优化
hello world smile18 小时前
Dart中List API用法大全
flutter·list·dart