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

调用GoogleNetHTTPTransport时出现‘JKS not found’错误求助

Hey there! Let's break down your issue step by step, since you're new to Google's authentication and API ecosystem.

1. Why You're Seeing the KeyStoreException

The error java.security.KeyStoreException: JKS not found happens because Android doesn't use the JKS (Java KeyStore) format by default—it relies on BKS (Bouncy Castle KeyStore) or the system's built-in trust store instead.

When you call GoogleNetHttpTransport.newTrustedTransport(), it tries to load a JKS-formatted trust store to verify the authenticity of Google's servers during HTTPS connections. Since this file doesn't exist on Android, the method throws that exception.

To clarify: The KeyStore here acts as a secure repository for trusted CA (Certificate Authority) certificates. It ensures that when your app connects to Google's APIs, it's talking to a legitimate Google server, not a malicious imposter.

2. The Fix: Use Android-Compatible HTTP Transport

Google provides a dedicated transport for Android apps that works with the system's native trust store. Here's how to fix your code:

Step 1: Replace the Transport Instance

Instead of GoogleNetHttpTransport.newTrustedTransport(), use AndroidHttp.newCompatibleTransport(). This method is designed to work seamlessly with Android's security infrastructure.

Step 2: Update Your Imports

Make sure you add this import at the top of your file:

import com.google.api.client.extensions.android.http.AndroidHttp;

Step 3: Modify the Flow Builder

Update the part where you build the GoogleAuthorizationCodeFlow to use the Android-compatible transport:

flow = new GoogleAuthorizationCodeFlow
    .Builder(AndroidHttp.newCompatibleTransport(), 
             JacksonFactory.getDefaultInstance(),
             clientSecrets,
             scopes)
    .setDataStoreFactory(new MemoryDataStoreFactory())
    .setAccessType("offline")
    .build();

3. Code Optimization Tips

Your current code works but can be tightened up for reliability and maintainability:

a. Use Try-With-Resources for Input Streams

Your InputStream and Reader aren't being closed, which can cause memory leaks. Use try-with-resources to auto-close them:

try (InputStream jsonInput = resources.openRawResource(R.raw.credential_info);
     Reader credentialReader = new InputStreamReader(jsonInput)) {
    Log.v("GoogleAut", "credential reader created");
    clientSecrets = GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(), credentialReader);
} catch (IOException e) {
    e.printStackTrace();
    Log.v("ERROR GoogleAut","Failed to load client secrets");
}

b. Improve Error Handling

Avoid catching generic Exception—catch specific exceptions to handle them more precisely. For example, instead of catching Exception in the final authorize call, catch IOException and GeneralSecurityException separately.

c. Avoid Redundant Null Checks

resources.openRawResource(R.raw.credential_info) won't return null if the resource exists (it'll throw a NotFoundException if it's missing). You can remove the redundant NullPointerException catch block and handle NotFoundException instead.

d. Persist Credentials (Optional)

MemoryDataStoreFactory stores credentials only in memory, so your app will re-authenticate every time it restarts. For a better user experience, use a persistent data store like SharedPreferencesDataStoreFactory (from the com.google.api-client:google-api-client-android library).

Modified Full authorize() Method

Here's your updated code with all the fixes and optimizations:

private Credential authorize(Context context) {
    GoogleClientSecrets clientSecrets = null;

    // Load client secrets with auto-closing streams
    try (InputStream jsonInput = context.getResources().openRawResource(R.raw.credential_info);
         Reader credentialReader = new InputStreamReader(jsonInput)) {
        Log.v("GoogleAut", "Credential reader created");
        clientSecrets = GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(), credentialReader);
    } catch (Resources.NotFoundException e) {
        e.printStackTrace();
        Log.v("ERROR GoogleAut", "Credential resource not found");
    } catch (IOException e) {
        e.printStackTrace();
        Log.v("ERROR GoogleAut", "Failed to read credential file");
    }

    if (clientSecrets == null) {
        Log.v("ERROR GoogleAut", "Client secrets could not be loaded");
        return null;
    }

    List<String> scopes = Arrays.asList(SheetsScopes.SPREADSHEETS);
    GoogleAuthorizationCodeFlow flow = null;

    try {
        flow = new GoogleAuthorizationCodeFlow
                .Builder(AndroidHttp.newCompatibleTransport(),
                         JacksonFactory.getDefaultInstance(),
                         clientSecrets,
                         scopes)
                .setDataStoreFactory(new MemoryDataStoreFactory())
                .setAccessType("offline")
                .build();
    } catch (IOException e) {
        e.printStackTrace();
        Log.v("ERROR GoogleAut", "IOException during flow creation");
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
        Log.v("ERROR GoogleAut", "Security exception during flow creation");
    }

    if (flow == null) {
        Log.v("ERROR GoogleAut", "Authorization flow could not be built");
        return null;
    }

    try {
        return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver())
                .authorize("user");
    } catch (IOException e) {
        e.printStackTrace();
        Log.v("ERROR GoogleAut", "IO error during authorization");
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
        Log.v("ERROR GoogleAut", "Security error during authorization");
    }

    Log.v("ERROR GoogleAut", "Authorization failed");
    return null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:14:55