Search code examples
javaandroid-studiogoogle-drive-apigoogle-api-java-client

How to restore file from GDrive?


I am making an app which stores its SQLite Database backup on GDrive. I succeeded in signing in and uploading the file in the drive but failed to restore it. Following is the code. I use SQLiteDatabase to store the fileID so that when it is required while updating and restoring, it can be used. I am looking for a method which will make use of FileID to restore. Error occurs at file.getDownloadUrl() and file.getContent().

 class DriveClassHelper 
{
    private final Executor mExecutor = Executors.newSingleThreadExecutor();
    private static Drive mDriveService;

    private String FileID = null;

    private static String filePath = "/data/data/com.example.gdrivebackup/databases/Data.db";


    DriveClassHelper(Drive mDriveService) 
    {
        DriveClassHelper.mDriveService = mDriveService;
    }

    // ---------------------------------- TO BackUp on Drive  -------------------------------------------

    public Task<String> createFile() 
    {
        return Tasks.call(mExecutor, () ->
                {

                    File fileMetaData = new File();
                    fileMetaData.setName("Backup");
                    java.io.File file = new java.io.File(filePath);
                    String mimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType("application/x-sqlite-3");
                    FileContent mediaContent = new FileContent(mimeType, file);
                    File myFile = null;

                    FileID = getFileIDFromDatabase();

                    try {
                        if (FileID != null) {
                            Log.i("CALLED : ", FileID);
                            //mDriveService.files().delete().execute();
                            myFile = mDriveService.files().update(FileID, fileMetaData, mediaContent).execute();
                        } else {
                            myFile = mDriveService.files().create(fileMetaData, mediaContent).execute();
                            MainActivity.demoSQLite.insertData(myFile.getId());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    if (myFile == null) {
                        throw new IOException("Null Result when requesting file creation");
                    }

                    Log.i("ID:", myFile.getId());
                    return myFile.getId();
                }
        );
    }

    // -------------------------------------------------------------------------------------------------

    // ---------------------------------- TO get File ID  -------------------------------------------

    private static String getFileIDFromDatabase() 
    {
        String FileIDFromMethod = null;
        Cursor result = MainActivity.demoSQLite.getData();

        if (result.getCount() == 0) {
            Log.i("CURSOR :", "NO ENTRY");
            return null;
        } else {
            while (result.moveToNext()) {
                FileIDFromMethod = result.getString(0);
            }
            return FileIDFromMethod;
        }
    }

    // -------------------------------------------------------------------------------------------------

    // ---------------------------------- TO Restore  -------------------------------------------


    public static class Restore extends AsyncTask<Void, Void, String>
    {
        @Override
        protected String doInBackground(Void... params) {
            String fileId = null;
            try
            {
                fileId = getFileIDFromDatabase();

                if (fileId != null)
                {
                    File file = mDriveService.files().get(fileId).execute();
                    downloadFile(file);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return fileId;
        }

        private void downloadFile(File file)
        {
            InputStream mInput = null;
            FileOutputStream mOutput = null;


            if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) //Error occurs at file.getDownloadUrl()
            {
                try
                {
                    HttpResponse resp = mDriveService.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl())).execute();

                    mInput = resp.getContent();
                    String outFileName = "file://" + Environment.getDataDirectory().getPath() + filePath;
                    // Log.e("com.example.myapp", "getDatabasePath="+ getDatabasePath(""));
                    //Log.e("com.example.myapp", "outFileName="+outFileName);
//                  String outFileName = "../databases/" + "Quickpay.db";
                    mOutput = new FileOutputStream(outFileName);
                    byte[] mBuffer = new byte[1024];
                    int mLength;
                    while ((mLength = mInput.read(mBuffer)) > 0)
                    {
                        mOutput.write(mBuffer, 0, mLength);
                    }
                    mOutput.flush();
                }
                catch (IOException e)
                {
                    // An error occurred.
                    e.printStackTrace();
                    // return null;
                }
                finally
                {
                    try
                    {
                        //Close the streams
                        if (mOutput != null)
                        {
                            mOutput.close();
                        }
                        if (mInput != null)
                        {
                            mInput.close();
                        }
                    }
                    catch (IOException e)
                    {
                        Log.e("com.example.myapp", "failed to close databases");
                    }
                }
            }
            else
            {
                // The file doesn't have any content stored on Drive.
                // return null;
                Log.e("com.example.myapp", "No content on Drive");
            }
        }
    }
}

The Gradle file is like

implementation 'com.google.android.gms:play-services-auth:16.0.1'
    implementation('com.google.apis:google-api-services-drive:v3-rev136-1.25.0')
            {
                exclude group: 'org.apache.httpcomponents'
            }
    implementation('com.google.api-client:google-api-client-android:1.26.0')
            {
                exclude group: 'org.apache.httpcomponents'
            }
    implementation 'com.google.http-client:google-http-client-gson:1.26.0'

Solution

  • As far as i know Download URL is only avalibale in Google drive api v2 and not in V3.

    Short lived download URL for the file. This field is only populated for files with content stored in Google Drive; it is not populated for Google Docs or shortcut files.

    It was not very stable in my opinion as not all file types would return a download url.

    Using Google Drive v3 you should download the file using a stream.

    String fileId = "0BwwA4oUTeiV1UVNwOHItT0xfa2M";
    OutputStream outputStream = new ByteArrayOutputStream();
    driveService.files().get(fileId)
        .executeMediaAndDownloadTo(outputStream);
    

    This should work with the restore. Let me know if it doesnt and i will have a look its been a while since i have tried restore.