android - 如何以编程方式从 Android 中的 Google 驱动器选择的文件下载并保存在本地目录中?

标签 android google-drive-android-api android-googleapiclient

我在我的应用程序中使用 Google Drive API,我可以从 google drive 中选择(在我的例子中是 .doc/docx/.pdf)文件,到目前为止一切正常。但我想下载所选文件并需要使用 Multipart 将该文件发送到我们的服务器。我尝试了多种方法,我得到了 DriveIdDriveFile 但遗憾的是我无法下载所选文件。

我已经完成了 Android developer documentation

我正在使用以下代码

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.drive.Drive; 
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveId;
import com.google.android.gms.drive.DriveResource;
import com.google.android.gms.drive.OpenFileActivityBuilder;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory; 
import com.google.api.services.drive.DriveScopes;

public class DriveActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {
/**
 * DriveId of an existing folder to be used as a parent folder in
 * folder operations samples.
 */
public static final String EXISTING_FOLDER_ID = "0B2EEtIjPUdX6MERsWlYxN3J6RU0";
/**
 * DriveId of an existing file to be used in file operation samples..
 */
public static final String EXISTING_FILE_ID = "0ByfSjdPVs9MZTHBmMVdSeWxaNTg";
/**
 * Extra for account name.
 */
protected static final String EXTRA_ACCOUNT_NAME = "account_name";
/**
 * Request code for auto Google Play Services error resolution.
 */
protected static final int REQUEST_CODE_RESOLUTION = 1;
/**
 * Next available request code.
 */
protected static final int NEXT_AVAILABLE_REQUEST_CODE = 2;
private static final String TAG = "===GoogleDriveActivity";
private static final int REQUEST_CODE_OPENER = 2;
/**
 * Google API client.
 */
private GoogleApiClient mGoogleApiClient;
private static final String[] SCOPES = {DriveScopes.DRIVE_FILE};

final HttpTransport transport = AndroidHttp.newCompatibleTransport();
final JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
private String accountName;
DriveResource.MetadataResult metadataResult;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    connect();
}

@Override
protected void onStop() {
    if (mGoogleApiClient != null) {
        mGoogleApiClient.disconnect();
    }
    super.onStop();
}

@Override
protected void onRestart() {
    super.onRestart();
    connect();
}


private void connect() {
    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Drive.API)
                .addScope(Drive.SCOPE_FILE)
                .addScope(Drive.SCOPE_APPFOLDER) // required for App Folder sample
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }
    mGoogleApiClient.connect();
}

/**
 * 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()) {
        // show the localized error dialog.
        GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
        return;
    }
    try {
        result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
    } catch (IntentSender.SendIntentException e) {
        Log.e(TAG, "Exception while starting resolution activity", e);
    }
}


/**
 * Getter for the {@code GoogleApiClient}.
 */
public GoogleApiClient getGoogleApiClient() {
    return mGoogleApiClient;
}

@Override
public void onConnected(Bundle connectionHint) {
    IntentSender intentSender = Drive.DriveApi
            .newOpenFileActivityBuilder()
            .setMimeType(new String[]{"application/msword", " application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.google-apps.document", "application/pdf"})
            .build(getGoogleApiClient());
    AccountManager manager = (AccountManager) getSystemService(ACCOUNT_SERVICE);
    Account[] list = manager.getAccountsByType("com.google");
    //Getting the first account because that is the primary account for that user
    accountName = list[0].name;
    try {
        startIntentSenderForResult(
                intentSender, REQUEST_CODE_OPENER, null, 0, 0, 0);
    } catch (IntentSender.SendIntentException e) {
        Log.w(TAG, "Unable to send intent", e);
    }
  }

 /**
 * Handles resolution callbacks.
 */
@Override
protected void onActivityResult(int requestCode, int resultCode,
                                Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case REQUEST_CODE_OPENER:
                Intent intent = null;
                if (resultCode == RESULT_OK) {
                    DriveId driveId = data.getParcelableExtra(
                            OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
                    String resourceId = driveId.getResourceId();
                    DriveFile file = driveId.asDriveFile();
                }
                break;
            case REQUEST_CODE_RESOLUTION:
                mGoogleApiClient.connect();
                break;
            default:
                super.onActivityResult(requestCode, resultCode, data);
        }
     }
  }
}

有人可以帮我以编程方式从谷歌驱动器下载选定的文件吗?

提前致谢。

最佳答案

您可以通过两种方式下载它,通过 REST或使用 GDAA .您可以使用其中任何一种,具体取决于您舒适编码的位置。

使用 REST 时:

/*************************************************************************
   * get file contents
   * @param resId  file driveId
   * @return       file's content  / null on fail
   */
  static InputStream read(String resId) {
    if (mGOOSvc != null && mConnected && resId != null) try {
      File gFl = mGOOSvc.files().get(resId).setFields("downloadUrl").execute();
      if (gFl != null){
        String strUrl = gFl.getDownloadUrl();
        return mGOOSvc.getRequestFactory()
        .buildGetRequest(new GenericUrl(strUrl)).execute().getContent();
      }
    } catch (Exception e) { /* error handling */ }
    return null;
  }

使用 GDAA 时:

/************************************************************************************************
   * get file contents
   * @param id file driveId
   * @return file's content  / null on fail
   */
  static byte[] read(String id) {
    byte[] buf = null;
    if (mGAC != null && mGAC.isConnected() && id != null) try {
      DriveFile df = Drive.DriveApi.getFile(mGAC, DriveId.decodeFromString(id));
      DriveContentsResult rslt = df.open(mGAC, DriveFile.MODE_READ_ONLY, null).await();
      if ((rslt != null) && rslt.getStatus().isSuccess()) {
        DriveContents cont = rslt.getDriveContents();
        buf = UT.is2Bytes(cont.getInputStream());
        cont.discard(mGAC);    // or cont.commit();  they are equiv if READONLY
      }
    } catch (Exception e) { UT.le(e); }
    return buf;
  }

查看此 SO 帖子以获取 differentiation of Drive Rest in GDAA .

1 The GDAA's main identifier, the DriveId lives in GDAA (GooPlaySvcs) only and does not exist in the REST Api. You must retrieve 'ResourceId' which is the main identifier in the REST Api (see SO 29030110).

2 ResourceId can be obtained from the DriveId only after GDAA committed (uploaded) the file/folder (see SO 22874657)

3 You will run into a lot of timing issues caused by the fact that GDAA 'buffers' network requests on it's own schedule (system optimized), whereas the REST Api let your app control the waiting for the response. In general, if you scan these SO questions, you'll find a lot of chatter about these issues (it's a mess, though).

希望这对您有所帮助。

关于android - 如何以编程方式从 Android 中的 Google 驱动器选择的文件下载并保存在本地目录中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43169487/

相关文章:

android - 谷歌云端硬盘 Android API : Deleted folder still exists in query

Android Google Drive SDK - 如何显示所选文件夹中的文件列表

Android Marshmallow getLastLocation/LocationListeners 不工作

android - ionic build android 在更新 cordova 后抛出 "Uh oh!"错误

android - 根据屏幕尺寸转换 X 和 Y 像素

android - AdMob推广中DisplayUrl要放什么?

android - 备份/恢复 SQLite 数据库到 Google Drive 应用程序文件夹

android - 如何在限制特定位置的android中使用google places api?

java - onCreate 与 onStart 中的 GoogleAPIClient 连接

android - fragment 中不合适的上下文菜单