首页 > 解决方案 > Android getDeclaredConstructors() 对于 Android 28 (Pie) 的行为不同

问题描述

我知道,这看起来是个坏主意,但我的项目在这里有这一行:

val constructor = SQLiteQuery::class.java.declaredConstructors.first()

该类本身有一个非公共构造函数,但这正是我需要进一步工作的构造函数。

SQLiteQuery(SQLiteDatabase db, String query, CancellationSignal cancellationSignal) {
   super(db, query, null, cancellationSignal);
   mCancellationSignal = cancellationSignal;
}

设置时它工作正常targetSdkVersion 27。但是,当我targetSdkVersion 28在 Android 9 上设置 this 时会出现问题。构造函数列表是空的(因此甚至不包括私有的)。

我在 API / 文档中找不到任何更改。源代码还显示了上面提到的构造函数。

问题是:为什么会这样?如何获得完整的构造函数列表?

标签: javaandroidreflectionconstructor

解决方案


好的,根据 Mikes 的评论,原因是 Andriod 方面的一些安全“改进”。

从 Android 9 开始,它们限制(甚至通过反射)许多方法和字段。

https://developer.android.com/about/versions/pie/restrictions-non-sdk-interfaces

因此,当您使用您的应用程序时,您可能会在 LogCat 中看到一些警告。对我们来说,例如这个:

Accessing hidden field Landroid/database/sqlite/SQLiteProgram;->mBindArgs:[Ljava/lang/Object; (light greylist, reflection)

它告诉我们想要的构造函数受到限制(即不可用),这导致构造函数列表返回空(并导致崩溃)。

谷歌声明了受限方法和字段的数量如下:

名单大致如下:

白名单(也称为 SDK)~= 74,000 个方法和字段

light-greylist ~= 11,000 方法和字段 dark-greylist ~= 121,000

方法和字段黑名单 ~= 9,000 个方法和字段

请注意,它只是“起作用”(崩溃来自后来使用空返回值,但调用本身没有抛出),因为light greylist如果方法“更暗”,它会抛出异常。

如果您只有浅灰色警告,最简单的解决方案确实是 27(而不是 28)的目标版本。这会“为你争取时间”,直到他们可能会进一步限制下一个 Android 版本。对于抛出错误,这可能不是您想要的,因为它仍然可能崩溃!


推荐阅读