我想将我们的 Android 应用程序资产提取到一个Android 资产包中,因为我们超过了 150 MB AAB(Android 应用程序包)的大小限制。在进行测试时,我遵循了Android App Bundle Test Instructions并将我的 Android Studio Run/Debug 配置从 app bundle 更改为 APK。执行此更改后,我可以在运行时从资产包中找到资产,同时调试我的应用程序。
但是,后来在运行时,我意识到 JDK11 方法Optional.isEmpty
不再像以前使用 Run/Debug 配置Default APK时那样向后移植。这是它之前脱糖的方式。
C$r8$backportedMethods$utility$Optional$0$isEmpty.isEmpty(someVariable)
经过一些 Google 研究后,我将Desugaring 库合并到我的项目中,这实际上解决了这个反向移植问题。但是,当继续时,我意识到作为依赖项拉入 Android 应用程序的库的某些部分正在使用以下方法。
public static ConcurrentHashMap.KeySetView newKeySet()
根据this stackoverflow article,这是一个导致以下异常的已知问题。
Process: com.test.android_application, PID: 20849
java.lang.NoSuchMethodError: No static method newKeySet()Lj$/util/concurrent/ConcurrentHashMap$KeySetView; in class Lj$/util/concurrent/ConcurrentHashMap; or its super classes (declaration of 'j$.util.concurrent.ConcurrentHashMap')
这是我的 build.gradle 文件:
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
defaultConfig {
applicationId "com.myAndroidApp"
minSdkVersion 21
targetSdkVersion 30
versionName "MyApplication"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
ndk {
abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64"
}
}
signingConfigs {
debug {
storeFile file('debug_signing/debug.keystore')
storePassword androidDebugStorePassword
keyAlias 'androiddebugkey'
keyPassword androidDebugKeyPassword
}
release {
Properties releaseSigningProperties = new Properties()
def releasePropsFile = file(releaseApiKeyFile)
if (releasePropsFile.canRead()) {
releaseSigningProperties.load(new FileInputStream(releasePropsFile))
if (releaseSigningProperties != null) {
storeFile file(releaseStoreFile)
storePassword releaseSigningProperties['releaseStorePassword']
keyAlias releaseSigningProperties['releaseKeyAlias']
keyPassword releaseSigningProperties['releaseKeyPassword']
}
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
multiDexKeepFile file('multidex-config.txt')
signingConfig signingConfigs.release
}
debug{
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
multiDexKeepFile file('multidex-config.txt')
signingConfig signingConfigs.debug
}
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation group: 'com.myProject', name: 'internalDependency', version: '1.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.cardview:cardview:1.0.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
testImplementation 'junit:junit:4.13.1'
testImplementation 'org.hamcrest:hamcrest-library:1.3'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:core:1.4.0'
androidTestUtil 'androidx.test:orchestrator:1.4.0'
// Lifecycle components
def archLifecycleVersion = '2.2.0'
implementation "androidx.lifecycle:lifecycle-extensions:$archLifecycleVersion
}
运行配置Default APK仅向后移植该Optional.isEmpty
方法并保持public static ConcurrentHashMap.KeySetView newKeySet()
不变(未对其执行脱糖操作)。这是我也想从 app bundle 为 APK实现的行为。
我显然可以重写被拉入 Android 应用程序的库中的这段代码,但问题仍然存在,Gradle 任务的区别是应用程序安装选项Default APK和APK from app bundle之间的区别。
我已经找到了这篇文章,但没有详细介绍。
此外,在构建应用程序时还会执行以下 Gradle 任务:
Default APK : assembleDebug
APK from app bundle : extractApksForDebug