我有一个应用程序,我想作为付费应用程序进入市场.我想有其他版本的"试用"版本,时间限制为5天?
我该怎么做呢?
目前大多数开发人员使用以下3种技术之一来实现此目的.
第一种方法很容易被规避,第一次运行应用程序时将日期/时间保存到文件,数据库或共享首选项,并在每次运行应用程序后检查试用期是否结束.这很容易规避,因为卸载和重新安装将允许用户有另一个试用期.
第二种方法更难以规避,但仍然可以避开.使用硬编码定时炸弹.基本上使用这种方法,您将难以编写试用版的结束日期,并且下载和使用该应用程序的所有用户将无法同时使用该应用程序.我使用这种方法是因为它易于实现,而且大多数情况下我只是不想经历第三种技术的麻烦.用户可以通过手动更改手机上的日期来规避这一点,但大多数用户都不会遇到麻烦做这样的事情.
第三种技术是我听说过能够真正完成你想做的事情的唯一方法.您必须设置服务器,然后每当您的应用程序启动时,您的应用程序都会将电话唯一标识符发送到服务器.如果服务器没有该电话ID的条目,则它会生成一个新条目并记下时间.如果服务器确实有电话ID的条目,那么它会进行简单检查以查看试用期是否已过期.然后,它会将试用期满检查的结果传回给您的申请.这种方法不应该是可以绕过的,但确实需要建立一个网络服务器等.
在onCreate中执行这些检查始终是一种好习惯.如果到期结束,则弹出一个AlertDialog,其中包含指向应用程序完整版本的市场链接.只包含一个"确定"按钮,一旦用户点击"确定",拨打"完成()"即可结束活动.
我开发了一个Android试用版SDK,您可以直接放入Android Studio项目,它将为您处理所有服务器端管理(包括离线宽限期).
简单地说就是使用它
将库添加到主模块中 build.gradle
dependencies { compile 'io.trialy.library:trialy:1.0.2' }
在主活动的onCreate()
方法中初始化库
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Initialize the library and check the current trial status on every launch Trialy mTrialy = new Trialy(mContext, "YOUR_TRIALY_APP_KEY"); mTrialy.checkTrial(TRIALY_SKU, mTrialyCallback); }
添加回调处理程序:
private TrialyCallback mTrialyCallback = new TrialyCallback() { @Override public void onResult(int status, long timeRemaining, String sku) { switch (status){ case STATUS_TRIAL_JUST_STARTED: //The trial has just started - enable the premium features for the user break; case STATUS_TRIAL_RUNNING: //The trial is currently running - enable the premium features for the user break; case STATUS_TRIAL_JUST_ENDED: //The trial has just ended - block access to the premium features break; case STATUS_TRIAL_NOT_YET_STARTED: //The user hasn't requested a trial yet - no need to do anything break; case STATUS_TRIAL_OVER: //The trial is over break; } Log.i("TRIALY", "Trialy response: " + Trialy.getStatusMessage(status)); } };
要开始试用,请mTrialy.startTrial("YOUR_TRIAL_SKU", mTrialyCallback);
在Trialy开发人员信息中心中找到您的应用密钥和试用版SKU .
这是一个老问题,但无论如何,也许这会对某人有所帮助.
如果您想采用最简单的方法(如果卸载/重新安装应用程序或用户手动更改设备的日期将失败),这可能是这样的:
private final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); private final long ONE_DAY = 24 * 60 * 60 * 1000; @Override protected void onCreate(Bundle state){ SharedPreferences preferences = getPreferences(MODE_PRIVATE); String installDate = preferences.getString("InstallDate", null); if(installDate == null) { // First run, so save the current date SharedPreferences.Editor editor = preferences.edit(); Date now = new Date(); String dateString = formatter.format(now); editor.putString("InstallDate", dateString); // Commit the edits! editor.commit(); } else { // This is not the 1st run, check install date Date before = (Date)formatter.parse(installDate); Date now = new Date(); long diff = now.getTime() - before.getTime(); long days = diff / ONE_DAY; if(days > 30) { // More than 30 days? // Expired !!! } } ... }
嘿伙计这个问题和snctln的答案激发了我基于方法3作为我的学士论文的解决方案.我知道目前的状态不是为了高效使用,但我很想听听你对它的看法!你会用这样的系统吗?您是否希望将其视为云服务(配置服务器时没有问题)?关注安全问题或稳定性原因?我完成单身汉程序后,我想继续研究该软件.所以现在我需要你的反馈!
源代码托管在GitHub上https://github.com/MaChristmann/mobile-trial
有关系统的一些信息: - 系统有三个部分,一个Android库,一个node.js服务器和一个用于管理多个试用版应用程序和发布者/开发者帐户的配置程序.
它仅支持基于时间的试用,它使用您的(游戏商店或其他)帐户而不是电话ID.
对于Android库,它基于Google Play许可验证库.我修改它以连接到node.js服务器,此外库试图识别用户是否更改了系统日期.它还在AES加密的共享首选项中缓存检索到的试用许可证.您可以使用配置程序配置缓存的有效时间.如果用户"清除数据",库将强制进行服务器端检查.
服务器正在使用https并对许可检查响应进行数字签名.它还为CRUD试用版应用程序和用户(发布者和开发人员)提供了API.与许可证验证类似图书馆开发人员可以在测试应用程序中测试他们的行为实施,并提供测试结果.因此,您可以在配置程序中明确将许可响应设置为"许可","未许可"或"服务器错误".
如果您使用炙手可热的新功能更新您的应用,您可能希望每个人都可以再次尝试.在配置程序中,您可以通过设置应触发此操作的版本代码,为具有过期许可证的用户续订试用许可证.例如,用户在版本代码3上运行您的应用程序,并且您希望他尝试使用版本代码4的功能.如果他更新应用程序或重新安装它,他可以再次使用完整的试用期,因为服务器知道他最后尝试过哪个版本时间.
一切都在Apache 2.0许可下
最简单和最好的方法是实现BackupSharedPreferences.
即使卸载并重新安装了应用程序,也会保留首选项.
只需将安装日期保存为首选项,您就可以开始使用了.
这是理论:http: //developer.android.com/reference/android/app/backup/SharedPreferencesBackupHelper.html
以下是示例: Android SharedPreferences备份不起作用
方法4:使用应用程序安装时间.
由于API级9(2.3.2的Android,2.3.1,机器人2.3,姜饼)有firstInstallTime和lastUpdateTime在PackageInfo
.
阅读更多: 如何从Android获取应用安装时间