0

TL;博士 我是一名 android 开发人员,我基本上拥有同一个应用程序的多个副本,它们之间略有不同。尽管我尽了最大努力,但每当我需要对所有应用程序进行一次更改时,我都不得不对每个应用程序副本(以下简称“风味”)进行复制和粘贴样式修改。这在 Android 中尤其令人发指,因为给定应用程序中涉及的语言/文件类型的数量 - C 用于本机代码,Java 用于常规代码,.xml 文件用于数据、布局和操作系统权限等。我知道的技巧避免仅在 Java 或 C 中工作的复制和粘贴编码不会同时扩展到两者,或扩展到 .xml 文件。我一直在使用 Apache ANT 并成功地创建了一个自定义 build/ 文件夹,并在其中包含不同构建目标的相关文件,但它有点笨拙,

我想知道是否有一个构建系统可以为我处理所有这些;我愿意接受任何建议,尽管我想到的解决方案特定于一种独立于语言/文件系统的#include 方法,对于构建时的给定风格,该方法将整个文件注入到 src/ 树中,或者将代码片段注入到该 src/ 树中的各种 .java、.c 和 .xml 模板文件中。

一个很长的具体例子的解释:

口味差异的例子:在谷歌商店我必须使用谷歌应用内购买sdk;但在亚马逊商店我必须使用亚马逊应用内购买 sdk。不同的口味搭配不同的广告伙伴。某些风格需要不同的 i18n 语言文件;或不同设备的图形和布局资产;等等等等。任何给定的风格本质上都是基本代码,加上任意数量的这些“附加组件”,其中每个附加组件都需要一些自定义代码和文件添加到该应用程序的 src/ 树中。每当我需要更改附加组件时,我最终不得不在使用它的应用程序的每个风格中复制并粘贴更改,这是一个可怕的痛苦。

作为一个具体的例子,假设我有一个 android 游戏并且我已经实现了一个自定义 Flurry Appcircle 广告视图。这通常涉及以下内容:

  1. 向游戏的 AndroidManifest.xml添加"<activity>""<service>"和/或标签"<uses-permission>"
  2. 在 apk 的 res/values-xx/strings.xml 文件夹系统中为广告添加了多"<string>"行,其中 xx 是语言代码(即西班牙语翻译将进入 res/values-es/strings.xml)
  3. 用于广告的 res/layout 或 assets/ 中的一个或多个图像或布局资源。
  4. 实际 Flurry Inc sdk 在 libs/ 中以 Java .jar 文件的形式出现 - 如果需要以不同方式处理不同的硬件架构,则可能有多个 jar 文件。
  5. 游戏 Activity 类中的 Java 代码,例如 onStart 或 onStop,用于查询 Appcircle 广告并显示它。为避免代码重复,我通常将其写在一个基类中,该基类包含“if(appcircleAdsEnabled(){...}”中的所有代码,创建该方法的默认实现,返回 false,@Override 并返回 true在各种儿童活动课上。

这会导致一些问题:

  1. Flurry .jar 现在是基类的一个依赖项,用于编译无论广告是否以任何给定风格启用。我希望构建器在构建时注意到代码或资源未使用并将其从最终的 apk 中删除;但没有保证,失败会导致 (A) 最终二进制文件大小膨胀和 (B) 潜在 PR 问题或更糟(尤其是来自搜索代码包含的自动扫描仪 - 在一个稍微不同的示例中,我很难保证亚马逊应用商店“是的,Google Play Billing 存在,但未使用。”)
  2. 由于Android将资源文件转化为java常量的方式,和(1)一样,res/*文件也可能成为所有从这个Base Class派生出来的游戏的不必要依赖。
  3. 我发现的一些库/方法坚持将它们的代码添加到特定位置或以特定方式添加,这完全排除了基类方法。
  4. 对于每个单独的游戏,我仍然必须至少编辑其 AndroidManifest 以“打开此功能”并请求显示广告所需的相关操作系统权限。
  5. 记住哪个“添加”与哪个文件中的哪个更改相关是很乏味的。例如,在任何给定风格的 AndroidManifest.xml 中,我无法跟踪哪些附加组件需要哪些权限。如果我删除 Flurry 插件,我还需要 INTERNET 权限来做其他事情吗?

我希望存在,以及我要问的是,是否有某种方法可以将文件和代码片段注入到某些框架文件系统中/顶部,每个附加组件都由此类文件的集合组成,并且代码片段并在构建时动态注入,构建系统跨多个附加组件合并行,并动态处理依赖项包含。IE 对于我的 Flurry Ad 附加组件,我将拥有:

  1. 一些文件“文件”集合,包括我对各种 .xml 文件(如 AndroidManifest.xml)的 xml 添加、我对各种 .java 文件(如 Activity 子类)的代码添加,以及在某些情况下要注入的整个文件本身不同的地方(如广告布局文件)
  2. 在一些骨架模板文件树中,不完整的版本,例如 AndroidManifest.xml、MyActivity.java 等,具有类似于语言无关的#include 语法,指示来自 FILES 的数据将进入那里。
  3. 同样在该模板文件树中, src/ 中带有“缺少文件”的目录将在构建时从 FILES 动态复制
  4. 某种用于 FILES 的构建指令脚本,指示包含此附加组件时的去向,以获取骨架模板文件树并将其转变为完全充实的构建/树。

同样,理想情况下,它能够同时处理多个“附加组件”;即我可能有一些文件给这个广告商,还有一些文件给那个计费提供商等等,一个给定的产品只是它包含的模块的列表,构建系统在构建时神奇地将它们编织在一起。

4

1 回答 1

0

这似乎正是Gradle Build Variants 系统旨在解决的问题 - 它处理将多个版本的AndroidManifest.xml、资源和 Java 包合并到一个或多个单独的应用程序中。具体来说,多口味变体似乎满足了您以各种方式将多个功能组合在一起的要求。

Gradle 作为Android Studio的一部分提供,这是一个基于 IntelliJ 的 IDE,专为 Android Gradle 项目构建。如果您不熟悉 Gradle ,可以考虑查看众多Gradle 构建指南之一。

于 2013-09-24T03:57:56.790 回答