java - 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 / 文档中找不到任何更改。源代码还显示了上面提到的构造函数。
问题是:为什么会这样?如何获得完整的构造函数列表?
解决方案
好的,根据 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 版本。对于抛出错误,这可能不是您想要的,因为它仍然可能崩溃!
推荐阅读
- arrays - 无法迭代字典数组,因为它说“键入'Any'的值没有下标”
- utf-8 - gpload 抛出异常“错误:编码“UTF8”的无效字节序列:0xe5b82e”
- jquery - jQuery发布错误'必须是字符串类型'
- msp430 - MSP430,我怎样才能让它进入睡眠模式20分钟?
- javascript - 全部反应 ref 和查询选择器
- android - 我如何要求用户在登录我的 Android 应用程序时始终输入他的密码/使用指纹?
- dependencies - Gradle 不会下载 fabric-sdk-java 的依赖项
- oracle - 在事务回滚的情况下处理全局临时表中的数据
- sql-server - 如何通过比较 2 个表来根据日期时间获取数据库中的最新记录
- dart - Dart2 路由器实现