Flutter问题记录 - Unable to find bundled Java version(续)


前言

Flutter问题记录 - Unable to find bundled Java version文章中主要对Unable to find bundled Java version报错进行了分析,虽然从最终结果上看,Android端构建运行失败和出现这个报错的原因应该是一致的,但是没有进行原因分析。这里做一些简单分析作为上篇文章的补充。

开发环境

  • Android Studio: 2022.1.1
  • Flutter: 3.3.10

问题描述

Android端构建运行失败,报错信息如下:

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

2023/08/14更新:当前问题已被修复,如果你还遇到以上报错,可以参考这篇文章Android问题记录 - Unable to make field private final java.lang.String java.io.File.path accessible(持续更新)

问题分析

当我们在Android Studio中点击运行Flutter项目到Android设备时,控制台会输出:

Launching xxx.dart on xxx in debug mode...
Running Gradle task 'assembleDebug'...
...

当然,如果项目没执行过pub get,还会有这个输出:

Running "flutter pub get" in xxx...

对于Launching xxx.dart on xxx in debug mode...输出和要分析的问题没有什么关系,不过,如果你对整个运行流程感兴趣的话,可以在Flutter框架项目下的packages/flutter_tools/lib/src/resident_runner.dart文件中找到这个输出的相关代码:

final String modeName = coldRunner.debuggingOptions.buildInfo.friendlyModeName;
final bool prebuiltMode = coldRunner.applicationBinary != null;
globals.printStatus(
  'Launching ${getDisplayPath(coldRunner.mainPath, globals.fs)} '
  'on ${device!.name} in $modeName mode...',
);

对于Running Gradle task 'assembleDebug'...输出就是这次问题分析的关键了,在Flutter框架项目下搜索关键词Running Gradle task

screenshot1

上篇文章的问题分析可以知道,问题出在Android Studio移除了jre目录,进而导致javaPath的拼接出现了问题。那现在这问题会不会是因为运行Gradle task时也用到了错误的javaPath呢?继续在gradle.dart文件中搜索javaPath

gradle.dart文件中buildGradleApp方法的部分代码:

try {
  exitCode = await _processUtils.stream(
    command,
    workingDirectory: project.android.hostAppGradleRoot.path,
    allowReentrantFlutter: true,
    environment: <String, String>{
      if (javaPath != null)
        'JAVA_HOME': javaPath!,
    },
    mapFunction: consumeLog,
  );
} on ProcessException catch (exception) {
  consumeLog(exception.toString());
  // Rethrow the exception if the error isn't handled by any of the
  // `localGradleErrors`.
  if (detectedGradleError == null) {
    rethrow;
  }
} finally {
  status.stop();
}

可以看到,确实用到了javaPath,那这个和android_studio.dart文件里面的javaPath有什么关联吗?选中javaPath跳转定义的地方,发现来到了android_studio.dart文件,是一个顶级方法:

String? get javaPath => globals.androidStudio?.javaPath;

Dart的顶级方法意味着只要导入android_studio.dart文件,就可以直接调用javaPath方法。从方法定义中的javaPath继续跳转,来到了AndroidStudio类里面。

AndroidStudio类部分代码:

class AndroidStudio implements Comparable<AndroidStudio> {
  AndroidStudio(
    this.directory, {
    Version? version,
    this.configured,
    this.studioAppName = 'AndroidStudio',
    this.presetPluginsPath,
  }) : version = version ?? Version.unknown {
    _init(version: version);
  }
  
  String? _javaPath;
  bool _isValid = false;
  final List<String> _validationMessages = <String>[];

  String? get javaPath => _javaPath;

  void _init({Version? version}) {
    _isValid = false;
    _validationMessages.clear();

    if (configured != null) {
      _validationMessages.add('android-studio-dir = $configured');
    }

    if (!globals.fs.isDirectorySync(directory)) {
      _validationMessages.add('Android Studio not found at $directory');
      return;
    }

    final String javaPath = globals.platform.isMacOS ?
        version != null && version.major < 2020 ?
        globals.fs.path.join(directory, 'jre', 'jdk', 'Contents', 'Home') :
        globals.fs.path.join(directory, 'jre', 'Contents', 'Home') :
        globals.fs.path.join(directory, 'jre');
    final String javaExecutable = globals.fs.path.join(javaPath, 'bin', 'java');
    if (!globals.processManager.canRun(javaExecutable)) {
      _validationMessages.add('Unable to find bundled Java version.');
    } else {
      RunResult? result;
      try {
        result = globals.processUtils.runSync(<String>[javaExecutable, '-version']);
      } on ProcessException catch (e) {
        _validationMessages.add('Failed to run Java: $e');
      }
      if (result != null && result.exitCode == 0) {
        final List<String> versionLines = result.stderr.split('\n');
        final String javaVersion = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
        _validationMessages.add('Java version $javaVersion');
        _javaPath = javaPath;
        _isValid = true;
      } else {
        _validationMessages.add('Unable to determine bundled Java version.');
      }
    }
  }
}

继续在类里面搜索_javaPath,来到了AndroidStudio类的初始化方法_init

screenshot2

可以发现Android端构建运行和flutter doctor命令执行一样,也用到了AndroidStudio类里面拼接的javaPath。当Android Studio移除jre目录后,初始化androidStudio对象时拼接的javaPath路径有问题导致没有给_javaPath赋值,从而导致Android端构建运行时获取的javaPathnull。由此可以验证Android端构建运行失败的原因和出现Unable to find bundled Java version报错的原因是一致的。

解决方案

请看这篇文章Flutter问题记录 - Unable to find bundled Java version中的解决方案。

最后

如果这篇文章对你有所帮助,点赞👍加星🌟支持一下吧,谢谢~


本篇文章由@crasowas发布于CSDN。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Flutter是Google开发的一款跨平台框架,用于开发Android和iOS应用程序。在Windows上使用Flutter进行开发时,确保安装的Windows版本是1的版本是非常重要的。 如果您遇到了无法确认已安装的Windows版本是否是1版本的问题,可以通过以下步骤来解决: 1. 首先,打开计算机的“设置”选项。可以通过在桌面上右键单击并选择“设置”来打开它。 2. 在“设置”窗口中,选择“系统”选项。 3. 在“系统”选项中,选择“关于”选项。 4. 在“关于”页面中,您将找到计算机的详细信息,包括安装的Windows版本。检查该信息,确认是否为Windows 1版本。 如果您发现安装的Windows版本不是1版本,则需要更新您的Windows操作系统。对于Windows 1版本的安装,您可以通过以下步骤来更新您的操作系统: 1. 打开计算机的“设置”选项。 2. 选择“更新和安全”选项。 3. 在“更新和安全”窗口中,选择“Windows 更新”选项。 4. 在“Windows 更新”选项中,选择“检查更新”按钮。 5. 系统将自动检查更新并提供可用的更新。如果有更新可用,请选择“安装更新”按钮来更新您的Windows操作系统。 请注意,安装更新可能需要一段时间,视您的网络连接和计算机性能而定。一旦更新完成,您现在应该具有安装了Windows 1版本的操作系统。 总之,为了在Windows上使用Flutter进行开发,确保安装的Windows版本是1版本是至关重要的。通过按照上述步骤检查和更新Windows操作系统,您现在应该可以确认并确保安装的Windows版本是1版本。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值