简体   繁体   中英

How to auth automatically with Dropbox Java/Android SDK v2?

In order to improve app quality i'm working on testing: unit tests and UI tests. Since i'm having Dropbox support in the app i'd like to test it and i need to auth to Dropbox account before testing (in my android app the users are able to save the files, read them, rename, etc - basic file routines).

Dropbox provides Java/Android SDK v2 with examples but even command-line tool requires some manual actions - open browser app with the URL and select account:

// Run through Dropbox API authorization process
        DbxRequestConfig requestConfig = new DbxRequestConfig("examples-authorize");
        DbxWebAuth webAuth = new DbxWebAuth(requestConfig, appInfo);
        DbxWebAuth.Request webAuthRequest = DbxWebAuth.newRequestBuilder()
            .withNoRedirect()
            .build();

        String authorizeUrl = webAuth.authorize(webAuthRequest);
        System.out.println("1. Go to " + authorizeUrl);
        System.out.println("2. Click \"Allow\" (you might have to log in first).");
        System.out.println("3. Copy the authorization code.");
        System.out.print("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.finishFromCode(code);
        } catch (DbxException ex) {
            System.err.println("Error in DbxWebAuth.authorize: " + ex.getMessage());
            System.exit(1); return;
        }

        System.out.println("Authorization complete.");
        System.out.println("- User ID: " + authFinish.getUserId());
        System.out.println("- Access Token: " + authFinish.getAccessToken());

Any possibility to make Dropbox auth automatically without manual interaction? I expect to provide app key/secret, account email/password and get accessToken for the session.

PS. I'd like to avoid using Robelectric+Espresso and keep it in unit/integration tests, not in UI tests.

No, the Dropbox API doesn't offer a way to automate the app authorization flow.

Note that you can store and re-use access tokens though, so you may want to just get one for your test account once manually, and then re-use that.

Here is my test template (i hope it helps somebody). You have to do TODO and run the test manually twice at least (to paste auth code and access token) and then you can do the testing. All the next tests invocations do not require to do anything manually.

public class DropboxFileSystemTest {

    // credentials
    private static final String APP_KEY = ""; // TODO : paste your app key
    private static final String APP_SECRET = ""; // TODO : paste your app secret

    // do run the test and follow the instructions
    private static final String accountEmail = "test@domain.com"; // TODO : paste your test Dropbox account
    private static String authCode; // TODO : run the test and paste auth code
    private static String accessToken // TODO : run the test and paste access

    private DbxAppInfo appInfo = new DbxAppInfo(APP_KEY, APP_SECRET);

    // Run through Dropbox API authorization process
    private DbxRequestConfig requestConfig = new DbxRequestConfig(DropboxFileSystemTest.class.getSimpleName());
    private DbxWebAuth webAuth = new DbxWebAuth(requestConfig, appInfo);

    private void startAuth() throws IOException {
        DbxWebAuth.Request webAuthRequest = DbxWebAuth.newRequestBuilder()
            .withNoRedirect()
            .build();

        String authorizeUrl = webAuth.authorize(webAuthRequest);
        System.out.println("1. Go to " + authorizeUrl);
        System.out.println("2. Click \"Allow\" (you might have to log in first). WARNING: log-in to " + accountEmail);
        System.out.println("3. Copy the authorization code.");
        System.out.println("4. Paste the authorization code to this test `this.authCode` value");
        System.out.println("5. Re-run the test");
    }

    private DbxClientV2 client; // to be used for the requests

    private void initWithAccessToken() {
        DbxRequestConfig config = new DbxRequestConfig(UUID.randomUUID().toString());
        client = new DbxClientV2(config, accessToken);
    }

    private void initAndVerifyAccount() throws DbxException {
        initWithAccessToken();

        // check expected account (trying to prevent user account to be wiped out)
        DbxClientV2 client = DbxClientHolder.get().getClient();
        FullAccount account = client.users().getCurrentAccount();
        if (!account.getEmail().equals(accountEmail))
            throw new RuntimeException("Wrong account: current is " + account.getEmail() + ", but " + accountEmail + " is expected");
    }

    private void clearFileSystem() throws FileSystemException {
        // TODO : clear Dropbox file system
    }

    @Before
    public void setUp() throws IOException, FileSystemException, DbxException {
        auth();
        clearFileSystem();
    }

    private void finishAuth() {
        DbxAuthFinish authFinish;
        try {
            authFinish = webAuth.finishFromCode(authCode);
        } catch (DbxException ex) {
            System.err.println("Error in DbxWebAuth.authorize: " + ex.getMessage());
            System.exit(1); return;
        }

        System.out.println("Authorization complete.");
        System.out.println("- User ID: " + authFinish.getUserId());
        System.out.println("- Access Token: " + authFinish.getAccessToken());
        System.out.println();

        System.out.println("1. Copy the access token");
        System.out.println("2. Paste the access token to this test `this.accessToken` value");
        System.out.println("3. Re-run the test");

        accessToken = authFinish.getAccessToken();
    }

    private void auth() throws IOException, FileSystemException, DbxException {
        if (accessToken == null) {
            if (authCode != null ) {
                finishAuth();
                throw new RuntimeException("Manual actions required: copy-paste access token");
            } else {
                startAuth();
                throw new RuntimeException("Manual actions required: copy-paste authCode");
            }
        } else {
            initAndVerifyAccount();
        }
    }

    @After
    public void tearDown() throws FileSystemException {
        if (client != null) {
            clearFileSystem();
        }
    }

    @Test
    public void testSmth() {
        // TODO : write your test using `this.client` for requests
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM