Skip to content

Instantly share code, notes, and snippets.

@zeroarst
Last active August 29, 2015 14:05
Show Gist options
  • Save zeroarst/10071064adcf171277f9 to your computer and use it in GitHub Desktop.
Save zeroarst/10071064adcf171277f9 to your computer and use it in GitHub Desktop.
A handy util that help you to let the users interact with twitter authorization page by using webview embbed in dialogframent plus twitter4j
package com.zeroarst.android;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import com.zeroarst.android.BuildConfig;
import com.zeroarst.android.R;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
public class TwitterUtils {
//change to your twitter app consumer key here
private static String TWITTER_CONSUMER_KEY = "YOUR_TWITTER_CONSUMER_KEY";
//change to your twitter app consumer secret here
private static String TWITTER_CONSUMER_SECRET = "YOUR_TWITTER_CONSUMER_SECRET";
//change to your preferences name here
private static final String PREFS_NAME = "TWITTER.PREFS";
//change to your twitter access token prefs key if you have
private static final String KEY_TWITTER_ACCESS_TOKEN = "KEY_TWITTER_ACCESS_TOKEN";
//change to your twitter access token secret prefs key if you have
private static final String KEY_TWITTER_ACCESS_TOKEN_SECRET = "KEY_TWITTER_ACCESS_TOKEN_SECRET";
private static final String TWITTER_CALLBACK_URL = "twitter://callback";
private static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
public static Twitter getTwitter(Context context) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
cb.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
// Access Token
String access_token = prefs.getString(KEY_TWITTER_ACCESS_TOKEN, "");
// Access Token Secret
String access_token_secret = prefs.getString(KEY_TWITTER_ACCESS_TOKEN_SECRET, "");
AccessToken accessToken = new AccessToken(access_token, access_token_secret);
return new TwitterFactory(cb.build()).getInstance(accessToken);
}
public static void loginTwitter(final FragmentActivity activity) {
final TwitterLoginDialogFragment.OnTwitterLoginListener listener;
if (!(activity instanceof TwitterLoginDialogFragment.OnTwitterLoginListener)) {
throw new ClassCastException(
activity.toString() + " must implement " + TwitterLoginDialogFragment.OnTwitterLoginListener.class.getSimpleName());
}
TwitterLoginDialogFragment mFg = TwitterLoginDialogFragment.newInstance();
mFg.show(activity.getSupportFragmentManager(), "TWitterLoginDialog");
}
public static boolean isTwitterLoggedInAlready(Context context) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
return prefs.getString(KEY_TWITTER_ACCESS_TOKEN, null) != null && prefs.getString(KEY_TWITTER_ACCESS_TOKEN_SECRET,
null) != null;
}
public static void clearToken(Context context) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor e = prefs.edit();
e.remove(KEY_TWITTER_ACCESS_TOKEN);
e.remove(KEY_TWITTER_ACCESS_TOKEN_SECRET);
e.commit();
}
public static class TwitterLoginDialogFragment extends DialogFragment {
public static final String ARGS_REQUEST_TOKEN = "ARGS_REQUEST_TOKEN";
Twitter mTwitter;
WebView mWebView;
View mLoadingIndicator;
public interface OnTwitterLoginListener {
void onSuccess(Twitter twitter);
void onCancel();
void onFailed(TwitterException e);
}
OnTwitterLoginListener mListener;
public static TwitterLoginDialogFragment newInstance() {
TwitterLoginDialogFragment fg = new TwitterLoginDialogFragment();
Bundle args = new Bundle();
fg.setArguments(args);
return fg;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mWebView = new WebView(getActivity());
mWebView.setLayoutParams(lp);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if (mLoadingIndicator != null)
mLoadingIndicator.setVisibility(View.VISIBLE);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(TWITTER_CALLBACK_URL)) {
//if user cancel
if (url.contains("denied")) {
dismiss();
mListener.onCancel();
} else {
handleTwitterLoginCallback(url);
}
return true;
}
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (mLoadingIndicator != null)
mLoadingIndicator.setVisibility(View.GONE);
}
});
mLoadingIndicator = createLoadView();
mWebView.addView(mLoadingIndicator);
//init Dialog
Dialog dialog = new Dialog(getActivity(), R.style.NoFrameDialogTheme);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(mWebView);
//change to your preferable padding of the dialog
Resources r = getActivity().getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, r.getDisplayMetrics());
dialog.getWindow().getDecorView().setPadding(px, px, px, px);
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
return dialog;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//init Twitter object
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
cb.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
Configuration config = cb.build();
TwitterFactory factory = new TwitterFactory(config);
mTwitter = factory.getInstance();
//check whether RequestToken object is stored, launch AsyncTask to get it if not
if (getArguments().containsKey(ARGS_REQUEST_TOKEN)) {
mWebView.loadUrl(((RequestToken) getArguments().get(ARGS_REQUEST_TOKEN)).getAuthenticationURL());
} else {
new AsyncTask<Void, Void, RequestToken>() {
@Override
protected RequestToken doInBackground(Void... params) {
try {
return mTwitter.getOAuthRequestToken(TWITTER_CALLBACK_URL);
} catch (final TwitterException e) {
if (BuildConfig.DEBUG)
Log.e("Twitter Login Error", "> " + e.getMessage());
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mListener.onFailed(e);
}
});
}
return null;
}
@Override
protected void onPostExecute(final RequestToken requestToken) {
if (requestToken != null) {
getArguments().putSerializable(ARGS_REQUEST_TOKEN, requestToken);
mWebView.loadUrl(((RequestToken) getArguments().get(ARGS_REQUEST_TOKEN)).getAuthenticationURL());
}
}
}.execute();
}
}
//change to your preferable view for indicating web page loading
public View createLoadView() {
TextView tv = new TextView(getActivity());
tv.setText("Loading...");
tv.setTextSize(16);
tv.setBackgroundColor(Color.RED);
tv.setTextColor(Color.WHITE);
WebView.LayoutParams lp = new WebView.LayoutParams(WebView.LayoutParams.WRAP_CONTENT, WebView.LayoutParams.WRAP_CONTENT, 0,
0);
tv.setLayoutParams(lp);
return tv;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (getTargetFragment() != null) {
try {
mListener = (OnTwitterLoginListener) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException(
getTargetFragment().toString() + " must implement " + OnTwitterLoginListener.class.getSimpleName());
}
} else {
try {
mListener = (OnTwitterLoginListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(
activity.toString() + " must implement " + OnTwitterLoginListener.class.getSimpleName());
}
}
}
private void handleTwitterLoginCallback(final String url) {
final AsyncTask<Void, Void, AccessToken> asyncTask = new AsyncTask<Void, Void, AccessToken>() {
@Override
protected AccessToken doInBackground(Void... params) {
final Uri uri = Uri.parse(url);
// oAuth verifier
final String verifier = uri.getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);
try {
// Get the access token
return mTwitter.getOAuthAccessToken(verifier);
} catch (final TwitterException e) {
if (BuildConfig.DEBUG)
Log.e("Twitter Login Error", "> " + e.getMessage());
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mListener.onFailed(e);
}
});
}
return null;
}
@Override
protected void onPostExecute(AccessToken accessToken) {
if (accessToken == null)
return;
// After getting access token, access token secret
// store them in application preferences
SharedPreferences prefs = getActivity().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor e = prefs.edit();
e.putString(KEY_TWITTER_ACCESS_TOKEN, accessToken.getToken());
e.putString(KEY_TWITTER_ACCESS_TOKEN_SECRET, accessToken.getTokenSecret());
e.commit();
if (BuildConfig.DEBUG) {
Log.e("Twitter OAuth Token", "> " + accessToken.getToken());
Log.e("Twitter OAuth Token Secret", "> " + accessToken.getTokenSecret());
}
dismiss();
mListener.onSuccess(mTwitter);
}
};
asyncTask.execute();
}
}
}
package com.zeroarst.android;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import com.zeroarst.android.BuildConfig;
import com.zeroarst.android.R;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
public class TwitterUtils {
//change to your twitter app consumer key here
private static String TWITTER_CONSUMER_KEY = "pq6f776HNmtNEYQixsbTXXo2g";
//change to your twitter app consumer secret here
private static String TWITTER_CONSUMER_SECRET = "uiNMLJ9MQxrpQqu36ZPQNUKx6qUdDie8lN2oMSO7mW70L2KsN7";
//change to your preferences name here
private static final String PREFS_NAME = "TWITTER.PREFS";
//change to your twitter access token prefs key if you have
private static final String KEY_TWITTER_ACCESS_TOKEN = "KEY_TWITTER_ACCESS_TOKEN";
//change to your twitter access token secret prefs key if you have
private static final String KEY_TWITTER_ACCESS_TOKEN_SECRET = "KEY_TWITTER_ACCESS_TOKEN_SECRET";
private static final String TWITTER_CALLBACK_URL = "twitter://callback";
private static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
public static Twitter getTwitter(Context context) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
cb.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
// Access Token
String access_token = prefs.getString(KEY_TWITTER_ACCESS_TOKEN, "");
// Access Token Secret
String access_token_secret = prefs.getString(KEY_TWITTER_ACCESS_TOKEN_SECRET, "");
AccessToken accessToken = new AccessToken(access_token, access_token_secret);
return new TwitterFactory(cb.build()).getInstance(accessToken);
}
public static void loginTwitter(final FragmentActivity activity) {
final TwitterLoginDialogFragment.OnTwitterLoginListener listener;
if (!(activity instanceof TwitterLoginDialogFragment.OnTwitterLoginListener)) {
throw new ClassCastException(
activity.toString() + " must implement " + TwitterLoginDialogFragment.OnTwitterLoginListener.class.getSimpleName());
}
TwitterLoginDialogFragment mFg = TwitterLoginDialogFragment.newInstance();
mFg.show(activity.getSupportFragmentManager(), "TWitterLoginDialog");
}
public static boolean isTwitterLoggedInAlready(Context context) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
return prefs.getString(KEY_TWITTER_ACCESS_TOKEN, null) != null && prefs.getString(KEY_TWITTER_ACCESS_TOKEN_SECRET,
null) != null;
}
public static void clearToken(Context context) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor e = prefs.edit();
e.remove(KEY_TWITTER_ACCESS_TOKEN);
e.remove(KEY_TWITTER_ACCESS_TOKEN_SECRET);
e.commit();
}
public static class TwitterLoginDialogFragment extends DialogFragment {
public static final String ARGS_REQUEST_TOKEN = "ARGS_REQUEST_TOKEN";
Twitter mTwitter;
WebView mWebView;
View mLoadingIndicator;
public interface OnTwitterLoginListener {
void onSuccess(Twitter twitter);
void onCancel();
void onFailed(TwitterException e);
}
OnTwitterLoginListener mListener;
public static TwitterLoginDialogFragment newInstance() {
TwitterLoginDialogFragment fg = new TwitterLoginDialogFragment();
Bundle args = new Bundle();
fg.setArguments(args);
return fg;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mWebView = new WebView(getActivity());
mWebView.setLayoutParams(lp);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if (mLoadingIndicator != null)
mLoadingIndicator.setVisibility(View.VISIBLE);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(TWITTER_CALLBACK_URL)) {
//if user cancel
if (url.contains("denied")) {
dismiss();
mListener.onCancel();
} else {
handleTwitterLoginCallback(url);
}
return true;
}
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (mLoadingIndicator != null)
mLoadingIndicator.setVisibility(View.GONE);
}
});
mLoadingIndicator = createLoadingView();
mWebView.addView(mLoadingIndicator);
//init Dialog
Dialog dialog = new Dialog(getActivity(), R.style.NoFrameDialogTheme);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(mWebView);
//change to your preferable padding of the dialog
Resources r = getActivity().getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, r.getDisplayMetrics());
dialog.getWindow().getDecorView().setPadding(px, px, px, px);
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
return dialog;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//init Twitter object
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
cb.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
Configuration config = cb.build();
TwitterFactory factory = new TwitterFactory(config);
mTwitter = factory.getInstance();
//check whether RequestToken object is stored, launch AsyncTask to get it if not
if (getArguments().containsKey(ARGS_REQUEST_TOKEN)) {
mWebView.loadUrl(((RequestToken) getArguments().get(ARGS_REQUEST_TOKEN)).getAuthenticationURL());
} else {
new AsyncTask<Void, Void, RequestToken>() {
@Override
protected RequestToken doInBackground(Void... params) {
try {
return mTwitter.getOAuthRequestToken(TWITTER_CALLBACK_URL);
} catch (final TwitterException e) {
if (BuildConfig.DEBUG)
Log.e("Twitter Login Error", "> " + e.getMessage());
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mListener.onFailed(e);
}
});
}
return null;
}
@Override
protected void onPostExecute(final RequestToken requestToken) {
if (requestToken != null) {
getArguments().putSerializable(ARGS_REQUEST_TOKEN, requestToken);
mWebView.loadUrl(((RequestToken) getArguments().get(ARGS_REQUEST_TOKEN)).getAuthenticationURL());
}
}
}.execute();
}
}
//change to your preferable view for indicating web page loading
public View createLoadingView() {
TextView tv = new TextView(getActivity());
tv.setText("Loading...");
tv.setTextSize(16);
tv.setBackgroundColor(Color.RED);
tv.setTextColor(Color.WHITE);
WebView.LayoutParams lp = new WebView.LayoutParams(WebView.LayoutParams.WRAP_CONTENT, WebView.LayoutParams.WRAP_CONTENT, 0,
0);
tv.setLayoutParams(lp);
return tv;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (getTargetFragment() != null) {
try {
mListener = (OnTwitterLoginListener) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException(
getTargetFragment().toString() + " must implement " + OnTwitterLoginListener.class.getSimpleName());
}
} else {
try {
mListener = (OnTwitterLoginListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(
activity.toString() + " must implement " + OnTwitterLoginListener.class.getSimpleName());
}
}
}
private void handleTwitterLoginCallback(final String url) {
final AsyncTask<Void, Void, AccessToken> asyncTask = new AsyncTask<Void, Void, AccessToken>() {
@Override
protected AccessToken doInBackground(Void... params) {
final Uri uri = Uri.parse(url);
// oAuth verifier
final String verifier = uri.getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);
try {
// Get the access token
return mTwitter.getOAuthAccessToken(verifier);
} catch (final TwitterException e) {
if (BuildConfig.DEBUG)
Log.e("Twitter Login Error", "> " + e.getMessage());
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mListener.onFailed(e);
}
});
}
return null;
}
@Override
protected void onPostExecute(AccessToken accessToken) {
if (accessToken == null)
return;
// After getting access token, access token secret
// store them in application preferences
SharedPreferences prefs = getActivity().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor e = prefs.edit();
e.putString(KEY_TWITTER_ACCESS_TOKEN, accessToken.getToken());
e.putString(KEY_TWITTER_ACCESS_TOKEN_SECRET, accessToken.getTokenSecret());
e.commit();
if (BuildConfig.DEBUG) {
Log.e("Twitter OAuth Token", "> " + accessToken.getToken());
Log.e("Twitter OAuth Token Secret", "> " + accessToken.getTokenSecret());
}
dismiss();
mListener.onSuccess(mTwitter);
}
};
asyncTask.execute();
}
}
}
@zeroarst
Copy link
Author

zeroarst commented Sep 1, 2014

Few notes:

(1) 2 dependencies: com.android.support:support-v4, twitter4j
If you are using android studio, add these two lines to the block of dependencies in build.gradle file located in your project:
compile 'org.twitter4j:twitter4j-core:4.0.2'
compile 'com.android.support:support-v4:19.+'

(2) Modifiy TWITTER_CONSUMER_KEY and TWITTER_CONSUMER_SECRET to yours.

(3) Your Activity must extended FragmentActivity and implement TwitterUtils.TwitterLoginDialogFragment.OnTwitterLoginListener.

(4) You can change the loading view by modifing the createLoadingView method.

(5) Once authorized successfully, you can access twitter object in the callback method onSuccess(Twitter twitter), do whatever you want afterwards.

It also support screen oreientation.

Check out the sample TwitterUtilsSampleActivity.java.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment