2
votes

I am sure this is an easy question to answer, but I've been unable to find out how to instancate a DriveId and/or DriveFolder with the Drive resource id using the Google Drive Android API v 12.

I have read the Google Drive Android API documentation and have managed to create a file on my Google Drive from my Android app in the root folder, but now I want to create the file in a specific folder and I'm unsure how to go about this.

A lot of the code I've seen (such as this Stackoverflow answer) uses the deprecated Google DriveApi to get a DriveId from the resource id of the folder.

I have tried to use the DriveId method decodeFromString but when I ran the following code, I get an error saying the DriveId is invalid:

String googleDriveFolderId = "16TwNeDF9_inOK4X5AaGnVMNycNVxxMtd";
DriveFolder projectFolder = DriveId.decodeFromString(googleDriveFolderId).asDriveFolder();

What am I doing wrong?

2

2 Answers

0
votes

Create a folder

To create a folder, call DriveResourceClient.createFolder(), passing in a reference to the parent folder and the metadata object containing the title and other attributes to set the values for the folder.

The following code sample demonstrates how to create a new folder in the root folder:

private void createFolder() {
    getDriveResourceClient()
            .getRootFolder()
            .continueWithTask(task -> {
                DriveFolder parentFolder = task.getResult();
                MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                                                      .setTitle("New folder")
                                                      .setMimeType(DriveFolder.MIME_TYPE)
                                                      .setStarred(true)
                                                      .build();
                return getDriveResourceClient().createFolder(parentFolder, changeSet);
            })
            .addOnSuccessListener(this,
                    driveFolder -> {
                        showMessage(getString(R.string.file_created,
                                driveFolder.getDriveId().encodeToString()));
                        finish();
                    })
            .addOnFailureListener(this, e -> {
                Log.e(TAG, "Unable to create file", e);
                showMessage(getString(R.string.file_create_error));
                finish();
            });
}

on Success, try calling getDriveId().

0
votes

What I am trying to do is simply not possible using the Google Drive Android API. I guess this is because the DriveResource does not get a resourceId until it has been uploaded.

See this SO answer which discusses how you aren't able to access any file or folder that isn't created by your app. I tested this and it's true - when I run a Query for a folder that I created manually in my root folder I cannot find it, but when I create a folder with the same name from my app, I get 1 query result.

Also see this SO thread which says you need to use another Google Drive API (they suggested the REST API) to be able to specify a folder programmatically (without using a popup where the user selects a folder). Unfortunately that won't work for me because I am building an offline app - precisely the reason I chose to work with Google Drive.

I ended up making a compromise and working with the root folder - luckily for me my project is to be used with very specific Google accounts so I am able to do this. My code looks something like this:

private void createFile() {
    // [START create_file]
    final Task<DriveFolder> rootFolderTask = getDriveResourceClient().getRootFolder();
    final Task<DriveContents> createContentsTask = getDriveResourceClient().createContents();
    Tasks.whenAll(rootFolderTask, createContentsTask)
            .continueWithTask(task -> {
                DriveFolder parent = rootFolderTask.getResult();
                DriveContents contents = createContentsTask.getResult();
                OutputStream outputStream = contents.getOutputStream();
                try (Writer writer = new OutputStreamWriter(outputStream)) {
                    writer.write("Hello World!");
                }

                MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                                                      .setTitle("HelloWorld.txt")
                                                      .setMimeType("text/plain")
                                                      .setStarred(true)
                                                      .build();

                return getDriveResourceClient().createFile(parent, changeSet, contents);
            })
            .addOnSuccessListener(this,
                    driveFile -> {
                        showMessage(getString(R.string.file_created,
                                driveFile.getDriveId().encodeToString()));
                        finish();
                    })
            .addOnFailureListener(this, e -> {
                Log.e(TAG, "Unable to create file", e);
                showMessage(getString(R.string.file_create_error));
                finish();
            });
    // [END create_file]
}

If you can't compromise and use the root folder, I would suggest that you create a folder from within your app into the root folder and then save the string representation of the DriveId which you can use the next time you run the code. I haven't yet tested if the folder could be used by another instance of the app running on a different device, but I would hope so (fingers crossed).

Another option is displaying a popup so the user can select the folder manually. See this demo example.