title: Updating an SQLite database using the Google Drive Android API
body: <p>Using the <a href="https://developers.google.com/drive/android/files" rel="nofollow noreferrer">Google Drive API for Android</a> and some answers on Stack Overflow, I have managed to implement Google Sign-In into my app, and backup the SQLite database stored on the user's device to Google Drive.</p>
  
  <p>For reference, here is how I save the database to Google Drive (this is done in a <code>final class</code> called <code>DriveDbHandler</code>):</p>
  
  <pre><code>private static final String LOG_TAG = "DriveDbHandler";
  
  private static final String PACKAGE_NAME = "com.package.example";
  
  private static final String DATABASE_PATH =
          "/data/data/" + PACKAGE_NAME + "/databases/" + DbHelper.DATABASE_NAME;
  
  private static final String FILE_NAME = DbHelper.DATABASE_NAME;
  private static final String MIME_TYPE = "application/x-sqlite-3";
  
  private DriveDbHandler() {
  }
  
  
  public static void tryCreatingDbOnDrive(final GoogleApiClient googleApiClient) {
      // We need to check if the database already exists on Google Drive. If so, we won't create
      // it again.
  
      Query query = new Query.Builder()
              .addFilter(Filters.and(
                      Filters.eq(SearchableField.TITLE, FILE_NAME),
                      Filters.eq(SearchableField.MIME_TYPE, MIME_TYPE)))
              .build();
      DriveFolder appFolder = Drive.DriveApi.getAppFolder(googleApiClient);
  
      appFolder.queryChildren(googleApiClient, query).setResultCallback(
              new ResultCallback&lt;DriveApi.MetadataBufferResult&gt;() {
                  @Override
                  public void onResult(@NonNull DriveApi.MetadataBufferResult metadataBufferResult) {
                      if (!metadataBufferResult.getStatus().isSuccess()) {
                          Log.e(LOG_TAG, "Query for " + FILE_NAME + " unsuccessful!");
                          return;
                      }
  
                      int count = metadataBufferResult.getMetadataBuffer().getCount();
  
                      Log.d(LOG_TAG, "Successfully ran query for " + FILE_NAME + " and found " +
                              count + " results");
  
                      if (count &gt; 1) {
                          Log.e(LOG_TAG, "App folder contains more than one database file! " +
                                  "Found " + count + " matching results.");
                          return;
                      }
  
                      // Create the database on Google Drive if it doesn't exist already
                      if (count == 0) {
                          Log.d(LOG_TAG, "No existing database found on Google Drive");
                          saveToDrive(googleApiClient);
                      }
                  }
              });
  }
  
  private static void saveToDrive(final GoogleApiClient googleApiClient) {
      Log.d(LOG_TAG, "Starting to save to drive...");
  
      // Create content from file
      Drive.DriveApi.newDriveContents(googleApiClient).setResultCallback(
              new ResultCallback&lt;DriveApi.DriveContentsResult&gt;() {
                  @Override
                  public void onResult(@NonNull DriveApi.DriveContentsResult driveContentsResult) {
                      if (!driveContentsResult.getStatus().isSuccess()) {
                          Log.w(LOG_TAG, "Drive contents result not a success! " +
                                  "Not saving data to drive.");
                          return;
                      }
  
                      Log.d(LOG_TAG, "Created drive contents for file");
                      createNewFile(googleApiClient, driveContentsResult.getDriveContents());
                  }
              });
  }
  
  private static void createNewFile(GoogleApiClient googleApiClient, DriveContents driveContents) {
      // Write file to contents (see http://stackoverflow.com/a/33610727/4230345)
      File file = new File(DATABASE_PATH);
      OutputStream outputStream = driveContents.getOutputStream();
      try {
          InputStream inputStream = new FileInputStream(file);
          byte[] buf = new byte[4096];
          int c;
          while ((c = inputStream.read(buf, 0, buf.length)) &gt; 0) {
              outputStream.write(buf, 0, c);
              outputStream.flush();
          }
          outputStream.close();
      } catch (IOException e) {
          e.printStackTrace();
      }
      Log.d(LOG_TAG, "Written file to output stream of drive contents");
  
      // Create metadata
      MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
              .setTitle(FILE_NAME)
              .setMimeType(MIME_TYPE)
              .build();
  
      // Create the file on Google Drive
      DriveFolder folder = Drive.DriveApi.getAppFolder(googleApiClient);
      folder.createFile(googleApiClient, metadataChangeSet, driveContents).setResultCallback(
              new ResultCallback&lt;DriveFolder.DriveFileResult&gt;() {
          @Override
          public void onResult(@NonNull DriveFolder.DriveFileResult driveFileResult) {
              if (!driveFileResult.getStatus().isSuccess()) {
                  Log.w(LOG_TAG, "File did not get created in Google Drive!");
                  return;
              }
  
              Log.i(LOG_TAG, "Successfully created file in Google Drive");
          }
      });
  }
  </code></pre>
  
  <p>So here's my issue:</p>
  
  <p>I can save the database to Google Drive, but <strong>how do I update the Google Drive version with any changes made locally?</strong></p>
  
  <p>For example, I can delete 3 rows from table A and then add 5 rows to table B locally (to the device's SQLite database), but how do I update the Google Drive version with this change?</p>
  
  <p>I have considered deleting the entire Drive file and re-uploading it, but this would result in a different <code>DriveId</code> for that file, to my understanding. </p>
  
  <p>I'm wondering if I would be able to take advantage of the API's modification handling (explained <a href="https://developers.google.com/drive/android/files#lifecycle_of_a_drive_file" rel="nofollow noreferrer">here</a>), where changes are queued for upload if the device has no internet connection.</p>