列出来自Google云端硬盘的文件,并获取Android中所选文件的downloadUrl

幼敏悟过人,读书辄成诵。这篇文章主要讲述列出来自Google云端硬盘的文件,并获取Android中所选文件的downloadUrl相关的知识,希望能为你提供帮助。
我试图通过我的android应用程序显示用户在其Google云端硬盘上的文件列表,一旦用户选择了文件,我想获得该帐户的downloadUrlBearer token,以便将其提供给我的应用服务器下载它。
我一直在环顾四周,看起来很混乱。 Google云端硬盘有2个SDK,Android SDK和Java SDK(基于REST)。
我成功地获得了文件列表并使用Android SDK显示它(我没有构建任何UI),当用户选择文件时,我得到了关于该文件的所有metadata但downloadUrl。我确实得到了像webContentLinkalternateLink这样的链接,但事实证明,由于文件没有共享,我无法将这些链接传递给我的服务器下载它。
经过一些研究,我发现可以使用java SDK访问downloadUrl。我的问题是,我是否必须构建自己的UI来显示我获得的文件列表?如果我必须构建我的UI来显示这些文件,我该如何处理文件夹层次结构?
下面是打印有关File数据的代码。我已经基于tutorial实现了这段代码。

public class GoogleDriveActivity extends Activity {private GoogleApiClient mGoogleApiClient; public com.google.api.services.drive.Drive mService; public GoogleAccountCredential credential; public static final int REQUEST_AUTHORIZATION = 3; public static final int REQUEST_ACCOUNT_PICKER = 4; private static final String PREF_ACCOUNT_NAME = "accountName"; private static final String[] SCOPES = {DriveScopes.DRIVE_METADATA_READONLY}; final HttpTransport transport = AndroidHttp.newCompatibleTransport(); final JsonFactory jsonFactory = GsonFactory.getDefaultInstance(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_google_drive); SharedPreferences settings = getPreferences(Context.MODE_PRIVATE); credential = GoogleAccountCredential.usingOAuth2( getApplicationContext(), Arrays.asList(SCOPES)) .setBackOff(new ExponentialBackOff()) .setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, "abc.test@gmail.com")); mService = new com.google.api.services.drive.Drive.Builder( transport, jsonFactory, credential) .setApplicationName("My Application") .build(); }@Override public void onResume() { super.onResume(); refreshResults(); }@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_AUTHORIZATION: if (resultCode != RESULT_OK) { chooseAccount(); } break; case REQUEST_ACCOUNT_PICKER: Log.w("gd", "in account picker"); if (resultCode == RESULT_OK & & data != null & & data.getExtras() != null) { String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); if (accountName != null) { credential.setSelectedAccountName(accountName); SharedPreferences settings = getPreferences(Context.MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); editor.putString(PREF_ACCOUNT_NAME, accountName); editor.commit(); } } else if (resultCode == RESULT_CANCELED) { Log.W("gd", "in cancelled"); } break; default: super.onActivityResult(requestCode, resultCode, data); break; } }private void chooseAccount() { startActivityForResult( credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); }private void refreshResults() { new GoogleDriveAsync(this).execute(); }public class GoogleDriveAsync extends AsyncTask< Void, Void, Void> {private GoogleDriveActivity activity; @Override protected Void doInBackground(Void... voids) { try { getDataFromApi(); } catch (final GooglePlayServicesAvailabilityIOException availabilityException) { Log.w("gd", "GPS unavailable"); } catch (UserRecoverableAuthIOException userRecoverableException) { Log.w("gd", "user recoverable"); activity.startActivityForResult( userRecoverableException.getIntent(), GoogleDriveActivity.REQUEST_AUTHORIZATION); } catch (Exception e) { Log.w("gd", "general exception " + e.getMessage()); } return null; }GoogleDriveAsync(GoogleDriveActivity activity) { this.activity = activity; }/** * Fetch a list of up to 10 file names and IDs. * * @return List of Strings describing files, or an empty list if no files * found. * @throws IOException */ private List< String> getDataFromApi() throws IOException { // Get a list of up to 10 files. List< String> fileInfo = new ArrayList< String> (); FileList result = activity.mService.files().list() .setMaxResults(10) .execute(); List< File> files = result.getItems(); if (files != null) { for (File file : files) { fileInfo.add(String.format("%s (%s) (%s) ", file.getTitle(), file.getId(), file.getDownloadUrl())); } } Log.w("gd", "file info is " + fileInfo.toString()); return fileInfo; } } }

编辑:请查看我的答案(不是接受的答案)的工作样本。用例是:列出用户的所有Google Drive文件,选择后,获取文件的downloadUrlaccess_token
答案要使用基于GDAA的应用程序之外的文件/文件夹,您需要所谓的ResourceID。此ResourceId是一个唯一标识Google云端硬盘对象的字符串(请参阅here)
将DriveId变为ResourceId:
DriveId driveId = metadata.getDriveId(); String resourceId = driveId.getResourceId();

拥有ResourceId后,您可以从中为您的服务器应用构建“下载URL”。如果您转到drive.google.com,选择文件/文件夹并执行rightbutton> getLink,则会找到ResourceID字符串。 (看起来像'https://drive.google.com/open?id=0B1mQUW2__I_am_the_resource_id')
只需将此字符串'0B1mQUW2__I_am_the_resource_id'带到'TryIt' playground here并将其粘贴到'fileId'字段即可。
所以,简短的回答是你不需要RESTful Api来获取你可以在其他地方使用的文件/文件夹标识符。
问题的第二部分,“如果我必须构建我的UI以显示这些文件,我该如何处理文件夹层次结构?”在这些2个演示(GDAADemo,RESTDemo)的MainActivity的'createTree()/ testTree()'方法中得到了回答(某种程度上)。这些是在GDAA和REST Apis上实现的相同任务,选择主要取决于您的应用程序需要的SCOPE(GDAA仅支持FILE范围,而REST支持FILE和DRIVE范围)
祝好运
另一答案Activity
public class GoogleDriveActivity extends Activity implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {private GoogleApiClient mGoogleApiClient; final HttpTransport transport = AndroidHttp.newCompatibleTransport(); final JsonFactory jsonFactory = GsonFactory.getDefaultInstance(); public static final int REQUEST_CODE_RESOLUTION = 1; public static final int REQUEST_CODE_SELECT = 2; private static final String[] SCOPES = { DriveScopes.DRIVE_FILE}; private static final String TAG = "GoogleDrive"; private String accountName; @Override protected void onResume() { super.onResume(); setupGoogleClient(); }@Override protected void onPause() { super.onPause(); if (mGoogleApiClient != null) { mGoogleApiClient.disconnect(); } }@Override public void onConnected(Bundle bundle) { IntentSender intentSender = Drive.DriveApi .newOpenFileActivityBuilder() .build(mGoogleApiClient); 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_SELECT, null, 0, 0, 0); } catch (IntentSender.SendIntentException e) { Log.w(TAG, "Unable to send intent to connect to Google API client " + e.getMessage()); }}@Override public void onConnectionFailed(ConnectionResult connectionResult) { if (!connectionResult.hasResolution()) { return; } try { connectionResult.startResolutionForResult(this, REQUEST_CODE_RESOLUTION); } catch (IntentSender.SendIntentException e) { Log.w(TAG, "Unable to send intent to connect to Google API client " + e.getMessage()); } }@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE_SELECT: if (resultCode == RESULT_OK) { DriveId driveId = data.getParcelableExtra(OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID); String resourceId = driveId.getResourceId(); new GoogleDriveAsync(this).execute(resourceId); } finish(); break; case REQUEST_CODE_RESOLUTION: if (resultCode == RESULT_OK) { mGoogleApiClient.connect(); } break; default: super.onActivityResult(requestCode, resultCode, data); break; } }@Override public void onConnectionSuspended(int i) { Log.w(TAG, "Connection to Google API client suspended"); }private void setupGoogleClient() { if (mGoogleApiClient == null) { mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(Drive.API) .addScope(Drive.SCOPE_FILE) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); } mGoogleApiClient.connect(); }class GoogleDriveAsync extends AsyncTask< String, Void, Void> { private GoogleDriveActivity activity; GoogleDriveAsync(GoogleDriveActivity activity) { this.activity = activity; }@Override protected Void doInBackground(String... args) { try { String id = args[0]; GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(getApplicationContext(), Arrays.asList(SCOPES)); credential.setBackOff(new ExponentialBackOff()); credential.setSelectedAccountName(accountName); com.google.api.services.drive.Drive service = new com.google.api.services.drive.Drive.Builder(transport, jsonFactory, credential).build(); File file = service.files().get(id).setFields("downloadUrl").execute(); if (file != null) { String strUrl = file.getDownloadUrl(); String token = GoogleAuthUtil.getToken(activity, accountName, "oauth2: " + Drive.SCOPE_FILE); //This is your downloadUrl and token Log.w(TAG, "download link is " + strUrl + " and token is " + token); } } catch (final GooglePlayServicesAvailabilityIOException availabilityException) { Log.w(TAG, "Google Play Services not available to get downloadUrl of selected file"); } catch (UserRecoverableAuthIOException userRecoverableException) { Log.w(TAG, "User authorization error in getting downloadUrl " + userRecoverableException.getMessage()); } catch (Exception e) { Log.w(TAG, "Exception in getting downloadUrl " + e.getMessage()); } return null; } } }

AndroidManifest(相关部分):
< uses-permission android:name="android.permission.GET_ACCOUNTS" /> < activity android:name="com.myapp.GoogleDriveActivity" android:label="@string/app_name" < meta-data android:name="com.google.android.apps.drive.APP_ID" android:value="https://www.songbingjia.com/android/id=< your-gogole-project-id>"/> < /activity>

【列出来自Google云端硬盘的文件,并获取Android中所选文件的downloadUrl】build.gradle(相关部分):
compile 'com.google.android.gms:play-services-drive:7.8.0' compile 'com.google.api-client:google-api-client:1.20.0' compile 'com.google.api-client:google-api-client-android:1.20.0' compile 'com.google.api-client:google-api-client-gson:1.20.0' compile 'com.google.apis:google-api-services-drive:v2-rev170-1.20.0'


    推荐阅读