【问题标题】:After disconnecting app Google Drive Android API still returns successful results, but doesn't upload file断开应用程序后,Google Drive Android API 仍然返回成功结果,但不上传文件
【发布时间】:2014-06-03 09:38:09
【问题描述】:

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

要连接客户端,我使用以下代码(简化):

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
}

要上传文件,我使用以下代码(简化):

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 Drive。

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

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

【问题讨论】:

  • 你能发布一个简单而完整的例子吗? (当然,没有您的 API 密钥)
  • @CheokYanCheng 我认为上面的代码应该足够了。
  • this code still returns successful results for all invocations 表示apiClient.blockingConnect(...) 仍然返回成功的结果?还是只有newContentsgetContents().getOutputStream()
  • @ben75 是的,apiClient.blockingConnect(...) 也返回成功结果。
  • 您是否尝试调用listChildren()queryChildren() 并检查结果中是否存在文件?

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您没有收到 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;
        }
    

    【讨论】:

    • 从我的代码中可以看出,我没有捕捉到Exception。虽然这种情况是有道理的,但我希望你描述的这种行为。不幸的是,它目前不是这样工作的。
    • 你不是在抑制异常还是在层次结构中抛出异常?检查您的班级是否没有抛出异常(并在其他地方捕获它)或者您是否没有抑制它们。因为这段代码应该需要 try/catch 块。
    • 正如我所说,我确实检查了行为(使用日志和调试器)。结果存在,并且出于某种原因,它们成功了。不抛出异常。
    【解决方案3】:

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

    通过将 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 >= 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;
    

    希望这会有所帮助。

    【讨论】:

    • 我不是在寻找“如何”教程。此外,我不需要通过IntentSender 创建文件 - 我需要在我的流程中完成
    猜你喜欢
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多