NealXGS
NealXGS

Reputation: 61

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.

Upvotes: 3

Views: 1379

Answers (1)

NealXGS
NealXGS

Reputation: 61

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.

Upvotes: 1

Related Questions