【问题标题】:Android free and paid with different functionalityAndroid 免费和付费的不同功能
【发布时间】:2012-06-22 14:27:27
【问题描述】:

我了解开发免费和付费版本应用程序的最佳方式是拥有一个包含程序主要部分的库项目。然后免费和付费项目将使用这个库项目。这允许免费和付费项目拥有不同的资源。

但是,我的问题是我们如何限制免费应用程序中的功能(或为付费应用程序扩展它)?例如,我的免费应用程序只能访问数据库表中的最新行,而付费应用程序可以访问所有行。

执行此操作的一种方法是在资源中设置一个布尔标志,将其设置为 true 表示付费,false 表示免费。在运行时,库项目检查布尔标志并相应地改变行为。然而,这似乎很容易被黑客入侵以应对任何潜在的攻击。有更好的方法吗?

使用一款免费应用然后使用应用内结算来解锁专业功能会更容易吗?

【问题讨论】:

标签: android


【解决方案1】:

恕我直言,Java/Android 在这种情况下并不容易。理想情况下,您应该拥有一个代码库,并且能够随意编译付费或免费版本。免费版本将禁用关键方法/类,因此没有人可以修改数据库或 xml 来启用应用程序的全部功能。

一种方法是使用条件编译,Java 也不支持。但是,有一些 Ant 任务可以做到这一点,例如http://prebop.sourceforge.net/doc.html。您可以像这样在代码中添加一些内容:

/* $if paid_version$ */
public void paid_method() {

}
/* $endif$ */

如果您正在构建的 ant 目标没有定义变量paid_version,上述代码将被删除。

如何设置 prebop 是另一个话题,虽然很复杂,但值得拥有一个单一的代码库。

2013 年 5 月更新:基于 Gradle 的新 Android 构建系统使构建付费和免费 APK 变得更加容易。有关“构建变体”的主题,请参见 Android Tools 网站。简而言之,您可以像这样构建您的源代码:

/src/main/
/src/paid/
/src/free/

所有共享代码位于/src/main,付费代码位于/src/paid,免费代码位于/src/free。构建系统将为您创建付费和免费 APK。但是,仍然缺少的一项功能是在源代码本身中进行条件编译的能力。在撰写本文时,Gradle 构建工具仍处于测试状态,因此希望在最终版本中添加。

【讨论】:

  • 这是一个非常好的解决方案。不幸的是,在花了一天时间试图了解 ant 和 prebop 的工作原理后,我放弃了并重新使用 Android 库项目。
  • 暂时不要放弃。我花了一周的时间来正确设置它。关键是首先要学习如何进行基本的 ant 构建。一旦您对 ant 感到满意,您就可以添加各种可以在构建期间操纵项目的 ant 任务。例如你有一个布尔标志来启用专业功能,对吧?您可以让 ant 在构建时将此布尔标志设置为 false,这意味着不会编译 pro 功能部分。然后使用像 Jenkins 这样的 CI,让您每次签入时都可以吐出专业版和免费构建版。
  • 这对于防止非法解锁您的付费功能非常有用。 OTOH,如果您想通过应用内付款逐步启用这些功能,那就不好了。我还想知道有人将您的免费应用程序转换为付费版本的威胁有多大?如果你的普通用户不是很懂计算机/黑客倾向,那么如果几个熟练的人这样做能省几块钱,那又有什么关系呢?他们最终不会有任何可以公开发布的东西,而不是仅仅花费几美元购买您的应用程序,然后将其传播出去。想法?
  • 我还没有玩过应用内支付,显然如果你的应用中有一大段代码启用了付费功能,那么它总是有被其他人反编译和启用的风险。使用条件编译,您的付费功能不会出现在免费版本中,因此无法启用,但它可能不适用于应用内支付。 Finallu,您必须考虑这样一个事实,一旦您的 apk 被黑客入侵,它可以重新分发给任何人,因此可能不会只有少数人免费搭车。
【解决方案2】:

切勿在 Res 或 SharedPrefs 中保存任何用于指定应用是否已付费的标志。有根电话可以访问这些并可以修改它们。 我也有这个问题,写了两个单独的应用程序(复制付费的应用程序并删除了一些方法,添加了广告等)。这是最简单的解决方案。

【讨论】:

  • 这不是一个非常可维护的方法。如果你发现了一个错误,你必须修复它两次。
  • 好吧,@Styx,任何体面的源代码控制管理都允许将更改从一个分支合并到另一个分支。所以,bluewhile 的解决方案是完全合理的
【解决方案3】:

IMO 您从单一来源创建多个应用版本的最佳方法使用库项目。

我最近尝试过这个,它似乎工作得很好。虽然我没有尝试将基于此的代码发布到 Google Play,但我已经创建了单独的应用程序,它们可以在测试设备上同时运行,并带有自己的图标。

由于 Android 上的单独应用必须各自具有不同的包名称,因此配置单独行为的最简单方法是在库中测试该包名称,以查看它目前是在免费版本还是付费版本中运行。该测试可以在库项目中定义的自定义应用程序派生对象中进行;可以通过调用 getPackageName() 获取包名。

您的免费和付费应用至少可能只需要一个 AndroidManifest.xml 文件和一些资源(例如,区分免费和付费的应用图标)。

在两个应用程序的清单中,您希望应用程序元素的 android.name 属性设置为自定义应用程序派生类的完整路径(如库中所定义)。当然,您会希望将清单元素本身的 package= 属性设置为一个不同的包,该包以 .free 或 .paid 之类的结尾,用于相应的应用程序。清单中的 Activity 对象可以有一个 android:name 属性,该属性设置为库中正确的 Activity 派生类(使用完整路径)。

然后,启用付费功能的代码将简单地调用在您的自定义应用程序对象中测试包的方法,解析包名称,并在此基础上决定是运行付费版本还是免费版本,然后启用或禁用相应的付费功能。

这里有一个非常有用的示例(虽然有些旧,但仍然相关),其中包含完整代码:

https://github.com/donnfelker/FullAndLiteVersionSharedLibrary/blob/master/FooLibrary/src/com/example/foolibrary/FooLibraryApplication.java

【讨论】:

  • 感谢您的回复。最后,我完成了一个图书馆项目。查看我提出的另一个问题和我收到的答案。它可能对您有所帮助:stackoverflow.com/questions/11176113/…
  • 在另一个线程中,我被正确地纠正了建议库中的变体行为可以以测试包含应用程序的包名称为条件。根据使用库的模块来配置库行为可能会违反模块化。因此,在应用上述方法时,所有应用程序特定信息都应驻留在应用程序中。如果您只是禁用功能,则可以根据应用程序包执行此操作,但如果您有免费和付费的对话框变体,那么这些对话框应该驻留在应用程序中,而不是库中。跨度>
  • 关于这种需求(对于库项目)是如何演变的,我怀疑开发人员通常会创建一个功能齐全的应用程序,然后然后决定创建一个带有禁用功能的免费版本,这导致大部分完整的应用程序最终进入库项目,并测试库中的应用程序包以控制禁用。这可以说是不理想的,因为您将未使用的东西加载到免费应用程序中。 OTOH,如果您想稍后启用功能(例如,使用应用内付款),则有必要。而且在库和应用程序之间划分完整的应用程序也可能会损害一致性。
  • 并不是说要继续下去,但是关于上面最后一点,从哲学上讲,考虑是否应该应用模块化的通常设计要求来要求分离出于唯一目的而被抑制的功能是很有趣的从用户那里提取付款。模块化通常用于将功能相关的特征组合在一起。您可能拥有与整个任务类别中的任何一个任务相关的代码,然后将该代码限制为这些任务的特定子集以获得免费版本。一个开关适用于此;不需要分开。
  • 没想到这么详细的回答和跟进。我沿着图书馆项目包含大部分功能的路线走。免费的应用程序项目只是一个非常小的项目,除了提供对库项目各个部分的访问权限之外,它什么都没有。然后,付费应用程序项目具有附加功能。另一个线程中的代码对 2 个单独的部分有很大帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多