Ayx*_*xan 3 android licensing android-lvl kotlin android-studio
我正在尝试为 Android studio 中的一个用 Kotlin 编写的应用程序设置 Google Play 许可。我的目标是避免用户在不通过商店购买我的应用程序的情况下共享 APK 文件。
我尝试过的:
我尝试按照他们的文档进行操作。这不是很有用。它跳过了许多细节,而且它并不是真正的教程。我无法使用它。
我看过这个问题,它确实有一个又长又详细的类似教程的答案。但这个答案似乎早已过时了。它会导致大量警告并以“意图必须明确”异常终止。
我的问题总结是:
如何通过 Google 设置许可证检查,以便未通过商店购买该应用程序的人无法安装它。尽管我无法找到任何正确的答案,但这似乎是一件很常见的事情。
Ayx*_*xan 10
以下是我在 2020 年如何让它发挥作用:
library现在您的项目中应该有一个文件夹:app并单击打开模块设置:library并点击OK:minSdk 版本不应在 android 清单文件中声明。您可以将版本从清单移动到 build.gradle 文件中的defaultConfig。
转到库 > 清单 > AndroidManifest.xml并删除该行<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="15" />。
minSdkVersion为 4,并根据需要更改compileSdkVersion和,然后buildToolsVersion单击:targetSdkVersionSync NowMainActivity.kt。1.1 您的 Base64 唯一应用程序密钥
如何获得:
A。转到您的开发者控制台。关联。
b. 如果您尚未为您的应用创建申请草案,请立即创建。
C。创建草稿后,最好将草稿上传
.apk为 Alpha 版或 Beta 版。让它不发布。d. 点击
Services & APIse. 向下滚动并找到
YOUR LICENSE KEY FOR THIS APPLICATIONF。将密钥复制到您的应用程序中,如下所示:
Run Code Online (Sandbox Code Playgroud)private const val BASE64_PUBLIC_KEY = "YOUR LICENSE KEY FOR THIS APPLICATION";确保没有空格。
1.2 盐
A。什么是盐?
盐是随机数据,是散列密码时的附加输入。它们用于防御字典攻击和 彩虹表攻击。
b. 我怎样才能得到一个?
这是生成随机盐的好链接。应该正好有 20 个随机整数,因此输入
20要生成的随机字符串的数量,每个字符串应该是2字符长(用于本示例,但不一定如此)。检查数字,并检查是否允许相同的字符串。它们也可以是负数。尝试删除任何冗余,例如00 -> 0,为了一致性。C。我该把盐放在哪里?
声明变量时,只需放入此代码即可,除非使用随机盐。
Run Code Online (Sandbox Code Playgroud)private val SALT = byteArrayOf(YOUR RANDOM SALT COMMA SEPARATED 20 INTEGERS)
// 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)
}
}
Run Code Online (Sandbox Code Playgroud)
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.vending.CHECK_LICENSE"/>
Run Code Online (Sandbox Code Playgroud)
Service Intent must be explicit: Intent { act=com.android.vending.licensing.ILicensingService }
Run Code Online (Sandbox Code Playgroud)
应用此答案中的修复。
| 归档时间: |
|
| 查看次数: |
1833 次 |
| 最近记录: |