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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了列出来自Google云端硬盘的文件,并获取Android中所选文件的downloadUrl相关的知识,希望对你有一定的参考价值。

我试图通过我的android应用程序显示用户在其Google云端硬盘上的文件列表,一旦用户选择了文件,我想获得该帐户的downloadUrlBearer token,以便将其提供给我的应用服务器下载它。

我一直在环顾四周,看起来很混乱。 Google云端硬盘有2个SDK,Android SDKJava SDK(基于REST)。

我成功地获得了文件列表并使用Android SDK显示它(我没有构建任何UI),当用户选择文件时,我得到了关于该文件的所有metadatadownloadUrl。我确实得到了像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个演示(GDAADemoRESTDemo)的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="id=<your-gogole-project-id>"/>
</activity>

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'

以上是关于列出来自Google云端硬盘的文件,并获取Android中所选文件的downloadUrl的主要内容,如果未能解决你的问题,请参考以下文章

python 适用于Google云端硬盘的Python终端客户端,可轻松上传,删除,列出,共享文件或文件夹。 (参见评论中的用法)

打开云端硬盘应用以创建文件并获取链接

如何在从Google Site添加时设置对Google云端硬盘文件/文件夹的权限

获取Google Drive演示文稿文件的链接

使用Android应用无法在Google云端硬盘上看到PC上传的文件

google 云端硬盘中的文件无法下载