【问题标题】:Android dynamic feature module, resource not foundAndroid动态功能模块,找不到资源
【发布时间】:2019-02-05 15:09:37
【问题描述】:

当下载的功能模块发布到 Play 商店时,我在启动 Activity 时遇到问题。它总是在下载的模块活动中的 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();
                });

我完全不知道下一步该尝试什么。似乎在安装更新并且重新启动应用程序还不够之前,它不会更新资源列表,还是我只是缺少一些简单的东西?

【问题讨论】:

  • 我也有同样的问题
  • 没有一个答案对我有用,在我添加一个 applicationIdSuffix 之前工作正常。
  • 我在获取颜色时仍然遇到同样的错误。

标签: android android-app-bundle android-module


【解决方案1】:

您始终可以从动态模块中的主项目访问资源,因此您可以将动态模块的资源放在主应用程序中,然后使用主应用程序中的 R.java。

但是,打开这些资源的正确方法是在动态交付的活动中使用 SplitCompat.install(this)

【讨论】:

  • 在我的情况下没有解决它,applicationIdSuffix 似乎让谷歌感到困惑。有时资源实际上是在没有改变任何东西的情况下找到的,这更奇怪。
【解决方案2】:

这似乎是 com.android.tools.build:gradle:3.2.1 中的一个错误 当我升级到 3.3.0 后,问题自行解决了。

希望它可以帮助遇到此问题的其他人...

【讨论】:

  • 不幸的是,这并没有帮助我解决同样的问题。 3.3.0、3.3.1 - 没有成功。
  • @despectra 你找到解决办法了吗?
  • @despectra 你们谁找到了解决方案?
【解决方案3】:

我遇到了完全相同的问题;全新安装因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 的示例,它完全符合您的要求。

https://codelabs.developers.google.com/codelabs/on-demand-dynamic-delivery/index.html?index=..%2F..index#1

至于我的情况,我必须确保包名是正确的。例如,如果主模块的包名是com.example.foo,动态模块是com.example.foo.dynamic_activity,那么在动态模块中启动Activity会如下所示。

Intent().setClassName(
    "com.example.foo",
    "com.example.foo.dynamic_activity.DynamicActivity"
).also {
    startActivity(it)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多