断开应用后,Google Drive Android API仍会返回成功结果,但不会上传文件

时间:2014-06-03 09:38:09

标签: android google-play-services google-drive-android-api

我使用Google Drive Android API(作为Google Play服务的一部分)将文件上传到云端。

使用以下代码(简化)连接客户端I

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
}

使用以下代码(简化)上传文件I:

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();

除了一个特定的用户案例外,一切都按预期工作。当用户从"已连接的应用中删除我们的应用时(使用Google设置应用程序)此代码仍会返回所有调用的成功结果。虽然文件永远不会上传到Google云端硬盘。

与Google Play服务的连接也会成功。

是API的错误还是以某种方式检测到用户断开了应用程序?

3 个答案:

答案 0 :(得分:1)

我不知道内部/外部的API,但是此页面可能会有所帮助https://support.google.com/drive/answer/2523073?hl=en。我会仔细检查accounts.google.com页面并验证是否已删除所有权限。这不会解决api行为,但至少可以验证权限。

答案 1 :(得分:0)

您是否收到UserRecoverableAuthIOException?因为你应该。任何尝试读取/上传到驱动器用户断开应用程序的位置应该返回此异常。您可能正在捕捉常规异常并错过了此消息。尝试调试,看看你是否没有得到这个例外。

如果你是,你所要做的就是重新申请

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

然后处理这样的回复:

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;
    }

答案 2 :(得分:-1)

要创建文件,请尝试根据this

发送IntentSender

通过将IntentSender提供给另一个应用程序,您授予它执行您指定的操作的权利,就好像另一个应用程序是您自己(具有相同的权限和标识)。看起来像待定意图。您可以使用

创建文件
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);
                    }
                }
            };

在这里

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

如果requestCode&gt; = 0,则当活动退出时,此代码将在onActivityResult()中返回。 在onActivityResult()你可以

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

尝试获取此类apiClient

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

你可以像这样获得mAccountName

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;

希望这会有所帮助。