After disconnecting app Google Drive Android API still returns successful results, but doesn't upload file

人走茶凉 提交于 2019-12-10 14:00:01

问题


I'm using Google Drive Android API (as part of Google Play Services) to upload files to cloud.

To connect client I'm using following code (simplified):

apiClient = new GoogleApiClient.Builder(context)
            .addApi(Drive.API)
            .setAccountName(preferences.getString("GOOGLE_DRIVE_ACCOUNT", null))
            .build();

ConnectionResult connectionResult = apiClient.blockingConnect(SERVICES_CONNECTION_TIMEOUT_SEC, TimeUnit.SECONDS);
if (!connectionResult.isSuccess()) {
    throw new ApiConnectionException(); //our own exception
}

To upload file I'm using something following code (simplified):

DriveApi.ContentsResult result = Drive.DriveApi.newContents(apiClient).await();
if (!result.getStatus().isSuccess()) {
    /* ... code for error handling ... */
    return;
}

OutputStream output = result.getContents().getOutputStream();
/* ... writing to output ... */

//create actual file on Google Drive
DriveFolder.DriveFileResult driveFileResult = Drive.DriveApi
            .getFolder(apiClient, folderId)
            .createFile(apiClient, metadataChangeSet, result.getContents())
            .await();

Everything works as expected except for one particular user case. When user removes our app from "Connected apps" (using Google Settings application) this code still returns successful results for all invocations. Although file is never uploaded to Google Drive.

Connection to Google Play Services also succeeds.

Is it a bug of API or it can be somehow detected that user disconnected the application?


回答1:


I don't know the API inside/out, however this page may help https://support.google.com/drive/answer/2523073?hl=en. I would double check the accounts.google.com page and verify that all permissions are being removed. This won't solve the api behaviour but at least you can verify the permissions.




回答2:


Aren't you getting a UserRecoverableAuthIOException? Because you should. Any try to read/upload to drive where a user disconnected the app should return this Exception. You are probably catching general Exceptions and missing this. Try debugging to see if you aren't getting this exception.

If you are, all you have to do is re-request

        catch (UserRecoverableAuthIOException e) {
            startActivityForResult(e.getIntent(), COMPLETE_AUTHORIZATION_REQUEST_CODE);
        }

And then deal with the response like this:

case COMPLETE_AUTHORIZATION_REQUEST_CODE:
        if (resultCode == RESULT_OK) {
            // App is authorized, you can go back to sending the API request
        } else {
            // User denied access, show him the account chooser again
        }
        break;
    }



回答3:


For creating a file try sending a IntentSender which according to this

By giving a IntentSender to another application, you are granting it the right to perform the operation you have specified as if the other application was yourself (with the same permissions and identity). Looks like a Pending Intent. You can create a file using

ResultCallback<ContentsResult> onContentsCallback =
                    new ResultCallback<ContentsResult>() {
                @Override
                public void onResult(ContentsResult result) {
                    // TODO: error handling in case of failure
                    MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
                            .setMimeType(MIME_TYPE_TEXT).build();
                    IntentSender createIntentSender = Drive.DriveApi
                            .newCreateFileActivityBuilder()
                            .setInitialMetadata(metadataChangeSet)
                            .setInitialContents(result.getContents())
                            .build(mGoogleApiClient);
                    try {
                        startIntentSenderForResult(createIntentSender, REQUEST_CODE_CREATOR, null,
                                0, 0, 0);
                    } catch (SendIntentException e) {
                        Log.w(TAG, "Unable to send intent", e);
                    }
                }
            };

In here

`startIntentSenderForResult (IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)`

If requestCode >= 0, this code will be returned in onActivityResult() when the activity exits. in your onActivityResult() you can

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        //REQUEST_CODE_CREATOR == 1
        case REQUEST_CODE_CREATOR:
            if (resultCode == RESULT_OK) {
                DriveId driveId = (DriveId) data.getParcelableExtra(
                        OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
                showMessage("File created with ID: " + driveId);
            }
            finish();
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
        }
    }

Try to get the apiClient like this

mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(Drive.API).addScope(Drive.SCOPE_FILE)
                    .setAccountName(mAccountName).addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this).build();



  /**
     * Called when {@code mGoogleApiClient} is connected.
     */
    @Override
    public void onConnected(Bundle connectionHint) {
        Log.i(TAG, "GoogleApiClient connected");
    }

     /**
     * Called when {@code mGoogleApiClient} is disconnected.
     */
    @Override
    public void onConnectionSuspended(int cause) {
        Log.i(TAG, "GoogleApiClient connection suspended");
    }

    /**
     * Called when {@code mGoogleApiClient} is trying to connect but failed.
     * Handle {@code result.getResolution()} if there is a resolution is
     * available.
     */
    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
        if (!result.hasResolution()) {
            GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
            return;
        }
        try {
            result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
        } catch (SendIntentException e) {
            Log.e(TAG, "Exception while starting resolution activity", e);
        }
    }

You can get the mAccountName like this:

Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
            if (accounts.length == 0) {
                Log.d(TAG, "Must have a Google account installed");
                return;
            }
            mAccountName = accounts[0].name;

Hope this helps.



来源:https://stackoverflow.com/questions/24011801/after-disconnecting-app-google-drive-android-api-still-returns-successful-result

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!