Backup/Restore a Realm database on Google Drive with Drive API (2/3)

Last week we’ve seen how to backup and restore a local instance of a Realm Database. Now let’s try to do more using the same code base, like upload our database to Google Drive.

There’re 2 ways to integrate your app with Google Drive on Android:

REST API allows you to do way more than Android one and it’s also well documented. I’ve also noticed a few bugs with the latter, like a sync delay while receiving metadata. On another side, Android API is integrated with Google Play Services and offers better performance. It also handles some aspects you had to implement manually with REST API like network errors.

Because we’re going to upload/download just a single file we’ll use Android API.

I’m not explaining every step of adding Drive API in your app, all is widely described on Android Developers website.

If you’re lazy, here’s an example GoogleDrive class we used for Glucosio.

After you added Drive API to your app, it’s time to write the actual class that will save a copy of our realm database on Drive and eventually download it again.

First, let’s write some useful method we need to open the folder picker and allow the user to select where to save the exported database.

private void openFolderPicker() {
try {
if (mGoogleApiClient!=null && mGoogleApiClient.isConnected()){
if (intentPicker==null)
intentPicker = buildIntent();

// Start the intent to choose a folder
startIntentSenderForResult(
intentPicker, REQUEST_CODE_PICKER, null, 0, 0, 0);
}
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Unable to send intent", e);
showErrorDialog();
}
}
private IntentSender buildIntent(){
return Drive.DriveApi
.newOpenFileActivityBuilder()
.setMimeType(new String[]{DriveFolder.MIME_TYPE})
.build(mGoogleApiClient);
}

We do the same for the file picker that will allow the user to select the database to import back in the app.

private void openFilePicker() {
IntentSender intentSender = Drive.DriveApi
.newOpenFileActivityBuilder()
        // these mimetypes enable these folders/files
// types to be selected
// In this case we only need to open plain text
                .setMimeType(new String[] { DriveFolder.MIME_TYPE, "text/plain"})
.build(mGoogleApiClient);
        try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_SELECT, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Unable to send intent", e);
showErrorDialog();
}
}

The result of the two methods will be handled in activity’s onActivityResult() (we’ll get back on this later).

The method to upload the database on Drive will take the folder chosen by the user, open it and create a new file in it. Later, we’ll upload its content, converting our realm database to a byte array.

Note that we used realm.getPath() to get our original Realm database, as I previously written in the precedent article.

We now make a method to do the inverse process: get the file chosen by the picker, download its content and converting it to a realm file.

Yes, we’re using realm.getPath() again ;)

Dulcis in fundo, we need to write onActivityResult() methods that will call the methods we previously written when a picker is closed.

@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_PICKER:
intentPicker = null;

if (resultCode == RESULT_OK) {
//Get the folder drive id
DriveId mFolderDriveId = (DriveId) data.getParcelableExtra(
OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);

uploadToDrive(mFolderDriveId);
}
break;

case REQUEST_CODE_SELECT:
if (resultCode == RESULT_OK) {
// get the selected item's ID
DriveId driveId = (DriveId) data.getParcelableExtra(
OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);

DriveFile file = driveId.asDriveFile();
downloadFromDrive(file);

} else {
showErrorDialog();
}
finish();
break;

}
}

Done! As usual, here’s the final class we wrote for Glucosio.

Happy coding :)


Do you want to build useful things that could have a big impact on people’s lives? Join us at Glucosio.