如何为Android应用实施Google Play许可? [英] How can I implement Google Play Licensing for an Android app?

查看:262
本文介绍了如何为Android应用实施Google Play许可?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

解决方案

我有一段时间以来我一直致力于在我的应用程序中实现许可,并最终使其正常运行。我想分享一些我认为对入门有帮助的事情以及我发现的一些问题和解决方案。我在下面链接的android开发教程是可以的,但它对我没那么有用,所以我决定做一个教程。享受,我希望它对您有所帮助!



链接到开发者页面此处



1。入门



您需要的东西。



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



如何获得:



a。转到开发人员控制台。 链接。



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



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



d。点击服务& API



e。向下滚动并找到此应用程序的许可证密钥



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

  private static final String BASE64_PUBLIC_KEY =此应用程序的许可密钥; 

确保没有空格。



1.2盐



a。什么是盐?



是随机数据,是散列密码时的附加输入。它们用于抵御字典攻击彩虹表攻击。



b。我如何获得一个?



这是一个很好的链接生成随机盐。应该有完全 20个随机整数,因此将 20 输入要生成的随机字符串数量,每个字符串应为 2 字符长(用于此示例,不一定是这样)。检查数字,并选中允许相同的字符串。它们也可以是负数。尝试删除任何冗余,例如 00 - > 0 ,为了保持一致。



c。我在哪里放盐?



当声明变量时,只需输入此代码,除了你的随机盐。

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

2。将LVL(许可)库导入Eclipse和您需要的代码



2.1导入库



a。打开 Android SDK Manager



b。转到额外



c。安装 Google Play许可库



d。找到您的 SDK 安装路径,该路径列在SDK管理器的顶部。



e。进入后,请导航至:< sdk> / extras / google / play_licensing



f。在eclipse中,单击文件然后 import ,然后现有Android代码进入工作区当它询问你的文件路径时,导航到 play_licensing 文件夹,然后点击 library 。 / p>

g。导入名为 library 的项目后,右键单击它,然后点击 properties 。点击左侧的 Android ,然后导航到底部并检查 Is Library ,然后点击apply。这让eclipse知道你可以将这个项目代码用作库。



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



i。您的项目已设置为进入下一步。



2.2要与 SALT 和 KEY

  private Handler mHandler; 
私有LicenseChecker mChecker;
private LicenseCheckerCallback mLicenseCheckerCallback;
布尔许可;
boolean checkingLicense;
boolean didCheck;

2.3代码



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

  private void doCheck (){

didCheck = false;
checkingLicense = true;
setProgressBarIndeterminateVisibility(true);

mChecker.checkAccess(mLicenseCheckerCallback);
}


私有类MyLicenseCheckerCallback实现LicenseCheckerCallback {

@Override
public void allow(int reason){
/ / TODO自动生成的方法stub
if(isFinishing()){
//如果Activity正在完成,请不要更新UI。
返回;
}
Log.i(许可证,已接受!);

//您可以在此处执行其他操作,例如将许可状态保存到
// SharedPreference,以便应用程序只需检查一次许可证。

licensed = true;
checkingLicense = false;
didCheck = true;

}

@SuppressWarnings(弃用)
@Override
public void dontAllow(int reason){
// TODO Auto生成的方法stub
if(isFinishing()){
//如果Activity正在完成,请不要更新UI。
返回;
}
Log.i(许可证,拒绝!);
Log.i(许可证,拒绝理由:+原因);

//您可以在此处执行其他操作,例如将许可状态保存到
// SharedPreference,以便应用程序只需检查一次许可证。

licensed = false;
checkingLicense = false;
didCheck = true;

showDialog(0);

}

@SuppressWarnings(弃用)
@Override
public void applicationError(int reason){
// TODO Auto生成方法stub
Log.i(许可证,错误:+原因);
if(isFinishing()){
//如果活动结束,请不要更新UI。
返回;
}
licensed = true;
checkingLicense = false;
didCheck = false;

showDialog(0);
}


}

protected Dialog onCreateDialog(int id){
//我们只有一个对话框。
返回新的AlertDialog.Builder(this)
.setTitle(未使用的应用程序对话标题)
.setMessage(此应用程序未获得许可,请从Play商店购买。)
.setPositiveButton(Buy,new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog,int which 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(许可证,密钥监听器);
完成();
返回true;
}
})
.create();

}

2.4获取设备ID



过去有关于是否使用SIM序列或 TelephonyManager.getDeviceId(); 但通常建议您使用以下代码获取设备的 ANDROID_ID 以获得最大兼容性。

  String deviceId = Secure.getString(getContentResolver(),Secure.ANDROID_ID); 
Log.i(Device Id,deviceId); //记录你应该做的一个例子:)

2.5创建许可证检查器



a。在您致电 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中的第一个(此... getApplicationContext (),我似乎没有它,但为了以防万一。



2.6添加权限



a。您需要向应用程序添加两个权限清单文件。

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

2.7确保你有正确的进口!



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



2.8如何调用许可证



a。只需致电 doCheck(); 每当您想要检查许可证时。例如,如果应用程序首次运行,请进行检查。



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



3.1配置测试设备



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



3.2配置开发者控制台



一个。打开您的开发者控制台,然后转到左侧的设置



b。查找许可证测试



c。确保您的电子邮件地址列在具有测试访问权限的Gmail帐户



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



4。需要尝试的事项



4.1条件许可检查



a。如果要在 SharedPreferences 中保存 didCheck 数据,可以尝试使用此代码。

  if(didCheck == false){
Toast.makeText(this,Checking application license ...,Toast.LENGTH_SHORT).show() ;
doCheck();
Log.i(正在检查!,检查许可证!);
}

4.2加密 SharedPreferences 使用 SecurePreferences



a。转到此链接



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



c 。阅读 ReadMe.md 以获取有关实施此信息的信息。



5。疑难解答



许可可能是排除故障的一个难题,仅仅因为还有许多问题可能出错。例如,可能存在网络问题或服务器问题,使您想要撕掉头发。使用正确的日志记录将有助于此,如果出现问题,您还可以获取服务器响应代码,并且可以将其跟踪到服务器或应用程序。我不得不多次这样做。



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



可能的修正:



a。确保您的应用具有正确的 KEY



b。确保记录进度的每一步



c。检查您的日志以获取许可服务中的任何内容。找出出错的地方非常有用。



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



5.2我的应用总是说已获许可 NOT_LICENSED 无论我在测试回复中设置了什么



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



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



c。清除您的应用数据。



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



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

  LICENSED =十六进制:0x0100,十进制:256 
NOT_LICENSED =十六进制:0x0231,十进制:561
重试=十六进制:0x0123,十进制:291
LICENSED_OLD_KEY =十六进制:0x2,十进制:2
ERROR_NOT_MARKET_MANAGED =十六进制:0x3,十进制:3
ERROR_SERVER_FAILURE =十六进制:0x4,十进制:4
ERROR_OVER_QUOTA =十六进制:0x5,十进制:5
ERROR_CONTACTING_SERVER =十六进制:0x101,十进制:257
ERROR_INVALID_PACKAGE_NAME =十六进制:0x102,十进制:258
ERROR_NON_MATCHING_UID =十六进制:0x103,十进制:259

5.4更多!他们会来的!



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



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


I saw the stock Android-Developer licensing library instructions, but the overview seems to omit several key steps in the process and fails to fully explain how to get something working.

Can someone provide an explicit set of operations that worked to get the licensing library set up on an Android app so it checks to ensure that a user has paid for an app in Google Play before allowing use?

解决方案

I have been working on implementing licensing in my app for some time now and finally have it working. I wanted to share some of the things I found helpful for getting started and some problems and solutions that I found with everyone. The android dev tutorial I have linked below is ok, but it wasn't that useful for me, so I decided to make a tutorial. Enjoy, and I hope it helps you!

Link to developer page here.

1. Getting started

Things you will need.

1.1 Your Base64 unique application key

How to get it:

a. Go to your developer console. Link.

b. If you haven't already created an application draft for your app, do it now.

c. Once you have created the draft, it is a good idea to upload your .apk as Alpha or Beta. Leave it unpublished.

d. Click Services & APIs

e. Scroll down and find YOUR LICENSE KEY FOR THIS APPLICATION

f. Copy the key into your app like this:

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

Make sure that there are no spaces.

1.2 A salt

a. What is a salt?

A salt is random data that is additional input when hashing a password. They are used to defend against dictionary attacks and rainbow table attacks.

b. How do I get one?

This is a good link to generate a random salt. There should be exactly 20 random integers, so put 20 in for the amount of random strings to generate, each string should be 2 characters long (used for this example, it doesn't have to be). Check numeric digits, and check Identical strings are allowed. They can be negative numbers too. Try to remove any redundancy, e.g. 00 -> 0, for the sake of consistency.

c. Where do I put the salt?

When declaring variables just put this code in, except with your random salt.

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

2. Importing the LVL (Licensing) library into Eclipse and the code you need

2.1 Importing the library

a. Open Android SDK Manager

b. Go to Extras

c. Install Google Play Licensing Library

d. Find your SDK install path which is listed at the top of the SDK manager.

e. Once you are there, navigate to: <sdk>/extras/google/play_licensing

f. In eclipse, click file then import, then Existing Android Code Into Workspace and when it asks you for the file path, navigate to the play_licensing folder and click on library.

g. Once the project named library has been imported, right click it, then hit properties. Click Android on the left and navigate to the bottom and check Is Library, then hit apply. This lets eclipse know that you can use this project code as a library.

h. Right click on your app that you are adding licensing to, and click properties, then hit Android. Go to the bottom and click library and add it to the build path. This should import the library to the Android Dependencies folder.

i. Your project is set up to go to the next step.

2.2 Variables to declare along with your SALT and KEY

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

2.3 The code

Paste this code near the bottom of your app. This implementation will notify the user if the license is not valid and prompt them to buy the app or exit it.

    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 Getting your device id

There has been some debate about this in the past about whether or not to use the sim serial or TelephonyManager.getDeviceId(); but it is generally recommended you use the following code to get the ANDROID_ID of your device for maximum compatibility.

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

2.5 Creation of the license checker

a. Before you call doCheck(); you must put this code in your app to make sure everything gets created properly.

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

When I was doing my implemetation of LVL, I read that if you are having problems with Licensing, you can change the first this in the mChecker = new LicenseChecker(this... to getApplicationContext(), mine seemed to work without it, but just in case.

2.6 Adding permissions

a. There are two permissions that you need to add to your applications manifest file.

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

2.7 Make sure you have the proper imports!

You have probably already done this, but I figured it would be a good place for you to check.

2.8 How to call the license to be checked

a. Simply call doCheck(); whenever you want to check the license. For example if the app is on its first run, do the check.

3. How do I test the licensing to make sure it works before publishing it?

3.1 Configuring the testing device

a. I have my personal phone that I also use for testing. It is recommended that there be only one Google account registered on the phone, historically it makes things a little easier. You can check the accounts by going to Settings -> Accounts.

3.2 Configuring the developer console

a. Open your developer console and go to Settings on the left hand side.

b. Find License Testing

c. Make sure that your email address is listed under Gmail accounts with testing access

d. Now, you can change the test response to whatever you like for testing purposes. The app should respond accordingly. Remember that if you are saving the data via SharedPrefs you will need to clear your app data every time you test it. Make sure that you click save after you change the test response or nothing will happen! I forgot about this multiple times and I ended up with a migraine, then I saw that stinking save button. Lol.

4. Things to try

4.1 Conditional license checking

a. You can try this code if you are saving the didCheck data in SharedPreferences.

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

4.2 Encrypting your SharedPreferences using SecurePreferences

a. Go to this link.

b. Copy and paste the code from SecurePreferences.java into a class with the exact same name into your project.

c. Read the ReadMe.md for info on implementing this.

5. Troubleshooting

Licensing can be one heck of a headache to troubleshoot, simply because there are many more things that can go wrong. For example, there could be network problems or server problems that make you want to rip your hair out. Use of proper logging will help with this, you can also get the server response codes if there is a problem and you can trace it to the server or your app. I have had to do this on multiple occasions.

5.1 I can't get my app to return anything from the server

Possible Fixes:

a. Make sure that your app has the correct KEY.

b. Make sure you are logging each step of the progress

c. Check your log for anything from the licensing service. It can be useful for figuring out where something went wrong.

d. Make sure allow() and dontAllow() and applicationError() have @Override tags.

5.2 My app always says LICENSED or NOT_LICENSED no matter what I set it to in the test response

a. The best cure I have for this is just to wait. It seems that if you do lots of testing in a short period of time, it will always send you server code 291 which is the retry code. I waited overnight and everything worked fine the next morning.

b. You can clear the data (not just cache) of the Google Play app and the Google Play Services app. Then open play back up and accept all the licenses and try again.

c. Clear your app data.

5.3 List of server response codes for debugging

You should get these decimal values for int reason if you log them. Use this table to reference what the server is actually sending to your app.

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 Room for more! They will come!

I hope this helps you guys! I tried to share my headaches and fixes with you guys as best I can and I hope this helps!

If I made any errors, be sure to tell me about them so I can get them fixed ASAP!

这篇关于如何为Android应用实施Google Play许可?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆