Simple actions with Google Drive API v2

In this post I'll describe how to make simple actions with Google Drive from own apps.

First of all you have to do these steps:
  • Enable the Drive API from Google API Console
  • Add Drive API v2 to your project
  • Make sure the Google Play Services client library is being included in the Android's project build path
You can find official doc here. It is very simple.

Now we can try to use API.

In order to use Google Drive, we have to choose a Google Account. It is very easy, and I described it in a previous post. In a real app, you can save your account in preferences.

CREATE A FOLDER

When we use Google Drive API, we have to get a token. We can use this code:
private void initService() {
     mCredential = GoogleAccountCredential.usingOAuth2(this, DriveScopes.DRIVE);
     if (mAccountName != null) {
         mCredential.setSelectedAccountName(mAccountName);
         mService = getDriveService(mCredential);
     }
}

private Drive getDriveService(GoogleAccountCredential credential) {
    return new Drive.Builder(AndroidHttp.newCompatibleTransport(),
    new GsonFactory(), credential).build();
}
If the user has already authorized the application the Drive service will be authorized and work as expected.
If the user has not authorized the application using the Drive service will throw an UserRecoverableAuthException containing an Intent that can be used to display to the user the authorization grant dialog.
/**
  * Create a folder
  */
  private void createFolder() {
    Thread t = new Thread(new Runnable() {
       @Override
       public void run() {
          try{
             if (mService == null)
                initService();
             .... 
          } catch (UserRecoverableAuthIOException e) {
             Intent intent = e.getIntent();
             startActivityForResult(intent, REQUEST_AUTHORIZATION_FOLDER);
          }

Here you can see our authorization grant dialog.

When we authorize an app, we can find it (and remove it) in Google Account Page > Security > Connected applications and sites

Finally to create a folder we can complete our code with:
    private static final String MIME_FOLDER = "application/vnd.google-apps.folder";
    private static final String FOLDER_NAME = "backup";

    File body = new File();
    body.setTitle(FOLDER_NAME);
    body.setMimeType(MIME_FOLDER);

    File file = mService.files().insert(body).execute();
In the Drive API, a folder is essentially a file identified by the special folder MIME type application/vnd.google-apps.folder.
We can create a new folder by inserting a file with this MIME type and a folder title.

Google Drive assigns a unique id to this folder.We can see from log:
Folder created : [title]=backup [id]=0B43XsXwiguvuNzJwc0ZZZ3VEMWM

CREATE A FILE

Now we can create a file in this folder.
private void createFile() {
   Thread t = new Thread(new Runnable() {
     @Override
     public void run() {

       if (mService == null)
          initService();

       try {
          // Create Folder if it doesn't exis
          File folder = _createFolder();

          String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
         Locale.ITALIAN).format(new Date());

          File body = new File();
          body.setTitle("Example file " + timeStamp);
          body.setMimeType(MIME_TEXT_PLAIN);
          body.setDescription("File Description");

          String bodyText = " Lorem ipsum dolor sit amet, consectetur adipisici elit,"
                      + "sed eiusmod tempor incidunt "
                      + "ut labore et dolore magna aliqua. Ut enim ad minim veniam," 
                      + "quis nostrud exercitation ullamco labor....";
 
          // Set the parent folder.
          body.setParents(Arrays.asList(new ParentReference()
           .setId(folder.getId())));

          ByteArrayContent content = ByteArrayContent.fromString("text/plain", bodyText);
          File file = mService.files().insert(body, content).execute();
          .....
       } catch (UserRecoverableAuthIOException e) {
                Intent intent = e.getIntent();
                startActivityForResult(intent, REQUEST_AUTHORIZATION_FILE);
       } catch (IOException e) {
                Log.e("TAG", "Error in upload", e);
       }
     }
  });
  t.start();
}
It is important to use body.setParents() if you want to put file in a folder.


SEARCH A FOLDER OR A FILE

    Files.List request = mService.files().list()
        .setQ("mimeType = '" + MIME_FOLDER + "' and title = '" + FOLDER_NAME + "' ");

    FileList files = request.execute();

    if (files != null) {
        for (File file : files.getItems()) {
            Log.i(TAG, "Folder exists [title]=" + file.getTitle()
                 + " [id]=" + file.getId());
      ......
        }
    }
We can use q parameter which is a search query combining one or more search clauses.
I like this parameter, it is very powerful.
You can find full doc here
In our example we have:
{q=mimeType = 'application/vnd.google-apps.folder' and title = 'backup'}

This is log output:
Folder exists [title]=backup [id]=0B43XsXwiguvuNzJwc0ZZZ3VEMWM

Pay attention!
If you move your file (or your folder) in BIN folder it already exists !!

RETRIEVE FILES IN A FOLDER

We can use this code.
private void retrieveFiles(){
   ....
   Files.List request = mService.files().list()
      .setQ("mimeType = '" + MIME_TEXT_PLAIN
                           + "' and '" + folder.getId()
                           + "' in parents ");

   FileList files = request.execute();

   if (files != null) {
      for (File file : files.getItems()) {

        // Meta data
        Log.i(TAG, "Title: " + file.getTitle());
        Log.i(TAG, "Description: " + file.getDescription());
        Log.i(TAG, "MIME type: " + file.getMimeType());
        String content=getContentFile(file); 
    .....
}

private String getContentFile(File file) {
   String result;
  
   if (file!=null && file.getDownloadUrl() != null
         && file.getDownloadUrl().length() > 0) {
   
   try {
      GenericUrl downloadUrl = new GenericUrl(file.getDownloadUrl());
      HttpResponse resp = mService.getRequestFactory().buildGetRequest(downloadUrl).execute();
      InputStream inputStream = null;

      try {
         inputStream = resp.getContent();
         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
         StringBuilder content = new StringBuilder();
         char[] buffer = new char[1024];
         int num;

         while ((num = reader.read(buffer)) > 0) {
             content.append(buffer, 0, num);
         }
         result = content.toString();
     
     } finally {
        if (inputStream != null) {
            inputStream.close();
     }
     .....
}
In our example we get all files in backup folder.
To do this, we use a search with q parameter. In this case we have this search, where '0B43XsXwiguvuNzJwc0ZZZ3VEMWM' is the backup folder id:
{q=mimeType = 'text/plain' and '0B43XsXwiguvuNzJwc0ZZZ3VEMWM' in parents }

This is log output:
Title: Example file 20130404_115646
Description: File Description
MIME type: text/plain

Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco labor....



You can get code from GitHub:

Comments

Post a Comment

Popular posts from this blog

AntiPattern: freezing a UI with Broadcast Receiver

NotificationListenerService and kitkat

How to centralize the support libraries dependencies in gradle