Recently, I'm doing a feature based on Dynamic Modules, and I want to load a class from dynamic modules. Since base app can't access class in dynamic module, I use direct reflection to do this. Below is my reflection code:
const val PROVIDER_CLASS= "com.google.android.samples.dynamicfeatures.ondemand.BaseData\$Provider"
fun loadReflection() {
val moduleProvider = Class.forName(PROVIDER_CLASS).kotlin.objectInstance as Share3dFeature.Provider
}
button.setOnClickListener {
loadReflection()
}
All right in debug mode. However, when I put it in Google Play Store and test the on-demand modules functions, it always crashes when I click button to load reflection class after finishing installing module. And the exceptions are:
java.io.FileNotFoundException: /data/app/***/base.apk (No such file or directory)
java.io.FileNotFoundException: /data/app/***/split_config.en.apk (No such file or directory)
Caused by: java.lang.IllegalStateException: No BuiltInsLoader implementation was found. Please ensure that the META-INF/services/ is not stripped from your application and that the Java virtual machine is not running under a security manager
Then all right when relaunch app. This crash only occurs at the first time finishing installing module and call reflection code.
After changing many configs about on-demand module, I still can't fix this bug. By accident, I call reflection code in the callback of SplitInstallManager, it won't crash. And I click button to load module is OK.
private val listener = SplitInstallStateUpdatedListener { state ->
when (state.status()) {
SplitInstallSessionStatus.INSTALLED -> {
Class.forName(PROVIDER_CLASS).kotlin.objectInstance as Share3dFeature.Provider
toastAndLog("installed version: ${context?.packageManager?.getPackageInfo(requireContext().packageName, 0)?.versionName}")
}
}
}
That's magical, why I should load reflection section firstly in the callback of SplitInstallManager
?