之前在物理设备(API 31 - 33)上测试成功的源代码,现在在 AVD Android Studio 模拟器(Pixel 4 API 34)上测试时,会出现异常:
FATAL EXCEPTION: main
Process: com.org.project, PID: 11295
java.lang.NoSuchMethodError: No virtual method indent(I)Ljava/lang/String; in class
Ljava/lang/String; or its super classes (declaration of 'java.lang.String' appears in
/apex/com.android.art/javalib/core-oj.jar)
at
这些是模拟器属性:
Properties
avd.ini.displayname Pixel 5 API 33 2
avd.ini.encoding UTF-8
AvdId Pixel_5_API_33_2
disk.dataPartition.size 6442450944
fastboot.chosenSnapshotFile
fastboot.forceChosenSnapshotBoot no
fastboot.forceColdBoot no
fastboot.forceFastBoot yes
hw.accelerometer yes
hw.arc false
hw.audioInput yes
hw.battery yes
hw.camera.back virtualscene
hw.camera.front emulated
hw.cpu.ncore 4
hw.device.hash2 MD5:3274126e0242a0d86339850416b0ce34
hw.device.manufacturer Google
hw.device.name pixel_5
hw.dPad no
hw.gps yes
hw.gpu.enabled yes
hw.gpu.mode auto
hw.initialOrientation Portrait
hw.keyboard yes
hw.lcd.density 440
hw.lcd.height 2340
hw.lcd.width 1080
hw.mainKeys no
hw.ramSize 1536
hw.sdCard yes
hw.sensors.orientation yes
hw.sensors.proximity yes
hw.trackBall no
image.androidVersion.api 33
image.sysdir.1 system-images\android-33\google_apis\x86_64\
PlayStore.enabled false
runtime.network.latency none
runtime.network.speed full
showDeviceFrame yes
skin.dynamic yes
tag.display Google APIs
tag.id google_apis
vm.heapSize 228
在项目内查看Java源代码时,方法就在那里:
/**
* a comment explaining the method...
* @since 12
*/
public String indent(int n) {
if (isEmpty()) {
return "";
}
Stream<String> stream = lines();
if (n > 0) {
final String spaces = " ".repeat(n);
stream = stream.map(s -> spaces + s);
} else if (n == Integer.MIN_VALUE) {
stream = stream.map(s -> s.stripLeading());
} else if (n < 0) {
stream = stream.map(s -> s.substring(Math.min(-n, s.indexOfNonWhitespace())));
}
return stream.collect(Collectors.joining("\n", "", "\n"));
}
据我所知,Android 对标准库的专有使用在 Java 11 时停止了。
从那时起,添加了额外的 Gradle/编译/插件选项,以利用属于 11 以上版本的 Java 工具。这些是本项目中使用的配置:
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.gms.google-services'
}
android {
namespace 'com.me.myproject'
compileSdk 34
defaultConfig {
applicationId "com.me.myproject"
minSdkVersion 26
targetSdkVersion 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
}
dependencies {
testImplementation 'junit:junit:4.13.2'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.3' // << This is the main plugin in charge of compatibility.
}
apply plugin: 'kotlin-android'
此特定模拟器正在使用 Android Studio 的计算机上运行,该 Android Studio 管理与 IDE 捆绑在一起的 Java 库。在我看来,Android Studio(和其他 IntelliJ 产品)将此 JDK 分配给在此 IDE 中打开的每个项目。
这意味着 Gradle、编译器甚至 IDE 上使用的 Java 运行时都使用“合成”JAVA_HOME,而且也是由 IDE 配置分配的合成 Gradle。 这样 IDE 执行的任何操作都会作用于这些自动生成的全局变量,即为每个项目分配一个变量。
这使得诸如
检查 Java 版本或运行 Gradle 命令之类的任务变得非常困难,因为人们无法使用 Windows 的 CLI,甚至无法使用 Android Studio 本身在“终端”选项卡下提供的 CLI...它使用默认的 Windows PowerShell。
这就是为什么我发现 Gradle 文档几乎毫无意义,因为该文档是在假设机器中安装了完整的 Gradle 程序的情况下编写的。Android Studio有一个Gradle插件,它有一个CLI,这个CLI(有点隐藏)是唯一可以处理这些自动生成的变量的,所以,任何需要在Gradle上运行的任务都需要通过这个来完成CLI.
对于与 JVM 所需的任何交互,我发现与其有效交互的唯一方法是通过一些 UI 面板。
其中一个位于“项目结构”中,另一个位于 IDE“设置”中,另一个通过右键单击测试类来定义“VM 选项”。
build.gradle
文件中修复。
对于在模拟器的 ART(Android 运行时)中运行的 JVM,没有提供让您选择特定 JDK 的选项。
我认为答案可能在于其中一些配置,也许答案在于某些
build.gradle
配置。
现已在 AVD Android Studio 模拟器(Pixel 4 API 34)上进行测试这与您所显示的模拟器属性不符。特别是,这些属性表明 API 级别是 33,而不是 34:
avd.ini.displayname Pixel 5 API 33 2
AvdId Pixel_5_API_33_2
image.androidVersion.api 33
image.sysdir.1 system-images\android-33\google_apis\x86_64\
indent()
已添加到 API 级别 34 的 Android SDK 中。我不希望在您的模拟器映像上找到
indent()
。