I successfully created a backup system for my SQLite database that saves to SD card storage. However, I realized this approach has a major flaw. If my phone gets lost, broken, or damaged, the backup stored on the SD card will be gone too. This makes the whole backup strategy pointless since both the original data and backup are on the same device.
I want to use Google Drive for cloud storage instead since it’s secure and free. I looked at Google’s official quickstart guide and got the basic demo working. But I’m stuck on how to adapt it for my database backup needs.
I found some sample code online but it uses old deprecated methods. When I remove the deprecated parts, the code runs but only creates an empty file on Google Drive. I think the deprecated section was responsible for actually uploading the database content.
Here’s my current code attempt:
public class CloudBackupManager extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
private static final String TAG = "CloudBackup";
private GoogleApiClient client;
private boolean isResolvingError = false;
private DriveFile backupFile;
private static final int ERROR_DIALOG_ID = 200;
private static final String DB_NAME = "userdata";
private static final String BACKUP_FILE_NAME = "database_backup";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
client = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
public void onStart() {
super.onStart();
if(!isResolvingError) {
client.connect();
}
}
@Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "Successfully connected to Drive");
Drive.DriveApi.newDriveContents(client).setResultCallback(driveContentsCallback);
}
final private ResultCallback<DriveApi.DriveContentsResult> driveContentsCallback = new ResultCallback<DriveApi.DriveContentsResult>() {
@Override
public void onResult(DriveApi.DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
Log.e(TAG, "Failed to create drive contents");
return;
}
String fileType = MimeTypeMap.getSingleton().getExtensionFromMimeType("db");
MetadataChangeSet metadata = new MetadataChangeSet.Builder()
.setTitle(BACKUP_FILE_NAME)
.setMimeType(fileType)
.setStarred(true)
.build();
Drive.DriveApi.getRootFolder(client)
.createFile(client, metadata, result.getDriveContents())
.setResultCallback(fileCreatedCallback);
}
};
final private ResultCallback<DriveFileResult> fileCreatedCallback = new ResultCallback<DriveFileResult>() {
@Override
public void onResult(DriveFileResult result) {
if (!result.getStatus().isSuccess()) {
Log.e(TAG, "File creation failed");
return;
}
backupFile = result.getDriveFile();
backupFile.open(client, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(fileOpenCallback);
}
};
final private ResultCallback<DriveApi.DriveContentsResult> fileOpenCallback = new ResultCallback<DriveApi.DriveContentsResult>() {
@Override
public void onResult(DriveApi.DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
Log.e(TAG, "Cannot open file for writing");
return;
}
try {
FileInputStream inputStream = new FileInputStream(getDatabaseFile());
BufferedInputStream bufferedInput = new BufferedInputStream(inputStream);
byte[] dataBuffer = new byte[8 * 1024];
DriveContents driveContent = result.getDriveContents();
BufferedOutputStream bufferedOutput = new BufferedOutputStream(driveContent.getOutputStream());
int bytesRead = 0;
while((bytesRead = bufferedInput.read(dataBuffer)) > 0) {
bufferedOutput.write(dataBuffer, 0, bytesRead);
}
bufferedInput.close();
// THIS METHOD IS DEPRECATED - Need modern alternative
/*
backupFile.commitAndCloseContents(client, driveContent).setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
// Handle upload completion
}
});
*/
} catch (Exception e) {
e.printStackTrace();
}
}
};
private File getDatabaseFile() {
return this.getDatabasePath(DB_NAME);
}
@Override
public void onConnectionSuspended(int cause) {
Log.w(TAG, "Drive connection suspended");
}
}
Can someone help me replace the deprecated commitAndCloseContents method with the current approach? I need to actually upload the database file content to Google Drive successfully.