带有产品风味和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 { (...) } } 

表现:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.myapp"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:name=".MyApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/MyTheme"> <activity android:name=".ui.dashboard.DashboardListActivity" android:launchMode="singleTop" android:configChanges="orientation|keyboardHidden|screenSize"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest> 

代码中的相关部分:

 <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:theme="@style/MycujooPlayerTheme.AppBarOverlay" app:layout_behavior=".ui.view.ScrollBehavior"> 

你正在定义你的行为

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

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

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

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

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

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

这不是一个Kotlin问题。

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

从Android 文档

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

 <manifest package="com.myapp" > 

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

 <manifest package="${applicationId}" > 

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

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

 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"