2015-04-24 3 views
7

Мне удалось создать резервную копию моей базы данных на SD-карте и восстановить ее там, но понял, что целью моей резервной копии является обеспечение безопасности данных и в этом если само физическое устройство повреждено, потеряно или самопроизвольно сгорело, так что резервная копия на SD-карте. Таким образом, наличие резервной копии в том же месте, что и оригинал в этом случае, совершенно откровенно поражает цель резервного копирования.Использование Google Диска для резервного копирования и восстановления базы данных SQLite

Так что я думал об использовании Google Диска в качестве более безопасного места для хранения файла db, и это бесплатно. Я заглянул в демо-версию Google quickstart, в которой я работал нормально. Но я до сих пор не знаю, как это сделать для моего дела.

Я нашел код, с которым нужно возиться, но он по-прежнему использует некоторые устаревшие методы, и до сих пор мне удалось запустить его при отсутствии устаревшей области, но он только создает пустой двоичный файл на моем Google Диске, поэтому я думаю, что устаревшая область - это место, где она фактически загружает содержимое резервной копии БД. Если бы кто-нибудь мог помочь, это было бы очень полезно.

Я оставлю это внизу, если кто-нибудь сможет его использовать, чтобы лучше объяснить мне вещи. Я также отмечал устаревший метод ниже, он близок к концу.

public class ExpectoPatronum extends Activity implements ConnectionCallbacks, OnConnectionFailedListener { 

private static final String TAG = "MainActivity"; 
private GoogleApiClient api; 
private boolean mResolvingError = false; 
private DriveFile mfile; 
private static final int DIALOG_ERROR_CODE =100; 
private static final String DATABASE_NAME = "demodb"; 
private static final String GOOGLE_DRIVE_FILE_NAME = "sqlite_db_backup"; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // Create the Drive API instance 
    api = new GoogleApiClient.Builder(this).addApi(Drive.API).addScope(Drive.SCOPE_FILE). 
      addConnectionCallbacks(this).addOnConnectionFailedListener(this).build(); 
} 

@Override 
public void onStart() { 
    super.onStart(); 
    if(!mResolvingError) { 
     api.connect(); // Connect the client to Google Drive 
    } 
} 

@Override 
public void onStop() { 
    super.onStop(); 
    api.disconnect(); // Disconnect the client from Google Drive 
} 

@Override 
public void onConnectionFailed(ConnectionResult result) { 
    Log.v(TAG, "Connection failed"); 
    if(mResolvingError) { // If already in resolution state, just return. 
     return; 
    } else if(result.hasResolution()) { // Error can be resolved by starting an intent with user interaction 
     mResolvingError = true; 
     try { 
      result.startResolutionForResult(this, DIALOG_ERROR_CODE); 
     } catch (SendIntentException e) { 
      e.printStackTrace(); 
     } 
    } else { // Error cannot be resolved. Display Error Dialog stating the reason if possible. 
     ErrorDialogFragment fragment = new ErrorDialogFragment(); 
     Bundle args = new Bundle(); 
     args.putInt("error", result.getErrorCode()); 
     fragment.setArguments(args); 
     fragment.show(getFragmentManager(), "errordialog"); 
    } 
} 

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if(requestCode == DIALOG_ERROR_CODE) { 
     mResolvingError = false; 
     if(resultCode == RESULT_OK) { // Error was resolved, now connect to the client if not done so. 
      if(!api.isConnecting() && !api.isConnected()) { 
       api.connect(); 
      } 
     } 
    } 
} 

@Override 
public void onConnected(Bundle connectionHint) { 
    Log.v(TAG, "Connected successfully"); 

    /* Connection to Google Drive established. Now request for Contents instance, which can be used to provide file contents. 
     The callback is registered for the same. */ 
    Drive.DriveApi.newDriveContents(api).setResultCallback(contentsCallback); 
} 

final private ResultCallback<DriveApi.DriveContentsResult> contentsCallback = new ResultCallback<DriveApi.DriveContentsResult>() { 

    @Override 
    public void onResult(DriveApi.DriveContentsResult result) { 
     if (!result.getStatus().isSuccess()) { 
      Log.v(TAG, "Error while trying to create new file contents"); 
      return; 
     } 

     String mimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType("db"); 
     MetadataChangeSet changeSet = new MetadataChangeSet.Builder() 
       .setTitle(GOOGLE_DRIVE_FILE_NAME) // Google Drive File name 
       .setMimeType(mimeType) 
       .setStarred(true).build(); 
     // create a file on root folder 
     Drive.DriveApi.getRootFolder(api) 
       .createFile(api, changeSet, result.getDriveContents()) 
       .setResultCallback(fileCallback); 
    } 

}; 

final private ResultCallback<DriveFileResult> fileCallback = new ResultCallback<DriveFileResult>() { 

    @Override 
    public void onResult(DriveFileResult result) { 
     if (!result.getStatus().isSuccess()) { 
      Log.v(TAG, "Error while trying to create the file"); 
      return; 
     } 
     mfile = result.getDriveFile(); 
     mfile.open(api, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(contentsOpenedCallback); 
    } 
}; 

final private ResultCallback<DriveApi.DriveContentsResult> contentsOpenedCallback = new ResultCallback<DriveApi.DriveContentsResult>() { 

    @Override 
    public void onResult(DriveApi.DriveContentsResult result) { 

     if (!result.getStatus().isSuccess()) { 
      Log.v(TAG, "Error opening file"); 
      return; 
     } 

     try { 
      FileInputStream is = new FileInputStream(getDbPath()); 
      BufferedInputStream in = new BufferedInputStream(is); 
      byte[] buffer = new byte[8 * 1024]; 
      DriveContents content = result.getDriveContents(); 
      BufferedOutputStream out = new BufferedOutputStream(content.getOutputStream()); 
      int n = 0; 
      while((n = in.read(buffer)) > 0) { 
       out.write(buffer, 0, n); 
      } 

      in.close(); 
commitAndCloseContents is DEPRECATED -->/**mfile.commitAndCloseContents(api, content).setResultCallback(new ResultCallback<Status>() { 
       @Override 
       public void onResult(Status result) { 
        // Handle the response status 
       } 
      });**/ 
     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

}; 

private File getDbPath() { 
    return this.getDatabasePath(DATABASE_NAME); 
} 

@Override 
public void onConnectionSuspended(int cause) { 
    // TODO Auto-generated method stub 
    Log.v(TAG, "Connection suspended"); 

} 

public void onDialogDismissed() { 
    mResolvingError = false; 
} 

public static class ErrorDialogFragment extends DialogFragment { 
    public ErrorDialogFragment() {} 

    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     int errorCode = this.getArguments().getInt("error"); 
     return GooglePlayServicesUtil.getErrorDialog(errorCode, this.getActivity(), DIALOG_ERROR_CODE); 
    } 

    public void onDismiss(DialogInterface dialog) { 
     ((ExpectoPatronum) getActivity()).onDialogDismissed(); 
    } 
} 
} 
+0

Убедитесь, что вы понимаете разницу между Drive REST API и GDAA. Для вашего случая использования gdaa - лучший способ пойти, поэтому вы должны игнорировать любой быстрый старт, который не является gdaa. В стороне, размещение большого количества кода в вопрос не очень полезно. – pinoyyid

+0

См. Следующее: http://stackoverflow.com/questions/33602812/backup-restore-sqllite-database-to-google-drive-app-folder/39044477#39044477 – Jose19589

ответ

4

Оба API, используемых для доступа к приложению Google Диск с двоичным содержимым. Так что вам нужно всего лишь загрузить файл двоичного DB, дать ему правильный тип MIME и NAME (название).
Выбор API зависит от вас, GDAA ведет себя как «локальный» объект с загрузкой/загрузкой, обработанной сервисами Google Play, REST Api более низкоуровневый, что дает вам больше контроля, но вы должны заботиться о сетевых проблемах (включение/выключение Wi-Fi и т. д.), т. е. вам обычно приходится создавать службу синхронизации для этого. С GDAA это делается для вас GooPlaySvcs. Но я отвлекся.
Я могу указать на это GitHub demo, довольно недавно (GooPlaySvcs 7.00. +), Я использую для тестирования различных проблем REST/GDAA. MainActivity немного осложнен тем, что он позволяет переключаться между различными учетными записями Google, но если вы пройдете через these hurdles, вы можете использовать обертку REST или GDAA CRUD.

Посмотрите на this line. Буфер байта [] содержит двоичные данные JPEG, и он имеет тип mime «image/jpeg» (и временное имя). Единственное, что вы должны сделать, если это загрузить файл базы данных в байт [] буфера, используя конструкцию так:

private static final int BUF_SZ = 4096; 

    static byte[] file2Bytes(File file) { 
    if (file != null) try { 
     return is2Bytes(new FileInputStream(file)); 
    } catch (Exception ignore) {} 
    return null; 
    } 

    static byte[] is2Bytes(InputStream is) { 
    byte[] buf = null; 
    BufferedInputStream bufIS = null; 
    if (is != null) try { 
     ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); 
     bufIS = new BufferedInputStream(is); 
     buf = new byte[BUF_SZ]; 
     int cnt; 
     while ((cnt = bufIS.read(buf)) >= 0) { 
     byteBuffer.write(buf, 0, cnt); 
     } 
     buf = byteBuffer.size() > 0 ? byteBuffer.toByteArray() : null; 
    } catch (Exception e) {le(e);} 
    finally { 
     try { 
     if (bufIS != null) bufIS.close(); 
     } catch (Exception e) {le(e);} 
    } 
    return buf; 
    } 

Я не помню тип MIME для БД SQLite, но я уверен, что это может быть сделано, так как я делал именно это однажды (сейчас код, к сожалению, отсутствует). И я помню, что мог реально получить доступ и изменить SQLite DB в облаке, используя какое-то веб-приложение.

Good Luck

UPDATE:
После того как я написал выше тирады я смотрел на демо вы говорите. Если у вас есть работа, самый простой способ - это правильно подключить ваш файл DB here, установить правильный MIME, и вам хорошо идти. Возьмите выбор.
И для решения вашей «устаревшей» проблемы. GDAA по-прежнему разрабатывается, и быстрый старт старше года. Это мир, в котором мы живем :-)

+0

Спасибо за ссылку и пояснения, они очищены несколько моих вопросов. Решил пойти с вашим предложением, просто работая над удалением части «снимок» и заменяя ее чем-то другим. Я пробовал работать над другим, но до сих пор все еще получаю пустой двоичный файл. Я просто доберусь до этого в другой раз. Сейчас я просто буду работать над восстановлением db из файла диска, у вас не было бы никаких указателей на это? – Cytus

+0

Ядро, на котором вы должны сосредоточиться, находится здесь: https://github.com/seanpjanson/GDAADemo/blob/master/src/main/java/com/andyscan/gdaademo/GDAA.java#L143. Измените метод так, чтобы он соответствовал вашей среде и выполнил проверку «buf» (обратите внимание, что это buf.length). В конце вы должны увидеть файл в GooDrive, и длина должна быть одинаковой. Попробуйте загрузить его на свой рабочий стол, сравните его с оригиналом с вашего устройства Android. GDAA не заботится о том, какой файл вы отправляете, он просто перемещает байты вверх, создает объект и прикрепляет метаданные (название, mime, описание, ...) – seanpj

+0

@seanpj Ссылка кажется сломанной !! Не могли бы вы обновить! – shadygoneinsane

Смежные вопросы