2

once I've connected my application to Drive, I've created a folder.

Now, I want to create another folder inside that folder, but I don't know its DriveId.

@Override
    public void onConnected(Bundle connectionHint) {
        Log.d("DEBUG", "Succesfully connected to Drive.");

        MetadataChangeSet metadata = new MetadataChangeSet.Builder()
                                            .setTitle(getResources().getString(R.string.app_name_short))
                                            .build();

        Drive.DriveApi.getRootFolder(mGoogleApiClient).createFolder(mGoogleApiClient, metadata);

        // Here I would like to retrieve the just created folder and create a subfolder in it

    }

How am I supposed to achieve that?

Moreover, I would like to check in advance if a folder with that name already exists, since the above code is creating a new folder on every connection. And Drive seems to allow the creation of many folders with the same name.

Zagorax
  • 11,440
  • 8
  • 44
  • 56

3 Answers3

0

Set a ResultCallback to be called when the create is finished, where you get the ContentsResult passed in.

The example from the documentation is below:

public class CreateFileActivity {

    // ...

    ResultCallback<ContentsResult> contentsCallback = new
            ResultCallback<ContentsResult>() {
        @Override
        public void onResult(ContentsResult result) {
            if (!result.getStatus().isSuccess()) {
                // Handle error
                return;
            }

            MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                    .setTitle("New file")
                    .setMimeType("text/plain").build();
            // Create a file in the root folder
            Drive.DriveApi.getRootFolder(getGoogleApiClient())
                    .createFile(getGoogleApiClient(), changeSet, result.getContents())
                    .addResultCallback(this);
        }
    }
}
Rajesh
  • 15,724
  • 7
  • 46
  • 95
0

Here is an 'await' version (for simplicity - must be run on non-UI thread) of the solution (initialization / connection of GoogleApiClient is standard and can be found elsewhere):

  static final String MIMEFLDR  = "application/vnd.google-apps.folder";
  private GoogleApiClient  _gac;

  DriveFolder myFldr = getOrCreateFldr(null, "myFolder");
  DriveFolder myChildFldr = getOrCreateFldr(myFldr, "myChildFolder");

  private DriveId findFirst(String title, String mime, DriveFolder fldr) {
    ArrayList<Filter> fltrs = new ArrayList<Filter>();
    fltrs.add(Filters.eq(SearchableField.TRASHED, false));
    if (title != null)  fltrs.add(Filters.eq(SearchableField.TITLE, title));
    if (mime  != null)  fltrs.add(Filters.eq(SearchableField.MIME_TYPE, mime));
    Query qry = new Query.Builder().addFilter(Filters.and(fltrs)).build(); 
    MetadataBufferResult rslt = (fldr == null) ? Drive.DriveApi.query(_gac, qry).await() : 
                                                   fldr.queryChildren(_gac, qry).await();
    MetadataBuffer mdb = null;
    if (rslt.getStatus().isSuccess()) try {
      mdb = rslt.getMetadataBuffer();
      for (Metadata md : mdb) {
        if ((md == null) || (!md.isDataValid()) || md.isTrashed()) continue;
        return md.getDriveId();
      }
    } catch (Exception e) {}
    finally { if (mdb != null) mdb.close(); } 
    return null;
  }

  private DriveFolder getOrCreateFldr(DriveFolder fldr, String titl) {
    DriveFolder df = null;
    try {
      DriveId dId = findFirst(titl, MIMEFLDR, fldr);
      if (dId != null) {                 // exists
        df = Drive.DriveApi.getFolder(_gac, dId);
      } else {                           // doesn't exist, create in folder / root
        df = createFldr((fldr == null) ? Drive.DriveApi.getRootFolder(_gac) : fldr,  titl);
      }
    } catch (Exception e) {UT.le(e);}
    return df;
  }

  private DriveFolder createFldr(DriveFolder fldr, String name) {
    DriveFolder drvFldr = null;
    try { 
      MetadataChangeSet meta = 
              new MetadataChangeSet.Builder().setTitle(name).setMimeType(MIMEFLDR).build();
      drvFldr = fldr.createFolder(_gac, meta).await().getDriveFolder();
    } catch (Exception e) {}
    return drvFldr;
  }

It can easily be turned into a callback version but it would look messy. Be carefull with the findFirst() method though, Google Drive allows multiple files / folders with the same name (since only the ResourceId / DriveId are unique identifiers).

Recursive folder creation is shown in this GitHub project in case you want to dig deeper.

seanpj
  • 6,735
  • 2
  • 33
  • 54
0

I tried to integrate several answers, and I added my part to get a method that works. Surely there will be a more elegant and encapsulated way than this one that I developed, but it is the best I can offer now.

Once the DriveId object is obtained from the metadata, what follows is to obtain the DriveFolder object using the asDriveFolder() method.

Thanks to @Bikesh M Annur and @seanpj who contributed in How to get DriveId of created folder in Google Drive Android API.

private DriveFolder mFolder;

private void getDriveFolder(String folderName) {

    Query query = new Query.Builder().addFilter(Filters.and(
            Filters.eq(SearchableField.TITLE, folderName),
            Filters.eq(SearchableField.TRASHED, false))).build();

    getDriveResourceClient().query(query).addOnSuccessListener(new OnSuccessListener<MetadataBuffer>() {
        @Override
        public void onSuccess(MetadataBuffer metadata) {
            mFolder = null;

            for (Metadata md : metadata) {
                if (md == null) continue;
                DriveId dId  = md.getDriveId();      // here is the "Drive ID"
                String title = md.getTitle();
                String mime  = md.getMimeType();

                if (md.isFolder()) {
                    mFolder = dId.asDriveFolder();   // Returns the "DriveFolder" object
                    break;
                }
            }

            if (mFolder != null) {
                // Or better from here you can take your actions
                //...
            }
        }
    });
}

NOTE: Keep in mind that in Google Drive you can create a folder with the same name several times. This routine will return the first one from the list. It is up to you to detect which of all the repeats you want to take.

Diego Soto
  • 375
  • 3
  • 8