繁体   English   中英

具有产品风味和Kotlin的ClassNotFoundException

[英]ClassNotFoundException with product flavors and Kotlin

我有一个主要用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"
            app:layout_behavior=".ui.view.ScrollBehavior">

您将行为定义为

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

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

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

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

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

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

这不是Kotlin的问题。

抛出java.lang.ClassNotFoundException:由造成找不到类“ com.myapp 公测 .ui.view.ScrollBehavior”

从Android 文档

每个Android应用程序都有一个看起来像Java包名称的唯一应用程序ID,例如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"
}

修改后的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"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM