4

An application is published on Play Store and it is using 'application data folder' for the backup-restore purpose using Drive API. Everything works fine. However, this API is about to be turned down on 6th December, 2019 according to Google's announcement. Therefore, in order to support existing users, I have been migrating to latest API according to migration guidlines and an official sample app.

I can successfully authenticate using the code (from the official link) below.

GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                                         .requestEmail()
                                         .requestScopes(new Scope(DriveScopes.DRIVE_APPDATA))
                                         .build();
GoogleSignInClient client = GoogleSignIn.getClient(this, signInOptions);

// The result of the sign-in Intent is handled in onActivityResult.
startActivityForResult(client.getSignInIntent(), REQUEST_CODE_SIGN_IN);

I am also using correct scope - DriveScopes.DRIVE_APPDATA as mentioned in the official documentation.

I am also seeing correct values of 'email' and 'granted scopes' inside onActivityResult()

if (requestCode == REQUEST_CODE_SIGN_IN && resultCode == RESULT_OK) {

   GoogleSignIn.getSignedInAccountFromIntent(data).addOnSuccessListener(new OnSuccessListener<GoogleSignInAccount>() {
                @Override
                public void onSuccess(GoogleSignInAccount googleSignInAccount) {

                    Log.e("TAG", "Email - " + googleSignInAccount.getEmail()); // prints correct value
                    Log.e("TAG", "Granted scopes - " + googleSignInAccount.getGrantedScopes()); // prints correct value

                    GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(getActivity(), Collections.singleton(DriveScopes.DRIVE_APPDATA));
                    credential.setSelectedAccount(googleSignInAccount.getAccount());

                    Drive googleDriveService = new Drive.Builder(
                            AndroidHttp.newCompatibleTransport(),
                            new GsonFactory(),
                            credential)
                            .setApplicationName("App Name") // Changed it for now
                            .build();
                    mDriveServiceHelper = new DriveServiceHelper(googleDriveService);

                    queryFiles();
                }
            });
}

However, whenever I try to access a backup file in queryFiles() using the code (from the official link) below,

FileList files = driveService.files().list()
    .setSpaces("appDataFolder")
    .setFields("nextPageToken, files(id, name)")
    .setPageSize(10)
    .execute();
for (File file : files.getFiles()) {
  System.out.printf("Found file: %s (%s)\n",
      file.getName(), file.getId());
}

It throws the following error

{
  "errors": [
   {
    "domain": "usageLimits",
    "reason": "dailyLimitExceededUnreg",
    "message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
    "extendedHelp": "https://code.google.com/apis/console"
   }
  ],
  "code": 403,
  "message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
 }

Kindly help me fix the error. I believe that as everything is working fine with the published version, everything should be correct in terms of configuring on Google API console.

Harsh4789
  • 677
  • 7
  • 17

2 Answers2

7

I probably can't find ALL threads with this problem but I can try to help in a few or so.

PRIMARY ANSWER

IF you're using ProGuard same as I am. ProGuard can cause this error to happen during query. I fixed it using the following.

# Fix OAuth Drive API failure for release builds
-keep class * extends com.google.api.client.json.GenericJson { *; }
-keep class com.google.api.services.drive.** { *; }
-keepclassmembers class * { @com.google.api.client.util.Key <fields>; }

SECONDARY ANSWER

Note that you DO NOT need to use keys/tokens using the Drive rest API with Android like you may find from other solutions (it may not hurt either, but it can). It doesn't match up here to what people talk about elsewhere (here they don't know what they're talking about).

See my notes here for further info: Google Drive via OAuth release version receives dailyLimitExceededUnreg

IF you have the problem however in debug build then you did not do everything correctly. My notes should get you on the right track.

If you need further help, I might assist because of how nuts it is.

EXAMPLE OF GETTING A FILE FROM DRIVE WITH THE NEW API USE

Just see from the following link

public Task<Pair<String, String>> readFile(String fileId)

https://github.com/gsuitedevs/android-samples/blob/master/drive/deprecation/app/src/main/java/com/google/android/gms/drive/sample/driveapimigration/DriveServiceHelper.java

The id comes from the query result where the id is part of that query info attached to that which is returned from the Drive query. The id is the file id for the file you want to retrieve. Pass that in to readFile and it gives you the file contents back that you can save locally to java.io.File eg fileOutputStream.write(contents.getBytes()); the contents of which is pair.second. You would then have your hopefully (because sometimes we have more work to do) identical java.io.File.

You can see a basic query if you need one in the the link sample as well but its missing some important info because depending on what you do you may need to check if trashed, get file size, modify time, md5, set order, etc. You may need to see https://developers.google.com/drive/api/v2/reference/files/list and https://developers.google.com/drive/api/v3/reference/files etc to figure that out. If enough files, there will be a paged requirement as well.

I know using Drive from code is a bit nuts (well, it is to me anyway lol) so hang in there =)

CmosBattery
  • 934
  • 7
  • 13
  • Updated my link with all the info you should need. – CmosBattery Oct 15 '19 at 00:28
  • You nailed it. I have spent a few days to resolve it but couldn't. I wish I could accept your answer more than once because you deserve that. Anyways, I will upvote your answer too. Apart from this, could you please help me in how can I save the file to local storage? Because I could not figure out a way to convert 'com.google.api.services.drive.model.File' to 'java.io.File'. – Harsh4789 Oct 15 '19 at 08:09
  • Updated the answer to help you get to a java.io.File – CmosBattery Oct 15 '19 at 12:52
  • Thanks a lot for the update. Instead of using the readFile() method as is, I am directly saving InputStream to the local storage so it has become easier than the way given in the official GitHub project. – Harsh4789 Oct 16 '19 at 05:02
  • Thanks. It really worked about ProGuard. Stupid Google.....Why not write in docs – EricZhao Nov 06 '19 at 02:50
  • @CmosBattery, thanks a lot for that proguard rule! I was getting crazy here, man. Awesome! – oak Jul 11 '20 at 15:37
  • Thanks for your answer. This saved me from a terrible gloom. I was already getting really frustrated trying to figure out what was wrong. Immediately I enabled minify or upload the app to playstore, the rest API stopped working until I included the proguard rules. – Chuba Samuel - DCOR Aug 13 '20 at 01:45
-1

For Documentation purposes as a troubleshooting step:

Go to

https://console.developers.google.com/project/<project-id>/apiui/api

Or for Google Scripts:

https://script.google.com/home/usersettings

Replace with the ID of your application and check that the Google Drive API is turned on.

If it isn't - make sure to get a new token after turning it on if this is the case.

Rafa Guillermo
  • 14,474
  • 3
  • 18
  • 54
  • Thank you very much for your response but the app is published on Play Store and it can successfully backup and restore using deprecated API. Also, I have verified once again that Google Drive API is enabled. – Harsh4789 Oct 14 '19 at 10:06
  • Make sure you are not using the same token as the one you were using before you enabled the Drive API, as the old one will only be valid for the Android Drive API that's being deprecated. – Rafa Guillermo Oct 14 '19 at 10:55
  • I would greatly appreciate if you could mention about how to verify this token part. I tried to create a new Oauth Client Id on API Console but it does not let me create saying that 'The fingerprint you specified is already used by an Android OAuth2 client ID in this project or another project' – Harsh4789 Oct 14 '19 at 12:47
  • Have a look at the answer [here](https://stackoverflow.com/questions/49565332/the-fingerprint-you-specified-is-already-used-by-an-android-oauth2-client-id-in), I believe this is related to your question. – Rafa Guillermo Oct 14 '19 at 14:32
  • Anyone who brings up tokens as to fixing this problem, I will automatically down vote because its wrong here. – CmosBattery Oct 14 '19 at 23:50
  • @CmosBattery This is why I made this a [community wiki](https://meta.stackexchange.com/a/11741/564292). It is not always a definitive solution but there are many users who this will be an issue for and additional troubleshooting steps are always welcome. – Rafa Guillermo Oct 15 '19 at 06:55