You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PlayIntegrity API调用:如何处理GOOGLE_SERVER_UNAVAILABLE错误

PlayIntegrity API 获取Token时出现GOOGLE_SERVER_UNAVAILABLE错误的排查方案

问题描述

我正在开发一款Android安全应用,决定采用PlayIntegrity API替代SafetyNet API。已完成Play控制台与Cloud控制台等必要配置步骤,但在获取token时遇到了GOOGLE_SERVER_UNAVAILABLE错误,求问该问题的可能原因及解决方案。

相关代码

@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");
}

可能原因及解决方案

  • 临时服务器波动:Google服务器偶尔会出现短时不可用,这是最常见的诱因。可以稍后重试,建议在代码中添加指数退避重试逻辑(比如首次等待1秒,第二次2秒,最多重试3次),避免频繁请求加剧服务器压力。
  • 网络环境异常:
    • 设备处于不稳定网络或受限环境(如企业内网、VPN),导致无法正常连接Google服务器。可切换至稳定Wi-Fi/移动数据测试,关闭无关VPN或代理。
    • 检查Google Play服务版本,旧版本可能存在兼容性问题,前往Google Play商店更新至最新版。
  • 配置遗漏或错误:
    • 确认Cloud控制台已正确启用Play Integrity API,且API密钥的限制规则(绑定的应用包名、SHA-1证书指纹)完全正确。
    • 核对Play控制台中应用的签名证书,确保与Cloud控制台配置的证书指纹一致(包括测试签名和发布签名场景)。
  • 请求频率超限:即便错误码是GOOGLE_SERVER_UNAVAILABLE,短时间内大量请求也可能触发服务器限流。检查代码是否存在重复调用requestIntegrityToken的情况,合理调整请求频率。
  • Nonce生成问题:代码中Nonce依赖JNI的getNonce()方法,需确认该方法返回的字符串合法,且最终生成的Base64编码Nonce符合要求(无换行、采用URL安全编码)。

内容的提问来源于stack exchange,提问作者androminor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:45:41