Upload Any File to Google Drive,
using Google Drive API
Herewith, another method to upload files from your AppInventor App to Google Drive, this time using the Google Drive API, so no messing around with google apps script, or converting files to base64, ... just clean and simple file uploads (on the surface....)
The method requires you to setup a cloud project on the Google Cloud Console, to then verify the project with your account (as test user), and then to generate access and refresh tokens that can be used in the app to authenticate with Google Drive, and allow file uploads, to a folder of your choice. Two videos have been created (please excuse the mistakes and wrong turns I made) to show the creation of a cloud project, and then the verification, along with accessing the tokens.
VIDEO Part 1 - Setting up Google Cloud Project
(Seems we only need the www.googleapis.com/auth/drive.file scope) - see also Addendum below
VIDEO Part II - Verifying Cloud Project and Getting Tokens
Commands used in Part 2 as text
SETUP - cont'd
AppInventor App creation time
We now have our client_id, client_secret and refresh token. This is sufficient for the creation of blocks to send a POSTText request to Google, in order to return an access_token.
Once we have the access_token, blocks can be created to upload the file. But there is a catch. The web component cannot use multipart, therefore we have to send two web calls, the first (POSTFile) to upload the actual file (which is untitled and goes to the root folder of Google Drive), the second (PATCHtext) to send the metadata (filename, folderId) which correctly names the file, and moves it to the designated folder.
It took a fair bit of head scratching and trial and error to figure out how to do this, the issues were eventually solved (light bulb moment) when I threw some parameters at the API Explorer, which returns the code, including the correct headers, needed for cURL and HTTP.
The blocks shown below are setup to ensure that we only call for a refresh_token when one is needed, a Get Access Token button is included to show the access_token being returned.
In the "simple" demo, a file is available in the assets for testing uploads. You can upload the same file as many times as you like, it does NOT overwrite.
The workflow of the blocks goes something like this:
Press the Upload File button
This initiates the uploadFile procedure, to upload the file
In the Web2.GotText event we first test if "Invalid Credentials" is returned in the responseContent (which means there is no valid access_token)
If it is, then we run the callAccessToken procedure
This fetches a new access_token, and initiates the uploadFile procedure again
If we already have a valid access_token, the the file is uploaded to Google Drive root, with an "Untitled" filename
From this, the responseContent returns the id of the file created on Google Drive
We use the fileId when the second web call is then made with the metadata (filename, folderId) using PATCHText
The file on Google Drive is renamed and moved to the designated folder
The responseContent returned contains the filename and the fileID for reuse in the app.
The following web pages were a great help in getting this all setup:
I have only scratched the surface here of what is possible using the Google Drive API, I guess listing a folder, and downloading files is next on the list....
This tutorial has the cloud project setup in Testing mode, with a single test user. A developer could move such a project into Production, get the project verified, then any user could connect to the project to upload files to their own google drive.
On using the above, and also by seeking out solutions for listing and downloading files, I learnt much more about how this all works.
If when setting up an 0Auth Client ID with "TV" as the device, you are severely restricted on which scopes you can use. The "drive.file" scope certainly allows the app to upload files, but you can only list and download the files that you upload. This sandbox is for the most part a good thing, because it does not expose the entirety of your google drive, however some may find this restricting, and will want to be able to offer other folders and files on the google drive for the app to access.
After doing some digging around, I found this, which explains a similar approach, but uses "Web App" instead of "TV", and requires you to have a domain named web server ( you just have to have one, you do not need to use it after setup). With this method, I was able to setup my AppInventor app with the "drive" scope (a much more sensitive/restricted scope, giving full access to google drive), but this should be controllable through the setup in the AppInventor app .
Below, the commands required to get the "refresh_token" needed:
In a browser:
this (for me) returned a code in the url address bar:
I then took this code and ran it in the following cURL command:
It maybe that all your app needs is the "drive.file" scope, or perhaps "drive.readonly" (for listing and downloads only)...
You can request more than one scope, just put each one in a list, separated by a space, e.g.
Using the drive or drive.readonly scope, here are some blocks to download a file or to list files in a specific folder, using the Google Drive API with AppInventor: