package com.dropbox.client2.android; import android.app.Activity; import android.content.Context; import android.content.Intent; import com.dropbox.client2.DropboxAPI; import com.dropbox.client2.session.AbstractSession; import com.dropbox.client2.session.AccessTokenPair; import com.dropbox.client2.session.AppKeyPair; import java.util.Arrays; /** * Keeps track of a logged in user and contains configuration options for the * {@link DropboxAPI}. Has methods specific to Android for authenticating * users via the Dropbox app or web site. * <br><br> * A typical authentication flow when no user access token pair is saved is as * follows: * <br> * <pre> * AndroidAuthSession session = new AndroidAuthSession(myAppKeys, myAccessType); * * // When user wants to link to Dropbox, within an activity: * session.startOAuth2Authentication(this); * * // When user returns to your activity, after authentication: * if (session.authenticationSuccessful()) { * try { * session.finishAuthentication(); * * AccessTokenPair tokens = session.getAccessTokenPair(); * // Store tokens.key, tokens.secret somewhere * } catch (IllegalStateException e) { * // Error handling * } * }</pre> * <br> * When a user returns to your app and you have tokens stored, just create a * new session with them: * <br> * <pre> * AndroidAuthSession session = new AndroidAuthSession( * myAppKeys, myAccessType, new AccessTokenPair(storedAccessKey, storedAccessSecret)); * </pre> */ public class AndroidAuthSession extends AbstractSession { /** * Creates a new session to authenticate Android apps with the given app * key pair and access type. The session will not be linked because it has * no access token or secret. * * @deprecated {@code AccessType} is unnecessary. */ public AndroidAuthSession(AppKeyPair appKeyPair, AccessType type) { super(appKeyPair, type); } /** * Creates a new session to authenticate Android apps with the given app * key pair and access type. The session will be linked to the account * corresponding to the given access token pair. * * @deprecated {@code AccessType} is unnecessary. */ public AndroidAuthSession(AppKeyPair appKeyPair, AccessType type, AccessTokenPair accessTokenPair) { super(appKeyPair, type, accessTokenPair); } /** * Creates a new session to authenticate Android apps with the given app * key pair. The session will not be linked because it has no access token * or secret. */ public AndroidAuthSession(AppKeyPair appKeyPair) { super(appKeyPair); } /** * Creates a new session to authenticate Android apps with the given app * key pair and access type. The session will be linked to the account * corresponding to the given OAuth 1 access token pair. */ public AndroidAuthSession(AppKeyPair appKeyPair, AccessTokenPair accessTokenPair) { super(appKeyPair, accessTokenPair); } /** * Creates a new session to authenticate Android apps with the given app * key pair and access type. The session will be linked to the account * corresponding to the given OAuth 2 access token. */ public AndroidAuthSession(AppKeyPair appKeyPair, String oauth2AccessToken) { super(appKeyPair, oauth2AccessToken); } /** * Starts the Dropbox authentication process by launching an external app * (either the Dropbox app if available or a web browser) where the user * will log in and allow your app access. * * @param context the {@link Context} which to use to launch the * Dropbox authentication activity. This will typically be an * {@link Activity} and the user will be taken back to that * activity after authentication is complete (i.e., your activity * will receive an {@code onResume()}). * * @throws IllegalStateException if you have not correctly set up the AuthActivity in your * manifest, meaning that the Dropbox app will * not be able to redirect back to your app after auth. */ public void startOAuth2Authentication(Context context) { startOAuth2Authentication(context, null); } /** * Starts the Dropbox authentication process by launching an external app * (either the Dropbox app if available or a web browser) where the user * will log in and allow your app access. * <p/> * This variant should be used when app has previously authenticated against other users. * * @param context the {@link Context} which to use to launch the * Dropbox authentication activity. This will typically be an * {@link Activity} and the user will be taken back to that * activity after authentication is complete (i.e., your activity * will receive an {@code onResume()}). * @param alreadyAuthedUids An array of any other user IDs currently authenticated with this * app. This parameter may be null if no user IDs are previously * authenticated. The authentication screen will encourage the user to * not authorize these user accounts. (Note that the user may still * authorize the accounts.) * * @throws IllegalStateException if you have not correctly set up the AuthActivity in your * manifest, meaning that the Dropbox app will * not be able to redirect back to your app after auth. */ public void startOAuth2Authentication(Context context, String[] alreadyAuthedUids) { startOAuth2Authentication(context, null, alreadyAuthedUids); } /** * Starts the Dropbox authentication process by launching an external app * (either the Dropbox app if available or a web browser) where the user * will log in and allow your app access. * <p/> * This variant should be used when app wishes to authenticate a specific uid. * * @param context the {@link Context} which to use to launch the * Dropbox authentication activity. This will typically be an * {@link Activity} and the user will be taken back to that * activity after authentication is complete (i.e., your activity * will receive an {@code onResume()}). * @param desiredUid Encourage the user to authenticate the account defined by this user * ID. (Note that the user still can authenticate other accounts.) * This parameter may be null if no specific user ID is desired. * @param alreadyAuthedUids An array of any other user IDs currently authenticated with this * app. This parameter may be null if no user IDs are previously * authenticated. The authentication screen will encourage the user to * not authorize these user accounts. (Note that the user may still * authorize the accounts.) * @throws IllegalStateException if you have not correctly set up the * AuthActivity in your manifest, meaning that the Dropbox app will * not be able to redirect back to your app after auth. */ public void startOAuth2Authentication(Context context, String desiredUid, String[] alreadyAuthedUids) { AppKeyPair appKeyPair = getAppKeyPair(); if (!AuthActivity.checkAppBeforeAuth(context, appKeyPair.key, true /*alertUser*/)) { return; } if (alreadyAuthedUids != null && Arrays.asList(alreadyAuthedUids).contains(desiredUid)) { throw new IllegalArgumentException("desiredUid cannot be present in alreadyAuthedUids"); } // Start Dropbox auth activity. AuthActivity.setAuthParams(appKeyPair.key, null, desiredUid, alreadyAuthedUids); Intent intent = new Intent(context, AuthActivity.class); if (!(context instanceof Activity)) { // If starting the intent outside of an Activity, must include // this. See startActivity(). Otherwise, we prefer to stay in // the same task. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } context.startActivity(intent); } /** * Starts the Dropbox authentication process by launching an external app * (either the Dropbox app if available or a web browser) where the user * will log in and allow your app access. * * @param context the {@link Context} which to use to launch the * Dropbox authentication activity. This will typically be an * {@link Activity} and the user will be taken back to that * activity after authentication is complete (i.e., your activity * will receive an {@code onResume()}). * * @throws IllegalStateException if you have not correctly set up the * AuthActivity in your manifest, meaning that the Dropbox app will * not be able to redirect back to your app after auth. * * @deprecated Use {@link #startOAuth2Authentication} */ public void startAuthentication(Context context) { AppKeyPair appKeyPair = getAppKeyPair(); if (!AuthActivity.checkAppBeforeAuth(context, appKeyPair.key, true /*alertUser*/)) { return; } // Start Dropbox auth activity. AuthActivity.setAuthParams(appKeyPair.key, appKeyPair.secret, null, null); Intent intent = new Intent(context, AuthActivity.class); if (!(context instanceof Activity)) { // If starting the intent outside of an Activity, must include // this. See startActivity(). Otherwise, we prefer to stay in // the same task. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } context.startActivity(intent); } /** * Returns whether the user successfully authenticated with Dropbox. * Reasons for failure include the user canceling authentication, network * errors, and improper setup from within your app. */ public boolean authenticationSuccessful() { Intent data = AuthActivity.result; if (data == null) { return false; } String token = data.getStringExtra(AuthActivity.EXTRA_ACCESS_TOKEN); String secret = data.getStringExtra(AuthActivity.EXTRA_ACCESS_SECRET); String uid = data.getStringExtra(AuthActivity.EXTRA_UID); if (token != null && !token.equals("") && secret != null && !secret.equals("") && uid != null && !uid.equals("")) { return true; } return false; } /** * Sets up a user's access token and secret in this session when you return * to your activity from the Dropbox authentication process. Should be * called from your activity's {@code onResume()} method, but only * after checking that {@link #authenticationSuccessful()} is {@code true}. * * @return the authenticated user's Dropbox UID. * * @throws IllegalStateException if authentication was not successful prior * to this call (check with {@link #authenticationSuccessful()}. */ public String finishAuthentication() throws IllegalStateException { Intent data = AuthActivity.result; if (data == null) { throw new IllegalStateException(); } String token = data.getStringExtra(AuthActivity.EXTRA_ACCESS_TOKEN); if (token == null || token.length() == 0) { throw new IllegalArgumentException("Invalid result intent passed in. " + "Missing access token."); } String secret = data.getStringExtra(AuthActivity.EXTRA_ACCESS_SECRET); if (secret == null || secret.length() == 0) { throw new IllegalArgumentException("Invalid result intent passed in. " + "Missing access secret."); } String uid = data.getStringExtra(AuthActivity.EXTRA_UID); if (uid == null || uid.length() == 0) { throw new IllegalArgumentException("Invalid result intent passed in. " + "Missing uid."); } if (token.equals("oauth2:")) { setOAuth2AccessToken(secret); } else { setAccessTokenPair(new AccessTokenPair(token, secret)); } return uid; } @Override public void unlink() { super.unlink(); AuthActivity.result = null; } }