7

I have a public (anyone with the link can view) file on my Google Drive and I want to use the content of it in my Android app.

From what I could gather so far, I need the fileID, the OAuth token and the client ID - these I already got. But I can't figure out what is the exact methodology of authorising the app or fetching the file.

EDIT:

Simply reading it using file.readAsLines didn't work:

final file = new File(dogListTxt);
  Future<List<String>> dogLinks = file.readAsLines();

  return dogLinks;

The dogLinks variable isn't filled with any data, but I get no error messages.

The other method I tried was following this example but this is a web based application with explicit authorization request (and for some reason I was never able to import the dart:html library).

The best solution would be if it could be done seamlessly, as I would store the content in a List at the application launch, and re-read on manual refresh button press.

I found several old solutions here, but the methods described in those doesn't seem to work anymore (from 4-5 years ago).

Is there a good step-by-step tutorial about integrating the Drive API in a flutter application written in dart?

Zoltán Györkei
  • 1,025
  • 5
  • 13
  • 21
  • 2
    Please provide concrete information about what you tried and what didn't work with these attempts (code, and error messages) – Günter Zöchbauer Apr 04 '18 at 05:47
  • Please see the EDIT part above: this is already a new approach, which at least builds, but doesn't give any error messages or result either. – Zoltán Györkei Apr 04 '18 at 07:43
  • It seems I did get some error after all, and this method can't be used to open remote files: FileSystemException: Cannot open file, path = 'https://drive.google.com/file/d/1UZWDwA2SXnizz__ZodlLp82MQCi1WnvM' (OS Error: No such file or directory, errno = 2) – Zoltán Györkei Apr 04 '18 at 07:47
  • 1
    You can't use `dart:html` in Flutter. `dart:html` can only be used in browser apps. https://stackoverflow.com/questions/48477625/how-to-use-google-api-in-flutter/48485898#48485898 might help with https://pub.dartlang.org/packages/googleapis – Günter Zöchbauer Apr 04 '18 at 08:00

3 Answers3

15

I had quite a bit of trouble with this, it seems much harder than it should be. Also this is for TXT files only. You need to use files.export() for other files.

First you need to get a list fo files.

ga.FileList textFileList = await drive.files.list(q: "'root' in parents");

Then you need to get those files based on ID (This is for TXT Files)

ga.Media response = await drive.files.get(filedId, downloadOptions: ga.DownloadOptions.FullMedia);

Next is the messy part, you need to convert your Media object stream into a File and then read the text from it. ( @Google, please make this easier.)

List<int> dataStore = []; 
    response.stream.listen((data) {  
     print("DataReceived: ${data.length}");
     dataStore.insertAll(dataStore.length, data);     
   }, onDone: () async {  
     Directory tempDir = await getTemporaryDirectory(); //Get temp folder using Path Provider
     String tempPath = tempDir.path;   //Get path to that location
      File file = File('$tempPath/test'); //Create a dummy file
      await file.writeAsBytes(dataStore); //Write to that file from the datastore you created from the Media stream
      String content = file.readAsStringSync(); // Read String from the file
      print(content); //Finally you have your text
      print("Task Done");  
   }, onError: (error) {  
     print("Some Error");  
   });  
Yonkee
  • 1,781
  • 3
  • 31
  • 56
  • Do you have any other way to get the response because I'm using driveApi v3 version and this line does not work "ga.Media response = await drive.files.get(filedId, downloadOptions: ga.DownloadOptions.FullMedia);" because drive.files.get() returns an Future which could not be receive in a ga.Media type. Is there any other way around this. Anyhelp would be appreciated, thanks – Madhav mishra Feb 09 '22 at 18:45
  • @Yonkee your code won't work with driveApi v3, will you please update your code, I can't figure out how to solve it please. – Abdullah Bahattab Jun 15 '23 at 23:53
  • @AbdullahBahattab it works perfectly fine, have you tried replacing `ga.Media` response by `Media media` and `response` by `media`. – Antonin GAVREL Jun 22 '23 at 15:50
  • Thank you I have found a solution 5 days ago. – Abdullah Bahattab Jun 22 '23 at 23:45
0

There currently is no good step-by-step tutorial, but using https://developers.google.com/drive/api/v3/manage-downloads as a reference guide for what methods to use in Dart/Flutter via https://pub.dev/packages/googleapis: to download or read the contents of a Google Drive file, you should be using googleapis/Drive v3, or specifically, the methods from the FilesResourceApi class.

  • drive.files.export(), if this is a Google document
    • /// Exports a Google Doc to the requested MIME type and returns the exported content. Please note that the exported content is limited to 10MB.
  • drive.files.get(), if this something else, a non-Gdoc file
    • /// Gets a file's metadata or content by ID.

Simplified example:

var drive = new DriveApi(http_client);

drive.files.get(fileId).then((file) {
  // returns file
});

However, what I discovered was that this Dart-GoogleAPIs library seemed to be missing a method equivalent to executeMediaAndDownloadTo(outputStream). In the original Google Drive API v3, this method adds the alt=media URL parameter to the underlying HTTP request. Otherwise, you'll get the error, which is what I saw:

403, message: Export requires alt=media to download the exported content.

And I wasn't able to find another way to insert that URL parameter into the current request (maybe someone else knows?). So as an alternative, you'll have to resort to implementing your own Dart API to do the same thing, as hinted by what this OP did over here https://github.com/dart-lang/googleapis/issues/78: CustomDriveApi

So you'll either:

  1. do it through Dart with your own HttpClient implementation and try to closely follow the REST flow from Dart-GoogleAPIs, but remembering to include the alt=media
  2. or implement and integrate your own native-Android/iOS code and use the original SDK's convenient executeMediaAndDownloadTo(outputStream)

(note, I didn't test googleapis/Drive v2, but a quick examination of the same methods looks like they are missing the same thing)

TWL
  • 6,228
  • 29
  • 65
0

I wrote this function to get file content of a file using its file id. This is the simplest method I found to do it.

   Future<String> _getFileContent(String fileId) async {
    var response = await driveApi.files.get(fileId, downloadOptions: DownloadOptions.fullMedia);
    if (response is! Media) throw Exception("invalid response");
    return await utf8.decodeStream(response.stream);
  }

Example usage:

    // save file to app data folder with 150 "hello world"s
    var content = utf8.encode("hello world" * 150);
    driveApi.files
        .create(File(name: fileName, parents: [appDataFolder]),
            uploadMedia: Media(Stream.value(content), content.length))
        .then((value) {
      Log().i("finished uploading file ${value.id}");
      var id = value.id;
      if (id != null) {
        // after successful upload, read the recently uploaded file content
        _getFileContent(id).then((value) => Log().i("got content is $value"));
      }
    });
Rosenpin
  • 862
  • 2
  • 11
  • 40