集成新版Google Drive Android SDK时遇ApiException 17错误求助
com.google.android.gms.common.api.ApiException: 17 with Google Drive Android SDK 12.0.1 Hey Tony, let's break down why you're hitting this error and how to fix it quickly—your old AnyCopy version worked because it relied on a deprecated feature that's no longer supported in newer SDK versions.
What's Causing the Error?
The error API: Drive.API_CONNECTIONLESS is not available on this device (error code 17 = API_UNAVAILABLE) happens because Google removed support for the connectionless Drive API in recent Google Play Services releases. The API_CONNECTIONLESS mode was a legacy way to access Drive without a persistent user session, but it's been phased out in favor of the connected API model that requires explicit user authentication.
Step-by-Step Fixes
1. Replace Drive.API_CONNECTIONLESS with the Connected API
First, you need to swap out the deprecated connectionless API for the standard Drive.API in your client setup. If your old code looked like this:
GoogleApiClient client = new GoogleApiClient.Builder(context) .addApi(Drive.API_CONNECTIONLESS) .build();
Change it to use the connected API instead:
GoogleApiClient client = new GoogleApiClient.Builder(context) .addApi(Drive.API) .addScope(Drive.SCOPE_FILE) // Or Drive.SCOPE_APPFOLDER, depending on your needs .build();
Note: For even better compatibility with modern SDKs, consider migrating to the newer DriveClient and DriveResourceClient APIs instead of the older GoogleApiClient.
2. Implement the Modern Authentication Flow
Newer Drive SDK versions require explicit user sign-in with Google to access Drive resources. Here's a quick example of how to set this up:
// 1. Configure sign-in options with Drive scopes val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestScopes(Drive.SCOPE_FILE) .build() // 2. Get a GoogleSignInClient val signInClient = GoogleSignIn.getClient(context, signInOptions) // 3. Launch the sign-in flow startActivityForResult(signInClient.signInIntent, REQUEST_CODE_DRIVE_SIGN_IN) // 4. Handle the sign-in result in onActivityResult override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_DRIVE_SIGN_IN) { val signInTask = GoogleSignIn.getSignedInAccountFromIntent(data) try { val account = signInTask.getResult(ApiException::class.java) // Initialize Drive clients for future operations val driveClient = Drive.getDriveClient(context, account) val driveResourceClient = Drive.getDriveResourceClient(context, account) // Use these clients for your backup/restore logic } catch (e: ApiException) { // Handle sign-in failures here Log.e("AnyCopy", "Drive sign-in failed: ${e.statusCode}") } } }
3. Update Your Play Services Dependencies
Make sure your build.gradle (Module level) is using a compatible, up-to-date version of the Drive Play Services library. Instead of 12.0.1 (which is quite old), use a recent stable release to avoid compatibility gaps:
dependencies { implementation 'com.google.android.gms:play-services-drive:17.0.0' implementation 'com.google.android.gms:play-services-auth:20.7.0' }
4. Double-Check Your Cloud Console Configuration
Even though your old setup worked, it's worth verifying:
- The OAuth 2.0 Client ID in your
google-services.jsonmatches the one in Google Cloud Console. - The Drive API is still enabled for your project in Cloud Console.
- The package name and signing fingerprint for your refactored app match the client ID configuration.
Key Takeaway
The core issue is that the connectionless Drive API is no longer supported. By migrating to the connected API model with explicit user authentication, updating your dependencies, and verifying your configuration, you'll get your backup/restore functionality working again in the refactored AnyCopy app.
内容的提问来源于stack exchange,提问作者Tony Tang

