Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid parent folder error for AppFolder in Drive API

I get an invalid parent folder error, and I've seen the solutions to use resource ID rather than Drive ID, but it's a different scenario here.

I'm trying to access the AppFolder, and this just uses the GoogleApiClient like so:

this.appFolder = Drive.DriveApi.getAppFolder(mGoogleApiClient);

When I later try to create a file in it, I get the above error.

DriveFolder.DriveFileResult fileResult = appFolder.createFile(mGoogleApiClient, changeSet, driveContentsResult.getDriveContents()).await();

Then fileResult.getStatus() gives me the erros.

This used to work for me before. What's different is that I've manually emptied my app's data on Google Drive (delete hidden app data). But I haven't disconnected the app - so I would assume that appFolder will continue to work the same way...

So far the only workaround is uninstalling the app, but this way I lose my data.

This is reproducible. Please help.

like image 759
mmagician Avatar asked Oct 20 '15 23:10

mmagician


2 Answers

Update: This issue, #4483, was fixed in January 2017. The following fix may not apply anymore.

Since this continues to be an outstanding issue, I have taken steps to establish a work-around that can be done with code without resorting to user intervention.

As @seanpj says, this issue does not always occur and seems to be dependent upon the sync status of the Drive service. However, if the problem does occur, the following method works for me to circumvent the problem. I post it here in case it may be helpful to someone else. The Javadoc has more information.

/**
 * Works around the Drive API for Android (GDAA) issue where the appDataFolder becomes
 * unavailable after hidden app data is deleted through the online Drive interface
 * (Settings->Manage Apps->Delete hidden app data) by using the REST v3 API to create an
 * empty file in appDataFolder. The file is immediately deleted after creation but leaves
 * the appDataFolder in working order.
 * See <a href="https://code.google.com/a/google.com/p/apps-api-issues/issues/detail?id=4483"
 * target="_blank">apps-api-issues #4483</a>
 * <p>
 * Call this method after a call to the Drive API fails with error code 1502
 * (DriveStatusCodes.DRIVE_RESOURCE_NOT_AVAILABLE) when dealing with the appDataFolder then
 * try the failed operation again.
 * <p>
 * This method assumes that all appropriate permissions have been granted and authorizations
 * made prior to invocation.
 *
 * @param context - Context
 * @param account The account name that has been authorized, e.g., [email protected].
 * @throws IOException From the REST API.
 */
private void fixAppDataFolder(Context context, String account) throws IOException {
    final String[] SCOPES = {DriveScopes.DRIVE_APPDATA};
    GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(
            context, Arrays.asList(SCOPES)).setBackOff(new ExponentialBackOff());
    HttpTransport transport = AndroidHttp.newCompatibleTransport();
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
    com.google.api.services.drive.Drive driveService;

    credential.setSelectedAccountName(account);
    driveService = new com.google.api.services.drive.Drive.Builder(
            transport, jsonFactory, credential)
            .setApplicationName("Your app name here")
            .build();

    File fileMetadata = new File();
    fileMetadata.setName("fixAppDataFolder")
            .setMimeType("text/plain")
            .setParents(Collections.singletonList("appDataFolder"));

    File appDataFile = driveService.files()
            .create(fileMetadata)
            .setFields("id")
            .execute();

    driveService.files().delete(appDataFile.getId()).execute();
} // fixAppDataFolder
like image 101
Cheticamp Avatar answered Nov 15 '22 19:11

Cheticamp


Although this does not solve your problem, your question got me interested, so I ran a little test using this demo (follow "appfolder" in this code). Here's what I learned:

First, I could reproduce your problem using the following sequence

1/ getAppFolder(mGAC)  
2/ create folder DEMOROOT in app folder
3/ create folder 2015-10 in DEMOROOT  
4/ create file with content in 151022-075754 in 2015-10  

5/ list full tree ... result \DEMOROOT\2015-10\151022-075754  
6/ read content of 151022-075754 ... OK

so far so good. Without disconnecting, I go to

drive.google.com > Settings > Manage Apps > Options > Delete hidden app data

Now, there should be no objects in the app folder, I run:

1/ getAppFolder(mGAC)  
2/ list full tree ... result \DEMOROOT\2015-10\151022-075754  
3/ read content of 151022-075754 ... FAIL

As you can see, in my situation the getAppFolder(mGAC) returns valid DriveFolder (DriveId) that can be used. Even the DriveId string looks the same. Listing of folders/files returns valid objects. It is not supposed to, but I know there is a latency I have to count on, so the list result may change later to reflect the deletion. Attempt to read the file content fails.

A few minutes later (GDAA probably synchronized), the same attempt to list fails, still understandable result, but another attempt to create any object (folder/file) in app folder fails with 'invalid parent folder' error as you pointed out. Disconnect / re-connect does not help, so the app is toasted.

This points to a serious bug that should be addressed. Again the same as in SO 30172915, an uneducated user's action can cause irreparable damage - loss of data to the Android App with no known remedy.

like image 21
seanpj Avatar answered Nov 15 '22 18:11

seanpj