使用多种模板/风格构建单个 Apk

Posted

技术标签:

【中文标题】使用多种模板/风格构建单个 Apk【英文标题】:Build Single Apk with multiable template/flavors 【发布时间】:2019-09-24 12:56:09 【问题描述】:

是否可以构建具有超过 1 种产品风格的 apk?

例如: 我有一个具有 3 种风格的项目(App1 - App2 - App3)。 并且每个app都有自己的applicationId等配置。

现在我想构建不同的模板(不同的 XML 布局),并且用户应该能够从应用程序内部从布局切换到另一个。

我的问题是 res 文件夹会很大而且很难维护,所以我试图找到一种方法来分离不同的布局并尽可能保持干净。

如果可以这样做,那么我如何打算或重新启动应用程序以构建其他风格?

我想到的另一件事是在主资源中构建所有 XML 文件并选择不同的限定符,就像我们在创建不同的屏幕尺寸(sm - larg - 等)时所做的那样,但我无论如何都找不到添加自定义限定符.

我的Gradle 代码是这样的:

flavorDimensions "default"

    productFlavors 

        demo 
            applicationId "test.demo"
            versionCode 2
            versionName "1.1.2"
            resValue "string", "backage_name_file", "test.demo.fileprovider"
            resValue "string", "bc", "com.demo"
            resValue "string", "bc_e", "extra_data.com.demo"
            resValue "string", "default_hostname", "demo.test.com"
            resValue "string", "default_username", "demo"
            resValue "string", "default_password", "demo"
        
         AppOne 
            applicationId "test.AppOne"
            versionCode 2
            versionName "1.1.2"
            resValue "string", "backage_name_file", "test.AppOne.fileprovider"
            resValue "string", "bc", "com.AppOne"
            resValue "string", "bc_e", "extra_data.com.AppOne "
            resValue "string", "default_hostname", "AppOne.test.com"
            resValue "string", "default_username", "AppOne"
            resValue "string", "default_password", "AppOne"
        
          AppTwo 
            applicationId "test.AppTwo"
            versionCode 2
            versionName "1.1.2"
            resValue "string", "backage_name_file", "test.AppTwo.fileprovider"
            resValue "string", "bc", "com.AppTwo"
            resValue "string", "bc_e", "extra_data.com.AppTwo"
            resValue "string", "default_hostname", "demoAppTwotest.com"
            resValue "string", "default_username", "AppTwo"
            resValue "string", "default_password", "AppTwo"
        

【问题讨论】:

恕我直言,如果您只想根据用户输入切换布局,则不需要使用产品风味。可以简单地通过一些if 语句来实现。 我已经在使用多种风格的 apk,我不想使用 if 语句,因为如果我有 50 个 xml 文件并且每次我想制作新模板时都复制过去,那就太多了跨度> 我认为创建一个if语句比创建一个模块来切换布局更好。 好的,但我会遇到一些问题:首先,如果我有 2 个不同的布局 (xml) 文件,第一个将被称为 mainactivity.xml,第二个模板将被称为 mainactivity2,因为这将导致java数据绑定的问题。与活动风格相同。你觉得有更好的解决方案吗? 我发现了类似***.com/questions/28232261/… 的东西,您可以添加子风味,但如何在 java 中调用它? 【参考方案1】:

您无法构建具有多种风格的 APK,就像您无法在调试和发布 buildType 中构建一个一样。所选风味的配置/资源被拉入实际的 APK 元数据/清单中,因此无法在运行时修改。

您需要将所有内容包含在 res 文件夹中,但有一些方法可能有助于使其更易于管理。我推荐前 3 个选项,如果您有大量具有不同行为的代码 + 布局文件,则推荐第 4 个:

    Use Fragments 避免大部分 Java / Kotlin 代码需要重复。 Include XML layouts 而不是每次都重新定义一切以重用通用元素。 仔细命名您的文件,例如template1_backgroundtemplate2_background。 Use multiple modules,每个“模板”一个。然后,您将拥有多个合理的 res 文件夹。

我明白为什么风味似乎是解决方案,但由于您需要在一个应用程序中使用所有风味,不幸的是这种方法行不通。您可能会发现第 2 步将删除几乎所有重复文件,从而完全避免该问题!

【讨论】:

使用多个模块听起来不错,但我发现的唯一问题是如何在 java 类中调用它,我的意思是在片段/活动类中,如果 temp == temp_1 显示来自 module_1 的 xml,我该怎么说,如果我在主 src 中有 java 类或样式,我如何在模块中调用它?据我所知,您可以访问模块内部的内容,但模块无法访问外部的内容? 如果您的app 模块依赖于module1module2 等,它可以从它们内部调用任何东西(包括布局/java 类)。因此app 模块将控制加载适当的布局/类。话虽如此,步骤 1+2 值得先尝试,因为它们更容易(并且是很好的做法)。 如果没有,我会先尝试找到一个更简单的解决方案,看起来我会选择碎片选项【参考方案2】:

您可以使用 sourceSets 命令合并来自不同风格的资源。 SourceSet 允许您配置 buildVariants 资源文件夹 例如,您可以将 App2 风格配置为包括 App2 res 文件夹和 App1 res 文件夹。 示例代码:

sourceSets 


        App2Debug
            res.srcDirs = ['src/App1/res', 'src/App2/res']

        

    

【讨论】:

拥有不同 xml 名称的多个资源将导致数据绑定问题 你是什么意思数据库问题?什么问题? 对于数据绑定,您需要以这种方式在 java 中设置您的 xml:private FragmentHomePageViewBinding binding; binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home_page_view, container, false);现在,如果您有同一个 java 类的多个 xml,您将需要将第二个数据绑定重命名为 binding2 和 binding 3 等等,这意味着当您设置文本视图或在布局 我知道。还是不明白由此引起的问题?它不知道布局? 问题是如果我必须从 API 设置 textview,我将不得不为每个绑定执行多次,这不是最佳的,你可以想象一个有很多 id 的类在 UI 中,那么该类可以有多大

以上是关于使用多种模板/风格构建单个 Apk的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 使用带有 android 多种风格的 fastlane

如何为 jenkins 构建具有多种风格的应用程序设置 dexguard?

在使用 gradle 缓存时,在多风格的 android 库中使用不同的 res 值会在编译的 APK 中使用错误的值

如何在针对特定 Gradle 构建风格的同时从命令行运行单个单元测试方法

Crashlytics (Fabric) 为应用程序变体(构建类型、产品风格)分离组织

SpringBoot构建RESTful风格应用