Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create GoogleCredential by Access Token

I want to design an Android file viewer for Google Drive.

At first, I implemented the app by using of the Google Android API, as follows,

private void retrieveNextPage(){

    if(mHasMore == false)
        return;

    Query query = new Query.Builder().setPageToken(mNextPageToken).build();
    com.google.android.gms.drive.Drive.DriveApi.query(getGoogleApiClient(), query).setResultCallback(metadataBufferResultResultCallback);

}

However, the Android Drive API only allows the app to view and fetch the files that created by itself. I cannot access other files on the drive through the app.

Therefore, I turned to another option, directly manipulate the Java Drive API.

According to the example on developer guide for Java,

https://developers.google.com/drive/web/quickstart/quickstart-java

The users have to manually copy and paste the "Authorization Code" between the browser and app, which is not a practical way to acquire the Access Token in Android.

To come out a new way, I used the GoogleAuthUtil in Android API to acquire the Access Token, coincided with the GoogleCredential and Drive in Java API to fetch the file list, as follows,

private static List<File> retrieveFiles(Drive service) throws IOException{
    List<File> result = new ArrayList<File>();
    Files.List request = service.files().list();
    do {
        try{
            FileList fileList = request.execute();
            result.addAll(fileList.getItems());
            request.setPageToken(fileList.getNextPageToken());

        }catch (IOException e){
            Log.d(dbgT + "JavaRetrieveFiles", "Retrieved Failed");
            request.setPageToken(null);
        }
    }while (request.getPageToken() != null && request.getPageToken().length() > 0);

    return result;
}

private class RetrieveTokenTask extends AsyncTask<String, Void, String>{

    @Override
    protected String doInBackground(String... params){
        String accountName = params[0];
        String scopes = "oauth2:" + "https://www.googleapis.com/auth/drive";
        String token = null;

        try{
            token = GoogleAuthUtil.getToken(getApplicationContext(), accountName, scopes);
        }
        catch (IOException e){
            Log.e(excpTAG, "IO Exception: " + e.getMessage());
        }
        catch (UserRecoverableAuthException e){
            startActivityForResult(e.getIntent(), REQ_SIGN_IN_REQUIRED);
        }
        catch (GoogleAuthException e)
        {
            Log.e(excpTAG, "GoogleAuthException: " + e.getMessage());
        }

        return token;
    }

    @Override
    protected void onPostExecute(String s){
        super.onPostExecute(s);

        //Get Access Token
        Log.d( dbgT + "Token", s);
        EditText tokenText = (EditText) findViewById(R.id.tokenText);
        tokenText.setText(s);

        EditText fileNameText = (EditText) findViewById(R.id.editTextMeta);

        GoogleCredential credential = new GoogleCredential().setAccessToken(s);
        HttpTransport httpTransport = new NetHttpTransport();
        JsonFactory jsonFactory = new JacksonFactory();
        Drive service = new Drive.Builder(httpTransport, jsonFactory, null).setHttpRequestInitializer(credential).build();

        List<File> fileList;
        try{
            fileList = retrieveFiles(service);
            for(int i=0; i< fileList.size(); i++)
                fileNameText.append(fileList.get(i).getTitle());
        }catch(IOException e){
            Log.d(dbgT + "RetrieveFileList", "IO Exception" );
        }

    }
}

Unfortunately, the app always crashes by the causing of NetworkOnMainThreadException when request.execute() in retrieveFiles is invoked.

I checked my access token s, it is usually in form of ya29.xxx...etc., and it can also be passed to my other .NET program for retrieving files from Google Drive. Therefore I can certain the access token is correct.

So my question is, how to create a correct GoogleCredential by using of access token, instead of applying authorization code in setFromTokenResponse ?

Thanks in advance.

like image 926
NealXGS Avatar asked Jun 18 '26 13:06

NealXGS


1 Answers

Many thanks for Andy's tips, this problem is simply caused by the network operations occurs on the main thread, which is a very basic newbie error.

The Drive in Google Drive SDK for Java, using network libraries without any background/thread worker, and now it is functional after I put the retrieveFiles() into background.

Applying the GoogleAuthUtil in Google Play Android SDK to acquire the access token, and followed by GoogleCredential+Drive in Java SDK that use the token to do the file operation in Google Drive.

This is a right way to avoid the scope restriction in Android SDK for Google Drive, allowing the developers to acquire the full permissive of accessing Google Drive.

like image 142
NealXGS Avatar answered Jun 20 '26 09:06

NealXGS



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!