Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google drive to back up and restore database and shared preferences of Android application

I need to create a backup of my application which would include creating a backup of 2 databases and also the shared preferences using Google drive API. I was able to get the authentication done for the app and also create a new folder in Drive using the following code:

public class MainActivity2 extends BaseDemoActivity {

DriveId folderId;

@Override
public void onConnected(Bundle connectionHint) {
    super.onConnected(connectionHint);
    MetadataChangeSet changeSet = new MetadataChangeSet.Builder().setTitle("New folder").build();
    Drive.DriveApi.getRootFolder(getGoogleApiClient())
    .createFolder(getGoogleApiClient(), changeSet)
    .setResultCallback(folderCreatedCallback);
}

ResultCallback<DriveFolderResult> folderCreatedCallback = new ResultCallback<DriveFolderResult>() {
    @Override
    public void onResult(DriveFolderResult result) {
        if (!result.getStatus().isSuccess()) {
            showMessage("Error while trying to create the folder");
            return;
        }
        folderId = result.getDriveFolder().getDriveId();
        showMessage("Created a folder: " + result.getDriveFolder().getDriveId());
    }
};
}

I insert the file using

fileUri = Uri.fromFile(new java.io.File(Environment.getDataDirectory().getPath()
                        + "/data/com.example.myapp/databases/mydb.db"));

                java.io.File fileContent = new java.io.File(fileUri.getPath());

                FileContent mediaContent = new FileContent(getMimeType("db"), fileContent);
                File body = new com.google.api.services.drive.model.File();
                body.setTitle(fileContent.getName());
                body.setMimeType(getMimeType("db"));

                File file = service.files().insert(body, mediaContent).execute();

This works fine.

I restore using

AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            try {

                fileId="0B7Gol85MIbTJLTRxX1hZdDJjaEE";
                credential.setSelectedAccountName("the same drive account");
                service = getDriveService(credential);
                if (fileId != null) {
                    File file = service.files().get(fileId).execute();
                    downloadFile(service, file);
                }
                else return null;
            } catch (Throwable tr) {

            }
            return fileId;
        }

private void downloadFile(Drive service, File file) {
    InputStream mInput=null;
    FileOutputStream mOutput=null;
    if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
        try {
            HttpResponse resp = service.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl())).execute();

            mInput = resp.getContent();
            String outFileName = "file://"+Environment.getDataDirectory().getPath() + "/data/com.example.myapp/databases/InvoiceDataBase.db";
            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");
    }
}

When I backup again after a restore, I get

" /data/data/com.example.myapp/databases/mydb: open failed: ENOENT (No such file or directory)"

Now I need to upload my ".db" file in this folder and also upload shared preferences as an XML file. So my questions are:

  1. How do I upload my application database to this folder? solved.
  2. How do i RESTORE the database file back to the application?
  3. Can the user have full access to the files when he logs into his Google Drive account? Is there any other way to backup and restore ? I cannot use "Android Backup services" as that cannot be a forced backup.

TIA.

like image 941
sb_269 Avatar asked Feb 24 '14 10:02

sb_269


People also ask

How do I backup and restore data and apps on Android?

To start the process, go to Settings > System > Advanced > Backup. In here you'll see the option to Back up to Google Drive. Switch this on via the toggle button, then tap the Back up now button. The process will take a few minutes, depending on how much data there is to backup.

How do I restore my Android apps from Google backup?

Sign in to your Google Account, and agree to Android's terms of service. You'll receive a list of items that you can restore, like your apps, call history, device settings, contacts, and calendar. Since you did a full factory reset, choose everything, and hit restore to begin restoring your data.

Does Google backup application data?

Android preserves app data by uploading it to the user's Google Drive—where it's protected by the user's Google account credentials. The backup is end-to-end encrypted on devices running Android 9 or higher using the device's pin, pattern, or password. The amount of data is limited to 25MB per user of your app.

Can I restore apps and settings from Google backup later?

You can back up content, data and settings from your phone to your Google Account. You can restore your backed up information to the original phone or to some other Android phones. You can't use back up when you set up a personal device with a work profile or for work only, or when you set up a company-owned device.


1 Answers

The answer applies to both your SQLite dbase file and to your Shared Prefs.

First, turn anything you want to save into byte[] buffer. Here is an example for SQLite dbase:

  byte[] getDBBytes() {
   Context ctx = getApplicationContext();
    byte[] out = null;
    try {
      File from = ctx.getDatabasePath(ctx.getString(R.string.app_name));
      if (from.exists()) 
        out = strm2Bytes(new FileInputStream(from));
    } catch (Exception e) {}
    return out;
  }

(strm2Bytes() is a primitive that copies file to byte[] buffer).

Then use the DEMO ('Create a file in a folder', 'Edit contents') to put the data in a Drive file. Keep these two processes separate, since you'll be only updating contents if the file exists.

To get it back, start with 'Retrieve contents' just replace the BufferBuilder, StringBuilder with your own InputStream reader that produces the data you place back into your SQLite file. Something similar to :

  public static void setDB(InputStream is) {
    Context ctx = getApplicationContext();
    try {
      File to = ctx.getDatabasePath(ctx.getString(R.string.app_name));
      if (to.exists()) 
        to.delete(); 
      strm2File(is, to);
    } catch (Exception e) {}
  }

(again, strm2FIle() is a primitive that copies stream into a file)

Sorry, I'm giving you only high level ideas, I tried to pull functional snippets from my code, but it is so tangled that I would have to copy half of my stuff here.

like image 172
seanpj Avatar answered Sep 29 '22 17:09

seanpj