带有产品风味和Kotlin的ClassNotFoundException

我有一个主要在Kotlin编写的项目,但有一些Java类。 现在项目进展顺利,我想增加在不同的环境之间切换的可能性,为此我使用了风味:

productFlavors { prod { dimension "default" buildConfigField 'boolean', 'FABRIC', 'true' applicationId = "com.myapp" } beta { dimension "default" buildConfigField 'boolean', 'FABRIC', 'true' applicationId = "com.myapp.beta" } dev { dimension "default" buildConfigField 'boolean', 'FABRIC', 'false' applicationId = "com.myapp.dev" } } 

然而,当我运行的味道是不生产(这不会改变applicationId),我得到一个Java类的ClassDefNotFoundException:

 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.myapp.beta.ui.view.ScrollBehavior" on path: DexPathList[[zip file "/data/app/com.myapp.beta-1/base.apk"],nativeLibraryDirectories=[/data/app/com.myapp.beta-1/lib/arm64, /system/lib64, /vendor/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:380) at java.lang.ClassLoader.loadClass(ClassLoader.java:312) ... 33 more 

我正在使用Android Studio 3.0 beta 4和Kotlin插件版本1.1.3-2。

构建文件:

 apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' // Use experimental kapt implementation repositories { mavenCentral() maven { url "http://dl.bintray.com/ttymsd/maven" } maven { url 'https://jitpack.io' } } android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { applicationId "com.myapp" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } sourceSets { main.java.srcDirs += 'src/main/java' } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } flavorDimensions "default" productFlavors { prod { dimension "default" buildConfigField 'boolean', 'FABRIC', 'true' applicationId = "com.myapp" } beta { dimension "default" buildConfigField 'boolean', 'FABRIC', 'true' applicationId = "com.myapp.beta" } dev { dimension "default" buildConfigField 'boolean', 'FABRIC', 'false' applicationId = "com.myapp.dev" } } dataBinding { enabled = true } dependencies { (...) } } 

表现:

             

代码中的相关部分:

  

你正在定义你的行为

 app:layout_behavior=".ui.view.ScrollBehavior" 

这是一个相对的定义。 在这种情况下,相对于应用程序包。

所以实际使用的名称是context.getPackageName() + name ,因此您定义的应用程序ID被用作前缀。

要加载正确的行为,您必须将其定义为完全限定的名称

 app:layout_behavior="com.myapp.ui.view.ScrollBehavior" 

你也可以在这里使用字符串资源。

这不是一个Kotlin问题。

引起:java.lang.ClassNotFoundException:没有find类“com.myapp。beta .ui.view.ScrollBehavior”

从Android 文档

每个Android应用程序都有一个唯一的应用程序ID,看起来像一个Java包名称,比如com.example.myapp。 此ID在设备和Google Play商店中唯一标识您的应用

  

或有时我甚至看到(从来没有使用过)

  

改变它意味着你正在改变你的应用程序包的参考。 位于com.myapp的类将被搜索到com.myapp.beta 。 然后你的课程将不会被find。

与之合作的一种方式是将风格定义为(为了简单,我放弃了其他价值观)

 prod { applicationId = "com.myapp" } beta { applicationId = "com.myapp.beta" } dev { applicationId = "com.myapp.dev" } 

要不就

 beta { applicationIdSuffix ".beta" } dev { applicationIdSuffix ".dev" } 

在pusblish build.gradle之后编辑

注意添加一个后缀或一个完整的applicationId:

 //This will be append to your application id //applicationIdSuffix = "com.myapp.beta", should be applicationIdSuffix = ".beta" 

要么

 //This will replace your application Id applicationId "com.myapp.beta"