6

UPDATE (May 2015):
the 'trash' functionality has been implemented in GDAA, making the question below irrelevant.

ORIGINAL QUESTION:
As I play with the new "Google Drive Android API" (GDAA), I am running into a few discrepancies I can't figure out. Basically, I have an old app that uses the "com.google.api.services.drive" interface (insert, patch, update) and I WOULD LOVE to port it to GDAA.

First, GDAA vs. drive.google.com web app.
With the old service, I used the DriveScopes.DRIVE_FILE scope, so I assumed similar behavior/results. Files created with the old "DriveScopes.DRIVE_FILE" can be deleted by me (the Drive owner) in "https://drive.google.com" (I assume that my scope is DRIVE there) and subsequent Android app queries will not find them. It behaves as I would expect:

  1. The Android app creates files.
  2. User deletes them on "drive.google.com".
  3. Android app does not see them anymore.

With the new GDAA, it does not seem to work. Which brings me to the second point:

DELETE/TRASH functionality.
I was trying to test CRUD functionality and couldn't find DELETE at all (again, it may be my ignorance/shortsightedness). Deleting them from "drive.google.com" makes them invisible there, but the Android app still sees them. Metadata can inquire through "isTrashed()", but there is nothing in "MetadataChangeSet.Builder" that would let me delete/trash them, only setMimeType(), setStarred(), setTitle().

I'm lost, please help.

seanpj
  • 6,735
  • 2
  • 33
  • 54
  • what was the question? – Linda Lawton - DaImTo Jan 27 '14 at 08:37
  • Purely out of curiosity, why do you want to migrate from the REST API to the local API?. I had a look at the new API and decided to stick with what (mostly) works. There is a slight paradigm mismatch between Drive and Android local storage, so you are at the mercy of however Google end up matching the two. Specifically, I'm thinking about all of the rich meta data available in Drive, which may or may not be materialised in Android. – pinoyyid Jan 27 '14 at 11:48
  • 5
    The question is "WHERE IS THE DELETE (or Trash or setTrash()) IN NEW GOOGLE DRIVE API?". And the answer to your curiosity question is here: https://www.youtube.com/watch?v=quQyZdhPjxc and here: https://developers.google.com/drive/android/files My Android app needs to write/read files to Google Drive and the new API should take care of all the sync functionality. The functionality that's missing (indexable, description, fulltext) at this point I can supply myself in my app, and I hope they will catch up. Besides, I like to play with new toys. – seanpj Jan 27 '14 at 14:32
  • Deletion is not supported from Google Drive Android API, we're working on it for the next release which is soon. – Burcu Dogan Jan 27 '14 at 14:51
  • 2
    @pinoyyid Almost a year later, I must admit you were right. I can manage the syncs better myself. Actually, unpredictability of GDAA syncing makes it harder. And the inter-device update notifications (which I foolishly hoped for) are nowhere to be found. Where is the DELETE (see the comment above)? Interestingly, anytime I complain about the lack of support (https://developers.google.com/drive/support), I get promptly down-voted by a posse of wise men. – seanpj Oct 22 '14 at 12:25
  • Hi Seanj, after 2 weeks of playing with new Google Android API I must say exactly the same - it is simple not good enough yet. That's why I use now old API. However I have just 1 question for you - how to get push notification or change listeners work for android apps using old api? Looks like you can't - it seems that it works only for java apps which are running on some domain, which you must register. Or am I wrong? Thanks! – qkx Oct 23 '14 at 08:23
  • @gkx I am working on GCM - based implementation. – seanpj Oct 23 '14 at 10:10
  • @seanpj, are you still using the new Android API? Did you ever run into issues with remote data corruption? (Locally, everything is fine, so I don't think it's an application issue) – Stefan Haustein Dec 29 '14 at 23:33
  • @StefanHaustein No, I quit and backed-off to RESTful, because of the missing DELETE. Combining the two (REST for delete and GDAA for Search, Create, Retrieve, Update) introduces un-resolvable timing issues (i.e. you can easily GDAA-create a file in a REST-deleted folder - hours after delete - under user control). I am ready to get back as soon as I see some progress. And I strongly recommend to create/ maintain a REST/GDAA SCRUD wrapper. I can't comment on your problem, but I would suspect some MIME related maneuvers on Google Drive. Just a wild guess. – seanpj Dec 30 '14 at 00:57
  • MIME was my first guess, too, so I had switched from text/plain to application/binary... But this makes debugging even harder (no data inspection via the web interface). Biggest bummer is that there is no real forced sync (no idea what requestSync does / is supposed to do). So it's also super hard to reproduce bugs. There is not much that has given me that much grief recently... :-/ – Stefan Haustein Dec 30 '14 at 01:14
  • I mentioned MIME because (I faintly recall) I once uploaded a png file with "image/jpeg' mimetype metadata and then searched for "image/jpeg" mimetype. GooDrive meanwhile changed mimetype of MY file to "image/png", suggesting they are snooping inside the file content. Shows my foolishness when thinking these are my files. Silly me. – seanpj Dec 30 '14 at 02:09
  • @seanpj I wasn't able to change the MIME type for existing files at all via the Android API, although this is some of the things the API seems to permit... But maybe the metadata has just not synced yet... Would you mind pinging me on Email re: FS wrapper? My email address is stefan.haustein; the provider is gmail – Stefan Haustein Dec 31 '14 at 00:08

7 Answers7

5

If you want to have a full control over synchronization, do not use Google Drive Android NEW API (at least for now). It is not good enough yet (October 2014) or respectively it works in different way than "real time" OLD API. Main problems are, that you can't delete file, changes are not real-time, metadata are often cached a lot (when I make a search query, in results I can see deleted files even after many hours!). Probably due to some optimizations drive services runs when they want and how they want, so almost nothing is under your control - you never know how drive service uses cache, and you can't force drive service to "do the job right now because I need it".

Oh, and another disadvantage is, that code is much more complicated that same logic created in OLD API :)

qkx
  • 2,383
  • 5
  • 28
  • 50
  • 3
    My best achievement was to create a file in a folder 3 hours after the folder has been trashed using the web drive interface. I could happily write content, metadata to a file in never-never-land with no indication of error. And all that even if the trash has been manually emptied hours ago. Miracles happen... – seanpj Oct 24 '14 at 01:38
  • 3
    yeah, same with me. When you can't force this new API to clear cache and get fresh results, it is useless for purpose of synchronization in my opinion – qkx Oct 24 '14 at 09:42
  • 1
    Yeah, a year later and still no Delete function, and the web is still littered with code/examples/documentation from the non-GPS version of the Android Drive API, including the nice example from @Burcu that hasn't yet been updated. The downside of Google is that constant development means everything is a moving target, and documentation is constantly outdated. I've managed to convert Burcu's appdatapreferences code to the new API, but am still struggling to get fully working. Here's hoping the new year brings some new documentation and examples. – Alchete Dec 31 '14 at 16:01
4

Google Drive Android API doesn't sync with the remote resources instantly. Depending on the scheduler, it may take a while to sync. The scheduling is dependant to Android's account sync components those are making sure that network bandwidth and battery life is conserved and efficiently used.

Additionally, as of Developer Preview, we don't support deletion or trashing. But, the next release will likely to support these actions.

Burcu Dogan
  • 9,153
  • 4
  • 34
  • 34
1

While Google Drive Android API does not yet support delete, you can delete the contents (and, at the same time, rename the title, so that you can ignore it in future). This might be useful to devs using the AppFolder.

private void deleteContents(final DriveFile driveFile) {
  driveFile.open(mGoogleApiClient, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
    @Override
    public void onResult(DriveContentsResult result) {
      if (!result.getStatus().isSuccess()) {
        // oh noes!
        return;
      }
      DriveContents contents = result.getDriveContents();
      try {
        MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder().setTitle(DELETED_DRIVE_TITLE).build();
        contents.commit(mGoogleApiClient, metadataChangeSet).setResultCallback(
                new ResultCallback<Status>() {
                  @Override
                  public void onResult(Status status) {
                    if (!status.isSuccess()) {
                      // more oh noes!
                      return;
                    }
                    // nicely deleted
                  }
                });
      }
      catch (Exception e) {
        contents.discard(mGoogleApiClient);
      }
    }
  });
}
Mark
  • 7,446
  • 5
  • 55
  • 75
1

If you are working with App Folder (invisible to user), you goal to delete the file is only to save user space and never pick it again. So, you can use the "empty and forget" strategy.

From @Mark Carter (because the Android Drive API changed):

    private void deleteContents(final DriveFile driveFile) {
    driveFile.open(this.client, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
        @Override
        public void onResult(DriveApi.DriveContentsResult result) {
            if (!result.getStatus().isSuccess()) {
                // oh noes!
                return;
            }

            final DriveContents contents = result.getDriveContents();                

            try {
                MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder().setTitle("deleted").build();
                contents.commit(PhotoAdapter.this.client, metadataChangeSet).setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (!status.isSuccess()) {
                            // more oh noes!
                            return;
                        }
                        // nicely marked, now destroy data
                        OutputStream out = contents.getOutputStream();
                        try {
                            out.write(0x0);
                            //nicely empty
                        } catch (IOException e) {
                            //oh, no...
                            throw new RuntimeException(e);
                        }finally {
                            try {
                                out.close();
                            } catch (IOException e) {
                                //what we can do? Just log it
                            }
                        }
                    }
                });
            }
            catch (Exception e) {
                //Unsuccessful. Log it, rollback  contents and cry
                contents.discard(PhotoAdapter.this.client);
            }
        }

    });
}
Renascienza
  • 1,647
  • 1
  • 13
  • 16
  • throws IllegalStateException on `OutputStream out = contents.getOuputStream();` --- Drive Docs say `Once this DriveContents instance has been committed, used for creation, or discarded, it becomes closed and any subsequent method call will throw an IllegalStateException. ` – m02ph3u5 Mar 18 '15 at 09:55
  • Sorry, when i submit the code it wasn't tested yet. I fixed it later on my project but forget update it here. I will post an update asap. – Renascienza Mar 19 '15 at 11:11
1

The new Version of the Google Play Services (7.0.0 / March 2015) finally features DriveRessource.trash(). See https://developer.android.com/reference/com/google/android/gms/drive/DriveResource.html

Haven't tested it yet - I'll report back soon.

// edit Well, I tested it and it does work ... but not for files within the app folder: Cannot trash App Folder or files inside the App Folder. Apparently you cannot use this feature whilst using the app folder.

m02ph3u5
  • 3,022
  • 7
  • 38
  • 51
0

@Burcu Dogan, not sure if you'll see this but as per https://github.com/googledrive/android-demos/issues/4#issuecomment-33759142 will there be a sample to run GDrive operations from a service?

nLL
  • 5,662
  • 11
  • 52
  • 87
  • timed me out, trying again: You may try to pull some code from "AsyncTask" "doInBackground" here. https://github.com/seanpjanson/140201-GDAA/blob/master/awaits/MainActivity.java It may work as a service. At least I'm planning to use something similar. There is a bit of narrative in the readme.txt in the root. – seanpj Jan 31 '14 at 21:53
  • Thanks I'll have a look. But I realised that delete has not been implemented yet. I Mean putting converting to new api on hold for now – nLL Jan 31 '14 at 21:59
  • 1
    Yep, and also (per issue https://github.com/googledrive/android-demos/issues/3), deleting files in drive and expecting to see it on Android is quite unreliable (that's why I actually wrote that 140201-GDAA). But it is a good start and they will fix / support it soon, I guess. – seanpj Jan 31 '14 at 22:03
0

As of Google Play services 7.5, both delete and trash are supported: https://developers.google.com/drive/release-notes#drive_android_api_google_play_services_75_-_may_28th_2015

We recommend using trash for user visible files rather than delete, to give users the opportunity to restore any accidentally trashed content. Delete is permanent, and recommended only for App Folder content, where trash is not available.

Daniel
  • 1,239
  • 1
  • 13
  • 24