如何为Android应用程序实施Google Play许可?

我看到了Android-Developer许可证库的说明 ,但是这个概述似乎忽略了这个过程中的几个关键步骤,并没有完全解释如何得到一些工作。

有人可以提供一套明确的操作来获取在Android应用程序上设置的许可证库,以便在允许使用之前检查并确保用户在Google Play中支付了应用程序吗?

我一直在努力在我的应用程序中实施许可证一段时间,最后让它工作。 我想分享一些我觉得对于开始有帮助的事情,以及一些我发现每个人都遇到的问题和解决scheme。 我已经链接下面的Android开发教程是好的,但它不是对我有用,所以我决定做一个教程。 享受,我希望它可以帮助你!

链接到开发者页面在这里 。

1.开始

你需要的东西。

1.1您的Base64独特的应用程序密钥

如何得到它:

一个。 转到您的开发者控制台。 链接。

湾 如果您尚未为您的应用程序创build应用程序草稿,请立即执行。

C。 一旦你创build了草稿,最好把你的.apk上传为Alpha或者Beta。 不要发表。

d。 点击Services & APIs

即 向下滚动并findYOUR LICENSE KEY FOR THIS APPLICATION

F。 将密钥复制到您的应用程序,如下所示:

 private static final String BASE64_PUBLIC_KEY = "YOUR LICENSE KEY FOR THIS APPLICATION"; 

确保没有空格。

1.2盐

一个。 什么是盐?

salt是随机数据,在散列密码时是额外的input。 它们被用来防御字典攻击和彩虹表攻击。

湾 我如何得到一个?

这是生成随机盐的好链接。 应该有20个随机整数,所以把20随机string生成,每个string应该是2字符长(用于这个例子,它不一定是)。 检查数字,并检查是否允许相同的string。 他们也可以是负数。 尝试删除任何冗余,例如00 -> 0 ,为了一致性。

C。 我在哪里放盐?

当声明variables只是把这个代码,除了你的随机盐。

 private static final byte[] SALT = new byte[] {YOUR RANDOM SALT, COMMA SEPARATED, 20 INTEGERS}; 

2.将LVL(Licensing)库导入到Eclipse以及您需要的代码中

2.1导入库

一个。 打开Android SDK Manager

湾 去Extras

C。 安装Google Play Licensing Library

d。 find您在SDKpipe理器顶部列出的SDK安装path。

即 一旦你在那里,导航到: <sdk>/extras/google/play_licensing

F。 在eclipse中,单击file然后import ,然后将Existing Android Code Into Workspace ,当它询问您的文件path时,导航到play_licensing文件夹并单击library

G。 一旦导入了名为library的项目,右键单击它,然后点击properties 。 点击左侧的Android并导航到底部,选中Is Library ,然后点击Apply。 这让eclipse知道你可以使用这个项目代码作为一个库。

H。 右键单击要添加许可的应用程序,然后单击属性,然后点击Android 。 转到底部并单击library并将其添加到构buildpath。 这应该将库导入到Android Dependencies文件夹。

一世。 您的项目已设置好,可以进入下一步。

2.2与您的SALTKEY一起声明的variables

 private Handler mHandler; private LicenseChecker mChecker; private LicenseCheckerCallback mLicenseCheckerCallback; boolean licensed; boolean checkingLicense; boolean didCheck; 

2.3代码

将此代码粘贴到应用程序底部附近。 如果许可证无效,此实施将通知用户并提示他们购买应用程序或退出该应用程序。

  private void doCheck() { didCheck = false; checkingLicense = true; setProgressBarIndeterminateVisibility(true); mChecker.checkAccess(mLicenseCheckerCallback); } private class MyLicenseCheckerCallback implements LicenseCheckerCallback { @Override public void allow(int reason) { // TODO Auto-generated method stub if (isFinishing()) { // Don't update UI if Activity is finishing. return; } Log.i("License","Accepted!"); //You can do other things here, like saving the licensed status to a //SharedPreference so the app only has to check the license once. licensed = true; checkingLicense = false; didCheck = true; } @SuppressWarnings("deprecation") @Override public void dontAllow(int reason) { // TODO Auto-generated method stub if (isFinishing()) { // Don't update UI if Activity is finishing. return; } Log.i("License","Denied!"); Log.i("License","Reason for denial: "+reason); //You can do other things here, like saving the licensed status to a //SharedPreference so the app only has to check the license once. licensed = false; checkingLicense = false; didCheck = true; showDialog(0); } @SuppressWarnings("deprecation") @Override public void applicationError(int reason) { // TODO Auto-generated method stub Log.i("License", "Error: " + reason); if (isFinishing()) { // Don't update UI if Activity is finishing. return; } licensed = true; checkingLicense = false; didCheck = false; showDialog(0); } } protected Dialog onCreateDialog(int id) { // We have only one dialog. return new AlertDialog.Builder(this) .setTitle("UNLICENSED APPLICATION DIALOG TITLE") .setMessage("This application is not licensed, please buy it from the play store.") .setPositiveButton("Buy", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse( "http://market.android.com/details?id=" + getPackageName())); startActivity(marketIntent); finish(); } }) .setNegativeButton("Exit", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { finish(); } }) .setNeutralButton("Re-Check", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { doCheck(); } }) .setCancelable(false) .setOnKeyListener(new DialogInterface.OnKeyListener(){ public boolean onKey(DialogInterface dialogInterface, int i, KeyEvent keyEvent) { Log.i("License", "Key Listener"); finish(); return true; } }) .create(); } 

2.4获取您的设备ID

关于是否使用sim serial或TelephonyManager.getDeviceId();过去一直存在一些争议TelephonyManager.getDeviceId(); 但通常build议您使用以下代码来获取设备的ANDROID_ID以实现最大的兼容性。

 String deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID); Log.i("Device Id", deviceId); //AN EXAMPLE OF LOGGING THAT YOU SHOULD BE DOING :) 

2.5创build许可证检查器

一个。 在你调用doCheck();之前doCheck(); 你必须把这个代码放在你的应用程序中,以确保一切正确。

 mHandler = new Handler(); mLicenseCheckerCallback = new MyLicenseCheckerCallback(); mChecker = new LicenseChecker(this, new ServerManagedPolicy(this, new AESObfuscator(SALT, getPackageName(), deviceId)), BASE64_PUBLIC_KEY); 

当我正在执行LVL的实现时,我读到如果您在许可方面有问题,可以在mChecker = new LicenseChecker(this... to getApplicationContext()更改第一个,但是我似乎没有它,但是以防万一。

2.6添加权限

一个。 有两个权限需要添加到您的应用程序manifest文件。

 <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="com.android.vending.CHECK_LICENSE"/> 

2.7确保你有正确的import!

你可能已经这样做了,但我认为这将是一个很好的检查的地方。

2.8如何调用要检查的许可证

一个。 只需要调用doCheck(); 每当你想检查许可证。 例如,如果应用程序在第一次运行,请检查。

3.如何在发布之前testing许可证以确保其正常工作?

3.1configurationtesting设备

一个。 我有我的个人电话,我也用于testing。 build议在电话上只注册一个Google帐户,历史上它使事情变得更容易一些。 您可以通过转到Settings -> Accounts来检查Settings -> Accounts

3.2configuration开发者控制台

一个。 打开您的开发者控制台,并转到左侧的Settings

湾 查找License Testing

C。 确保您的电子邮件地址列在Gmail accounts with testing access

d。 现在,您可以将testing响应更改为任何您喜欢的testing目的。 应用程序应该做出相应的回应 请记住,如果您通过SharedPrefs保存数据,则每次testing时都需要清除应用程序数据。 确保您在更改testing响应后单击保存,否则什么都不会发生! 我多次忘记了这一点,最后我发现了一个偏头痛,然后我看到那个发臭的保存button。 大声笑。

4.要尝试的东西

4.1有条件的许可证检查

一个。 如果didCheck数据保存在SharedPreferences则可以尝试此代码。

  if(didCheck==false){ Toast.makeText(this, "Checking application license...", Toast.LENGTH_SHORT).show(); doCheck(); Log.i("Checking!", "Checking license!"); } 

4.2使用SecurePreferencesencryptionSharedPreferences

一个。 转到此链接 。

湾 将SecurePreferences.java的代码复制并粘贴到您的项目中,名称完全相同。

C。 阅读ReadMe.md以获取有关实现这一点的信息。

5.故障排除

许可证可能是一个令人头痛的故障排除,只是因为有更多的事情可能出错。 例如,可能有networking问题或服务器问题,使你想把你的头发。 使用正确的日志logging将有助于此,如果有问题,还可以获取服务器响应代码,并且可以将其跟踪到服务器或您的应用程序。 我不得不多次这样做。

5.1我无法让我的应用程序从服务器返回任何东西

可能的修正:

一个。 确保您的应用程序具有正确的KEY

湾 确保你正在logging每一步的进展

C。 检查您的日志中的许可服务的任何东西。 找出问题出在什么地方是很有用的。

d。 确保allow()dontAllow()applicationError()具有@Override标签。

5.2无论我在testing响应中设置了什么,我的应用程序总是会说LICENSEDNOT_LICENSED

一个。 我有这个最好的治疗方法就是等待。 看起来,如果你在很短的时间内进行大量的testing,它总会向你发送服务器代码291 ,这是重试代码。 我在一夜之间等待,第二天早上一切正常。

湾 您可以清除Google Play应用和Google Play服务应用的数据(不仅仅是caching)。 然后打开播放,接受所有的许可证,然后重试。

C。 清除您的应用数据。

5.3用于debugging的服务器响应代码列表

如果你logging它们,你应该得到这些十进制值。 使用此表来引用服务器实际发送到您的应用程序的内容。

 LICENSED = Hex: 0x0100, Decimal: 256 NOT_LICENSED = Hex: 0x0231, Decimal: 561 RETRY = Hex: 0x0123, Decimal: 291 LICENSED_OLD_KEY = Hex: 0x2, Decimal: 2 ERROR_NOT_MARKET_MANAGED = Hex: 0x3, Decimal: 3 ERROR_SERVER_FAILURE = Hex: 0x4, Decimal: 4 ERROR_OVER_QUOTA = Hex: 0x5, Decimal: 5 ERROR_CONTACTING_SERVER = Hex: 0x101, Decimal: 257 ERROR_INVALID_PACKAGE_NAME = Hex: 0x102, Decimal: 258 ERROR_NON_MATCHING_UID = Hex: 0x103, Decimal: 259 

5.4更多的空间! 他们会来!

我希望这可以帮助你们! 我试图与大家分享我的头痛,并尽我所能修复,我希望这有助于!

如果我犯了什么错误,一定要告诉我有关他们,所以我可以让他们尽快修复!