6

我需要创建我的应用程序的备份,其中包括创建2个数据库的备份以及使用Google驱动器API的共享首选项。我能得到的应用程序进行认证,并使用下面的代码创建驱动器的新文件夹:Google驱动器来备份和恢复Android应用程序的数据库和共享首选项

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()); 
    } 
}; 
} 

我插入使用

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(); 

能正常工作的文件。

我恢复使用

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"); 
    } 
} 

当我以后再备份恢复,我得到

“/data/data/com.example.myapp/databases/mydb:打开失败:ENOENT(没有这样的文件或目录)“

现在我需要上传我的”.db“文件在这个文件夹中,并上传共享首选项作为XML文件。所以我的问题是:

  1. 如何将我的应用程序数据库上传到此文件夹? 解决了。
  2. 如何将数据库文件恢复到应用程序?
  3. 登录到他的Google云端硬盘帐户后,用户是否可以完全访问这些文件?有没有其他的方法来备份和恢复?我无法使用“Android备份服务”,因为这不能成为强制备份。

TIA。

+0

你能帮我吗? – Lunchbox

+0

对不起,你还在寻找这个解决方案?我没有在网上SO –

+0

没问题,是的,我是。我试图使用下拉框来实现相同的目标,但我也很困难 – Lunchbox

回答

1

原来,唯一的问题是在实际添加数据之前创建文件。在写入db文件之前,调用dbhelper的构造函数。

用下面的代码:

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(); 

感谢您抽出宝贵的努力来帮助你们!

我一定会看看你的SQLiteExample @seanpj。如果我发现它是更好的解决方案,我会回来。

+0

)嗨,你能提供完整的文件插入方法吗?像outFileName变量和mInput变量吗? – Lunchbox

+0

整个班级即使你愿意。事情 – Lunchbox

3

答案适用于您的SQLite dbase文件和您的Shared Prefs。

首先,将任何你想保存到byte []缓冲区。下面是SQLite的质数据库的示例:

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(是一个基元副本文件为byte []缓冲液)。

然后使用DEMO'Create a file in a folder','Edit contents')将数据放入Drive文件。保持这两个过程是分开的,因为如果文件存在,只会更新内容。

为了让它恢复正常,请从'Retrieve contents'开始,用您自己的InputStream读取器替换BufferBuilder,StringBuilder,以生成放回SQLite文件的数据。类似的东西来:

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()是一种原始的那份流成一个文件)

对不起,我给你唯一的高层次的想法,我试图把从功能片段我的代码,但它很纠结,我不得​​不复制我的一半在这里的东西。

+0

我能够将数据库添加到驱动器。它备份时具有正确的值。但是当我恢复它时,数据库会在应用程序中创建,但是是空的。 –

+0

问题#3:在Drive中创建db文件的用户可以访问它,只需要小心,可能会有一些延迟问题。同时删除/剔除使用该网站的文件是相当不可靠的(请参阅此问题的讨论https://github.com/googledrive/android-demos/issues/3)。但是,我希望他们很快就会解决它。 – seanpj

+0

db'EMPTY'问题:我在系统中看不到相同的结果。仔细检查复制过程(缓冲区长度...),并确保SQLite dbs在你搞砸时全部关闭。我仍然处于开发过程中,如果我发现类似的问题,我会告诉你。 – seanpj