我正在开发一个Android安全应用程序,并决定实现PlayIntegrity API作为SafetyNet API的替代方案。我已经完成了启用Play和Cloud控制台等必要的设置步骤,然而,我遇到了一个问题,我得到一个错误'谷歌服务器不可用'当试图获得令牌。任何人都可以提供任何见解,为什么会发生这种情况和可能的解决方案?任何帮助都将不胜感激。
Please see below code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// playIntegritySetup.lol();
getToken();
}
private void getToken() {
String nonce = Base64.encodeToString(generateNonce(50).getBytes(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
// Create an instance of a manager.
IntegrityManager integrityManager = IntegrityManagerFactory.create(getApplicationContext());
// Request the integrity token by providing a nonce.
Task<IntegrityTokenResponse> integrityTokenResponse = integrityManager.requestIntegrityToken(
IntegrityTokenRequest.builder()
.setNonce(nonce)
.build());
integrityTokenResponse.addOnSuccessListener(new OnSuccessListener<IntegrityTokenResponse>() {
@Override
public void onSuccess(IntegrityTokenResponse integrityTokenResponse) {
String integrityToken = integrityTokenResponse.token();
SplashActivity.this.doIntegrityCheck(integrityToken);
Log.e("Integrity Token", "integrity token from the app" + integrityToken);
}
});
integrityTokenResponse.addOnFailureListener(e -> showErrorDialog("Error getting token from Google. Google said: " + getErrorText(e)));
}
private void doIntegrityCheck(String token) {
AtomicBoolean hasError = new AtomicBoolean(false);
Observable.fromCallable(() -> {
OkHttpClient okHttpClient = new OkHttpClient();
Response response = okHttpClient.newCall(new Request.Builder().url("money control url" + "token from backend server" + token).build()).execute();
Log.e("Token", "token from the app" + token);
if (!response.isSuccessful()) {
hasError.set(true);
return "Api request error. Code: " + response.code();
}
ResponseBody responseBody = response.body();
if (responseBody == null) {
hasError.set(true);
return "Api request error. Empty response";
}
JSONObject responseJson = new JSONObject(responseBody.string());
if (responseJson.has("error")) {
hasError.set(true);
return "Api request error: " + responseJson.getString("error");
}
if (!responseJson.has("deviceIntegrity")) {
hasError.set(true);
}
return responseJson.getJSONObject("deviceIntegrity").toString();
}) // Execute in IO thread, i.e. background thread.
.subscribeOn(Schedulers.io())
// report or post the result to main thread.
.observeOn(AndroidSchedulers.mainThread())
// execute this RxJava
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String result) {
if (hasError.get()) {
if (result.contains("MEETS_DEVICE_INTEGRITY") && result.contains("MEETS_BASIC_INTEGRITY")) {
//Here goes my other code
}
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
private String getErrorText(Exception e) {
String msg = e.getMessage();
if (msg == null) {
return "Unknown Error";
}
//the error code
int errorCode = Integer.parseInt(msg.replaceAll("\n", "").replaceAll(":(.*)", ""));
switch (errorCode) {
case IntegrityErrorCode.API_NOT_AVAILABLE:
return "API_NOT_AVAILABLE";
case IntegrityErrorCode.NO_ERROR:
return "NO_ERROR";
case IntegrityErrorCode.INTERNAL_ERROR:
return "INTERNAL_ERROR";
case IntegrityErrorCode.NETWORK_ERROR:
return "NETWORK_ERROR";
case IntegrityErrorCode.PLAY_STORE_NOT_FOUND:
return "PLAY_STORE_NOT_FOUND";
case IntegrityErrorCode.PLAY_STORE_ACCOUNT_NOT_FOUND:
return "PLAY_STORE_ACCOUNT_NOT_FOUND";
case IntegrityErrorCode.APP_NOT_INSTALLED:
return "APP_NOT_INSTALLED";
case IntegrityErrorCode.PLAY_SERVICES_NOT_FOUND:
return "PLAY_SERVICES_NOT_FOUND";
case IntegrityErrorCode.APP_UID_MISMATCH:
return "APP_UID_MISMATCH";
case IntegrityErrorCode.TOO_MANY_REQUESTS:
return "TOO_MANY_REQUESTS";
case IntegrityErrorCode.CANNOT_BIND_TO_SERVICE:
return "CANNOT_BIND_TO_SERVICE";
case IntegrityErrorCode.NONCE_TOO_SHORT:
return "NONCE_TOO_SHORT";
case IntegrityErrorCode.NONCE_TOO_LONG:
return "NONCE_TOO_LONG";
case IntegrityErrorCode.GOOGLE_SERVER_UNAVAILABLE:
return "GOOGLE_SERVER_UNAVAILABLE";
case IntegrityErrorCode.NONCE_IS_NOT_BASE64:
return "NONCE_IS_NOT_BASE64";
default:
return "Unknown Error";
}
}
private String generateNonce(int length) {
String nonce = "";
String allowed = getNonce();
for (int i = 0; i < length; i++) {
nonce = nonce.concat(String.valueOf(allowed.charAt((int) Math.floor(Math.random() * allowed.length()))));
}
return nonce;
}
public native String getNonce();
static {
System.loadLibrary("all-keys");
}
1条答案
按热度按时间zzzyeukh1#
我遇到了同样的问题,我找到了解决办法。
当您在Google Play之外工作时,您需要指定
cloudProjectNumber()
,这可以在Google云控制台中找到。引用自the doc:
重要提示:为了接收和解密Integrity API响应,Google Play上不可用的应用需要在其请求中包含其Cloud项目编号。您可以在Google Cloud Console的项目信息中找到此编号。
所以代码应该是这样的: