我有一个非常奇怪的错误,因为它只发生在从生成的.apk
安装应用程序后。当我尝试通过IDE运行应用程序时,它工作正常。
java.lang.IllegalAccessError: Method 'int <package>.BaseActivity$Companion.getANIMATION_SLIDE_FROM_RIGHT()' is inaccessible to class '<package>.MyActivity' (declaration of '<package>.MyActivity' appears in /data/app/<package>-mg7eYmJ8hX5WvkNWNZWMVg==/base.apk!classes3.dex)
如你所见,有一个名为BaseActivity
的类,它看起来像这样:
open class BaseActivity : AppCompatActivity() {
companion object {
@JvmStatic
protected val ANIMATION_DEFAULT = 0
@JvmStatic
protected val ANIMATION_SLIDE_FROM_RIGHT = 1
@JvmStatic
protected val ANIMATION_SLIDE_FROM_BOTTOM = 2
}
protected open var animationKind = ANIMATION_DEFAULT
// Some other stuff
}
现在每个活动都扩展了这个类,并经常覆盖animationKind
,如下所示:
class MyActivity: BaseActivity() {
override var animationKind = ANIMATION_SLIDE_FROM_RIGHT
// Some other stuff
}
问题是ANIMATION_SLIDE_FROM_RIGHT
无法进入MyActivity
。我将重复它只发生在手动生成的.apk
上。有趣的是,我没有使用multidex,但错误似乎表明BaseActivity
在classes3.dex
。这是我的gradle文件:
apply plugin:'com.android.application'apply plugin:'kotlin-android'apply plugin:'kotlin-android-extensions'apply plugin:'kotlin-kapt'
android {
compileSdkVersion 28
defaultConfig {
applicationId <package>
versionCode <versionCode>
versionName <versionName>
minSdkVersion 21
targetSdkVersion 28
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
androidExtensions {
experimental = true
}
}
dependencies {
// Dependencies
}
我尝试使用multidexEnabled false/true
,但唯一的变化是在false
状态下classes3.dex
后缀消失。
UPDATE
当然,当我将MyActivity
的animationKind
财产改为1
时,一切正常。
更新2
删除@JvmStatic
和保护可见性后它工作正常。
来自official Kotlin documentation:
Java允许从同一个包中的其他类访问受保护的成员,而Kotlin则不允许,因此Java类可以更广泛地访问代码
因此,请确保您的BaseActivity
和MyActivity
属于同一个包装。
如果两个活动不在同一个包中,那么它将通过从Studio直接运行完美运行,但是当您生成.apk并尝试通过安装该apk在设备上运行时它将崩溃(IllegalAccessError)。
虽然我不确定为什么会导致IllegalAccessError,但您应该定义这样的常量:
companion object {
const val ANIMATION_DEFAULT = 0
const val ANIMATION_SLIDE_FROM_RIGHT = 1
const val ANIMATION_SLIDE_FROM_BOTTOM = 2
}
这应该解决你的问题,否则使用@JvmField
而不是@JvmStatic
将是一个更好的选择。
确保您已在与调用代码相同的模块中声明失败的方法。
在我的情况下,我遇到以下错误:
java.lang.IllegalAccessError: Method 'boolean[] my.package.common.kotlin.AndroidExtensionsKt.$jacocoInit()' is inaccessible to class 'my.package.ui.first.FirstActivity$viewModel$2' (declaration of 'my.package.ui.first.FirstActivity$viewModel$2' appears in /data/app/my.package.dev-fdHNodmdXHv-b_heK4MXeA==/base.apk!classes8.dex)
at my.package.ui.first.FirstActivity$viewModel$2.invoke(FirstActivity.kt:18)
at my.package.ui.first.FirstActivity$viewModel$2.invoke(FirstActivity.kt:14)
at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
at my.package.ui.first.FirstActivity.getViewModel(Unknown Source:11)
at my.package.ui.first.FirstActivity.onCreate(FirstActivity.kt:23)
getViewModel()
在common
模块中声明,FirstActivity
在app
模块中声明:
inline fun <reified T : ViewModel> FragmentActivity.getViewModel(
factory: ViewModelProvider.Factory = ViewModelProvider.NewInstanceFactory()
) = ViewModelProviders.of(this, factory).get(T::class.java)
将getViewModel()
从common
模块移动到app
模块后,没有看到任何问题。