Replace hardcoded auth token with auth token fetched via account
This commit is contained in:
parent
9890ccebbb
commit
89d0050ca4
4 changed files with 601 additions and 0 deletions
84
vending-app/build.gradle
Normal file
84
vending-app/build.gradle
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'com.squareup.wire'
|
||||
|
||||
android {
|
||||
namespace "com.android.vending"
|
||||
compileSdkVersion androidCompileSdk
|
||||
buildToolsVersion "$androidBuildVersionTools"
|
||||
|
||||
defaultConfig {
|
||||
versionName vendingAppVersionName
|
||||
versionCode vendingAppVersionCode
|
||||
minSdkVersion androidMinSdk
|
||||
targetSdkVersion androidTargetSdk
|
||||
}
|
||||
|
||||
flavorDimensions = ['target']
|
||||
productFlavors {
|
||||
"default" {
|
||||
dimension 'target'
|
||||
}
|
||||
"huawei" {
|
||||
dimension 'target'
|
||||
versionNameSuffix "-hw"
|
||||
}
|
||||
"huaweilh" {
|
||||
dimension 'target'
|
||||
versionNameSuffix "-lh"
|
||||
versionCode vendingAppVersionCode - 1000
|
||||
matchingFallbacks = ['huawei']
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDirs += "build/generated/source/proto/main/java"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
buildFeatures {
|
||||
aidl = true
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'MissingTranslation'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':fake-signature')
|
||||
implementation project(':play-services-auth')
|
||||
|
||||
implementation "com.squareup.wire:wire-runtime:$wireVersion"
|
||||
implementation "com.android.volley:volley:$volleyVersion"
|
||||
}
|
||||
|
||||
wire {
|
||||
kotlin {
|
||||
javaInterop = true
|
||||
}
|
||||
}
|
||||
|
||||
if (file('user.gradle').exists()) {
|
||||
apply from: 'user.gradle'
|
||||
}
|
||||
|
||||
android.applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
output.outputFileName = variant.applicationId + "-" + variant.versionCode + variant.versionName.substring(vendingAppVersionName.length()) + ".apk"
|
||||
}
|
||||
}
|
||||
68
vending-app/src/main/AndroidManifest.xml
Normal file
68
vending-app/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ SPDX-FileCopyrightText: 2014 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<permission
|
||||
android:name="com.android.vending.CHECK_LICENSE"
|
||||
android:protectionLevel="normal" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.GET_ACCOUNTS"
|
||||
android:maxSdkVersion="22" />
|
||||
<uses-permission
|
||||
android:name="android.permission.USE_CREDENTIALS"
|
||||
android:maxSdkVersion="22" />
|
||||
|
||||
<application
|
||||
android:forceQueryable="true"
|
||||
android:icon="@mipmap/ic_app"
|
||||
android:roundIcon="@mipmap/ic_app"
|
||||
android:label="@string/app_name">
|
||||
|
||||
<activity
|
||||
android:name=".GrantFakeSignaturePermissionActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.Dialog.NoActionBar" />
|
||||
|
||||
<service
|
||||
android:name="com.android.vending.billing.InAppBillingService"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.vending.billing.InAppBillingService.BIND" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="com.android.vending.licensing.LicensingService"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.vending.licensing.ILicensingService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="com.google.android.finsky.externalreferrer.GetInstallReferrerService"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.finsky.BIND_GET_INSTALL_REFERRER_SERVICE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.vending.ui.MainActivity"
|
||||
android:theme="@style/Theme.Dialog.NoActionBar"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.INFO" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
package com.android.vending.licensing;
|
||||
|
||||
import static com.android.volley.Request.Method.GET;
|
||||
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.vending.AndroidVersionMeta;
|
||||
import com.android.vending.DeviceMeta;
|
||||
import com.android.vending.EncodedTriple;
|
||||
import com.android.vending.EncodedTripleWrapper;
|
||||
import com.android.vending.IntWrapper;
|
||||
import com.android.vending.LicenseRequestHeader;
|
||||
import com.android.vending.LicenseResult;
|
||||
import com.android.vending.Locality;
|
||||
import com.android.vending.LocalityWrapper;
|
||||
import com.android.vending.StringWrapper;
|
||||
import com.android.vending.Timestamp;
|
||||
import com.android.vending.TimestampContainer;
|
||||
import com.android.vending.TimestampContainer1;
|
||||
import com.android.vending.TimestampContainer1Wrapper;
|
||||
import com.android.vending.TimestampContainer2;
|
||||
import com.android.vending.TimestampStringWrapper;
|
||||
import com.android.vending.TimestampWrapper;
|
||||
import com.android.vending.UnknownByte12;
|
||||
import com.android.vending.UserAgent;
|
||||
import com.android.vending.Util;
|
||||
import com.android.vending.Uuid;
|
||||
import com.android.vending.V1Container;
|
||||
import com.android.volley.NetworkResponse;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
public abstract class LicenseRequest<T> extends Request<T> {
|
||||
|
||||
private final String xPsRh;
|
||||
private final String auth;
|
||||
private static final String TAG = "FakeLicenseRequest";
|
||||
|
||||
private static final int BASE64_FLAGS = Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING;
|
||||
private static final long ANDROID_ID = 1;
|
||||
|
||||
private final Response.Listener<T> successListener;
|
||||
|
||||
|
||||
protected LicenseRequest(String url, String auth, Response.Listener<T> successListener, Response.ErrorListener errorListener) {
|
||||
super(GET, url, errorListener);
|
||||
this.auth = auth;
|
||||
|
||||
this.successListener = successListener;
|
||||
|
||||
long millis = System.currentTimeMillis();
|
||||
TimestampContainer.Builder timestamp = new TimestampContainer.Builder()
|
||||
.container2(new TimestampContainer2.Builder()
|
||||
.wrapper(new TimestampWrapper.Builder().timestamp(makeTimestamp(millis)).build())
|
||||
.timestamp(makeTimestamp(millis))
|
||||
.build());
|
||||
millis = System.currentTimeMillis();
|
||||
timestamp
|
||||
.container1Wrapper(new TimestampContainer1Wrapper.Builder()
|
||||
.androidId(String.valueOf(ANDROID_ID))
|
||||
.container(new TimestampContainer1.Builder()
|
||||
.timestamp(millis + "000")
|
||||
.wrapper(makeTimestamp(millis))
|
||||
.build())
|
||||
.build()
|
||||
);
|
||||
String encodedTimestamps = new String(
|
||||
Base64.encode(Util.encodeGzip(timestamp.build().encode()), BASE64_FLAGS)
|
||||
);
|
||||
|
||||
Locality locality = new Locality.Builder()
|
||||
.unknown1(1)
|
||||
.unknown2(2)
|
||||
.countryCode("")
|
||||
.region(new TimestampStringWrapper.Builder()
|
||||
.string("").timestamp(makeTimestamp(System.currentTimeMillis())).build())
|
||||
.country(new TimestampStringWrapper.Builder()
|
||||
.string("").timestamp(makeTimestamp(System.currentTimeMillis())).build())
|
||||
.unknown3(0)
|
||||
.build();
|
||||
String encodedLocality = new String(
|
||||
Base64.encode(locality.encode(), BASE64_FLAGS)
|
||||
);
|
||||
|
||||
byte[] header = new LicenseRequestHeader.Builder()
|
||||
.encodedTimestamps(new StringWrapper.Builder().string(encodedTimestamps).build())
|
||||
.triple(
|
||||
new EncodedTripleWrapper.Builder().triple(
|
||||
new EncodedTriple.Builder()
|
||||
.encoded1("")
|
||||
.encoded2("")
|
||||
.empty("")
|
||||
.build()
|
||||
).build()
|
||||
)
|
||||
.locality(new LocalityWrapper.Builder().encodedLocalityProto(encodedLocality).build())
|
||||
.unknown(new IntWrapper.Builder().integer(5).build())
|
||||
.empty("")
|
||||
.deviceMeta(new DeviceMeta.Builder()
|
||||
.android(
|
||||
new AndroidVersionMeta.Builder()
|
||||
.androidSdk(0)
|
||||
.buildNumber("")
|
||||
.androidVersion("")
|
||||
.unknown(0)
|
||||
.build()
|
||||
)
|
||||
.unknown1(new UnknownByte12.Builder().bytes(new ByteString(new byte[]{}
|
||||
)).build())
|
||||
.unknown2(1)
|
||||
.build()
|
||||
)
|
||||
.userAgent(new UserAgent.Builder()
|
||||
.deviceProductName("")
|
||||
.deviceSoc("")
|
||||
.deviceModelName("")
|
||||
.finskyVersion("")
|
||||
.deviceName("")
|
||||
.androidId(ANDROID_ID) // must not be 0
|
||||
.deviceSignature("")
|
||||
.build()
|
||||
)
|
||||
.uuid(new Uuid.Builder()
|
||||
.uuid(UUID.randomUUID().toString())
|
||||
.unknown(2)
|
||||
.build()
|
||||
)
|
||||
.build().encode();
|
||||
this.xPsRh = new String(Base64.encode(Util.encodeGzip(header), BASE64_FLAGS));
|
||||
|
||||
//Log.d(TAG, "Product " + Build.PRODUCT + ", Board " + Build.BOARD + " Model " + Build.MODEL + " Device " + Build.DEVICE);
|
||||
|
||||
Log.v(TAG, "X-PS-RH: " + xPsRh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() {
|
||||
return Map.of(
|
||||
"X-PS-RH", xPsRh,
|
||||
"Authorization", "Bearer " + auth,
|
||||
"Connection", "Keep-Alive"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deliverResponse(T response) {
|
||||
successListener.onResponse(response);
|
||||
}
|
||||
|
||||
private static Timestamp makeTimestamp(long millis) {
|
||||
return new Timestamp.Builder()
|
||||
.seconds((int) (millis / 1000))
|
||||
.nanos(Math.floorMod(millis, 1000) * 1000000)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class V1 extends LicenseRequest<V1Container> {
|
||||
|
||||
public V1(String packageName, String auth, int versionCode, long nonce, Response.Listener<V1Container> successListener, Response.ErrorListener errorListener) {
|
||||
super("https://play-fe.googleapis.com/fdfe/apps/checkLicense?pkgn=" + packageName + "&vc=" + versionCode + "&nnc=" + nonce,
|
||||
auth, successListener, errorListener
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Response<V1Container> parseNetworkResponse(NetworkResponse response) {
|
||||
if (response != null && response.data != null) {
|
||||
try {
|
||||
LicenseResult result = LicenseResult.ADAPTER.decode(response.data);
|
||||
return Response.success(result.information.v1, null);
|
||||
} catch (IOException e) {
|
||||
return Response.error(new VolleyError(e));
|
||||
} catch (NullPointerException e) {
|
||||
// A field does not exist → user has no license
|
||||
return Response.success(null, null);
|
||||
}
|
||||
} else {
|
||||
return Response.error(new VolleyError("No response was returned"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class V2 extends LicenseRequest<String> {
|
||||
public V2(String packageName, String auth, int versionCode, Response.Listener<String> successListener,
|
||||
Response.ErrorListener errorListener) {
|
||||
super(
|
||||
"https://play-fe.googleapis.com/fdfe/apps/checkLicenseServerFallback?pkgn=" + packageName + "&vc=" + versionCode,
|
||||
auth, successListener, errorListener
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Response<String> parseNetworkResponse(NetworkResponse response) {
|
||||
if (response != null && response.data != null) {
|
||||
try {
|
||||
LicenseResult result = LicenseResult.ADAPTER.decode(response.data);
|
||||
return Response.success(result.information.v2.license.jwt, null);
|
||||
} catch (IOException e) {
|
||||
return Response.error(new VolleyError(e));
|
||||
} catch (NullPointerException e) {
|
||||
// A field does not exist → user has no license
|
||||
return Response.success(null, null);
|
||||
}
|
||||
} else {
|
||||
return Response.error(new VolleyError("No response was returned"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.android.vending.licensing;
|
||||
|
||||
import static android.accounts.AccountManager.KEY_AUTHTOKEN;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
import org.microg.gms.auth.AuthConstants;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class LicensingService extends Service {
|
||||
private static final String TAG = "FakeLicenseService";
|
||||
private RequestQueue queue;
|
||||
private AccountManager accountManager;
|
||||
|
||||
private static final String KEY_V2_RESULT_JWT = "LICENSE_DATA";
|
||||
|
||||
private static final String AUTH_TOKEN_SCOPE = "oauth2:https://www.googleapis.com/auth/googleplay";
|
||||
|
||||
/* Possible response codes for checkLicense v1, from
|
||||
* https://developer.android.com/google/play/licensing/licensing-reference#server-response-codes and
|
||||
* the LVL library.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The application is licensed to the user. The user has purchased the application, or is authorized to
|
||||
* download and install the alpha or beta version of the application.
|
||||
*/
|
||||
private static final int LICENSED = 0x0;
|
||||
/**
|
||||
* The application is licensed to the user, but there is an updated application version available that is
|
||||
* signed with a different key.
|
||||
*/
|
||||
private static final int NOT_LICENSED = 0x1;
|
||||
/**
|
||||
* The application is not licensed to the user.
|
||||
*/
|
||||
private static final int LICENSED_OLD_KEY = 0x2;
|
||||
/**
|
||||
* Server error — the application (package name) was not recognized by Google Play.
|
||||
*/
|
||||
private static final int ERROR_NOT_MARKET_MANAGED = 0x3;
|
||||
/**
|
||||
* Server error — the server could not load the application's key pair for licensing.
|
||||
*/
|
||||
private static final int ERROR_SERVER_FAILURE = 0x4;
|
||||
private static final int ERROR_OVER_QUOTA = 0x5;
|
||||
|
||||
/**
|
||||
* Local error — the Google Play application was not able to reach the licensing server, possibly because
|
||||
* of network availability problems.
|
||||
*/
|
||||
private static final int ERROR_CONTACTING_SERVER = 0x101;
|
||||
/**
|
||||
* Local error — the application requested a license check for a package that is not installed on the device.
|
||||
*/
|
||||
private static final int ERROR_INVALID_PACKAGE_NAME = 0x102;
|
||||
/**
|
||||
* Local error — the application requested a license check for a package whose UID (package, user ID pair)
|
||||
* does not match that of the requesting application.
|
||||
*/
|
||||
private static final int ERROR_NON_MATCHING_UID = 0x103;
|
||||
|
||||
private final ILicensingService.Stub mLicenseService = new ILicensingService.Stub() {
|
||||
|
||||
|
||||
@Override
|
||||
public void checkLicense(long nonce, String packageName, ILicenseResultListener listener) throws RemoteException {
|
||||
Log.v(TAG, "checkLicense(" + nonce + ", " + packageName + ")");
|
||||
try {
|
||||
PackageInfo packageInfo = getPackageManager().getPackageInfo(packageName, 0);
|
||||
int versionCode = packageInfo.versionCode;
|
||||
|
||||
// Verify caller identity
|
||||
if (packageInfo.applicationInfo.uid != getCallingUid()) {
|
||||
Log.e(TAG, "an app illegally tried to request v1 licenses for another app (caller: " + getCallingUid() + ")");
|
||||
listener.verifyLicense(ERROR_NON_MATCHING_UID, null, null);
|
||||
} else {
|
||||
|
||||
Account[] accounts = accountManager.getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE);
|
||||
|
||||
if (accounts.length == 0) {
|
||||
Log.e(TAG, "not checking license, as user is not signed in");
|
||||
} else accountManager.getAuthToken(
|
||||
accounts[0], AUTH_TOKEN_SCOPE, false,
|
||||
future -> {
|
||||
Request request = null;
|
||||
try {
|
||||
request = new LicenseRequest.V1(
|
||||
packageName,
|
||||
future.getResult().getString(KEY_AUTHTOKEN),
|
||||
versionCode, nonce, data -> {
|
||||
if (data != null) {
|
||||
Log.v(TAG, "licenseV1 result was " + data.result + " with signed data " +
|
||||
data.signedData);
|
||||
|
||||
try {
|
||||
if (data.result != null) {
|
||||
listener.verifyLicense(data.result, data.signedData, data.signature);
|
||||
} else {
|
||||
listener.verifyLicense(LICENSED, data.signedData, data.signature);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG,
|
||||
"After telling it the licenseV1 result, remote threw an Exception.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
Log.v(TAG, "licenseV1 result was that user has no license");
|
||||
sendError(listener, NOT_LICENSED);
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, "licenseV1 request failed with " + error.toString());
|
||||
sendError(listener, ERROR_CONTACTING_SERVER);
|
||||
});
|
||||
} catch (AuthenticatorException | IOException | OperationCanceledException e) {
|
||||
sendError(listener, ERROR_CONTACTING_SERVER);
|
||||
}
|
||||
|
||||
request.setShouldCache(false);
|
||||
queue.add(request);
|
||||
}, null);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "an app tried to request v1 licenses for package " + packageName + ", which does not exist");
|
||||
listener.verifyLicense(ERROR_INVALID_PACKAGE_NAME, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkLicenseV2(String packageName, ILicenseV2ResultListener listener, Bundle extraParams) throws RemoteException {
|
||||
Log.v(TAG, "checkLicenseV2(" + packageName + ", " + extraParams + ")");
|
||||
|
||||
try {
|
||||
PackageInfo packageInfo = getPackageManager().getPackageInfo(packageName, 0);
|
||||
int versionCode = packageInfo.versionCode;
|
||||
|
||||
// Verify caller identity
|
||||
if (packageInfo.applicationInfo.uid != getCallingUid()) {
|
||||
Log.e(TAG, "an app illegally tried to request v2 licenses for another app (caller: " + getCallingUid() + ")");
|
||||
listener.verifyLicense(ERROR_NON_MATCHING_UID, new Bundle());
|
||||
} else {
|
||||
Account[] accounts = accountManager.getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE);
|
||||
|
||||
if (accounts.length == 0) {
|
||||
Log.e(TAG, "not checking license, as user is not signed in");
|
||||
} else accountManager.getAuthToken(
|
||||
accounts[0], AUTH_TOKEN_SCOPE, false,
|
||||
future -> {
|
||||
try {
|
||||
Bundle result = future.getResult(10, TimeUnit.SECONDS);
|
||||
String auth = result.getString(KEY_AUTHTOKEN);
|
||||
|
||||
Request request = new LicenseRequest.V2(packageName, auth, versionCode, jwt -> {
|
||||
Log.v(TAG, "LicenseV2 returned JWT license value " + jwt);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_V2_RESULT_JWT, jwt);
|
||||
try {
|
||||
listener.verifyLicense(jwt == null ? NOT_LICENSED : LICENSED, bundle);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "After returning licenseV2 result, remote threw an Exception.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, "licenseV2 request failed with " + error.toString());
|
||||
sendError(listener, ERROR_CONTACTING_SERVER);
|
||||
});
|
||||
|
||||
request.setShouldCache(false);
|
||||
queue.add(request);
|
||||
|
||||
} catch (AuthenticatorException | IOException | OperationCanceledException e) {
|
||||
sendError(listener, ERROR_CONTACTING_SERVER);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, null
|
||||
);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "an app tried to request v1 licenses for package " + packageName + ", which does not exist");
|
||||
listener.verifyLicense(ERROR_INVALID_PACKAGE_NAME, new Bundle());
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
private static void sendError(ILicenseResultListener listener, int error) {
|
||||
try {
|
||||
listener.verifyLicense(error, null, null);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "After telling it that licenseV1 had an error (" + error + "), remote threw an Exception.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendError(ILicenseV2ResultListener listener, int error) {
|
||||
try {
|
||||
listener.verifyLicense(error, new Bundle());
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "After telling it that licenseV2 had an error (" + error + "), remote threw an Exception.");
|
||||
}
|
||||
}
|
||||
|
||||
public IBinder onBind(Intent intent) {
|
||||
queue = Volley.newRequestQueue(this);
|
||||
accountManager = AccountManager.get(this);
|
||||
|
||||
return mLicenseService;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue