驱动Api保存到文件夹,如果文件夹不存在,则创建而不是保存

时间:2015-12-02 21:55:47

标签: android google-drive-android-api

我使用Google Drive API在那里保存(用作备份)数据库,它工作得很好,但就好像我使用ROOT

Api电话:

  MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
                           ......build();


Drive.DriveApi.getRootFolder(mGoogleApiClient)
                        .createFile(mGoogleApiClient, metadataChangeSet, result.getDriveContents())
                        .setResultCallback(fileCallback);

CallBack保存文件:

final public ResultCallback < DriveFolder.DriveFileResult > fileCallback = new
            ResultCallback < DriveFolder.DriveFileResult > () {
                @Override
                public void onResult(DriveFolder.DriveFileResult result) {

                    if (!result.getStatus().isSuccess()) {


                        return;
                    }

                    Log.i(TAG, "Successfull !");
                }
            };

我知道我必须得到文件夹,但如果我这样做,我需要做一个CallBack来调用另一个回调然后保存?

不能直接在FOLDER里面做.createNewFile吗?没有做另一个查询文件夹,检查文件夹是否存在而不是创建文件夹,而不是使用DriveID,而不是创建文件?

1 个答案:

答案 0 :(得分:2)

请记住,在GooDrive世界中,树结构(文件夹,子文件夹,...)是海市蜃楼。驱动器是一个对象(文件,文件夹)的平面系统,其中一个元数据字段是一组父ID,实际上形成了父对象 - 子对象结构的概念。实际上,经典的树(一个父母很多孩子)甚至没有被强制执行,因此一个子对象可以出现在&#39;在更多的父母一方 这一事实说明您无法一次性创建OS类型的路径。必须先创建对象(父项),然后才能将其ID插入子对象中。元数据。

所以唯一的方法就是做你说的话:

    if folder exists
      return it's ID
    else
      return ID of newly created one

   create a child object with parent's ID

...以下是我如何创建类型结构的示例:

   / MYROOT / 2015 / 2015-12

(MYROOT,2015,2015-12是驱动根的子浮动)

new Thread(new Runnable() {
  @Override
  public void run() {
    DriveId Id = getFolder( getFolder( getFolder(
          Drive.DriveApi.getRootFolder(mGAC).getDriveId(), "MYROOT"),
        "2015",
      "2015-12"
    );
  }
}).start();

GoogleApiClient mGAC;

DriveId getFolder(DriveId parentId, String titl) {
  DriveId dId = null;
  if (parentId != null && titl != null) try {
    ArrayList<Filter> fltrs = new ArrayList<>();
    fltrs.add(Filters.in(SearchableField.PARENTS, parentId));
    fltrs.add(Filters.eq(SearchableField.TITLE, titl));
    fltrs.add(Filters.eq(SearchableField.MIME_TYPE, "application/vnd.google-apps.folder"));
    Query qry = new Query.Builder().addFilter(Filters.and(fltrs)).build();

    MetadataBuffer mdb = null;
    DriveApi.MetadataBufferResult rslt = Drive.DriveApi.query(mGAC, qry).await();
    if (rslt.getStatus().isSuccess()) try {
      mdb = rslt.getMetadataBuffer();
      if (mdb.getCount() > 0)
        dId = mdb.get(0).getDriveId();
    } catch (Exception ignore) {}
    finally { if (mdb != null) mdb.close(); }

    if (dId == null) {
      MetadataChangeSet meta = new Builder().setTitle(titl).setMimeType(UT.MIME_FLDR).build();
      DriveFolderResult r1 = parentId.asDriveFolder().createFolder(mGAC, meta).await();
      DriveFolder dFld = (r1 != null) && r1.getStatus().isSuccess() ? r1.getDriveFolder() : null;
      if (dFld != null) {
        MetadataResult r2 = dFld.getMetadata(mGAC).await();
        if ((r2 != null) && r2.getStatus().isSuccess()) {
          dId = r2.getMetadata().getDriveId();
        }
      }
    }
  } catch (Exception e) { e.printStackTrace(); }
  return dId;
}

在&#39; mdb.get(0).getDriveId()&#39;区域,你可以看到当你试图在驱动器上强加一个经典的树形结构时它会变得多么黑巧。这里的搜索可以返回多个具有相同名称的对象,因此我使用第一个。这里应该有一些错误报告。

正如您所看到的,可以用&#39; await()&#39;替换回调。方法,将代码展平为经典的DOS风格的意大利面条代码,只要你将整个序列放在UI线程之外(asynctask,thread,....)

但是,更优雅(IMO)的选项是使用结果回调中的递归调用。

  fromPath(Drive.DriveApi.getRootFolder(mGAC).getDriveId(), "MYROOT/2015/2015-12/file.jpg");
  ....
  void fromPath(final DriveId parentId, final String path) {
    if (parentId != null && path != null) {

      final int idx = path.indexOf('/');
      if (idx < 0) {
        // reached last path item - probably file name
        // CREATE FILE WITH patentID AND QUIT
        return;    //--- DONE -------------------->>>
      }

      final String titl = path.substring(0, idx);

      ArrayList<Filter> fltrs = new ArrayList<>();
      fltrs.add(Filters.in(SearchableField.PARENTS, parentId));
      fltrs.add(Filters.eq(SearchableField.TITLE, titl));
      fltrs.add(Filters.eq(SearchableField.MIME_TYPE, UT.MIME_FLDR));
      Query qry = new Query.Builder().addFilter(Filters.and(fltrs)).build();

      Drive.DriveApi.query(mGAC, qry).setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
        @Override
        public void onResult(DriveApi.MetadataBufferResult rslt) {
          MetadataBuffer mdb = null;
          if (rslt != null && rslt.getStatus().isSuccess()) {
            try {
              mdb = rslt.getMetadataBuffer();
              for (Metadata md : mdb) {
                if (md.isTrashed()) continue;
                fromPath(md.getDriveId(), path.substring(idx + 1));
                return; //+++ first found, NEXT +++++++>>>
              }
            } finally { if (mdb != null) mdb.close(); }
          }

          MetadataChangeSet meta = new Builder().setTitle(titl).setMimeType(UT.MIME_FLDR).build();
          parentId.asDriveFolder().createFolder(mGAC, meta)
          .setResultCallback(new ResultCallback<DriveFolderResult>() {
            @Override
            public void onResult(DriveFolderResult rslt) {
              DriveFolder dFld = rslt != null && rslt.getStatus().isSuccess() ? rslt.getDriveFolder() : null;
              if (dFld != null) {
                dFld.getMetadata(mGAC).setResultCallback(new ResultCallback<MetadataResult>() {
                  @Override
                  public void onResult(MetadataResult rslt) {
                    if (rslt != null && rslt.getStatus().isSuccess()) {
                      fromPath(rslt.getMetadata().getDriveId(), path.substring(idx + 1));
                      return; //+++ created, NEXT +++++++>>>
                    }
                  }
                });
              }
            }
          });
        }
      });
    }
  }

注意事项:
当我反复调用这个序列时,使用最后一个DriveId(如2015-12)作为JPEG图像文件的父级,我经历了奇怪的行为,比如突然得到一个&#39; null&#39;来自&#39; Drive.DriveApi.getRootFolder(mGAC).getDriveId()&#39;的结果。它不应该发生,我认为它是GDAA中的一个错误。我认为这是因为GDAA中使用的DriveId无效&#39;直到提交文件夹并在底层REST Api中解析ResourceId。不幸的是,没有completion event可用于文件夹创建,所以我通过在onConnected()中仅调用此序列一次并缓存&#39; 2015-12的DriveId以供稍后用作父级来解决此问题图像JPEG文件。 实际上你可以在尾部看到here(createTree()方法)文本文件,但是当我将TEXT切换为JPEG时,一切都失败了。

祝你好运