Tips

Unable to locate specific folders using Google Drive API

Pinterest LinkedIn Tumblr

I’m trying to get the URL of a file that is on my drive, knowing its name and the name of the parent folder. But the result is always null.

I’m using a service account with owner permission, I already put the correct credentials inside the project and shared the folder and file with the service account email, and still, the problem continues. When debugging the code it is possible to see that the size of List<File> folders = result.getFiles();  is 0.

Here is the complete code:

import android.content.Context;

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;

import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;

public class DriveAccessRunnable implements Runnable {

   private static final String APPLICATION_NAME = "School Grade";

   private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();

   private static Drive driveService;
   private final Context context;
   private final String parentFolderTitle;
   private final String fileName;
   private final DriveAccessCallback callback;

   public DriveAccessRunnable(Context context, String parentFolderTitle, String fileName, DriveAccessCallback callback) {
      this.context = context;
      this.parentFolderTitle = parentFolderTitle;
      this.fileName = fileName;
      this.callback = callback;
   }

   @Override
   public void run() {
      try {
         // Google Drive access code
         HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
         driveService = new Drive.Builder(httpTransport, JSON_FACTORY, getHttpRequestInitializer())
                 .setApplicationName(APPLICATION_NAME)
                 .build();

         // Get the URL of the file or null if not found
         String fileUrl = getFileUrl(parentFolderTitle, fileName);

        
         // Call the callback with the result
         callback.onFileUrlReceived(fileUrl);
      } catch (IOException | GeneralSecurityException e) {
         e.printStackTrace();
         // Call the callback with an error result
         callback.onError(e.getMessage());
      }

   }

   private HttpRequestInitializer getHttpRequestInitializer() throws IOException {
      InputStream credentialsStream = context.getResources().openRawResource(R.raw.credentials);

      GoogleCredentials credentials = GoogleCredentials.fromStream(credentialsStream)
              .createScoped(Collections.singletonList(DriveScopes.DRIVE_FILE));

      return new HttpCredentialsAdapter(credentials);
   }

   private String getFileUrl(String parentFolderTitle, String fileName) throws IOException {
     
       // Search parent folder by title
      FileList result = driveService.files().list()
              .setQ("mimeType='application/vnd.google-apps.folder' and trashed=false and name='" + parentFolderTitle + "'")
              .setSpaces("drive")
              .setFields("files(id)")
              .execute();

      List<File> folders = result.getFiles();

      if (!folders.isEmpty()) {
         String parentFolderId = folders.get(0).getId();

         
         // Browse files inside the parent folder
         result = driveService.files().list()
                 .setQ("'" + parentFolderId + "' in parents and trashed=false")
                 .setFields("files(name, webViewLink)")
                 .execute();

         List<File> files = result.getFiles();
         for (File file : files) {
            if (file.getName().equals(fileName)) {
               return file.getWebViewLink();
            }
         }
      }

      return null;
   }


   public interface DriveAccessCallback {
      void onFileUrlReceived(String fileUrl);
      void onError(String errorMessage);
   }
}

Vishal Swami is a hardcore Android programmer and Android programming has been his passion since he compiled his first hello-world program. Solving real problems of Android developers through tutorials has always been an interesting part for him.