//

GOOGLE PICKER WITH DRIVE

Google Drive is a file storage service that enables users to organize, backup, and share photos, videos, and other documents in the cloud. And allows you to access your files across many different devices, including smartphones.

Google Picker with Drive

Replaces your traditional upload form. Google Picker is a modal window we can put in our application that integrates with many of Google’s services, including Drive. It’s Easier Than input type=”file”"

Google Picker uploads files directly to the user’s Drive, which means...

  • It’s not taking up space on our server
  • It’s not using our bandwidth
  • We don’t have to write any upload code
  • It also looks a lot nicer than the standard file input

Google Developers Console

To get started ..

  • Create a New API Project
  • Enable the Google Picker API
  • Create a New OAuth Client ID
  • Create a Developer API Key

In our application..

  • Include the Google API Loader script
  • Authorize the User
  • Render the Picker

Creating a New API Project

In the Google Developers Console, create a new API Project.

Enabling the Google Picker API

In the sidebar, goto APIs & auth > APIs then enable the Google Picker API.

Creating a New OAuth Client ID

Goto APIs & auth > Credentials then click CREATE NEW CLIENT ID.

Creating a API Key

Goto APIs & auth > Credentials then click CREATE NEW KEY and choose Browser key.

Enter your site’s URL. The page will now show our newly created API key!

The Google API Loader script

This script will be used to load Google’s Authentication and Picker APIs.

<body>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>

this method gets called when the API Loader script is ready to use (we’ll define that method in a bit)

Loading The Picker API

Before we can create a Google Picker modal window, we need to first load the necessary API. We've setup a script tag which will call our local onApiLoad function when complete. Implement this function and have it load the auth and picker libraries.

<script>
  function onApiLoad() {
    gapi.load('auth');
    gapi.load('picker');
  }
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

Loading the Auth and Picker APIs

The method below gets called when the Auth API is done loading (we’ll define that method in a bit too)

function onApiLoad() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker');
}

this tells Google we want access to the user’s Drive, called after the user authenticates (we’ll implement that method next)

function onAuthApiLoad() {
window.gapi.auth.authorize({
'client_id': 'XXXXXXXXXXXX',
'scope': ['https://www.googleapis.com/auth/drive']
}, handleAuthResult);
}

Authenticating the User

Save the oauthToken and create the Picker.

var oauthToken;
function handleAuthResult(authResult) {
    if (authResult && !authResult.error) {
        oauthToken = authResult.access_token;
        createPicker();
    }
}

this is a method we’ll define next that will create our Picker

After Authentication

We're successfully loading the Google Auth and Google Picker libraries! After the auth library has loaded, we'll need to authorize with the Google API. To do this, create a new function named authenticateWithGoogle which will be run after the auth library has loaded.

<script>
  function onApiLoad() {
    gapi.load('auth', {'callback': authenticateWithGoogle});
    gapi.load('picker');
  }
  function authenticateWithGoogle() {
  }
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

Authenticate with Google

We can start the rest of the Google Authentication process now in our authenticateWithGoogle. Implement this function to authorize the https://www.googleapis.com/auth/drive scope with a client_id using the variable we defined. Don't worry about the callback on success yet, we'll do that next.

<script>
  var clientId = '720409271749-hqv3lb4u0q82t68vperem5oi3kosskol.apps.googleusercontent.com';
  function onApiLoad() {
    gapi.load('auth', authenticateWithGoogle);
    gapi.load('picker');  
  }
  function authenticateWithGoogle() {
    window.gapi.auth.authorize({
      'client_id': clientId,
      'scope': ['https://www.googleapis.com/auth/drive']
    });
  }
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

Handling Authentication

After we authenticate with Google with our API key, we can show our actual Picker! …assuming the authentication was successful. Create a new handleAuthentication function that will be called after authentication. In this function, save their access_token to the accessToken variable if authentication was successful.

<script>
  var clientId = '720409271749-hqv3lb4u0q82t68vperem5oi3kosskol.apps.googleusercontent.com';
  var accessToken;
  function onApiLoad() {
    gapi.load('auth', authenticateWithGoogle);
    gapi.load('picker');
  }
  function authenticateWithGoogle() {
    window.gapi.auth.authorize({
      'client_id': clientId,
      'scope': ['https://www.googleapis.com/auth/drive']},
      handleAuthentication);
  }
  function handleAuthentication(authResult) {
    if (authResult && !authResult.error) {
      accessToken = authResult.access_token;     
    }
  } 
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

Basic Picker

After successfully authenticating is a perfect time to set up our picker! Create a new setupPicker function which is executed after successful authentication. In this function, build out a new picker using our saved accessToken and render it.

<script>
  var clientId = '720409271749-hqv3lb4u0q82t68vperem5oi3kosskol.apps.googleusercontent.com';
  var developerKey = 'AIzaSyBTEWsJ4aXdoOzB4ey81eX9-ja7HejL4Qc';
  var accessToken;
  function onApiLoad() {
    gapi.load('auth', authenticateWithGoogle);
    gapi.load('picker');
  }
  function authenticateWithGoogle() {
    window.gapi.auth.authorize({
      'client_id': clientId,
      'scope': ['https://www.googleapis.com/auth/drive']
    }, handleAuthentication);
  }
  function handleAuthentication(result) {
    if(result && !result.error) {
      accessToken = result.access_token;
      setupPicker();
    }
  }
  function setupPicker() {
    var picker = new google.picker.PickerBuilder()
    .setOAuthToken(accessToken)
    .setDeveloperKey(developerKey)
    .build();
    picker.setVisible(true);    
  }
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

Adding Views

We've successfully rendered our Picker, but it's just an empty window. Let's add a new view to it so it does something.

Update setupPicker() to give our Picker the ability to upload files to Google Drive.

<script>
  var clientId = '720409271749-hqv3lb4u0q82t68vperem5oi3kosskol.apps.googleusercontent.com';
  var developerKey = 'AIzaSyBTEWsJ4aXdoOzB4ey81eX9-ja7HejL4Qc';
  var accessToken;
  function onApiLoad() {
    gapi.load('auth', authenticateWithGoogle);
    gapi.load('picker');
  }
  function authenticateWithGoogle() {
    window.gapi.auth.authorize({
      'client_id': clientId,
      'scope': ['https://www.googleapis.com/auth/drive']
    }, handleAuthentication);
  }
  function handleAuthentication(result) {
    if(result && !result.error) {
      accessToken = result.access_token;
      setupPicker();
    }
  }
  function setupPicker() {
    var picker = new google.picker.PickerBuilder()
      .addView(new google.picker.DocsUploadView())
      .setOAuthToken(accessToken)
      .setDeveloperKey(developerKey)
      .build();
    picker.setVisible(true);
  }
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

Let's give the Picker the ability to list files that a user can select.

Add the appropriate view to the Picker.

<script>
  var clientId = '720409271749-hqv3lb4u0q82t68vperem5oi3kosskol.apps.googleusercontent.com';
  var developerKey = 'AIzaSyBTEWsJ4aXdoOzB4ey81eX9-ja7HejL4Qc';
  var accessToken;
  function onApiLoad() {
    gapi.load('auth', authenticateWithGoogle);
    gapi.load('picker');
  }
  function authenticateWithGoogle() {
    window.gapi.auth.authorize({
      'client_id': clientId,
      'scope': ['https://www.googleapis.com/auth/drive']
    }, handleAuthentication);
  }
  function handleAuthentication(result) {
    if(result && !result.error) {
      accessToken = result.access_token;
      setupPicker();
    }
  }
  function setupPicker() {
    var picker = new google.picker.PickerBuilder()
      .setOAuthToken(accessToken)
      .setDeveloperKey(developerKey)
      .addView(new google.picker.DocsUploadView())
      .addView(new google.picker.DocsView())
      .build();
    picker.setVisible(true);
  }
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

Setting a Callback Function

We've given users the ability to view and select files with the DocsView, but clicking the select button doesn't do anything yet.

Define a callback function called myCallback() and set that as the Picker callback.

<script>
  var clientId = '720409271749-hqv3lb4u0q82t68vperem5oi3kosskol.apps.googleusercontent.com';
  var developerKey = 'AIzaSyBTEWsJ4aXdoOzB4ey81eX9-ja7HejL4Qc';
  var accessToken;
  function onApiLoad() {
    gapi.load('auth', authenticateWithGoogle);
    gapi.load('picker');
  }
  function authenticateWithGoogle() {
    window.gapi.auth.authorize({
      'client_id': clientId,
      'scope': ['https://www.googleapis.com/auth/drive']
    }, handleAuthentication);
  }
  function handleAuthentication(result) {
    if(result && !result.error) {
      accessToken = result.access_token;
      setupPicker();
    }
  }
  function setupPicker() {
    var picker = new google.picker.PickerBuilder()
      .setOAuthToken(accessToken)
      .setDeveloperKey(developerKey)
      .addView(new google.picker.DocsUploadView())
      .addView(new google.picker.DocsView())
      .setCallback(myCallback)
      .build();
    picker.setVisible(true);
  }
  function myCallback(data) {
    
  }
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

Setting a Callback Function

We've given users the ability to view and select files with the DocsView, but clicking the select button doesn't do anything yet.

Define a callback function called myCallback() and set that as the Picker callback.

js

Accessing File Metadata

What good is a callback function if it doesn't do anything?

Update myCallback to alert the name of the first file passed in.

[code 1="myCallback(data)" 2="{" 3="alert(data.docs[0" language="function"].name); }


## Handling Picker Actions

The callback function gets triggered when an event occurs in the Picker, not just selecting files.

Update myCallback to only alert the file name if the user clicked Select in the Picker modal.

```js
function myCallback(data) {
  if(data.action == google.picker.Action.PICKED) {
    alert(data.docs[0].name);
  }
}

Handling Picker Actions, Part 2

Remember, multiple events can trigger the callback function, so we need to react differently based on what event occurred.

Update myCallback to alert goodbye when the user clicks the Cancel button.

function myCallback(data) {
    if (data.action == google.picker.Action.PICKED) {
      alert(data.docs[0].name);
    } else if (data.action == google.picker.Action.CANCEL) {
      alert('goodbye');
    }
  }

Enabling New Features

In this particular Picker example, we only have one view, so the navigation sidebar isn't necessary. Fortunately, there's a feature we can enable that hides the navigation.

Update the Picker so that the navigation is hidden.

function setupPicker() {
  var picker = new google.picker.PickerBuilder()
    .setOAuthToken(accessToken)
    .setDeveloperKey(developerKey)
    .addView(new google.picker.DocsUploadView())
    .enableFeature(google.picker.Feature.NAV_HIDDEN)
    .setCallback(myCallback)
    .build();
  picker.setVisible(true);
}

Final source code:

<script>
  var clientId = '720409271749-hqv3lb4u0q82t68vperem5oi3kosskol.apps.googleusercontent.com';
  var developerKey = 'AIzaSyBTEWsJ4aXdoOzB4ey81eX9-ja7HejL4Qc';
  var accessToken;
  function onApiLoad() {
    gapi.load('auth', authenticateWithGoogle);
    gapi.load('picker');
  }
  function authenticateWithGoogle() {
    window.gapi.auth.authorize({
      'client_id': clientId,
      'scope': ['https://www.googleapis.com/auth/drive']
    }, handleAuthentication);
  }
  function handleAuthentication(result) {
    if(result && !result.error) {
      accessToken = result.access_token;
      setupPicker();
    }
  }
  function setupPicker() {
    var picker = new google.picker.PickerBuilder()
      .setOAuthToken(accessToken)
      .setDeveloperKey(developerKey)
      .addView(new google.picker.DocsUploadView())
      .enableFeature(google.picker.Feature.NAV_HIDDEN)
      .setCallback(myCallback)
      .build();
    picker.setVisible(true);
  }
  function myCallback(data) {
    if (data.action == google.picker.Action.PICKED) {
      alert(data.docs[0].name);
    } else if (data.action == google.picker.Action.CANCEL) {
      alert('goodbye');
    }
  }
</script>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>