在将功能发布到Play商店时,在下载的功能模块中启动活动时遇到问题。它总是在下载的模块活动中的setContentView()上崩溃。
java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx/xxxActivity}: android.content.res.Resources$NotFoundException: Resource ID #0x7e080000
Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x7e080000
at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:227)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2149)
at android.content.res.Resources.getLayout(Resources.java:1158)
at android.view.LayoutInflater.inflate(LayoutInflater.java:421)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
真正奇怪的是,如果我发布该应用程序的新版本(仅更改为versionCode)以播放商店并更新该应用程序,则一切正常。
当我卸载应用程序并再次安装时,崩溃返回。
我的应用程序继承了SplitCompatApplication(),只是为了确保自此以后我尝试添加:
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(newBase)
SplitCompat.install(this)
}
进入功能模块中的活动并禁用了proguard,以确保在缩小期间没有删除任何东西
我的SplitInstallStateUpdatedListener
private val listener = SplitInstallStateUpdatedListener { state ->
val multiInstall = state.moduleNames().size > 1
state.moduleNames().forEach { name ->
// Handle changes in state.
when (state.status()) {
SplitInstallSessionStatus.DOWNLOADING -> {
// In order to see this, the application has to be uploaded to the Play Store.
displayLoadingState(state, "Laddar ner $name")
}
SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> {
/*
This may occur when attempting to download a sufficiently large module.
In order to see this, the application has to be uploaded to the Play Store.
Then features can be requested until the confirmation path is triggered.
*/
startIntentSender(state.resolutionIntent()?.intentSender, null, 0, 0, 0)
}
SplitInstallSessionStatus.INSTALLED -> {
if(toInstall.isNotEmpty() && toInstall.contains(name)) {
toInstall.remove(name)
}
if(toInstall.isEmpty()) {
// Updates the app’s context with the code and resources of the
// installed module. (should only be for instant apps but tried it anyway, no change)
SplitInstallHelper.updateAppInfo(applicationContext)
Handler().post {
viewModel.goToOverview()
}
}
}
SplitInstallSessionStatus.INSTALLING -> displayLoadingState(state, "Installerar $name")
SplitInstallSessionStatus.FAILED -> {
toastAndLog("Error: ${state.errorCode()} for module ${state.moduleNames()}")
}
}
}
}
此代码根据用户声明下载模块,并在基本应用中启动活动
然后从BottomSheetDialogFragment开始下载的模块活动,如下所示:
xxx.setOnClickListener(view -> {
Intent intent = new Intent();
String packageName = Constants.MODULE_BASEPACKAGE + "." + Constants.MODULE_XXXXX;
intent.setClassName(getActivity().getPackageName(),packageName + ".XxxxxActivity" );
ParcelUuid parcelUuid = new ParcelUuid(UUID.randomUUID());
intent.putExtra("uuid", parcelUuid);
startActivity(intent);
dismiss();
});
我完全不知道下一步该怎么做。似乎直到安装更新并且应用程序重新启动还不够时才更新资源列表,或者我只是缺少一些简单的东西吗?
答案 0 :(得分:1)
这似乎是com.android.tools.build:gradle:3.2.1中的错误 当我升级到3.3.0时,问题自行解决。
希望它可以帮助遇到此问题的其他人...
答案 1 :(得分:1)
您始终可以从动态模块内部的主项目访问资源,因此可以将动态模块的资源放在主应用程序中,然后使用主应用程序中的R.java。
但是,打开这些资源的正确方法是在动态交付活动中使用SplitCompat.install(this)
答案 2 :(得分:0)
我有一个完全相同的问题;全新安装会因Resources$NotFoundException
而崩溃,但后续升级可以正常运行(不会再次下载动态模块)。但是我的情况略有不同,因为我不想在动态模块中启动Activity,而是想通过Navigation加载Fragment。在那种情况下,我应该已经导航过,让Navigation执行其工作而无需手动检查模块是否已加载(有关更多信息,请参考https://developer.android.com/guide/navigation/navigation-dynamic)。
// Just navigate without calling splitInstallManager.installedModules.contains()
findNavController().navigate(DynamicDeliveryDirections.actionDynamicFragment())
如果要启动活动,则确实需要像已经那样检查模块是否已加载。我建议您看一下Google的示例,它确实可以满足您的要求。
对于我的情况,我必须确保软件包名称正确。例如,如果主模块的程序包名称为com.example.foo
,而动态模块的名称为com.example.foo.dynamic_activity
,则在动态模块中启动Activity如下所示。
Intent().setClassName(
"com.example.foo",
"com.example.foo.dynamic_activity.DynamicActivity"
).also {
startActivity(it)
}