幼敏悟过人,读书辄成诵。这篇文章主要讲述列出来自Google云端硬盘的文件,并获取Android中所选文件的downloadUrl相关的知识,希望能为你提供帮助。
我试图通过我的android应用程序显示用户在其Google云端硬盘上的文件列表,一旦用户选择了文件,我想获得该帐户的downloadUrl
和Bearer token
,以便将其提供给我的应用服务器下载它。
我一直在环顾四周,看起来很混乱。 Google云端硬盘有2个SDK,Android SDK和Java SDK(基于REST
)。
我成功地获得了文件列表并使用Android SDK显示它(我没有构建任何UI),当用户选择文件时,我得到了关于该文件的所有metadata但downloadUrl
。我确实得到了像webContentLink
和alternateLink
这样的链接,但事实证明,由于文件没有共享,我无法将这些链接传递给我的服务器下载它。
经过一些研究,我发现可以使用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文件,选择后,获取文件的
downloadUrl
和access_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'
推荐阅读
- 如何从webapp重定向到Google云端硬盘应用
- 继续在Android上使用旧的Google云端硬盘API
- Jackson XML Mapper为列表编写两次元素名称
- JAXB ClassNotFoundException使用Java 11构建Spring Boot App 2.2.0
- Android - 在寻呼机中获取片段的上下文
- Android rtl viewpager with rtl tablayout
- Android Exoplayer,在屏幕旋转时恢复视频
- 如何在你的Cordova Android应用中添加对Samsung Multi Window和PopUp模式的支持
- 8个最佳的Magento扩展程序,将促进你的在线业务