8

I am using Google Drive.Api in order to get user's app data synced with users drive account.

The user database is in sqlite database format. I have successfully uploaded the file in binary to the drive but failing to download the file from within the app.

How I get the file URl :

  final GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(this, Arrays.asList(DriveScopes.DRIVE_FILE));
    credential.setSelectedAccountName(accountName);
    service = new com.google.api.services.drive.Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential).build();

    Query query = new Query.Builder()
            .addFilter(Filters.eq(SearchableField.TITLE, "BackupFile"))
            .build();


    final DriveFolder folder = Drive.DriveApi.getRootFolder(mGoogleApiClient);
    folder.queryChildren(mGoogleApiClient, query).setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
        @Override
        public void onResult(DriveApi.MetadataBufferResult metadataBufferResult) {
            final MetadataBuffer metadataBuffer = metadataBufferResult.getMetadataBuffer();
            int iCount = metadataBuffer.getCount();

            if (iCount == 1) {
                Log.i("Tag", "file was found");
                final DriveId myFileId = metadataBuffer.get(0).getDriveId();
                final DriveFile file = Drive.DriveApi.getFile(mGoogleApiClient, myFileId);

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        DriveResource.MetadataResult mdRslt = file.getMetadata(mGoogleApiClient).await();
                        if (mdRslt != null && mdRslt.getStatus().isSuccess()) {
                            String link = mdRslt.getMetadata().getWebContentLink();
                            Log.d("TAG", "Link to File:" + link);
                             DownloadBackup(link);
                        }
                    }
                }).start();

            }
            metadataBuffer.release();
        }
    });

Trying to download the File via:

public void DownloadBackup(String url){
        InputStream mInput=null;
        FileOutputStream mOutput=null;
        if(url != null && url.length() > 0 ){
        try {
                GoogleAccountCredential crd = GoogleAccountCredential.usingOAuth2(this, Arrays.asList(DriveScopes.DRIVE_FILE));
                crd.setSelectedAccountName(accountName);
                com.google.api.services.drive.Drive srv = new com.google.api.services.drive.Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), crd).build();
                mInput = srv.getRequestFactory().buildGetRequest(new GenericUrl(url)).execute().getContent();
                String outFileName = getApplicationContext().getDatabasePath(DatabaseHandler.DATABASE_NAME).getPath();
                mOutput = new FileOutputStream(outFileName);
                byte[] mBuffer = new byte[1024];
                int mLength;
                while ((mLength = mInput.read(mBuffer)) > 0) {
                    mOutput.write(mBuffer, 0, mLength);
                }
                mOutput.flush();
                Log.d("TAG", "Successfully Downloaded contents");
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    //Close the streams
                    if(mOutput != null){
                        mOutput.close();
                    }
                    if(mInput != null){
                        mInput.close();
                    }
                } catch (IOException e) {
                    Log.e("Tag", "failed to close databases");
                }
            }
        } else {
            // The file doesn't have any content stored on Drive.
            // return null;
            Log.e("Tag", "No content on Drive");
        }
    }

Error Log:

W/System.err﹕ com.google.api.client.http.HttpResponseException: 401 Unauthorized
W/System.err﹕ <HTML>
W/System.err﹕ <HEAD>
W/System.err﹕ <TITLE>Unauthorized</TITLE>
W/System.err﹕ </HEAD>
W/System.err﹕ <BODY BGCOLOR="#FFFFFF" TEXT="#000000">
W/System.err﹕ <H1>Unauthorized</H1>
W/System.err﹕ <H2>Error 401</H2>
W/System.err﹕ </BODY>
W/System.err﹕ </HTML>
W/System.err﹕ [ 06-12 11:01:05.447 26208:26236 W/System.err ]
        at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1061)
W/System.err﹕ at com.example.app.activities.Main.DownloadBackup(Main.java:487)
W/System.err﹕ at com.example.app.activities.Main$15$1.run(Main.java:332)
W/System.err﹕ at java.lang.Thread.run(Thread.java:841)
Amit
  • 13,134
  • 17
  • 77
  • 148
GenerikV
  • 91
  • 2
  • 5
  • Notice that you are mixing the Drive Android API (to query and get the link) and the Drive REST API (to download). It might be better to use the same API throughout. For the Android API see https://developers.google.com/drive/android/files For the REST API see https://developers.google.com/drive/web/quickstart/java – Ofir Jun 12 '15 at 22:00

1 Answers1

4

Here is how I do it successfully. Instead of saving the result of 'getWebContentLink', I save a file/folder ID (it is a string). And pass this ID to a method like this one:

 /*************************************************************************
   * get file contents
   * @param resId  file driveId
   * @return       file's content  / null on fail
   */
  static InputStream read(String resId) {
    if (mGOOSvc != null && mConnected && resId != null) try {
      File gFl = mGOOSvc.files().get(resId).setFields("downloadUrl").execute();
      if (gFl != null){
        String strUrl = gFl.getDownloadUrl();
        return mGOOSvc.getRequestFactory()
        .buildGetRequest(new GenericUrl(strUrl)).execute().getContent();
      }
    } catch (Exception e) { /* error handling */ }
    return null;
  }

retrieving a "downloadURL" and get the content. The full context of this method can be seen here.

Good Luck

seanpj
  • 6,735
  • 2
  • 33
  • 54
  • ... and I guess you can retrieve / save / use the "downloadUrl" string as well, but the ID (ResourceID) entity is considered the primary identifier. – seanpj Jun 12 '15 at 14:51
  • File gFl = mGOOSvc.files().get(resId).setFields("downloadUrl").execute(); Doesn't execute. Even when "if (mGOOSvc != null && mConnected && resId != null)" conditions are met. – GenerikV Jun 13 '15 at 09:53
  • I understand 'doesn't execute' as 'does not return'. If this is the case, the server is not responding. Have you tried to formulate the params (and test it) [here (bottom of the page)](https://developers.google.com/drive/v2/reference/files/get) – seanpj Jun 13 '15 at 11:25
  • 1
    As per Ofir 's comment above, you're mixing GDAA with REST. Possible but dangerous (latency / timing). Look at the difference between [GDAA](https://github.com/seanpjanson/GDAADemo) and [REST](https://github.com/seanpjanson/RESTDemo) implementations of CRUD. An be mindful of the difference between [DriveId and ResourceID](http://stackoverflow.com/questions/29030110/cannot-get-folderid-that-i-just-created-on-google-drive/29049474#29049474) – seanpj Jun 13 '15 at 11:36
  • Seems like I was using Drive.Id with your method. I used ResourceId and the file got downloaded successfully. Thanks a lot :D But now I have another issue, the downloaded file doesn't contain the content original .db file contained. – GenerikV Jun 13 '15 at 12:09
  • Before you go further, clean the REST vs. GDAA issue. Decide which one to use (GDAA is newer, more powerful, works off-line, but does not have all the functionality of the REST API). You can use the two demos I mentioned to get started. Or go for original Google resources on [GitHub](https://github.com/googledrive/android-demos) – seanpj Jun 13 '15 at 13:56
  • Done that now, Using GDAA for uploading as well as downloading the file. Just one more help needed, if you could guide me with editing/updating the same file. Method provided here https://github.com/seanpjanson/GDAADemo/blob/master/src/main/java/com/andyscan/gdrtdemo/GDAA.java#L217 is a bit confusing – GenerikV Jun 16 '15 at 09:28
  • What you want to update? It's metadata (filename, date, favorite,...) or it's content? – seanpj Jun 16 '15 at 13:45
  • Content of the SQLite database file. – GenerikV Jun 18 '15 at 01:57