Search code examples
androidgoogle-drive-android-api

Download file from google drive using google-api-services-drive:v3


i just can't manage to download file from google drive, i have just created. I can get the webContentLink. If i access this via browser, i can download file, but i can't download the same file via my app...i read almost every documentation about google drive, but i could not find any way to download file to my storage.

Here i get the link for the file...i can get what ever i want like this

downloadLink = m.getAlternateLink();
downloadLink = m.getEmbedLink();
downloadLink = m.getWebContentLink();
downloadLink = m.getWebViewLink();

or every other parameter like DriveId...

Here is my code to get it the infos for file on Drive:

Query query2 = new Query.Builder()
     .addFilter(Filters.and(Filters.eq(
     SearchableField.TITLE, "locations.csv"),
     Filters.eq(SearchableField.TRASHED, false)))
                                .build();
     Drive.DriveApi.query(mGoogleApiClient, query2)
     .setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
     @Override
     public void onResult(DriveApi.MetadataBufferResult result) {
       if (!result.getStatus().isSuccess()) {
         System.out.println("File does not exists");
           } else {
             for(Metadata m : result.getMetadataBuffer()) {
             if (m.getTitle().equals("locations.csv")) {
              downloadLink = m.getWebContentLink();
              }
           }
        }
      }
   });

In this folder, there is only one file located, i am sure. So i just need a way to get this one file downloaded in background to sd card or better specific folder.

Any help is welcome! Thanks.

MY SOLUTION

On click somewhere in code

driveFileMy.open(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null)
                    .setResultCallback(contentsOpenedCallback);

then i am doing this:

final private ResultCallback<DriveApi.DriveContentsResult>  contentsOpenedCallback =
        new ResultCallback<DriveApi.DriveContentsResult>() {
            @Override
            public void onResult(DriveApi.DriveContentsResult result) {
                if (!result.getStatus().isSuccess()) {
                    // display an error saying file can't be opened
                    return;
                }
                // DriveContents object contains pointers
                // to the actual byte stream
                DriveContents contents = result.getDriveContents();
                InputStream inputStream = contents.getInputStream();
                OutputStream out = null;
                try {
                    out = new FileOutputStream(filelocation);
                    byte[] buffer = new byte[1024];
                    int read;
                    while ((read = inputStream.read(buffer)) != -1) {
                        out.write(buffer, 0, read);
                    }

                    out.flush();
                    inputStream.close();
                    out.close();

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };

String filelocation is the location of output file, where it should be saved. Thanks everyone :)!


Solution

  • The Drive API has a full guide on working with file contents, i.e., getting a direct InputStream of the file.

    Given a DriveFile, you open it with

    DriveFile file = ...
    file.open(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null)
        .setResultCallback(contentsOpenedCallback);
    

    Using a ResultCallback that looks like:

    ResultCallback<DriveContentsResult> contentsOpenedCallback =
        new ResultCallback<DriveContentsResult>() {
      @Override
      public void onResult(DriveContentsResult result) {
        if (!result.getStatus().isSuccess()) {
          // display an error saying file can't be opened
          return;
        }
        // DriveContents object contains pointers
        // to the actual byte stream
        DriveContents contents = result.getDriveContents();
      }
    };
    

    You can then read from the InputStream via contents.getInputStream(), writing it out to local file if you'd like.

    Keep in mind that since Google Drive already keeps a local copy once you've opened a file, if you only need the contents within your app, it is better to use the InputStream directly rather than save it to yet another local file (doubling the storage space needed).