适用于Android Studio中Android应用程序的Google Play许可 [英] Google Play Licencing for an Android app in Android Studio

查看:109
本文介绍了适用于Android Studio中Android应用程序的Google Play许可的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为Android Studio中的应用程序为使用Kotlin编写的应用程序设置Google Play许可.我的目标是避免用户在不通过商店购买我的应用程序的情况下共享APK文件.

我尝试过的事情:

  • 我已经尝试通过他们的文档来关注 .这不是很有用.它跳过了许多细节,而实际上并不是教程.我无法使用它.

  • 我已经看到了这个问题,该问题确实有一个冗长而详细的类似于教程的答案.但是答案似乎已经过时了.它会引起很多警告,并以意图必须是明确的"终止.

我的总结问题是:

我该如何通过Google设置许可证检查,以便尚未通过商店购买该应用程序的人无法安装该应用程序.即使我在周围找不到任何适当的答案,这似乎是很常见的事情.

解决方案

这是我在2020年使它工作的方式:

  1. 打开Android Studio.


  1. 点击工具-> SDK Manager


  1. 切换到 SDK工具标签


  1. 确保已安装 Google Play许可库.如果尚未安装,请单击复选标记,然后单击应用.


  1. 在该屏幕上,您可以看到 Android SDK位置.复制该路径:


  1. 点击文件->新->导入模块... :


  1. 粘贴复制的路径,然后单击文本输入行右侧的小文件夹图标:


  1. 点击 Android \ Sdk \ extras \ google \ market_licensing \ library ,然后点击确定:


  1. 点击下一步:


  1. 检查所有内容,然后单击完成:


  1. 现在您应该在项目中有一个library文件夹:


  1. 右键单击app,然后单击打开模块设置:


  1. 点击依赖项:


  1. 点击加号按钮,然后选择 3模块依赖性:


  1. 检查library并单击确定:


  1. 再次单击确定,然后等待其同步.


  1. 如果您遇到错误

不应在Android清单文件中声明minSdk版本.您可以将版本从清单移动到build.gradle文件中的defaultConfig.

转到库>清单> AndroidManifest.xml ,然后删除行<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="15" />.


  1. 转到成绩脚本> build.gradle(模块:库):


  1. minSdkVersion更改为4,并根据需要更改compileSdkVersionbuildToolsVersiontargetSdkVersion,然后单击Sync Now:


  1. 现在库已准备就绪,我们需要许可证检查的实际实现.转到MainActivity.kt.


  1. 您需要找到您的Base 64公钥,并生成盐,如答案所示.我将引用该答案的必要部分,但将代码翻译为Kotlin:

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

如何获取:

a.转到您的开发者控制台. 链接.

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

c.创建草稿后,最好上传您的 .apk为Alpha或Beta.保留它未发布.

d.点击Services & APIs

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

f.像这样将密钥复制到您的应用中:

private const val BASE64_PUBLIC_KEY = "YOUR LICENSE KEY FOR THIS APPLICATION";

确保没有空格.

1.2盐

a.什么是盐?

是随机数据,是散列a时的附加输入 密码.它们用于防御词典攻击彩虹表攻击.

b.我怎么得到一个?

是生成随机盐的好链接.应该恰好 20个随机整数,因此请输入20表示要计算的随机字符串的数量 生成时,每个字符串的长度应为2个字符(用于此操作) 例如,不一定必须如此).检查数字,并检查 允许使用相同的字符串.它们也可以是负数.尝试 删除任何冗余,例如00 -> 0,为了保持一致.

c.我在哪里放盐?

在声明变量时,只需将这段代码放进去,除了 随机盐.

private val SALT = byteArrayOf(YOUR RANDOM SALT COMMA SEPARATED 20 INTEGERS)


  1. 第21步中的变量应添加到您的主要活动类别中.现在,您应该在主要活动中添加一些代码.这是大致的样子(请注意// TODO注释):

import android.os.Bundle
import android.provider.Settings
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.vending.licensing.*
import kotlin.system.exitProcess

class MainActivity : AppCompatActivity()
{
    companion object
    {
        private const val BASE64_PUBLIC_KEY = "YOUR LICENSE KEY FOR THIS APPLICATION" // TODO replace with your own key

        private val SALT = byteArrayOf(YOUR RANDOM SALT COMMA SEPARATED 20 INTEGERS) // TODO replace with your own salt
        
    }
    
    private val deviceId: String by lazy {
        Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
    }
    private lateinit var licenseCheckerCallback: LicenseCheckerCallback
    private lateinit var checker: LicenseChecker
    
    private fun doCheck()
    {
        checker.checkAccess(licenseCheckerCallback)
    }

    override fun onDestroy()
    {
        super.onDestroy()
        checker.onDestroy()
    }



    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)

        // Construct the LicenseCheckerCallback. The library calls this when done.
        licenseCheckerCallback = MyLicenseCheckerCallback()

        // Construct the LicenseChecker with a Policy.
        checker = LicenseChecker(
            this,
            ServerManagedPolicy(this, AESObfuscator(SALT, packageName, deviceId)),
            BASE64_PUBLIC_KEY // Your public licensing key.
        )

        doCheck()

        setContentView(R.layout.activity_main) // TODO Replace with your own layout
    }

    private fun displayResult(result: String)
    {
         // TODO you can change this how the info is displayed
        Toast.makeText(this, result, Toast.LENGTH_SHORT).show()
    }

    private inner class MyLicenseCheckerCallback : LicenseCheckerCallback
    {
        override fun allow(reason: Int)
        {
            if (isFinishing)
            {
                // Don't update UI if Activity is finishing.
                return
            }
            // Should allow user access.
        }

        override fun applicationError(errorCode: Int)
        {
             // TODO handle the error your own way. Calling `dontAllow` is common.
            dontAllow(Policy.NOT_LICENSED)
        }

        override fun dontAllow(reason: Int)
        {
            if (isFinishing)
            {
                // Don't update UI if Activity is finishing.
                return
            }
            

            if (reason == Policy.RETRY)
            {
                // If the reason received from the policy is RETRY, it was probably
                // due to a loss of connection with the service, so we should give the
                // user a chance to retry. So show a dialog to retry.

                // TODO handle Policy.RETRY
            }
            else
            {
                // Otherwise, the user isn't licensed to use this app.
                // Your response should always inform the user that the application
                // isn't licensed, but your behavior at that point can vary. You might
                // provide the user a limited access version of your app or you can
                // take them to Google Play to purchase the app.

                // TODO implement goto market
            }
            displayResult("Not Licensed")
            
            // TODO you may not abort if you have some other way to handle the fail case
            abort()
        }
    }

    private fun abort()
    {
        finishAffinity()
        exitProcess(0) 
    }
}


  1. 将以下权限添加到清单文件中:

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


  1. 如果您收到类似以下消息的异常消息:

Service Intent must be explicit: Intent { act=com.android.vending.licensing.ILicensingService }

答案中应用此修复程序.


  1. 仅此而已.请参阅我之前引用的答案以获取更多信息.我希望这可以节省其他人的时间.

I am trying to set up Google Play Licencing for an app in Android studio for an app written in Kotlin. My goal is to avoid users sharing APK files without purchasing my app through the store.

What I've tried:

  • I've tried following through their documentation. It's not very useful. It skips over many details and it's not really a tutorial. I couldn't use it.

  • I've seen this question, which does have a long and detailed tutorial-like answer. But the answer seems long-outdated. It causes lots of warnings and terminates with an exception "Intent must be explicit".

My question in summary is:

How can I set up license checking through Google so people who haven't purchased the app through the store can't install it. This seems to be a very common thing to do even though I couldn't manage to find much of any proper answer around.

解决方案

Here's how I got it working in 2020:

  1. Open Android Studio.


  1. Click Tools -> SDK Manager


  1. Switch to the SDK Tools tab


  1. Make sure Google Play Licensing Library is installed. If it's not installed, click the checkmark and click Apply.


  1. Up in that screen you can see Android SDK Location. Copy that path:


  1. Click File -> New -> Import Module...:


  1. Paste the path you copied and click the small folder icon on the right of the text-input line:


  1. Click Android\Sdk\extras\google\market_licensing\library and click OK:


  1. Click Next:


  1. Leave everything checked and click Finish:


  1. Now you should have a library folder in your project:


  1. Right click on app and click Open Module Settings:


  1. Click Dependencies:


  1. Click the plus button and choose 3 Module Dependency:


  1. Check library and click OK:


  1. Click OK again and wait for it to sync.


  1. If you get an error

The minSdk version should not be declared in the android manifest file. You can move the version from the manifest to the defaultConfig in the build.gradle file.

Go to library > manifests > AndroidManifest.xml and remove the line <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="15" />.


  1. Go to Gradle Scripts > build.gradle (Module: library):


  1. Change minSdkVersion to 4 and also change compileSdkVersion, buildToolsVersion and targetSdkVersion as necessary, then click Sync Now:


  1. Now that the library is ready, we need the actual implementation of the license checking. Go to MainActivity.kt.


  1. You need to find your Base 64 public key and also generate a salt as shown in this answer. I am going to quote the necessary part of that answer but translate the code to Kotlin:

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 const val 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 val SALT = byteArrayOf(YOUR RANDOM SALT COMMA SEPARATED 20 INTEGERS)


  1. Variables in step 21 should be added to your main activity class. Now, you should add some code to your main activity. Here's what it should roughly look like (Pay attention to // TODO comments):

import android.os.Bundle
import android.provider.Settings
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.vending.licensing.*
import kotlin.system.exitProcess

class MainActivity : AppCompatActivity()
{
    companion object
    {
        private const val BASE64_PUBLIC_KEY = "YOUR LICENSE KEY FOR THIS APPLICATION" // TODO replace with your own key

        private val SALT = byteArrayOf(YOUR RANDOM SALT COMMA SEPARATED 20 INTEGERS) // TODO replace with your own salt
        
    }
    
    private val deviceId: String by lazy {
        Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
    }
    private lateinit var licenseCheckerCallback: LicenseCheckerCallback
    private lateinit var checker: LicenseChecker
    
    private fun doCheck()
    {
        checker.checkAccess(licenseCheckerCallback)
    }

    override fun onDestroy()
    {
        super.onDestroy()
        checker.onDestroy()
    }



    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)

        // Construct the LicenseCheckerCallback. The library calls this when done.
        licenseCheckerCallback = MyLicenseCheckerCallback()

        // Construct the LicenseChecker with a Policy.
        checker = LicenseChecker(
            this,
            ServerManagedPolicy(this, AESObfuscator(SALT, packageName, deviceId)),
            BASE64_PUBLIC_KEY // Your public licensing key.
        )

        doCheck()

        setContentView(R.layout.activity_main) // TODO Replace with your own layout
    }

    private fun displayResult(result: String)
    {
         // TODO you can change this how the info is displayed
        Toast.makeText(this, result, Toast.LENGTH_SHORT).show()
    }

    private inner class MyLicenseCheckerCallback : LicenseCheckerCallback
    {
        override fun allow(reason: Int)
        {
            if (isFinishing)
            {
                // Don't update UI if Activity is finishing.
                return
            }
            // Should allow user access.
        }

        override fun applicationError(errorCode: Int)
        {
             // TODO handle the error your own way. Calling `dontAllow` is common.
            dontAllow(Policy.NOT_LICENSED)
        }

        override fun dontAllow(reason: Int)
        {
            if (isFinishing)
            {
                // Don't update UI if Activity is finishing.
                return
            }
            

            if (reason == Policy.RETRY)
            {
                // If the reason received from the policy is RETRY, it was probably
                // due to a loss of connection with the service, so we should give the
                // user a chance to retry. So show a dialog to retry.

                // TODO handle Policy.RETRY
            }
            else
            {
                // Otherwise, the user isn't licensed to use this app.
                // Your response should always inform the user that the application
                // isn't licensed, but your behavior at that point can vary. You might
                // provide the user a limited access version of your app or you can
                // take them to Google Play to purchase the app.

                // TODO implement goto market
            }
            displayResult("Not Licensed")
            
            // TODO you may not abort if you have some other way to handle the fail case
            abort()
        }
    }

    private fun abort()
    {
        finishAffinity()
        exitProcess(0) 
    }
}


  1. Add these permissions to your manifest file:

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


  1. If you get an exception with a message similar to:

Service Intent must be explicit: Intent { act=com.android.vending.licensing.ILicensingService }

Apply the fix in this answer.


  1. That should be all. See the answer I quoted previously for more info. I hope this saves others some time.

这篇关于适用于Android Studio中Android应用程序的Google Play许可的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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