The Solution with java 17, 2023.
Easy steps:
1.Adding the universal methods
private fun setStaticFieldViaReflection(field: Field, value: Any) {
field.isAccessible = true
getModifiersField().also {
it.isAccessible = true
it.set(field, field.modifiers and Modifier.FINAL.inv())
}
field.set(null, value)
}
private fun getModifiersField(): Field {
return try {
Field::class.java.getDeclaredField("modifiers")
} catch (e: NoSuchFieldException) {
try {
val getDeclaredFields0: Method =
Class::class.java.getDeclaredMethod(
"getDeclaredFields0",
Boolean::class.javaPrimitiveType
)
getDeclaredFields0.isAccessible = true
val fields = getDeclaredFields0.invoke(Field::class.java, false) as Array<Field>
for (field in fields) {
if ("modifiers" == field.name) {
return field
}
}
} catch (ex: ReflectiveOperationException) {
e.addSuppressed(ex)
}
throw e
}
}
2.Adding these flags to gradle (it can be changed for other cases)
android {
...
testOptions {
unitTests.all {
jvmArgs(
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED"
)
}
}
}
3.Examples of using
private val testSocManufacturer = "test-soc-manufacturer"
setStaticFieldViaReflection(
Build::class.java.getDeclaredField("SOC_MANUFACTURER"),
testSocManufacturer)
private val testSocModel = "test-soc-model"
setStaticFieldViaReflection(
Build::class.java.getDeclaredField("SOC_MODEL"),
testSocModel)
setStaticFieldViaReflection(
Build.VERSION::class.java.getDeclaredField("SDK_INT"),
30)