Android集成google license(License Verification Library)

当我们的应用上架google应用市场时,可能希望应用在被授权后才能使用。因此Google play为我们提供了许可服务,借助该服务,应用可以在运行时查询google play服务器,获取当前用户的许可状态,APP可以根据具体的情况禁止或允许用户进一步使用。以下是官方文档的链接:应用许可

本博客的重点在于如何集成官方提供的License Verification Library,来实现Google play的权限验证。

1. 设置发布账号,并生成应用的许可公钥;

2. 下载LVL;

git clone https://github.com/google/play-licensing

这是google的一个开源库,其中包括LVL库的源代码以及示例代码(比较奇怪的是这个库官方并没有放到sdk manager中,而且项目代码使用的sdk版本也非常的旧)。

LVL下载成功后,需要关注的是lvl_library中的内容,为了能够兼容集成应用的sdk版本,先要修改如下位置(app/build.gradle):

apply plugin: 'com.android.library'

android {
    compileSdkVersion 29

    defaultConfig {
        minSdkVersion 23
        targetSdkVersion 29
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

将编译的sdk版本和目标版本改为29,同时最小支持sdk版本改为23。

3. 集成LVL

将lvl_library文件夹拷贝到应用的app目录下,同时在app/build.gradle中加上:

implementation project(':lvl_library')

在settings.gradle中添加:

include ':app', ':lvl_library'

sync project即可。

4. 编写代码进行权限验证

权限验证的代码可以放到任意的Activity中,但是为了在某些情况下禁止未授权用户使用应用,往往是在作为应用入口的Activity中,比如MainActivity。

具体步骤如下:

4.1 声明常量保存公钥和盐:

private static final String BASE64_PUBLIC_KEY = "YOUR_PUBLIC_KEY";
private static final byte[] SALT = new byte[] {
        -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95, -45, 77, -117, -36, -113, -11, 32, -64, 89
};

这里使用的盐限定使用长度为20的字节数组。

4.2 通过公钥、盐和设备id实例化LicenseChecker:

private LicenseChecker mLicenseChecker;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ......
    String deviceId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
    mLicenseChecker = new LicenseChecker(
            this, new ServerManagedPolicy(this,
            new AESObfuscator(SALT, getPackageName(), deviceId)),
            BASE64_PUBLIC_KEY);
    checkLicense();
}

4.3 检查权限checkLicense方法

private void checkLicense() {
  if (!isAllowToUse()) {
    mLicenseChecker.checkAccess(new LicenseCheckerCallback() {
      @Override
      public void allow(int reason) {
        Log.d(TAG, "allow to use with reason " + reason);
        saveMsgToPrefs("isAllowToUse", "isAllowToUse", String.valueOf(true));
      }

      @Override
      public void dontAllow(int reason) {
        Log.d(TAG, "don't allow to use with reason " + reason);
        showNotAllowedDialog(reason == Policy.RETRY);
      }

      @Override
      public void applicationError(int errorCode) {
        Log.d(TAG, "application error with errorCode " + errorCode);
      }
    });
  }
}

在检查权限前,为了避免每次应用启动时重复验证,可以将验证的结果保存下来。isAllowToUse方法就是从本地获取之前的验证状态。

检查用户权限的核心方法是mLicenseChecker.checkAccess(),这个方法接收一个实现LicenseCheckedCallback接口的实例对象作为参数,上面实现的接口方法中:

(1)allow:说明当前用户是通过google应用市场下载的已授权的应用;

(2)dontAllow:大致可以分为两种情况,一种是用户网络问题导致无法验证权限;另一种则是用户未获得该应用的使用权限;

上面两个方法中都返回reason参数,reason是一个定义在Policy接口中的常量,有如下取值:

public interface Policy {
    ......
    public static final int LICENSED = 0x0100;  // 已授权
    public static final int NOT_LICENSED = 0x0231;  // 未授权
    public static final int RETRY = 0x0123;  // 无法获取授权信息,极有可能是网络不通导致无法验证授权信息
    ......
}

在dontAllow中,我们可以弹出一个对话框提示用户未获得使用权限,强制用户退出应用。或者提供一个按钮让用户重试(针对RETRY的情况)。例如:showNotAllowedDialog方法

private AlertDialog.Builder mNotAllowedDialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  
    ......
    mNotAllowedDialog = new AlertDialog.Builder(this);
    mNotAllowedDialog
      .setTitle(getResources().getString(R.string.unlicensed_dialog_title));
    mNotAllowedDialog.setCancelable(false);
    ......
}

private void showNotAllowedDialog(boolean isRetry) {
  if (isRetry) {
    mNotAllowedDialog.setMessage(getResources().getString(R.string.unlicensed_dialog_retry_body));
    mNotAllowedDialog.setPositiveButton(getResources().getString(R.string.retry), new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
        checkLicense();
      }
    });
    mNotAllowedDialog.setNegativeButton(getResources().getString(R.string.exit), new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
        finish();
      }
    });
  } else {
    mNotAllowedDialog.setMessage(getResources().getString(R.string.unlicensed_dialog_body));
    mNotAllowedDialog.setPositiveButton(getResources().getString(R.string.exit), new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
        finish();
      }
    });
  }

  mNotAllowedDialog.show();
}

(3)applicationError:这里包含了额外的异常情况,通过提供的errorCode参数来标识,errorCode定义在接口LicenseCheckerCallback中,有如下取值:

public interface LicenseCheckerCallback {
    ......
    public static final int ERROR_INVALID_PACKAGE_NAME = 1;  // 无效的包名
    public static final int ERROR_NON_MATCHING_UID = 2;  // 没有匹配的UID
    public static final int ERROR_NOT_MARKET_MANAGED = 3;  // 未上架google应用市场
    public static final int ERROR_CHECK_IN_PROGRESS = 4;  
    public static final int ERROR_INVALID_PUBLIC_KEY = 5;  // 无效的公钥
    public static final int ERROR_MISSING_PERMISSION = 6;  // 缺少权限
    ......
}

4.4 在主应用的AndroidManifest.xml中添加权限:

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

以上基本上就是完整的集成LVL的流程了。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值