Dysk Google do tworzenia kopii zapasowych i przywracania bazy danych oraz wspólnych preferencji aplikacji na Androida

Muszę utworzyć kopię zapasową mojej aplikacji, która obejmowałaby utworzenie kopii zapasowej 2 baz danych, a także współdzielonych preferencji za pomocą Google drive API. Udało mi się wykonać uwierzytelnianie dla aplikacji, a także utworzyć nowy folder na dysku za pomocą następującego kodu:

public class MainActivity2 extends BaseDemoActivity {

DriveId folderId;

@Override
public void onConnected(Bundle connectionHint) {
    super.onConnected(connectionHint);
    MetadataChangeSet changeSet = new MetadataChangeSet.Builder().setTitle("New folder").build();
    Drive.DriveApi.getRootFolder(getGoogleApiClient())
    .createFolder(getGoogleApiClient(), changeSet)
    .setResultCallback(folderCreatedCallback);
}

ResultCallback<DriveFolderResult> folderCreatedCallback = new ResultCallback<DriveFolderResult>() {
    @Override
    public void onResult(DriveFolderResult result) {
        if (!result.getStatus().isSuccess()) {
            showMessage("Error while trying to create the folder");
            return;
        }
        folderId = result.getDriveFolder().getDriveId();
        showMessage("Created a folder: " + result.getDriveFolder().getDriveId());
    }
};
}

Wstawiam plik używając

fileUri = Uri.fromFile(new java.io.File(Environment.getDataDirectory().getPath()
                        + "/data/com.example.myapp/databases/mydb.db"));

                java.io.File fileContent = new java.io.File(fileUri.getPath());

                FileContent mediaContent = new FileContent(getMimeType("db"), fileContent);
                File body = new com.google.api.services.drive.model.File();
                body.setTitle(fileContent.getName());
                body.setMimeType(getMimeType("db"));

                File file = service.files().insert(body, mediaContent).execute();
To działa dobrze.

Przywracam używając

AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            try {

                fileId="0B7Gol85MIbTJLTRxX1hZdDJjaEE";
                credential.setSelectedAccountName("the same drive account");
                service = getDriveService(credential);
                if (fileId != null) {
                    File file = service.files().get(fileId).execute();
                    downloadFile(service, file);
                }
                else return null;
            } catch (Throwable tr) {

            }
            return fileId;
        }

private void downloadFile(Drive service, File file) {
    InputStream mInput=null;
    FileOutputStream mOutput=null;
    if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
        try {
            HttpResponse resp = service.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl())).execute();

            mInput = resp.getContent();
            String outFileName = "file://"+Environment.getDataDirectory().getPath() + "/data/com.example.myapp/databases/InvoiceDataBase.db";
            Log.e("com.example.myapp", "getDatabasePath="+ getDatabasePath("")); 
            Log.e("com.example.myapp", "outFileName="+outFileName);
//              String outFileName = "../databases/" + "Quickpay.db";
            mOutput = new FileOutputStream(outFileName);
            byte[] mBuffer = new byte[1024];
            int mLength;
            while ((mLength = mInput.read(mBuffer)) > 0) {
                mOutput.write(mBuffer, 0, mLength);
            }
            mOutput.flush();
        } catch (IOException e) {
            // An error occurred.
            e.printStackTrace();
            // return null;
        }
        finally {
            try {
                    //Close the streams
                    if(mOutput != null){
                        mOutput.close();
                    }
                    if(mInput != null){
                        mInput.close();
                    }
            } catch (IOException e) {
                    Log.e("com.example.myapp", "failed to close databases");
            }
    }
    } else {
        // The file doesn't have any content stored on Drive.
        // return null;
        Log.e("com.example.myapp", "No content on Drive");
    }
}

Kiedy wykonuję kopię zapasową ponownie po przywróceniu, dostaję

" / data/data / com.przykład.myapp / databases/ mydb: open failed: ENOENT (brak takiego pliku lub katalogu)"

Teraz muszę wgrać mój".db " pliku w tym folderze, a także przesłać wspólne Preferencje jako plik XML. Więc moje pytania to:

  1. jak załadować bazę aplikacji do tego folderu? rozwiązany.
  2. jak przywrócić plik bazy danych z powrotem do aplikacji?
  3. czy użytkownik może mieć pełny dostęp do plików po zalogowaniu się na swój dysk Google konto? Czy istnieje inny sposób tworzenia kopii zapasowych i przywracania ? Nie mogę korzystać z "usług kopii zapasowych Androida", ponieważ nie może to być wymuszona kopia zapasowa.
TIA.
Author: sb_269, 2014-02-24

2 answers

Odpowiedź dotyczy zarówno Twojego pliku SQLITE dbase, jak i Twoich współdzielonych Prefs.

Najpierw Zamień wszystko, co chcesz zapisać w bufor bajtu []. Oto przykład dla SQLite dbase:

  byte[] getDBBytes() {
   Context ctx = getApplicationContext();
    byte[] out = null;
    try {
      File from = ctx.getDatabasePath(ctx.getString(R.string.app_name));
      if (from.exists()) 
        out = strm2Bytes(new FileInputStream(from));
    } catch (Exception e) {}
    return out;
  }

(strm2Bytes () jest prymitywem, który kopiuje plik do bufora bajtowego []).

Następnie użyj DEMO ('Tworzenie pliku w folderze', 'Edytuj zawartość' ), aby umieścić dane w pliku dysku. Zachowaj te dwa procesy oddzielnie, ponieważ będziesz aktualizować zawartość tylko wtedy, gdy plik istnieje.

Aby go odzyskać, zacznij od 'Odzyskaj Zawartość ' po prostu zamień BufferBuilder, StringBuilder na własny czytnik InputStream, który wytwarza dane, które umieścisz z powrotem w pliku SQLITE. Coś podobnego do:

  public static void setDB(InputStream is) {
    Context ctx = getApplicationContext();
    try {
      File to = ctx.getDatabasePath(ctx.getString(R.string.app_name));
      if (to.exists()) 
        to.delete(); 
      strm2File(is, to);
    } catch (Exception e) {}
  }
Strm2FIle() jest prymitywem, który kopiuje strumień do pliku)

Przepraszam, daję Ci tylko pomysły na wysoki poziom, próbowałem wyciągnąć funkcjonalne fragmenty z mojego kodu, ale jest on tak poplątany, że musiałbym skopiować połowę mojego rzeczy tutaj.

 3
Author: seanpj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-25 16:31:59

Okazało się, że jedynym problemem było stworzenie pliku przed dodaniem do niego danych. Wywołałem konstruktor mojego dbhelper przed zapisaniem do pliku db.

Zastosowano następujący kod:

java.io.File dir = myContext.getDatabasePath("myDb.db");
mOutput = new FileOutputStream(outFileName);
        byte[] mBuffer = new byte[1024];
        int mLength;
        while ((mLength = mInput.read(mBuffer)) > 0) {
            mOutput.write(mBuffer, 0, mLength);
        }
        mOutput.flush();

Dzięki za podjęcie wysiłku, aby pomóc chłopakom !

Na pewno przyjrzę się twojemu SQLiteExample @seanpj. Wrócę, jeśli znajdę lepsze rozwiązanie.

 2
Author: sb_269,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-26 03:59:12