diff --git a/README.md b/README.md index 1799a84..15e0a90 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,4 @@ This is an unofficial Java Twitter SDK implementation for Android. It contains a library and sample application project. Currently only supports authentication through a WebView dialog. -## TODO - -* Make methods to make Twitter API calls \ No newline at end of file +This fork builds upon the code from me.grantland.twitter and adds a nice method for doing API calls. diff --git a/twitter/src/me/grantland/twitter/Twitter.java b/twitter/src/me/grantland/twitter/Twitter.java index 7517c7f..b648919 100644 --- a/twitter/src/me/grantland/twitter/Twitter.java +++ b/twitter/src/me/grantland/twitter/Twitter.java @@ -1,11 +1,32 @@ package me.grantland.twitter; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Map; + +import oauth.signpost.OAuth; import oauth.signpost.OAuthConsumer; import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer; +import oauth.signpost.commonshttp.HttpRequestAdapter; +import oauth.signpost.commonshttp.HttpResponseAdapter; +import oauth.signpost.exception.OAuthException; +import oauth.signpost.http.HttpRequest; +import oauth.signpost.http.HttpResponse; + import android.app.Activity; import android.content.Intent; import android.util.Log; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicHeader; + /** * @author Grantland Chew */ @@ -16,6 +37,7 @@ public class Twitter { public static final String REQUEST_TOKEN = "https://twitter.com/oauth/request_token"; public static final String ACCESS_TOKEN = "https://twitter.com/oauth/access_token"; public static final String AUTHORIZE = "https://twitter.com/oauth/authorize"; + public static final String DATA_API_URL = "http://api.twitter.com/"; public static final String DENIED = "denied"; public static final String CALLBACK_SCHEME = "gc"; public static final String CALLBACK_URI = CALLBACK_SCHEME + "://twitt"; @@ -29,6 +51,8 @@ public class Twitter { // Used as default activityCode by authorize(). See authorize() below. public static final int DEFAULT_AUTH_ACTIVITY_CODE = 4242; + private DefaultHttpClient mHttpClient = null; + private OAuthConsumer mConsumer = null; private int mRequestCode; @@ -40,6 +64,10 @@ public Twitter(String consumerKey, String consumerSecret) { "You must specify your consumer key and secret when instantiating " + "a Twitter object. See README for details."); } + + mHttpClient = new DefaultHttpClient(); + mHttpClient.getParams().setBooleanParameter("http.protocol.expect-continue", false); + mConsumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret); } @@ -137,7 +165,6 @@ private boolean startTwitterActivity(Activity activity, String authorizeParams, private boolean startTwitterDialog(Activity activity, String authorizeParams, final DialogListener listener) { TwitterDialog dialog = new TwitterDialog(activity, mConsumer, authorizeParams, new DialogListener() { - @Override public void onComplete(String token, String secret) { if (DEBUG) Log.d(TAG, "access_key: " + token); if (DEBUG) Log.d(TAG, "access_secret: " + secret); @@ -147,12 +174,10 @@ public void onComplete(String token, String secret) { listener.onComplete(token, token); } - @Override public void onError(TwitterError error) { listener.onError(error); } - @Override public void onCancel() { listener.onCancel(); } @@ -209,6 +234,100 @@ public void authorizeCallback(int requestCode, int resultCode, Intent data) { } } + /** + * Submit a request to the Twitter API. You should have valid authorization before calling + * this method. + * + * @param method HTTP method, should be "GET" or "POST". + * @param path Path to API endpoint. For example, "1/statuses/update". + * @param parameters Any parameters to submit with the request, as key-value pairs. + * For example, "status", "Hi!", "include_entities", "true". + * @return The response string. This string is expected to be JSON-parsable. + */ + public String request(String method, String path, String... parameters) { + + Map parameterMap = new HashMap(); + for (int i = 0; i < parameters.length - 1; i += 2) { + parameterMap.put(parameters[i], parameters[i + 1]); + } + + return request(method, path, parameterMap); + } + + /** + * Submit a request to the Twitter API. You should have valid authorization before calling + * this method. + * + * @param method HTTP method, should be "GET" or "POST". + * @param path Path to API endpoint. For example, "1/statuses/update". + * @param parameters Any parameters to submit with the request, as key-value map. + * @return The response string. This string is expected to be JSON-parsable. + */ + public String request(String method, String path, Map parameters) { + + try { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.append(DATA_API_URL); + urlBuilder.append(path); + urlBuilder.append(".json"); + + HttpRequest request = null; + + if (method.equals("GET")) { + String glue = "?"; + for (Map.Entry entry : parameters.entrySet()) { + urlBuilder.append(glue); + urlBuilder.append(OAuth.percentEncode(entry.getKey()).getBytes()); + urlBuilder.append("="); + urlBuilder.append(OAuth.percentEncode(entry.getValue()).getBytes()); + glue = "&"; + } + + HttpGet getRequest = new HttpGet(urlBuilder.toString()); + request = new HttpRequestAdapter(getRequest); + } else if (method.equals("POST")) { + HttpPost postRequest = new HttpPost(urlBuilder.toString()); + + StringEntity body = new StringEntity(OAuth.formEncode(parameters.entrySet())); + body.setContentType(new BasicHeader("Content-Type", + "application/x-www-form-urlencoded")); + postRequest.setEntity(body); + + request = new HttpRequestAdapter(postRequest); + } else { + if (DEBUG) Log.d(TAG, "Invalid HTTP method: " + method); + return ""; + } + + mConsumer.sign(request); + + HttpResponse response = + new HttpResponseAdapter(mHttpClient.execute(((HttpUriRequest) request.unwrap()))); + + if (DEBUG) Log.d(TAG, "Response code: " + response.getStatusCode()); + + BufferedReader reader = new BufferedReader( + new InputStreamReader(response.getContent())); + + StringBuilder builder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + builder.append(line); + builder.append("\n"); + } + return builder.toString(); + } catch (MalformedURLException exception) { + if (DEBUG) Log.d(TAG, "Malformed URL exception: " + exception.toString()); + return ""; + } catch (IOException exception) { + if (DEBUG) Log.d(TAG, "I/O exception: " + exception.toString()); + return ""; + } catch (OAuthException exception) { + if (DEBUG) Log.d(TAG, "OAuth exception: " + exception.toString()); + return ""; + } + } + //============================================================================================== // Properties //============================================================================================== diff --git a/twitter/src/me/grantland/twitter/TwitterActivity.java b/twitter/src/me/grantland/twitter/TwitterActivity.java index b883a79..a28e0a2 100644 --- a/twitter/src/me/grantland/twitter/TwitterActivity.java +++ b/twitter/src/me/grantland/twitter/TwitterActivity.java @@ -5,6 +5,7 @@ import oauth.signpost.OAuthProvider; import oauth.signpost.commonshttp.CommonsHttpOAuthProvider; import oauth.signpost.exception.OAuthException; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.ProgressDialog; import android.content.DialogInterface; @@ -64,6 +65,7 @@ public void handleMessage (Message msg) { } @Override + @SuppressLint("SetJavaScriptEnabled") public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); @@ -84,7 +86,7 @@ public void onCreate(Bundle savedInstanceState) { mSpinner = new ProgressDialog(this); mSpinner.setMessage(getResources().getString(R.string.loading_loading)); mSpinner.setOnCancelListener(new OnCancelListener() { - @Override public void onCancel(DialogInterface dialog) { + public void onCancel(DialogInterface dialog) { cancel(); } }); diff --git a/twitter/src/me/grantland/twitter/TwitterDialog.java b/twitter/src/me/grantland/twitter/TwitterDialog.java index dd7600a..655ac3a 100644 --- a/twitter/src/me/grantland/twitter/TwitterDialog.java +++ b/twitter/src/me/grantland/twitter/TwitterDialog.java @@ -6,6 +6,7 @@ import oauth.signpost.OAuthProvider; import oauth.signpost.commonshttp.CommonsHttpOAuthProvider; import oauth.signpost.exception.OAuthException; +import android.annotation.SuppressLint; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; @@ -45,10 +46,10 @@ public class TwitterDialog extends Dialog { private static final int BORDER_ALPHA = 126; private static final int BORDER_RADIUS = 10; - private H mMainThreadHandler; + private final H mMainThreadHandler; - private OAuthConsumer mConsumer; - private OAuthProvider mProvider; + private final OAuthConsumer mConsumer; + private final OAuthProvider mProvider; private final DialogListener mListener; @@ -127,7 +128,7 @@ public void onCreate(Bundle savedInstanceState) { mSpinner = new ProgressDialog(getContext()); mSpinner.setMessage("Loading..."); mSpinner.setOnCancelListener(new OnCancelListener() { - @Override public void onCancel(DialogInterface dialog) { + public void onCancel(DialogInterface dialog) { cancel(); } }); @@ -149,7 +150,7 @@ public void onCreate(Bundle savedInstanceState) { setUpWebView(); setOnCancelListener(new OnCancelListener() { - @Override public void onCancel(DialogInterface dialog) { + public void onCancel(DialogInterface dialog) { mListener.onCancel(); } }); @@ -177,7 +178,8 @@ public void cancel() { //mWebView.stopLoading(); } - private void setUpWebView() { + @SuppressLint("SetJavaScriptEnabled") + private void setUpWebView() { LayoutInflater inflater = this.getLayoutInflater(); mWebView = (WebView)inflater.inflate(R.layout.twitter_layout, null); mWebView.getSettings().setJavaScriptEnabled(true);