【问题标题】:Backup/Restore SQLlite Database to Google Drive app folder将 SQLite 数据库备份/恢复到 Google Drive 应用文件夹
【发布时间】:2015-11-09 05:01:42
【问题描述】:

我正在尝试将应用程序数据库备份和恢复到谷歌驱动器应用程序文件夹的功能(用户不可见)。我浏览了为 android 提供的基本设置指南 setup guide,可以让用户授权应用程序并到达调用 onConnected 方法的位置。

我面临的问题是,我不确定如何将数据库文件 (.db) 从设备“发送”到 google drive app 文件夹。 Google 已共享 sn-p 用于创建新文件,仅此而已。我确实发现了一个先前提出的问题,与我正在寻找的 Google drive to back up and restore database and shared preferences of Android application 模糊相似,但又不是我想要的。

搜索 google 不会返回任何有用的链接,可能是因为这是相对较新的 api。

更新 1:

分享 onConnected() 代码,

    public void onConnected(Bundle bundle) {
    Toast.makeText(GoogleSignIn.this, "In onConnected activity", Toast.LENGTH_SHORT).show();

    // Testing to see if database is indeed uploaded to google drive app folder
    String db_name = "XXX_DB";
    String currentDBPath = "/data/" + "com.abc.efg" + "/databases/" + db_name;
    saveToDrive(
            Drive.DriveApi.getAppFolder(mGoogleApiClientDrive),
            "XXX_DB.db",
            "application/x-sqlite3",
            new java.io.File(currentDBPath)
    );
}

更新 2:

下面分享的解决方案非常适合将数据库上传到 google drive app 文件夹。对于那些可能面临类似问题的人,请尝试将数据库路径更改为 "/data/data/com.abc.efg/databases/" + db_name 而不是 "/data/com.abc.efg/databases/" + db_name

下一步是能够从 google drive app 文件夹中检索和恢复数据库。如果我能够让它工作,我会更新这个问题。

【问题讨论】:

    标签: android android-sqlite google-drive-android-api


    【解决方案1】:

    假设您有一个 MyDbFile.db 文件的路径,您可以使用如下构造:

     ... 
     saveToDrive(
       Drive.DriveApi.getAppFolder(getGoogleApiClient()),
       "MyDbFile.db", 
       "application/x-sqlite3",
       new java.io.File("\...\...\...\MyDbFile.db")
     );
     ...
    
    DriveId mDriveId;
    /******************************************************************
     * create file in GOODrive
     * @param pFldr parent's ID
     * @param titl  file name
     * @param mime  file mime type  (application/x-sqlite3)
     * @param file  file (with content) to create
     */
    void saveToDrive(final DriveFolder pFldr, final String titl,
                     final String mime, final java.io.File file) {
      if (getGoogleApiClient() != null && pFldr != null && titl != null && mime != null && file != null) try {
        // create content from file
        Drive.DriveApi.newDriveContents(getGoogleApiClient()).setResultCallback(new ResultCallback<DriveContentsResult>() {
          @Override
          public void onResult(DriveContentsResult driveContentsResult) {
            DriveContents cont = driveContentsResult != null && driveContentsResult.getStatus().isSuccess() ?
              driveContentsResult.getDriveContents() : null;
    
            // write file to content, chunk by chunk
            if (cont != null) try {
              OutputStream oos = cont.getOutputStream();
              if (oos != null) try {
                InputStream is = new FileInputStream(file);
                byte[] buf = new byte[4096];
                int c;
                while ((c = is.read(buf, 0, buf.length)) > 0) {
                  oos.write(buf, 0, c);
                  oos.flush();
                }
              }
              finally { oos.close();}
    
              // content's COOL, create metadata
              MetadataChangeSet meta = new Builder().setTitle(titl).setMimeType(mime).build();
    
              // now create file on GooDrive
              pFldr.createFile(getGoogleApiClient(), meta, cont).setResultCallback(new ResultCallback<DriveFileResult>() {
                @Override
                public void onResult(DriveFileResult driveFileResult) {
                  if (driveFileResult != null && driveFileResult.getStatus().isSuccess()) {
                    DriveFile dFil = driveFileResult != null && driveFileResult.getStatus().isSuccess() ?
                      driveFileResult.getDriveFile() : null;
                    if (dFil != null) {
                      // BINGO , file uploaded
                      dFil.getMetadata(getGoogleApiClient()).setResultCallback(new ResultCallback<MetadataResult>() {
                        @Override
                        public void onResult(MetadataResult metadataResult) {
                          if (metadataResult != null && metadataResult.getStatus().isSuccess()) {
                            DriveId mDriveId = metadataResult.getMetadata().getDriveId();
                          }
                        }
                      });
                    }
                  } else { /* report error */     }
                }
              });
            } catch (Exception e) { e.printStackTrace(); }
          }
        });
      } catch (Exception e) { e.printStackTrace(); }
    }
    
    /*******************************************************************
     * get file contents
     */
    void readFromGooDrive() {
      byte[] buf = null;
      if (getGoogleApiClient() != null && getGoogleApiClient().isConnected()) try {
        DriveFile df = Drive.DriveApi.getFile(getGoogleApiClient(), mDriveId);
        df.open(getGoogleApiClient(), DriveFile.MODE_READ_ONLY, null)
          .setResultCallback(new ResultCallback<DriveContentsResult>() {
          @Override
          public void onResult(DriveContentsResult driveContentsResult) {
            if ((driveContentsResult != null) && driveContentsResult.getStatus().isSuccess()) {
              DriveContents cont = driveContentsResult.getDriveContents();
              // DUMP cont.getInputStream() to your DB file
              cont.discard(getGoogleApiClient());    // or cont.commit();  they are equiv if READONLY
            }
          }
        });
      } catch (Exception e) { e.printStackTrace(); }
    }
    

    祝你好运

    【讨论】:

    • 欣赏代码。至少现在我知道该往哪个方向思考了。试图实现它,但我得到一个文件/文件夹未找到错误。使用 onConnected 方法代码更新了问题。有趣的是,这与我用于在设备存储中备份(和恢复)数据库的路径相同,并且它可以正常工作!
    • 这听起来可能很幼稚,但路径有效,您的代码也可以使用“/data/data/”.....而不是“/data/”!现在尝试反转该过程并从应用程序文件夹中获取数据库...
    • 我放在那里的路径(\...\...)是符号我不知道您的数据库文件在哪里,也不知道它的名称是什么。该代码仅处理将文件上传到驱动器。如果您需要重新下载,请使用您从上面上传中获得的 DriveId 并将其应用于“read()”方法here
    • 尝试使用给定的 read() 方法,但我不断收到未找到文件/文件夹的错误。这是我用来获取驱动器 ID 的代码(因为有多个文件),` MetadataBuffer mdb = result.getMetadataBuffer();字符串 ID = mdb.get(0).getDriveId(); ` 然后将 ID 传递给 read()。也尝试使用 getResourceId() (在阅读了您在 SO 中的一个回复之后),但没有运气。
    • 我已经修改了答案以包括 InputStream 的完整解决方案。您必须将输入流写入您的数据库文件。与this demo一起玩也可能会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 2012-02-20
    • 1970-01-01
    相关资源
    最近更新 更多