Skip to content

Advanced Use with OAuthLoginFragment

Nathan Esquenazi edited this page Jun 20, 2013 · 14 revisions

If you need to authenticate multiple different services from within a single Activity, then the simple OAuthLoginActivity approach probably won't work since each Activity is locked to a single client.

For more advanced usage such as this case, consider using the OAuthLoginFragment and embedding them into a regular FragmentActivity as outlined below. This approach is perfect anytime you don't want the Activity tied just a single type of client.

You can see a working code sample here in the MultiService OAuth Demo or read the guide below.

Configuring the REST Client

Assuming you have a configured REST client as explained in the README, you need to make sure each service has a different callback to allow the services to be identified uniquely during the OAuth flow.

The callback value do not matter, they just need to match between the client and the manifest.

public class FlickrClient extends OAuthBaseClient {
    // ...
    public static final String REST_CALLBACK_URL = "oauth://cpmultiflickr.com";
}

public class TwitterClient extends OAuthBaseClient {
    // ...
    public static final String REST_CALLBACK_URL = "oauth://cpmultitwitter.com";
}

Make sure to include the callbacks for each service within the manifest in separate VIEW intent-filter blocks:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
        android:host="cpmultiflickr.com"
        android:scheme="oauth" />
</intent-filter>
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
        android:host="cpmultitwitter.com"
        android:scheme="oauth" />
</intent-filter>

Create a new OAuthLoginFragment

Next define a fragment for each specific client:

public class TwitterLoginFragment extends OAuthLoginFragment<TwitterClient> {
    Button btnLoginTwitter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_twitter_login, container);
    }

    @Override
    public void onActivityCreated(Bundle saved) {
        super.onActivityCreated(saved);
	btnLoginTwitter = (Button) getActivity.findViewById(R.id.btnLoginTwitter);
        btnLoginTwitter.setOnClickListener(new ServiceButtonOnClickListener());
     }

     @Override
     public void onLoginSuccess() {
         // fires when twitter is authenticated, launch an intent as an example
         Intent i = new Intent(this, TimelineActivity.class);
         i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
         startActivity(i);
     }
	
     @Override
     public void onLoginFailure(Exception e) {
        // fires if twitter authentication fails
        e.printStackTrace();
     }

     private class ServiceButtonOnClickListener implements OnClickListener {
         @Override
	 public void onClick(View v) {
	     if (!getClient().isAuthenticated()) {
		  getClient().connect();
	     } else {
                 // ...client is already authenticated...
             }
         }
    }
}

Fragment XML in this case should just have a button that can be clicked to initiate the authentication process:

<Button
  android:id="@+id/btnTwitterLogin"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Connect to Twitter" />

Embed the Fragment in a FragmentActivity

Now you can embed any number of these fragments in a LoginActivity that extends from FragmentActivity:

public class LoginActivity extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_login);
    }
}

The LoginActivity might have XML looking like this:

<fragment
   android:id="@+id/fragment_twitter_login"
   android:name="com.codepath.apps.multiservicerestclient.fragments.TwitterLoginFragment"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   tools:layout="@layout/fragment_twitter_login" />

Using the REST Client

Using the client is similar to the README but you can get access to the shared client instance using the OAuthBaseClient getInstance method:

// Can be used in any activity to access authenticated client
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TwitterClient clientTwitter = 
            (TwitterClient) TwitterClient.getInstance(TwitterClient.class, this);
        clientTwitter.getHomeTimeline(new JsonHttpResponseHandler() {
	     @Override
	     public void onSuccess(JSONObject j) {
                 // ...
	     }
	});	
    }
}