How to Auto-sync Google Drive For Backup & Retrieve Files While Developing An Android App (Tutorial)

auto sync google drive example

In this Android app tutorial, we will learn how to auto-sync Google Drive API in order to let Android users access and download the files from Google Drive to an Android app.

This tutorial for Android Google Drive Sync is useful to those entrepreneurs who are looking to develop an android app for their own business & access all the data backed up with the help of Google Drive.

What is Google Drive?

Google Drive is a cloud-based storage service provided by Google. It is similar to other cloud storage services and is used to expand the storage capacity for keeping files beyond the limits of a hard drive. It syncs all stored documents, photos and many more files across a user’s device, including mobile devices, tablets and PCs.

How to Auto-sync google drive for backup

Google provides 15 GB of free cloud storage space to every user for signing up & creating a Gmail account. However, it’s necessary to know that all of this 15 GB free space is divided & shared between Gmail, Google Drive (Microsoft Office Docs, Presentations, Spreadsheet etc), Google Photos as well.

How Does it Work?

By signing up, a user can create a Google account which can be used to access Gmail, Google Play store, Google Drive, Google Photos and many other services. Once the google account is created, a user can log in into the account and access Google Drive from its menu to browse the stored files.

Benefits of Google Drive Sync

The main benefit of signing up for a google account and auto-sync google drive is that it can be accessed via the browser, on desktop and laptop or via smartphone also, which allows users to store & access data from anywhere as per their ease.

Google also provides the auto-sync features so that all the data of a user’s device can be automatically synced & uploaded to Google Drive without asking users for permission every time.

Moreover, accessing and storing data on the Google drive is much secure as all the data is encrypted and decrypted using 128-bit advanced encryption standard (AES) along with Transport Layer Security (TLS) standard when it goes from a user’s device and reaches to Google’s cloud storage.

Read Here: How to Use Android Wrap_Content

Want To Create An Android Application?

Validate your app idea and get a free quote.

Let’s see How to Auto-sync Google Drive in Android

  1. Create a new project in the Android Studio

  2. create new project

    Add package name & configuration

    Select Package name

  3. Create a new project in the Android Studio

  4. Add dependencies in your build.gradle file which is an in-app module

  5. add dependencies

    implementation 'androidx.multidex:multidex:2.0.1' implementation "com.google.android.gms:play-services-auth:16.0.1" implementation 'com.google.http-client:google-http-client-gson:1.26.0' implementation('com.google.api-client:google-api-client-android:1.26.0') implementation('com.google.apis:google-api-services-drive:v3-rev136-1.25.0') { 
    exclude group: 'com.google.guava' 
    }
    

    also, add packagingOptions in android { }

    packagingOptions { 
    exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE.txt' exclude 'META-INF/license.txt' exclude 'META-INF/NOTICE' exclude 'META-INF/NOTICE.txt' exclude 'META-INF/notice.txt' exclude 'META-INF/ASL2.0' 
    }
    
  6. Create a new project in the Google API console

  7. create new project in Google API console

     

  8. Enable Google Drive API from APIs & Services -> Library -> Google Drive API

  9. Enable Google Drive API

  10. Add Application Name in OAuth consent screen

  11. Add Application Name

  12. Add scope -> /auth/drive.file

  13. Add scope

     

  14. Now Create Credentials from APIs & Services -> Credentials -> Create credentials -> Create OAuth client ID

  15. Create API Credentials

     

    Create OAuth client ID

  16. just copy Client ID & Client Secret and paste to the string.xml file

  17. Enter Client ID and Client Secret

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.spaceo.gdrivesyncdemo">
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <application
                android:allowBackup="true"
                android:icon="@mipmap/ic_launcher"
                android:label="@string/app_name"
                android:roundIcon="@mipmap/ic_launcher_round"
                android:supportsRtl="true"
                android:usesCleartextTraffic="true"
                android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <meta-data
                    android:name="com.google.android.gms.version"
                    android:value="@integer/google_play_services_version"/>
        </application>
    </manifest>

    Activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:gravity="center">
        <Button android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Backup"
                android:id="@+id/btnBackup"
                android:layout_gravity="center"/>
        <Button android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Restore"
                android:layout_marginTop="24dp"
                android:id="@+id/btnRestore"
                android:layout_gravity="center"/>
    </LinearLayout>
    

    DriveServiceHelper.java

    package com.spaceo.gdrivesyncdemo.util;
    import androidx.core.util.Pair;
    import com.google.android.gms.tasks.Task;
    import com.google.android.gms.tasks.Tasks;
    import com.google.api.client.http.InputStreamContent;
    import com.google.api.services.drive.Drive;
    import com.google.api.services.drive.model.File;
    import com.google.api.services.drive.model.FileList;
    import java.io.*;
    import java.util.Collections;
    import java.util.concurrent.Executor;
    import java.util.concurrent.Executors;
    
    /**
     * A utility for performing read/write operations on Drive files via the REST API and opening a
     * file picker UI via Storage Access Framework.
     */
    public class DriveServiceHelper {
        private final Executor mExecutor = Executors.newSingleThreadExecutor();
        private final Drive mDriveService;
        public DriveServiceHelper(Drive driveService) {
            mDriveService = driveService;
        }
        public Task<String> uploadFile(String name, java.io.File fileTest) {
            return Tasks.call(mExecutor, () -> {
                File metadata = new File()
                        .setParents(Collections.singletonList("root"))
                        .setMimeType("text/plain")
                        .setName(name);
                InputStream targetStream = new FileInputStream(fileTest);
                InputStreamContent inputStreamContent = new InputStreamContent("text/plain", targetStream);
                File googleFile = mDriveService.files().create(metadata, inputStreamContent).execute();
                if (googleFile == null) {
                    throw new IOException("Null result when requesting file creation.");
                }
                return googleFile.getId();
            });
        }
    
    /**
         * Opens the file identified by {@code fileId} and returns a {@link Pair} of its name and
         * contents.
         */
    
    public Task<Pair<String, String>> readFile(String fileId) {
            return Tasks.call(mExecutor, () -> {
                // Retrieve the metadata as a File object.
                File metadata = mDriveService.files().get(fileId).execute();
                String name = metadata.getName();
                // Stream the file contents to a String.
                try (InputStream is = mDriveService.files().get(fileId).executeMediaAsInputStream();
                     BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
                    StringBuilder stringBuilder = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        stringBuilder.append(line);
                    }
                    String contents = stringBuilder.toString();
                    return Pair.create(name, contents);
                }
            });
        }
    
    /**
         * Returns a {@link FileList} containing all the visible files in the user's My Drive.
         *
         * <p>The returned list will only contain files visible to this app, i.e. those which were
         * created by this app. To perform operations on files not created by the app, the project must
         * request Drive Full Scope in the <a href="https://play.google.com/apps/publish">Google
         * Developer's Console</a> and be submitted to Google for verification.</p>
         */
    
    public Task<FileList> queryFiles() {
            return Tasks.call(mExecutor, () ->
                    mDriveService.files().list().setSpaces("drive").execute());
        }
    }
    

    RunTimePermission.kt

    package com.spaceo.gdrivesyncdemo.util
    import android.content.pm.PackageManager
    import android.os.Build
    import androidx.appcompat.app.AppCompatActivity
    import androidx.core.content.ContextCompat
    open class RunTimePermission : AppCompatActivity() {
        private var callback: ((Boolean) -> Unit)? = null
        fun requestPermission(permissions: Array<String>, callback: (isGranted: Boolean) -> Unit) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                var granted = true
                for (permission in permissions) {
                    if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                        granted = false
                        break
                    }
                }
                if (granted) {
                    callback(true)
                } else {
                    this.callback = callback
                    requestPermissions(permissions, Integer.MAX_VALUE)
                }
            } else callback(true)
        }
        override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
            if (requestCode == Integer.MAX_VALUE) {
                var granted = true
                for (i in 0 until grantResults.size) {
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                        granted = false
                        break
                    }
                }
                if (granted)
                    callback?.invoke(true)
                else onDenied()
            }
        }
        private fun onDenied() {
            callback?.invoke(false)
        }
    }
    

    MainActivity.kt

    package com.spaceo.gdrivesyncdemo
    import android.content.Intent
    import android.os.Bundle
    import android.os.Environment
    import android.widget.Toast
    import androidx.appcompat.app.AppCompatActivity
    import com.google.android.gms.auth.api.signin.GoogleSignIn
    import com.google.android.gms.auth.api.signin.GoogleSignInClient
    import com.google.android.gms.auth.api.signin.GoogleSignInOptions
    import com.google.android.gms.common.Scopes
    import com.google.android.gms.common.api.Scope
    import com.google.api.client.extensions.android.http.AndroidHttp
    import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
    import com.google.api.client.json.gson.GsonFactory
    import com.google.api.services.drive.Drive
    import com.google.api.services.drive.DriveScopes
    import com.spaceo.gdrivesyncdemo.util.DriveServiceHelper
    import com.spaceo.gdrivesyncdemo.util.RunTimePermission
    import kotlinx.android.synthetic.main.activity_main.*
    import java.io.File
    import java.io.FileOutputStream
    import java.io.FileWriter
    import java.lang.StringBuilder
    import java.util.*
    import java.util.jar.Manifest
    class MainActivity : RunTimePermission() {
        private val RQ_GOOGLE_SIGN_IN = 210
        private val BACKUP_FILE = "test.txt"
        private var isRestore = false
        private var mGoogleApiClient: GoogleSignInClient? = null
        private var mDriveServiceHelper: DriveServiceHelper? = null
        private var lastUploadFileId: String? = null
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            btnBackup.setOnClickListener {
                requestPermission(arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) { isGranted ->
                    if (isGranted) {
                        isRestore = false
                        if (mDriveServiceHelper == null)
                            googleAuth()
                        else {
                            val uploadTask = mDriveServiceHelper?.uploadFile(BACKUP_FILE, generateFile())
                            uploadTask?.addOnCompleteListener {
                                lastUploadFileId = uploadTask.result
                                println("lastUploadFileId==>$lastUploadFileId")
                                Toast.makeText(this@MainActivity, "Backup upload successfully", Toast.LENGTH_LONG).show()
                            }
                        }
                    }
                }
            }
            btnRestore.setOnClickListener {
                requestPermission(arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) { isGranted ->
                    if (isGranted) {
                        isRestore = true
                        if (mDriveServiceHelper == null)
                            googleAuth()
                        else {
                            if (null != lastUploadFileId) {
                                val downloadTask = mDriveServiceHelper?.readFile(lastUploadFileId)
                                downloadTask?.addOnCompleteListener {
                                    println("Name==>${downloadTask.result?.first}")
                                    println("Content==>${downloadTask.result?.second}")
                                    Toast.makeText(this@MainActivity, "Backup download successfully", Toast.LENGTH_LONG)
                                        .show()
                                }
                            }
                        }
                    }
                }
            }
        }
        private fun googleAuth() {
            val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestServerAuthCode(getString(R.string.web_client_id))
                .requestScopes(Scope(Scopes.PROFILE), Scope("https://www.googleapis.com/auth/drive.file"))
                .build()
            mGoogleApiClient = GoogleSignIn.getClient(this, signInOptions)
            startActivityForResult(mGoogleApiClient!!.signInIntent, RQ_GOOGLE_SIGN_IN)
        }
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
            if (requestCode == RQ_GOOGLE_SIGN_IN && resultCode == RESULT_OK) {
                val task = GoogleSignIn.getSignedInAccountFromIntent(data)
                task.addOnSuccessListener {
                    val credential = GoogleAccountCredential.usingOAuth2(
                        this,
                        Collections.singleton(DriveScopes.DRIVE_FILE)
                    )
                    credential.selectedAccount = it.account
                    val googleDriveService = Drive.Builder(
                        AndroidHttp.newCompatibleTransport(), GsonFactory(),
                        credential
                    ).setApplicationName(getString(R.string.app_name)).build()
                    mDriveServiceHelper = DriveServiceHelper(googleDriveService)
                    if (isRestore) {
                        if (null != lastUploadFileId) {
                            val downloadTask = mDriveServiceHelper?.readFile(lastUploadFileId)
                            downloadTask?.addOnCompleteListener {
                                println("Name==>${downloadTask.result?.first}")
                                println("Content==>${downloadTask.result?.second}")
                                Toast.makeText(this@MainActivity, "Backup download successfully", Toast.LENGTH_LONG).show()
                            }
                        }
                    } else {
                        val uploadTask = mDriveServiceHelper?.uploadFile(BACKUP_FILE, generateFile())
                        uploadTask?.addOnCompleteListener {
                            lastUploadFileId = uploadTask.result
                            println("lastUploadFileId==>$lastUploadFileId")
                            Toast.makeText(this@MainActivity, "Backup upload successfully", Toast.LENGTH_LONG).show()
                        }
                    }
                }
            }
        }
        private fun generateFile(): File {
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).mkdir()
            val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), BACKUP_FILE)
            if (!file.exists())
                file.createNewFile()
            val data = StringBuilder()
            for (i in 0..50) {
                data.append("$i. First string is here to be written. First string is here to be written.")
            }
            val fileOutputStream = FileOutputStream(file, true)
            fileOutputStream.write(data.toString().toByteArray())
            return file
        }
        override fun onDestroy() {
            super.onDestroy()
            if (null != mGoogleApiClient)
                mGoogleApiClient!!.signOut()
        }
    }
    


    Conclusion

    Using the above Google Drive Auto-sync example, we learned how to easily backup files from an Android device to Google Drive (Cloud backup) and also retrieve anytime. It also saves the memory on a mobile device as well as on Laptop, Desktop. You can get the source of this Android app tutorial from Github.

    Moreover, if you are looking to create an android app and wish to add this functionality within the app, you can get in touch with us through below contact us form. One of our sales representatives will get back to you shortly. The consultation is absolutely free of cost.

    You may also like,

    This page was last edited on December 28th, 2020, at 7:27.

Author Bio

Amit Patolia

Amit Patolia

Designation: Android Team Lead

Amit Patolia is an Android Team Lead at Space-O Technologies. He has over 7 years of experience in Android app development. He has guided to develop over 100 Android apps with unique features and functionalities. He also has expertise in Kotlin-based apps.

 
 

Have an App Idea?

Get your free consultation now

Leave a Reply

Your email address will not be published. Required fields are marked *