NewImage.pngHere’s a quick tutorial to add Dropbox support into a Java program in leJOS 0.9.0. It turned out to be far easier than I thought! Read on to discover how you can easily upload and download files to and from your Dropbox account from the EV3 in leJOS.

Dropbox? On the EV3?

The first thing to realise is that I’m not going to show you how to install the Dropbox helper on your EV3. Instead we’re going to use the Dropbox Core Java SDK to connect our EV3 to your existing Dropbox account (free or pro, doesn’t matter) and then upload and download files into the account.

Dropbox is well known as a cloud file-sync service that ‘just works’. I’ve been using it for years, both as a pro and business user, and the software runs in the background, never complains and just gets on with the business of keeping all of your files in sync. Luckily Dropbox have extended the same simplicity to their SDK; I was amazing at just how easy it is to use the Java SDK in leJOs 0.9.0 to upload images captured from a webcam to my Dropbox account.

The Dropbox team have done a great job explaining how to use the Java SDK in a series of tutorials here: https://www.dropbox.com/developers/core/start/java
Getting ready
There are a few steps to get everything set up, but once you’ve done the setup you won’t have to repeat it. I’m assuming that these things are in place:
  1. You have a Dropbox account
  2. You have Eclipse installed and leJOS plugin installed
  3. You have a wifi equipped EV3 connected onto your home wifi
  4. You are comfortable logging into your EV3 using ssh in the terminal; you’ll need to run a program on the command line to authorise your EV3 to talk to Dropbox.
The basic flow is to import the Dropbox Java SDK into Eclipse, and then use the Dropbox API to creation an authorisation key that allows the EV3 to talk to your Dropbox account.

Step 1: Download the Dropbox Core API

The Java SDK is here: https://www.dropbox.com/developers/core. Download the Zip file and extract it into a folder on your laptop.
NewImage

Step 2: Create a new leJOS project in Eclipse

I’m assuming you have a working leJOS installation and the leJOS Eclipse plugin installed. If not, go to the leJOS website and follow the instructions on the wiki to get everything set up. Let’s call it DropboxSetup for now.

Step 3: Import the Dropbox Jar files from the SDK into your project

Right click on the DropboxDigitalCamera project, select Properties and then choose ‘Java Build Path’. Click ‘Add External JARs…” and navigate to the two JAR files in the dropbox-sdk/lib folder. Import them into the project and your build path should look something like this:
NewImage

Step 4: Create a new Dropbox app

Log into your Dropbox account and then go to the https://www.dropbox.com/developers/apps page and create a new Dropbox app. Make sure you create a Dropbox API app, and give it a name. The name you choose here will be used in your Dropbox/Apps folder when the EV3 uploads and downloads files. This is safer than giving your EV3 access to the all of the files in your Dropbox account.
NewImage

Step 5: Get the app key and app secret

Dropbox uses an app key and secret assigned to your app to create an access token. The access token is what you need to store on the EV3 so that it can authenticate itself to Dropbox and get access to files in your account.
If you click on the app from Step 4 in the App Console, you’ll see the App key and App secret displayed. Copy these values (obviously I’ve blurred the App key for my Dropbox account here).
NewImage

Step 6: Copy the Dropbox JARs onto the EV3

The Dropbox JARs need to be copied onto the EV3. The easiest way to do this is with your file browser, or scp them from your computer to the EV3. I placed the JARs in /home/lejos/programs/lib.

Step 7: Authorise the EV3 to Dropbox, get the auth token

The last step is to log into the EV3 and run a small Java program to connect the EV3 to your Dropbox account and get the authorisation token. The auth token is saved locally on the SDcard in the EV3 and used by all subsequent programs that need to talk to Dropbox.
The code you need to run is based off the Dropbox tutorial. Copy the App key and secret into the code below and then upload it from Eclipse onto the EV3. ssh into your EV3 and run the code below on the command line as follows:
jrun -cp /home/lejos/programs/lib/dropbox-core-sdk-1.7.7.jar:/home/lejos/programs/lib/jackson-core-2.2.4.jar:GetAccessToken.jar GetAccessToken

NewImage


Here is a screenshot of me running the code on my EV3. I’ve blurred out the app key and secret, and the returned authorisation code!

Step 8: You’re done!

That’s it – your EV3 is now authorised to talk to your Dropbox account, and the authorisation token is stored in the file access-token.json on the  EV3. If you lose this file it’s easy to run this program again and re-create it. But don’t share it with anyone, otherwise they can access your Dropbox account!

The code

Here's the code you need.

import com.dropbox.core.*;
import com.dropbox.core.json.JsonReader;

import java.io.*;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;

import lejos.hardware.lcd.LCD;

/**
 * An example command-line application that runs through the web-based OAuth
 * flow (using {@link DbxWebAuth}).
 * 
 * By Mark Crosbie http://thinkbricks.net
 * Modified from the Dropbox tutorial code
 */
public class GetAccessToken {
	
	// The access token is saved in this file on the EV3 SDcard
	public static final String accessTokenFilename = "./access-token.json";
	
    public static void main(String[] args) throws IOException {
    	
    	LCD.clear();
    	
    	System.out.println("-- Get Dropbox auth token --");
    	System.out.println("1. Log into Dropbox and go to the App Console in your account");
    	System.out.println("2. Click on the app you created for the EV3");
    	System.out.print("3. Enter the App key value here: ");
        String appKey = new BufferedReader(new InputStreamReader(System.in)).readLine();
        if (appKey == null) {
            System.exit(1); return;
        }
        appKey = appKey.trim();
        
        System.out.println("");
        System.out.print("4. Enter the App secret value here: ");
        String appSecret = new BufferedReader(new InputStreamReader(System.in)).readLine();
        if (appSecret == null) {
            System.exit(1); return;
        }
        appSecret = appSecret.trim();
        System.out.println("");
        
    	System.out.println("5. Starting Dropbox auth flow");
    	DbxAppInfo appInfo = new DbxAppInfo(appKey, appSecret);

        String userLocale = Locale.getDefault().toString();
        DbxRequestConfig config = new DbxRequestConfig("JavaTutorial/1.0", userLocale);
        DbxWebAuthNoRedirect webAuth = new DbxWebAuthNoRedirect(config, appInfo);

        // Run through Dropbox API authorization process
        String authorizeUrl = webAuth.start();
        System.out.println("6. Go to " + authorizeUrl);
        System.out.println("7. Click \"Allow\" (you might have to log in first).");
        System.out.println("8. Copy the authorization code.");
        System.out.print("9. Enter the authorization code here: ");

        String code = new BufferedReader(new InputStreamReader(System.in)).readLine();
        if (code == null) {
            System.exit(1); return;
        }
        code = code.trim();

        DbxAuthFinish authFinish;
        try {
            authFinish = webAuth.finish(code);
        }
        catch (DbxException ex) {
            System.err.println("Error in DbxWebAuth.start: " + ex.getMessage());
            System.exit(1); return;
        }

        System.out.println("10. Authorization complete.");
        System.out.println("- User ID: " + authFinish.userId);
        System.out.println("- Access Token: " + authFinish.accessToken);

        // Save auth information to output file.
        DbxAuthInfo authInfo = new DbxAuthInfo(authFinish.accessToken, appInfo.host);
        try {
            DbxAuthInfo.Writer.writeToFile(authInfo, accessTokenFilename);
            System.out.println("Saved authorization information to \"" + accessTokenFilename + "\".");
        }
        catch (IOException ex) {
            System.err.println("Error saving to : " + ex.getMessage());
            System.err.println("Dumping to stderr instead:");
            DbxAuthInfo.Writer.writeToStream(authInfo, System.err);
            System.exit(1); return;
        }
    }
}