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

Cod*_*ity 41 java android licensing android-lvl

我看到了Android-Developer许可库的说明,但概述似乎省略了该过程中的几个关键步骤,并且未能完全解释如何使某些工作正常.

有人可以提供一组明确的操作,这些操作可以在Android应用程序上设置许可库,以便在允许使用之前检查以确保用户已在Google Play中为应用付费吗?

Cod*_*ity 156

我已经在我的应用程序中实施许可已有一段时间了,并最终使其正常运行.我想分享一些我发现对入门有帮助的事情以及我发现的一些问题和解决方案.我在下面链接的android开发教程是可以的,但它对我没用,所以我决定做一个教程.享受,我希望它能帮到你!

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

1.入门

你需要的东西.

1.1您的Base64唯一应用程序密钥

怎么弄它:

一个.转到开发人员控制台.链接.

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

C.创建草稿后,最好将您上传.apk为Alpha或Beta.保持未发表.

d.点击Services & APIs

即 向下滚动并找到YOUR LICENSE KEY FOR THIS APPLICATION

F.将密钥复制到您的应用中,如下所示:

private static final String BASE64_PUBLIC_KEY = "YOUR LICENSE KEY FOR THIS APPLICATION"; 
Run Code Online (Sandbox Code Playgroud)

确保没有空格.

1.2盐

一个.什么是盐?

酸盐是散列密码时即附加输入随机数据.它们用于防御字典攻击彩虹表攻击.

湾 我怎么得到一个?

是生成随机盐的良好链接.应该有正好 20个随机整数,因此20要生成随机字符串的数量,每个字符串应该是2字符长(用于此示例,它不必是).检查数字,并检查是否允许相同的字符串.他们也可以是负数.尝试删除任何冗余,例如00 -> 0,为了一致性.

C.我在哪里放盐?

声明变量时只需输入此代码,除了随机盐.

private static final byte[] SALT = new byte[] {YOUR RANDOM SALT, COMMA SEPARATED, 20 INTEGERS};
Run Code Online (Sandbox Code Playgroud)

2.将LVL(许可)库导入Eclipse以及所需的代码

2.1导入库

一个.打开Android SDK Manager

湾 去Extras

C.安装Google Play Licensing Library

d.找到SDKSDK管理器顶部列出的安装路径.

即 到达后,请导航至:<sdk>/extras/google/play_licensing

F.在eclipse中,单击file然后import,Existing Android Code Into Workspace当它询问您文件路径时,导航到该play_licensing文件夹并单击library.

G.library导入已命名的项目后,右键单击它,然后单击properties.单击Android左侧并导航到底部并检查Is Library,然后单击"应用".这让eclipse知道你可以将这个项目代码用作库.

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

一世.您的项目已设置为进入下一步.

2.2与你SALT和你一起声明的变量KEY

private Handler mHandler;
private LicenseChecker mChecker;
private LicenseCheckerCallback mLicenseCheckerCallback;
boolean licensed;
boolean checkingLicense;
boolean didCheck;
Run Code Online (Sandbox Code Playgroud)

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();

    }
Run Code Online (Sandbox Code Playgroud)

2.4获取设备ID

过去有关于是否使用SIM序列的问题存在争议,TelephonyManager.getDeviceId();但通常建议您使用以下代码来获得ANDROID_ID最佳兼容性.

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

2.5创建许可证检查程序

一个.在您致电之前,doCheck();您必须将此代码放入您的应用中,以确保所有内容都正确创建.

mHandler = new Handler();
mLicenseCheckerCallback = new MyLicenseCheckerCallback();
mChecker = new LicenseChecker(this, new ServerManagedPolicy(this, new   AESObfuscator(SALT, getPackageName(), deviceId)), BASE64_PUBLIC_KEY);
Run Code Online (Sandbox Code Playgroud)

当我在做我的拉特implemetation,我读了,如果您有授权的问题,您可以更改第一个thismChecker = new LicenseChecker(this...getApplicationContext(),雷似乎没有它的工作,但为了以防万一.

2.6添加权限

一个.您需要将两个权限添加到应用程序manifest文件中.

<uses-permission android:name="android.permission.INTERNET"/>  
<uses-permission android:name="com.android.vending.CHECK_LICENSE"/>        
Run Code Online (Sandbox Code Playgroud)

2.7确保您有正确的进口!

你可能已经这样做了,但我认为这是一个值得你检查的好地方.

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

一个.doCheck();只要您想检查许可证,只需致电.例如,如果应用程序首次运行,请进行检查.

3.如何在发布之前测试许可以确保其有效?

3.1配置测试设备

一个.我有我的私人电话,我也用它来测试.建议手机上只注册一个Google帐户,从历史上看,它会让事情变得更容易一些.您可以转到查看帐户Settings -> Accounts.

3.2配置开发人员控制台

一个.打开开发人员控制台,然后转到Settings左侧.

湾 找License Testing

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

d.现在,您可以将测试响应更改为您喜欢的任何测试响应以进行测试.应用应该做出相应的回应.请记住,如果您通过SharedPrefs保存数据,则每次测试时都需要清除应用数据.确保在更改测试响应后单击"保存",否则不会发生任何事情!我多次忘了这个,最后我得了一个偏头痛,然后我看到那个发臭的保存按钮.大声笑.

4.要尝试的事情

4.1条件许可检查

一个.如果要保存didCheck数据,可以尝试使用此代码SharedPreferences.

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

4.2加密SharedPreferences使用SecurePreferences

一个.转到此链接.

湾 将代码复制并粘贴SecurePreferences.java到项目中具有完全相同名称的类中.

C.阅读ReadMe.md有关实施此信息的信息.

5.故障排除

许可证可能是令人头疼的问题,因为还有许多问题可能会出错.例如,可能存在网络问题或服务器问题,这些问题会让您想要扯掉头发.使用正确的日志记录将有助于此,如果出现问题,您还可以获取服务器响应代码,并且可以将其跟踪到服务器或应用程序.我不得不多次这样做.

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

可能的修复:

一个.确保您的应用正确无误KEY.

湾 确保记录进度的每个步骤

C.从许可服务中检查您的日志.它可以用于找出出错的地方.

d.确保allow()dontAllow()applicationError()@Override标签.

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

一个.我对此有最好的治疗方法就是等待.看来如果你在很短的时间内做了很多测试,它总会发送给你的服务器代码291,这是重试代码.我等了一夜,第二天早上一切正常.

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

C.清除您的应用数据.

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

int reason如果您记录它们,您应该获得这些十进制值.使用此表来引用服务器实际发送到您的应用程序的内容.

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
Run Code Online (Sandbox Code Playgroud)

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

我希望这可以帮助你们!我试着尽可能地与你们分享我的头痛和修复,我希望这有帮助!

如果我犯了任何错误,请务必告诉我他们,以便我尽快修复它们!

  • 伟大的工作和承诺..欣赏它.保持良好的工作. (12认同)
  • 这不能得到足够的支持.它比官方的Google文档更能帮助我. (5认同)
  • 很好的解释,但重要的是,"<uses-permission android:name ="android.permission.INTERNET"/>`不是必需的.重要的是要说您的应用程序不需要直接互联网来验证许可证. (2认同)
  • 有趣的是,谷歌多年来没有更新他们关于LVL的任何文件,所以上述答案仍然相关(如果LVL仍然相关?).对于开发人员心目中如此严重的盗版保护问题,它似乎被谷歌推到了一边?为什么?我仍然对Google示例中已弃用的内容存在问题,以及如何在支持付费和免费应用的代码库中合并许可,但我将部分归功于上述答案.干杯. (2认同)