I have tried many example and did not find any good solution.
I want to store the data of my app to store in sqlite database then sync it with the google drive account o
My answer assumes that you have a keystore file to sign your app with. If you don't, this link shows you how.
The next thing you need to do is to download the Android and Google play Services SDKs and get an Android certificate, as described here
Now your app should be able to access the Google Drive APIs.
In your activity, create these variables
/**
* Handle access to Drive resources/files.
*/
DriveResourceClient mDriveResourceClient;
/**
* Base folder. This is where the backup will be created
*/
DriveFolder baseFolder;
/**
* Request code for google sign-in, to be used for result of Drive sign-in
* Can be any suitable value
*/
protected static final int REQUEST_CODE_SIGN_IN = 0;
/**
* String variables to hold file names, file paths etc.
*/
static final String BACK_UP = ;
static final String dbPath = ;
static final String DATABASE_NAME = ;
/*
* This text view is used to show the output from various operations
*/
private TextView tvDriveResult;
When the user starts the backup process call the function singIn()
/**
* Starts the sign-in process and initializes the Drive client.
*/
private void singIn() {
Set requiredScopes = new HashSet<>(2);
requiredScopes.add(Drive.SCOPE_FILE);
GoogleSignInAccount signInAccount = GoogleSignIn.getLastSignedInAccount(this);
if (signInAccount != null && signInAccount.getGrantedScopes().containsAll(requiredScopes)) {
initializeDriveClient(signInAccount);
} else {
GoogleSignInOptions signInOptions =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(Drive.SCOPE_FILE)
.build();
GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(this, signInOptions);
startActivityForResult(googleSignInClient.getSignInIntent(), REQUEST_CODE_SIGN_IN);
}
}
The singIn()
function will handle a user sign - in by starting Google Sign in Client. You will need to handle the result of this client. Use the following code.
/**
* Handles resolution callbacks.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_SIGN_IN:
if (resultCode != RESULT_OK) {
/* Sign-in may fail or be cancelled by the user. For this sample, sign-in is
* required and is fatal. For apps where sign-in is optional, handle appropriately
*/
Log.e(TAG, "Sign-in failed.");
return;
}
Task getAccountTask =
GoogleSignIn.getSignedInAccountFromIntent(data);
if (getAccountTask.isSuccessful()) {
initializeDriveClient(getAccountTask.getResult());
} else {
Log.e(TAG, "Sign-in failed.");
tvDriveResult.append("Sign-in failed\n");
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
After sign-in has been successfully completed, the drive client is initialised above by calling the initializeDriveClient(GoogleSignInAccount signInAccount)
function.
/**
* Continues the sign-in process, initializing the Drive clients with the current
* user's account.
*/
private void initializeDriveClient(GoogleSignInAccount signInAccount) {
mDriveClient = Drive.getDriveClient(getApplicationContext(), signInAccount);
mDriveResourceClient = Drive.getDriveResourceClient(getApplicationContext(), signInAccount);
onDriveClientReady();
}
After the drive client is set up, onDriveClientReady()
is called. This function proceeds to create / restore your back-up. The functionality here is very simple a. Get the base folder of the user's Google Drive account. b. Check if a back-up file exists. c. If yes, copy that backup to the local database file (over write complete file). d. If no, copy the local database file to the user's Google Drive base folder. You can add some finesse to this logic if you wish. My code is to help you understand the process.
/**
* Called after the user has signed in and the Drive client has been initialized.
*/
private void onDriveClientReady(){
/* Initialise the root folder. */
/* Since the tasks are executed in a separate execution threads, the remaining tasks are called from within each other */
getRootFolder();
}
The getRootFolder()
function proceeds as follows
private void getRootFolder() {
/* Get the app folder */
Task appFolderTask = mDriveResourceClient.getRootFolder();
appFolderTask
.addOnSuccessListener(this, new OnSuccessListener() {
@Override
public void onSuccess(DriveFolder driveFolder) {
tvDriveResult.append("Root folder found\n");
baseFolder = driveFolder;
/* Base folder is found, now check if backup file exists */
checkForBackUp();
/* Use this to delete files. Remember to comment out the line able it */
/* listFilesInBaseFolder(); */
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
tvDriveResult.append("Root folder not found, error: " + e.toString() + "\n");
}
});
}
There is also a function in here called listFilesInBaseFolder()
to delete (permanently delete not simply trash) all files you created. It has been commented out in. Use it in case you want to delete files you created, use with caution. As far as I can tell it works only on files that were created by your application.
Check for backup.
private void checkForBackUp() {
/* Build a query */
Query query = new Query.Builder()
.addFilter(Filters.eq(SearchableField.TITLE, BACK_UP))
.build();
/* Query contents of app folder */
Task queryTask = mDriveResourceClient.queryChildren(baseFolder, query);
/* Check for result of query */
queryTask
.addOnSuccessListener(this, new OnSuccessListener() {
@Override
public void onSuccess(MetadataBuffer metadataBuffer) {
/* if count is 0, the file doesn't exist */
if (metadataBuffer.getCount() == 0){
tvDriveResult.append("File " + BACK_UP + " not found\n");
/* Make file backup */
backUpDatabase();
} else {
tvDriveResult.append(metadataBuffer.getCount() + " Instances of file " + BACK_UP + " found\n");
Metadata metadata = metadataBuffer.get(0);
restoreBackUp(metadata.getDriveId().asDriveFile());
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
tvDriveResult.append("Could not search for file, error: " + e.toString() + "\n");
}
});
}
restoreBackUp(DriveFile driveFile)
will over write the local database file with the file found on Goole Drive.
private void restoreBackUp(DriveFile driveFile) {
tvDriveResult.append("Restoring from backup\n");
/* Get the path of the local backup */
File dbFileOld = new File(dbPath + DATABASE_NAME);
/* Check of dbFileExists on device, delete if it does because it needs to be completely over written */
if (dbFileOld.exists()){
dbFileOld.delete();
}
File dbFileNew = new File(dbPath + DATABASE_NAME);
/* File input stream from database to read from */
final FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(dbFileNew);
} catch (FileNotFoundException e) {
tvDriveResult.append("Could not get input stream from local file\n");
return;
}
/* Task to open file */
Task openFileTask =
mDriveResourceClient.openFile(driveFile, DriveFile.MODE_READ_ONLY);
/* Continue with task */
openFileTask.continueWithTask(new Continuation>(){
@Override
public Task then(@NonNull Task task) throws Exception {
DriveContents backupContents = task.getResult();
InputStream inputStream = backupContents.getInputStream();
tvDriveResult.append("Attempting to restore from database\n");
byte[] buffer = new byte[4096];
int c;
while ((c = inputStream.read(buffer, 0, buffer.length)) > 0){
fileOutputStream.write(buffer, 0, c);
}
fileOutputStream.flush();
fileOutputStream.close();
fileOutputStream.flush();
fileOutputStream.close();
tvDriveResult.append("Database restored\n");
/* Return statement needed to avoid task failure */
Task discardTask = mDriveResourceClient.discardContents(backupContents);
return discardTask;
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
tvDriveResult.append("Could not read file contents\n");
}
});
}
And lastly, backUpDatabase()
creates a backup of your local database.
private void backUpDatabase() {
tvDriveResult.append("Creating Drive back-up");
/* get the path of the local backup */
File dbFile = new File(dbPath + DATABASE_NAME);
/* Check of dbFileExists on device */
if (! dbFile.exists()){
tvDriveResult.append("Local database not found?!\n");
return;
}
/* File input stream from database to read from */
final FileInputStream fileInputStream;
try {
fileInputStream = new FileInputStream(dbFile);
} catch (FileNotFoundException e) {
tvDriveResult.append("Could not get input stream from local file\n");
return;
}
/* Task to make file */
final Task createContentsTask = mDriveResourceClient.createContents();
tvDriveResult.append("Creating a back-up of the Database File\n");
Tasks.whenAll(createContentsTask).continueWithTask(new Continuation>() {
@Override
public Task then(@NonNull Task task) throws Exception {
/* Retrieved the drive contents returned by the Task */
DriveContents contents = createContentsTask.getResult();
/* Output stream where data will be written */
OutputStream outputStream = contents.getOutputStream();
/* File output stream */
tvDriveResult.append("Attempting to write\n");
byte[] buffer = new byte[4096];
int c;
while ((c = fileInputStream.read(buffer, 0, buffer.length)) > 0){
outputStream.write(buffer, 0, c);
}
outputStream.flush();
outputStream.close();
fileInputStream.close();
tvDriveResult.append("Database written\n");
/* Save the file, using MetadataChangeSet */
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(BACK_UP)
.setMimeType("application/x-sqlite3")
.setStarred(false)
.build();
return mDriveResourceClient.createFile(baseFolder, changeSet, contents);
}
})
/* Task successful */
.addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(DriveFile driveFile) {
tvDriveResult.append("Back up file created\n");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
tvDriveResult.append("Could not create back up file\n");
}
});
}
And that is it! This should get you started with basic operations. I recommend going through Google's Developer Guide for a deeper dive.