anonymous
anonymous

Reputation: 1330

Google Drive API caching query results

I want to check if a folder exists in the root of the linked Google Drive account. If it exists, delete a file in that folder and create a new one in there. If it doesn't, create the folder and then create a file in it.

This is what I'm doing to query:

private void checkIfBackupFolderIsInDrive(final File databaseFile) {
        final Query backupFolderQuery = new Query.Builder()
                .addFilter(Filters.and(
                        Filters.eq(SearchableField.TITLE, DATABASE_BACKUP_FOLDER_NAME),
                        Filters.eq(SearchableField.MIME_TYPE, DriveFolder.MIME_TYPE),
                        Filters.eq(SearchableField.TRASHED, false)))
                .build();

        mDriveResourceClient.getRootFolder()
                .continueWithTask(task -> {
                    final DriveFolder rootFolder = task.getResult();
                    return mDriveResourceClient.queryChildren(rootFolder, backupFolderQuery);
                })
                .addOnSuccessListener(mActivity, metadataBuffer -> {
                    for (final Metadata metadata : metadataBuffer) {
                        final DriveFolder driveFolder = metadata.getDriveId().asDriveFolder();
                        final String title = metadata.getTitle();
                        final String mimeType = metadata.getMimeType();

                        if (title.equals(DATABASE_BACKUP_FOLDER_NAME) && mimeType.equals(DriveFolder.MIME_TYPE)) {
                            Utils.log("SettingsFragment", "Backup folder already exists");
                            deleteExistingDatabaseFileInFolder(driveFolder, databaseFile);
                            metadataBuffer.release();
                            return;
                        }
                    }

                    metadataBuffer.release();
                    createFolderToRootDriveFolder(databaseFile);
                })
                .addOnFailureListener(mActivity, e -> Utils.log("SettingsFragment", "Error retrieving files list: " + e.getMessage()));
    }

As you can see, I'm already calling the release() method on the metadataBuffer but when I delete the recently created folder, even emptied from the Trash and then execute the query again, it keeps saying that the folder already exists.

If I do not empty the trash, the new file is created inside the trashed folder.

I am using this version of the drive API alongside with this version of the auth API:

implementation 'com.google.android.gms:play-services-auth:16.0.0'
implementation 'com.google.android.gms:play-services-drive:15.0.1'

This is driving me nuts. How can I perform a clean query to avoid that behaviour to happen?

Thank you very much in advance.

Upvotes: 2

Views: 906

Answers (1)

anonymous
anonymous

Reputation: 1330

After a lot of energy spent on data research, I found the solution. Before making any query / operation that requires an up to date metadataBuffer you must call DriveClient.requestSync() to update it.

But be careful when using this method. According to the documentation below:

public abstract Task<Void> requestSync ()

Requests synchronization with the server to download any metadata changes that have occurred since the last sync with the server.

Typically, this method should be called when the user requests a refresh of their list of files. Once this method returns, performing a query will return fresh results.

In order to avoid excessive load on the device and server, sync requests are rate-limited. If the request has been rate-limited, the operation will fail with the DRIVE_RATE_LIMIT_EXCEEDED status. This indicates that a sync has already occurred recently so there is no need for another. After a sufficient backoff duration, the operation will succeed when re-attempted.

Source: Google APIs for Android.

My implementation is as follows:

private void refreshMetadata(final File databaseFile) {
    mDriveClient.requestSync()
            .addOnSuccessListener(aVoid -> checkIfBackupFolderIsInDrive(databaseFile))
            .addOnFailureListener(e -> Utils.log("SettingsFragment", "Could not update metadata buffer: " + e.getMessage()));

}

I request the sync. If successful I start the operations that I want to do. If it fails right now I'm only logging the event.

Upvotes: 1

Related Questions