Integrate Google Drive in Android Tutorial

Udemy Generic 728x90

Objective

In this tutorial, we will learn how to integrate Google Drive API with Android application and create, write and read files to Google Drive using  Google Drive APIs through a simple example.

 




 


 

Google Drive is a file hosting service created by Google. It provides file storage service and allows the user to upload files in the cloud and also share with other people. Using Google Drive API, we can synchronize files between computer or mobile device and Google Drive Cloud.

This tutorial explains, how to integrate Google Drive with an Android app and add a file to Drive from app. Also, we will read and download files stored on Google Drive through app. We will implement two buttons. One button will perform the process of file creation to Google Drive and another button will open a list of all your files. Clicking on a file in the list will open it in the browser. We can also read content of file and download the file.

 

Step 2

Create a New Project

Create a new project in Android Studio, goto File ⇒ New ⇒ New Projects.

 

Step 3

Create a New Project on Google Developer Console

To integrate Android application with Google Drive, create the credentials of project in the Google Developers Console. So, we need to create a project on Google Developer console. To create a project on Google Developer Console, follow these steps:

  • Go to Google Developer Console for Android. Fill your project name in the input field and click on the create button to create a new project on Google Developer console.
    create a project
  • We need to create credentials to access API. So, click on the Create credentials button.
    create credentials
  • Now, a pop window will open. Click on API Key option in the list to create API key.
    api key
  • We need an API key to call Google APIs for Android. So, click on the Android Key to identify your Android Project.
    Android key
  • Next, we need to add Package Name of the Android Project and SHA-1 fingerprint in the input fields to create API key.
    create_credentials
  • We need to generate SHA-1 fingerprint. So, open your terminal and run Keytool utility to get the SHA1 fingerprint. While running Keytool utility, you need to provide keystore password. Default development keytool password is “android”.
     keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
    

    keytool
  • Now, add Package name and SHA-1 fingerprint in input fields on credentials page. Finally, click on create button to create API key.credentials
  • This will create API key for Android. We will use the this API key to integrate Android application with Google Drive.
    APi_Key

 

Step 4

Enable Google Drive API

We need to enable Google Drive Api to access files stored on Google Drive from Android application. To enable Google Drive API, follow below steps:

  • Go to your Google Developer console Dashboard and click on Enable APIs get credentials like keys then you will see popular Google APIs . 
    enableapis
  • Click on Drive API link to open overview page of Google Drive API.
    driveapi
  • Click on the Enable button to enable Google drive API. It allows client access to Google Drive.
    enable google drive

 

Step 5

Add Internet Permission

App needs  Internet  access Google Drive files. Use the following code to set up Internet permissions in AndroidManifest.xml file :

<uses-permission android:name="android.permission.INTERNET" />

 

Step 6

Add Google Play Services

We will use Google play services API which includes the Google Drive Android API. So, we need to setup Google play services SDK in Android Application. Open your build.gradle(app module) file and add Google play services SDK as a dependencies.

dependencies {
  ....
    compile 'com.google.android.gms:play-services:8.4.0'
  ....
}

 

Step 7

Add API key in Manifest file

To use Google API in Android application, we need to add API key and version of the Google Play Service in the AndroidManifest.xml file. Add the following code inside <application> tag in the Manifest file.

&lt;meta-data
   android:name=&quot;com.google.android.geo.API_KEY&quot;
   android:value=&quot;AIzaSyAr_QSYJ3xl61fqJj1xxxxxxx-xxxxx&quot; /&gt;

&lt;meta-data
   android:name=&quot;com.google.android.gms.version&quot;
   android:value=&quot;@integer/google_play_services_version&quot; /&gt;

 

Step 8

Create Layout

As mentioned above, we will add a file to Google Drive and also read file stored on Google Drive. We will perform both the task on button’s click. So, add two Button widget in the activity_main.xml file.

&lt;Button
   android:id=&quot;@+id/createfile&quot;
   android:layout_width=&quot;match_parent&quot;
   android:layout_height=&quot;wrap_content&quot;
   android:text=&quot;Create a file on Google Drive&quot;
   android:onClick=&quot;onClickCreateMethod&quot;/&gt;

&lt;Button
   android:id=&quot;@+id/openfile&quot;
   android:layout_below=&quot;@+id/createfile&quot;
   android:layout_width=&quot;match_parent&quot;
   android:layout_height=&quot;wrap_content&quot;
   android:text=&quot;Open file from Google Drive&quot;
   android:onClick=&quot;onClickOpenFileMethod&quot;/&gt;

 

Integrate-Google-Drive-in-android

Step 9

Connect and Authorize the Google Drive Android API

We need to authenticate and connect Google Drive Android API with Android application. Authorization of Google Drive Android API is handled by the GoogleApiClient. We will use GoogleApiClient within onResume() method.


/**
 * Called when the activity will start interacting with the user.
 * At this point your activity is at the top of the activity stack,
 * with user input going to it.
 */
@Override
protected void onResume() {
   super.onResume();
   if (mGoogleApiClient == null) {

       /**
        * Create the API client and bind it to an instance variable.
        * We use this instance as the callback for connection and connection failures.
        * Since no account name is passed, the user is prompted to choose.
        */
         mGoogleApiClient = new GoogleApiClient.Builder(this)
                 .addApi(Drive.API)
                 .addScope(Drive.SCOPE_FILE)
                 .addConnectionCallbacks(this)
                 .addOnConnectionFailedListener(this)
                 .build();
        }

        mGoogleApiClient.connect();
    }

 

Step 10

Disconnect Google Drive Android API

When activity stops, we will disconnected Google Drive Android API connection with Android application by calling disconnect() method inside activity’s onStop() method.

@Override
protected void onStop() {
    super.onStop();
    if (mGoogleApiClient != null) {

         // disconnect Google Android Drive API connection.
         mGoogleApiClient.disconnect();
    }
    super.onPause();
}

 

Step 11

Implement Connection Callbacks and Connection Failed Listener

We will implement Connection Callbacks and Connection Failed Listener of Google API client in MainActivity.java file to know status about connection of Google API client. These listeners provide onConnected(), onConnectionFailed(), onConnectionSuspended() method to handle the connection issues between app and Drive.

If user has authorized the application, the onConnected() method is invoked. If user has not authorized application, onConnectionFailed() method is invoked and a dialog is displayed to user that your app is not authorized to access Google Drive.
In case connection is suspended, onConnectionSuspended() method is called. Use the following code in your Java file.

public class MainActivity extends Activity implements ConnectionCallbacks,
        OnConnectionFailedListener{

    private static final String TAG = &quot;Google Drive Activity&quot;;
    private GoogleApiClient mGoogleApiClient;
    private boolean fileOperation = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /**
     * Called when the activity will start interacting with the user.
     * At this point your activity is at the top of the activity stack,
     * with user input going to it.
     */

    @Override
    protected void onResume() {
        super.onResume();
        if (mGoogleApiClient == null) {

            /**
             * Create the API client and bind it to an instance variable.
             * We use this instance as the callback for connection and connection failures.
             * Since no account name is passed, the user is prompted to choose.
             */
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(Drive.API)
                    .addScope(Drive.SCOPE_FILE)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
        }

        mGoogleApiClient.connect();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mGoogleApiClient != null) {

            // disconnect Google API client connection
            mGoogleApiClient.disconnect();
        }
        super.onPause();
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {

        // Called whenever the API client fails to connect.
        Log.i(TAG, &quot;GoogleApiClient connection failed: &quot; + result.toString());

        if (!result.hasResolution()) {

            // show the localized error dialog.
            GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
            return;
        }

        /**
         *  The failure has a resolution. Resolve it.
         *  Called typically when the app is not yet authorized, and an  authorization
         *  dialog is displayed to the user.
         */

        try {

            result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);

        } catch (SendIntentException e) {

            Log.e(TAG, &quot;Exception while starting resolution activity&quot;, e);
        }
    }

   /**
    * It invoked when Google API client connected
    * @param connectionHint
    */
    @Override
    public void onConnected(Bundle connectionHint) {

        Toast.makeText(getApplicationContext(), &quot;Connected&quot;, Toast.LENGTH_LONG).show();
    }

   /**
    * It invoked when connection suspended
    * @param cause
    */
    @Override
    public void onConnectionSuspended(int cause) {

        Log.i(TAG, &quot;GoogleApiClient connection suspended&quot;);
    }
}

 

Connecting-Google-Android-API-with-Android-Application

 

Step 12

Create a File on Google Drive

Next, we will add a file on Google Drive. We will use createFile() method of Drive object to create file programmatically on Google Drive. In this example we are adding a new text file in the user’s root folder. When a file is added, we need to specify the initial set of metadata, file contents, and the parent folder.

 

Step 12.1

Create onClick() callback method

We need to create a callback onClickCreateFile() method and within this method, use Drive object to get DriveContent resource. Pass api client in the Drive object and call driveContentsCallback callback method to handle result of DriveContents.

A DriveContents resource contains a temporary copy of the file’s binary stream which is only available to application.

public void onClickCreateFile(View view){

      fileOperation = true;
      // create new contents resource
      Drive.DriveApi.newDriveContents(mGoogleApiClient)
                    .setResultCallback(driveContentsCallback);

}

 

Step 12.2

Result Handler of DriveContents

Handling the response requires to check if the call was successful or not. If the call was successful, we can retrieve the DriveContents resource.

We will create a result handler of DriveContents. Within this method, call CreateFileOnGoogleDrive() method and pass the result of DriveContentsResult.

/**
 * This is Result result handler of Drive contents.
 * this callback method call CreateFileOnGoogleDrive() method.
 */
final ResultCallback&lt;DriveContentsResult&gt; driveContentsCallback =
         new ResultCallback&lt;DriveContentsResult&gt;() {
            @Override
            public void onResult(DriveContentsResult result) {

                if (result.getStatus().isSuccess()) {
                     if (fileOperation == true){

                         CreateFileOnGoogleDrive(result);

                     }
                }
            }
        };

 

Step 12.3

Create File Programmatically

To create files, we need to use MetadataChangeSet object. By using this object, set the title(file name), file type. Also, we must use the createFile() method of the DriveFolder class and pass the google client api, metaDataChangeSet object, driveContents to create a file. Call result handler callback to handle result of created file.

Use following code to create a new text file in the user’s root folder:

/**
 * Create a file in root folder using MetadataChangeSet object.
 * @param result
 */
public void CreateFileOnGoogleDrive(DriveContentsResult result){

    final DriveContents driveContents = result.getDriveContents();

    // Perform I/O off the UI thread.
    new Thread() {
        @Override
        public void run() {
            // write content to DriveContents
            OutputStream outputStream = driveContents.getOutputStream();
            Writer writer = new OutputStreamWriter(outputStream);
            try {
                writer.write(&quot;Hello abhay!&quot;);
                writer.close();

             } catch (IOException e) {
                Log.e(TAG, e.getMessage());
             }

            MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                    .setTitle(&quot;abhaytest2&quot;)
                    .setMimeType(&quot;text/plain&quot;)
                    .setStarred(true).build();

            // create a file in root folder
            Drive.DriveApi.getRootFolder(mGoogleApiClient)
                    .createFile(mGoogleApiClient, changeSet, driveContents)
                    setResultCallback(fileCallback);
        }
   }.start();
}

 

create files on google drive

 

Step 12.4

Handle result of Created File

We will create a callback method to handle result of created file.

/**
 * Handle result of Created file
 */
final private ResultCallback&lt;DriveFolder.DriveFileResult&gt; fileCallback = new
        ResultCallback&lt;DriveFolder.DriveFileResult&gt;() {
            @Override
            public void onResult(DriveFolder.DriveFileResult result) {
                if (result.getStatus().isSuccess()) {

                  Toast.makeText(getApplicationContext(), &quot;file created: &quot;+&quot;&quot;+
                                result.getDriveFile().getDriveId(), Toast.LENGTH_LONG).show();

                }

                return;

            }
       };

 

Step 13

Read Google Drive file

We can read file which stored on Google Drive from Android application. We will open a list of files and folder from Android application and when user selects a file, it fallback on browser to open a file.

 

Step 13.1

Create Drive object

We need to create a callback onClickOpenFile() method and within this method, use Drive object to get DriveContent resource. Pass api client in Drive object and call driveContentsCallback callback method to handle result of Drive contents.

public void onClickOpenFile(View view){
    fileOperation = false;

     // create new contents resource
     Drive.DriveApi.newDriveContents(mGoogleApiClient)
            .setResultCallback(driveContentsCallback);
}

 

Step 13.2

Result handler of DriveContents

We have already created driveContentsCallback() above. This callback method again use to handle DriveContents, we call OpenFileFromGoogleDrive() method.

 /**
  * This is Result result handler of Drive contents.
  * this callback method call CreateFileOnGoogleDrive() method
  * and also call OpenFileFromGoogleDrive() method, send intent onActivityResult() method to handle result.
  */
  final ResultCallback&lt;DriveContentsResult&gt; driveContentsCallback =
          new ResultCallback&lt;DriveContentsResult&gt;() {
              @Override
              public void onResult(DriveContentsResult result) {

                  if (result.getStatus().isSuccess()) {

                      if (fileOperation == true) {

                          CreateFileOnGoogleDrive(result);

                      } else {

                          OpenFileFromGoogleDrive();

                      }
                  }
              }
          };

 

Step 13.3

Open List of Files and Folders

We will use newOpenFileActivityBuilder() method of the Drive object to ope list of files Google drive. In this example, we only select text file to read.

/**
 *  Open list of folder and file of the Google Drive
 */
 public void OpenFileFromGoogleDrive(){

     IntentSender intentSender = Drive.DriveApi
             .newOpenFileActivityBuilder()
             .setMimeType(new String[] { &quot;text/plain&quot;, &quot;text/html&quot; })
             .build(mGoogleApiClient);
     try {

         startIntentSenderForResult(

                 intentSender, REQUEST_CODE_OPENER, null, 0, 0, 0);

     } catch (SendIntentException e) {

         Log.w(TAG, &quot;Unable to send intent&quot;, e);
     }

 }

 

open google drive file

Step 13.4

Add Response Handler

The activity’s onActivityResult() method will be called, when user select a text file. In this method, we will retrieve selected file id and open file on browser.

 /**
  * Handle Response of selected file
  * @param requestCode
  * @param resultCode
  * @param data
  */
  @Override
  protected void onActivityResult(final int requestCode,
                                    final int resultCode, final Intent data) {
  switch (requestCode) {

         case REQUEST_CODE_OPENER:

             if (resultCode == RESULT_OK) {

                 mFileId = (DriveId) data.getParcelableExtra(
                         OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);

                 Log.e(&quot;file id&quot;, mFileId.getResourceId() + &quot;&quot;);

                 String url = &quot;https://drive.google.com/open?id=&quot;+ mFileId.getResourceId();
                 Intent i = new Intent(Intent.ACTION_VIEW);
                 i.setData(Uri.parse(url));
                 startActivity(i);
             }

             break;

         default:
             super.onActivityResult(requestCode, resultCode, data);
             break;
     }
 }

 

Step 14

Final Code

Here is the final code:

public class MainActivity extends Activity implements ConnectionCallbacks,
        OnConnectionFailedListener{

    private static final String TAG = &quot;Google Drive Activity&quot;;
    private static final int REQUEST_CODE_RESOLUTION = 1;
    private static final  int REQUEST_CODE_OPENER = 2;
    private GoogleApiClient mGoogleApiClient;
    private boolean fileOperation = false;
    private DriveId mFileId;
    public DriveFile file;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    /**
     * Called when the activity will start interacting with the user.
     * At this point your activity is at the top of the activity stack,
     * with user input going to it.
     */

    @Override
    protected void onResume() {
        super.onResume();
        if (mGoogleApiClient == null) {

            /**
             * Create the API client and bind it to an instance variable.
             * We use this instance as the callback for connection and connection failures.
             * Since no account name is passed, the user is prompted to choose.
             */
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(Drive.API)
                    .addScope(Drive.SCOPE_FILE)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
        }

        mGoogleApiClient.connect();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mGoogleApiClient != null) {

            // disconnect Google API client connection
            mGoogleApiClient.disconnect();
        }
        super.onPause();
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {

        // Called whenever the API client fails to connect.
        Log.i(TAG, &quot;GoogleApiClient connection failed: &quot; + result.toString());

        if (!result.hasResolution()) {

            // show the localized error dialog.
            GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
            return;
        }

        /**
         *  The failure has a resolution. Resolve it.
         *  Called typically when the app is not yet authorized, and an  authorization
         *  dialog is displayed to the user.
         */

        try {

            result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);

        } catch (SendIntentException e) {

            Log.e(TAG, &quot;Exception while starting resolution activity&quot;, e);
        }
    }

    /**
     * It invoked when Google API client connected
     * @param connectionHint
     */
    @Override
    public void onConnected(Bundle connectionHint) {

        Toast.makeText(getApplicationContext(), &quot;Connected&quot;, Toast.LENGTH_LONG).show();
    }

    /**
     * It invoked when connection suspend
     * @param cause
     */
    @Override
    public void onConnectionSuspended(int cause) {

        Log.i(TAG, &quot;GoogleApiClient connection suspended&quot;);
    }

    public void onClickCreateFile(View view){
        fileOperation = true;

        // create new contents resource
        Drive.DriveApi.newDriveContents(mGoogleApiClient)
                .setResultCallback(driveContentsCallback);

    }

    public void onClickOpenFile(View view){
        fileOperation = false;

        // create new contents resource
        Drive.DriveApi.newDriveContents(mGoogleApiClient)
                .setResultCallback(driveContentsCallback);
    }

    /**
     *  Open list of folder and file of the Google Drive
     */
    public void OpenFileFromGoogleDrive(){

        IntentSender intentSender = Drive.DriveApi
                .newOpenFileActivityBuilder()
                .setMimeType(new String[] { &quot;text/plain&quot;, &quot;text/html&quot; })
                .build(mGoogleApiClient);
        try {
            startIntentSenderForResult(

                    intentSender, REQUEST_CODE_OPENER, null, 0, 0, 0);

        } catch (SendIntentException e) {

            Log.w(TAG, &quot;Unable to send intent&quot;, e);
        }

    }

    /**
     * This is Result result handler of Drive contents.
     * this callback method call CreateFileOnGoogleDrive() method
     * and also call OpenFileFromGoogleDrive() method,
     * send intent onActivityResult() method to handle result.
     */
    final ResultCallback&lt;DriveContentsResult&gt; driveContentsCallback =
            new ResultCallback&lt;DriveContentsResult&gt;() {
                @Override
                public void onResult(DriveContentsResult result) {

                    if (result.getStatus().isSuccess()) {

                        if (fileOperation == true) {

                            CreateFileOnGoogleDrive(result);

                        } else {

                            OpenFileFromGoogleDrive();

                        }
                    }

                }
            };

    /**
     * Create a file in root folder using MetadataChangeSet object.
     * @param result
     */
    public void CreateFileOnGoogleDrive(DriveContentsResult result){

        final DriveContents driveContents = result.getDriveContents();

        // Perform I/O off the UI thread.
        new Thread() {
            @Override
            public void run() {
                // write content to DriveContents
                OutputStream outputStream = driveContents.getOutputStream();
                Writer writer = new OutputStreamWriter(outputStream);
                try {
                    writer.write(&quot;Hello abhay!&quot;);
                    writer.close();
                } catch (IOException e) {
                    Log.e(TAG, e.getMessage());
                }

                MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                        .setTitle(&quot;abhaytest2&quot;)
                        .setMimeType(&quot;text/plain&quot;)
                        .setStarred(true).build();

                // create a file in root folder
                Drive.DriveApi.getRootFolder(mGoogleApiClient)
                        .createFile(mGoogleApiClient, changeSet, driveContents)
                        .setResultCallback(fileCallback);
            }
        }.start();
    }

    /**
     * Handle result of Created file
     */
    final private ResultCallback&lt;DriveFolder.DriveFileResult&gt; fileCallback = new
            ResultCallback&lt;DriveFolder.DriveFileResult&gt;() {
                @Override
                public void onResult(DriveFolder.DriveFileResult result) {
                    if (result.getStatus().isSuccess()) {

                        Toast.makeText(getApplicationContext(), &quot;file created: &quot;+&quot;&quot;+
                                result.getDriveFile().getDriveId(), Toast.LENGTH_LONG).show();

                    }

                    return;

                }
            };

    /**
     *  Handle Response of selected file
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(final int requestCode,
                                    final int resultCode, final Intent data) {
        switch (requestCode) {

            case REQUEST_CODE_OPENER:

                if (resultCode == RESULT_OK) {

                    mFileId = (DriveId) data.getParcelableExtra(
                            OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);

                    Log.e(&quot;file id&quot;, mFileId.getResourceId() + &quot;&quot;);

                    String url = &quot;https://drive.google.com/open?id=&quot;+ mFileId.getResourceId();
                    Intent i = new Intent(Intent.ACTION_VIEW);
                    i.setData(Uri.parse(url));
                    startActivity(i);
                }

                break;

            default:
                super.onActivityResult(requestCode, resultCode, data);
                break;
        }
    }

}

 




 

Udemy Generic 728x90

Spread the word. Share this post!

  • Abdelaziz Belarbi

    Good article may be completed by sync file in appfolder

  • Ho Hieu

    Hi, why can I open another file in Google Drive , but the file I create from app ?

    • Артем Косякевич

      Just remove row .setMimeType(); it’s like a filter your files

  • Greenboigz

    Is there any reason why I am having trouble connecting to my Google account through this app. The error is “GoogleApiClient connection failed: ConnectionResult{statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent{cf43dba: [email protected]}, message=null}”

  • ashish parmar

    The error is “GoogleApiClient connection failed: ConnectionResult{statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent{cf43dba: [email protected]}, message=null}”

    Can you please help me for this error? I could not figure out what the problem after select the account ?

  • vipin

    please update a program for update the file on google derive and upload

  • Dmitry

    I have problem status{statuscode=sign_in, resolution=null}

    i had solution. I my case i need to auth on google console, DOWNLOAD JSON_FILE , rename to “client_id.json” and place this in my app directory

  • Nagaraj C

    On choosing the account for google drive it wont go to next screen…please help me to resolve

    • Marco João

      Same here… trying to fix…

    • Zoran Protic

      Same problem!