2

I've been trying to figure out what I'm doing wrong or if it's the intended behaviour. I am creating an app that uploads files to the Google Drive using Google Play Services Drive API. Before I create the parent folder I check if the folder already exists. For testing I delete the folder, then check in the app, however the app always detects that the folder is still there.

I have checked isTrashed on the MetaDataBuffer and it's always reported as false.

Is this a syncing issue between app and drive server?

This is the query that I use:

    new Query.Builder().addFilter(
       Filters.and(
            Filters.eq(SearchableField.TRASHED, false),
            Filters.eq(SearchableField.MIME_TYPE, MIME_TYPE_FOLDER),
            Filters.eq(SearchableField.TITLE, name)
    )).build();
sheilak
  • 5,833
  • 7
  • 34
  • 43
SteedsOfWar
  • 543
  • 2
  • 9
  • 23

3 Answers3

2

Welcome to the club :-). This issue is one of the known quirks (pardon, features) of GDAA discussed all over the place. What you see is the side-effect of having a 'buffering' layer between your app and GooDrive. When placing any GDAA related request, you're talking to GooPlaySvcs layer, that has no clue what other apps (http://drive.google.com) did to the Drive. So many weird things can happen, like for instance:

1/ create a folder with your app
2/ trash and permanently delete that folder using http://drive.google.com
3/ let your app create a file in that folder - no indication of failure, file is created in a folder somewhere in Google never-never-land

If you really need to know the current Drive status, you have to poll the Drive using the REST Api.

Another option to keep it under control is to write your folder/files into an appfolder, making them inaccessible to other apps. Then, not even you can delete a file 'from behind'. Be careful, though, there is a related problem/issue with the appfolder you can run into when testing.

Good Luck

Community
  • 1
  • 1
seanpj
  • 6,735
  • 2
  • 33
  • 54
  • 1
    Thanks, that's what i was looking for. I wasn't sure if it was something that i was missing in my code or expected behaviour. The problem i have is the app uploads those as a 'backup' for the user. So if the user decides to delete the folder i previously uploaded, then re-upload, i don't know what behaviour to expect. It's a pain, it looks like the REST api might be the better option. – SteedsOfWar Dec 06 '15 at 20:29
  • 1
    REST is quite straightforward with no surprises (GDAA actually sits on top of it). But you'll have to do a lot of housekeeping GDAA does (sync service, managing network state, etc...) – seanpj Dec 06 '15 at 20:40
  • 1
    thanks for the all the help. I don't think i have much choice, the sync'ing is going to cause me no end of headaches. The fact the app doesn't know if it's uploading to a deleted folder is a disaster from a ux perspective. Add to the fact the user is more likely to blame the app rather than how google drive api is working. – SteedsOfWar Dec 07 '15 at 15:19
  • 2
    I was surprised how nonchalant were Googlers about this issue when I raised it [here](http://stackoverflow.com/questions/30172915/user-disconnecting-app-in-drive-causes-loss-of-data-under-file-scope). And exactly, your app will be blamed. – seanpj Dec 07 '15 at 15:40
  • I have wasted quite some time trying to resolve this without success! This should be change, eg. by providing a flag that allows for fetching new changes for that very folder in advance. – Felix D. Dec 17 '16 at 21:55
  • 1
    @FelixD. Feeling your pain. Unfortunately can't help anymore, I have retired a year ago and do not have a clue about the state of things in the GDAA land. – seanpj Dec 19 '16 at 13:50
1

As Sean mentioned, GDAA has a caching layer that can cause your app to get stale query results. The way to ensure that the cache is up to date before you query it is to call DriveApi#requestSync. The caching layer allows your app to operate when offline. If the device is offline, the Drive API will upload your file when the device goes back online. The REST API is indeed more straightforward and can be a good option if you do not care about the offline case or is happy to handle it in your app. Hope this helps.

Ofir
  • 110
  • 3
1

This questions is a bit old but the answer might be useful for others having the exact same problem.

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.

anonymous
  • 1,320
  • 5
  • 21
  • 37