如何为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与您的SALT
和KEY
一起声明的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使用SecurePreferences
encryptionSharedPreferences
一个。 转到此链接 。
湾 将SecurePreferences.java
的代码复制并粘贴到您的项目中,名称完全相同。
C。 阅读ReadMe.md
以获取有关实现这一点的信息。
5.故障排除
许可证可能是一个令人头痛的故障排除,只是因为有更多的事情可能出错。 例如,可能有networking问题或服务器问题,使你想把你的头发。 使用正确的日志logging将有助于此,如果有问题,还可以获取服务器响应代码,并且可以将其跟踪到服务器或您的应用程序。 我不得不多次这样做。
5.1我无法让我的应用程序从服务器返回任何东西
可能的修正:
一个。 确保您的应用程序具有正确的KEY
。
湾 确保你正在logging每一步的进展
C。 检查您的日志中的许可服务的任何东西。 找出问题出在什么地方是很有用的。
d。 确保allow()
和dontAllow()
和applicationError()
具有@Override
标签。
5.2无论我在testing响应中设置了什么,我的应用程序总是会说LICENSED
或NOT_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更多的空间! 他们会来!
我希望这可以帮助你们! 我试图与大家分享我的头痛,并尽我所能修复,我希望这有助于!
如果我犯了什么错误,一定要告诉我有关他们,所以我可以让他们尽快修复!