com.expertiseandroid.lib.sociallib.connectors.TwitterConnector.java Source code

Java tutorial

Introduction

Here is the source code for com.expertiseandroid.lib.sociallib.connectors.TwitterConnector.java

Source

/** 
 * Copyright (C) 2010  Expertise Android
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.expertiseandroid.lib.sociallib.connectors;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.HTTP;
import org.scribe.http.Request;
import org.scribe.oauth.Token;
import org.xml.sax.SAXException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;

import com.expertiseandroid.lib.sociallib.connectors.interfaces.FollowersSocialNetwork;
import com.expertiseandroid.lib.sociallib.connectors.interfaces.PostsSocialNetwork;
import com.expertiseandroid.lib.sociallib.connectors.interfaces.SignedCustomRequestSocialNetwork;
import com.expertiseandroid.lib.sociallib.exceptions.NotAuthentifiedException;
import com.expertiseandroid.lib.sociallib.messages.HttpResponseWrapper;
import com.expertiseandroid.lib.sociallib.messages.ReadableResponse;
import com.expertiseandroid.lib.sociallib.messages.ScribeResponseWrapper;
import com.expertiseandroid.lib.sociallib.model.Post;
import com.expertiseandroid.lib.sociallib.model.twitter.TwitterStatus;
import com.expertiseandroid.lib.sociallib.model.twitter.TwitterUser;
import com.expertiseandroid.lib.sociallib.readers.TwitterReader;
import com.expertiseandroid.lib.sociallib.utils.Utils;

/**
 * A connector to Twitter that provides methods to retrieve data and post content
 * @author ExpertiseAndroid
 *
 */
public class TwitterConnector
        implements PostsSocialNetwork, FollowersSocialNetwork, SignedCustomRequestSocialNetwork {

    private static final String GET_USER = "http://api.twitter.com/1/account/verify_credentials.xml";
    private static final String GET_FOLLOWERS = "http://api.twitter.com/1/statuses/followers.xml";
    private static final String GET_FOLLOWED = "http://api.twitter.com/1/statuses/friends.xml";
    private static final String POST_CONTENT = "http://api.twitter.com/1/statuses/update.xml";
    private static final String POST_RETWEET = "http://api.twitter.com/1/statuses/retweet/";
    private static final String DOTXML = ".xml";
    private static final String GET_MY_TL = "http://api.twitter.com/1/statuses/user_timeline.xml";
    private static final String GET_FRIENDS_TL = "http://api.twitter.com/1/statuses/friends_timeline.xml";
    private static final String GET_HOME_TL = "http://api.twitter.com/1/statuses/home_timeline.xml";
    private static final String GET_PUBLIC_TL = "http://api.twitter.com/1/statuses/public_timeline.xml";
    private static final String LOGOUT = "http://api.twitter.com/version/account/end_session.xml";
    private static final String TWITTER_REQUEST = "http://api.twitter.com/oauth/request_token";
    private static final String TWITTER_ACCESS = "http://api.twitter.com/oauth/access_token";
    private static final String AUTHORIZE = "http://api.twitter.com/oauth/authorize";
    private static final String STATUS = "status";
    private static final String NETWORK = "Twitter";

    private CommonsHttpOAuthProvider httpOauthprovider;
    private Token accessToken;
    private TwitterReader reader;
    private boolean authentified;
    private String callback;

    /**
     * The OAuth consumer, used to sign OAuth requests
     */
    public CommonsHttpOAuthConsumer httpOauthConsumer;

    /**
     * The application's TwitPic key to upload photos
     */
    public String twitPicKey;

    protected TwitterConnector(String consumerKey, String consumerSecret, String callback) {
        this(consumerKey, consumerSecret, callback, "");
    }

    protected TwitterConnector(String consumerKey, String consumerSecret, String callback, String twitPicKey) {
        this.authentified = false;
        this.reader = new TwitterReader();
        this.twitPicKey = twitPicKey;
        this.callback = callback;
        httpOauthConsumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);
        httpOauthprovider = new CommonsHttpOAuthProvider(TWITTER_REQUEST, TWITTER_ACCESS, AUTHORIZE);

    }

    /**
     * Gets the current user's public timeline
     * @return a list of TwitterStatus corresponding to the public timeline
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws NotAuthentifiedException
     * @throws OAuthCommunicationException 
     * @throws OAuthExpectationFailedException 
     * @throws OAuthMessageSignerException 
     */
    public List<TwitterStatus> getPublicTimeLine()
            throws SAXException, ParserConfigurationException, IOException, NotAuthentifiedException,
            OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedGetRequest(GET_PUBLIC_TL);
        return reader.readStatuses(response);
    }

    /**
     * Gets the current user's home timeline
     * @return a list of TwitterStatus corresponding to the home timeline
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws NotAuthentifiedException
     * @throws OAuthCommunicationException 
     * @throws OAuthExpectationFailedException 
     * @throws OAuthMessageSignerException 
     */
    public List<TwitterStatus> getHomeTimeLine()
            throws SAXException, ParserConfigurationException, IOException, NotAuthentifiedException,
            OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedGetRequest(GET_HOME_TL);
        return reader.readStatuses(response);
    }

    /**
     * Gets the current user's friends timeline
     * @return a list of TwitterStatus corresponding to the friends timeline
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws NotAuthentifiedException
     * @throws OAuthCommunicationException 
     * @throws OAuthExpectationFailedException 
     * @throws OAuthMessageSignerException 
     */
    public List<TwitterStatus> getFriendsTimeLine()
            throws SAXException, ParserConfigurationException, IOException, NotAuthentifiedException,
            OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedGetRequest(GET_FRIENDS_TL);
        return reader.readStatuses(response);
    }

    /**
     * Gets the current user's timeline
     * @return a list of TwitterStatus corresponding to the user's timeline
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws NotAuthentifiedException
     * @throws OAuthCommunicationException 
     * @throws OAuthExpectationFailedException 
     * @throws OAuthMessageSignerException 
     */
    public List<TwitterStatus> getUserTimeLine()
            throws SAXException, ParserConfigurationException, IOException, NotAuthentifiedException,
            OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedGetRequest(GET_MY_TL);
        return reader.readStatuses(response);
    }

    /**
     * Gets the current user's timeline
     * @throws OAuthCommunicationException 
     * @throws OAuthExpectationFailedException 
     * @throws OAuthMessageSignerException 
     */
    public List<TwitterStatus> getWallPosts()
            throws SAXException, ParserConfigurationException, IOException, NotAuthentifiedException,
            OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        return getHomeTimeLine();
    }

    /**
     * Sends a tweet
     * @param tweet the tweet's content
     * @return true if the operation was successful
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws NotAuthentifiedException
     * @throws OAuthCommunicationException 
     * @throws OAuthExpectationFailedException 
     * @throws OAuthMessageSignerException 
     */
    public boolean tweet(String tweet)
            throws SAXException, ParserConfigurationException, IOException, NotAuthentifiedException,
            OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        List<NameValuePair> bodyParams = new ArrayList<NameValuePair>();
        bodyParams.add(new BasicNameValuePair(STATUS, tweet));
        ReadableResponse response = signedPostRequest(POST_CONTENT, bodyParams);
        return reader.readResponse(response);
    }

    /**
     * Retweets a tweet
     * @param id the numerical ID of the desired status
     * @return true if the operation was successful
     * @throws NotAuthentifiedException
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws OAuthCommunicationException 
     * @throws OAuthExpectationFailedException 
     * @throws OAuthMessageSignerException 
     */
    public boolean retweet(String id) throws NotAuthentifiedException, SAXException, ParserConfigurationException,
            IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedPostRequest(POST_RETWEET + id + DOTXML, new ArrayList<NameValuePair>());
        return reader.readResponse(response);
    }

    /**
     * Retweets a tweet
     * @param tweet the desired status
     * @return true if the operation was successful
     * @throws NotAuthentifiedException
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws OAuthCommunicationException 
     * @throws OAuthExpectationFailedException 
     * @throws OAuthMessageSignerException 
     */
    public boolean retweet(Post tweet) throws NotAuthentifiedException, SAXException, ParserConfigurationException,
            IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        return retweet(tweet.getId());
    }

    public boolean post(Post content) throws NotAuthentifiedException, SAXException, ParserConfigurationException,
            IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        return tweet(content.getContents());
    }

    public List<TwitterUser> getFollowed()
            throws SAXException, ParserConfigurationException, IOException, NotAuthentifiedException,
            OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedGetRequest(GET_FOLLOWED);
        return reader.readUsers(response);
    }

    public List<TwitterUser> getFollowers() throws IllegalStateException, IOException, SAXException,
            ParserConfigurationException, NotAuthentifiedException, OAuthMessageSignerException,
            OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedGetRequest(GET_FOLLOWERS);
        return reader.readUsers(response);
    }

    public TwitterUser getUser()
            throws SAXException, ParserConfigurationException, IOException, NotAuthentifiedException,
            OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedGetRequest(GET_USER);
        return reader.readUser(response);
    }

    public boolean isAuthentified() {
        return authentified;
    }

    public void requestAuthorization(Context ctx) throws OAuthMessageSignerException, OAuthNotAuthorizedException,
            OAuthExpectationFailedException, OAuthCommunicationException {
        String authUrl = httpOauthprovider.retrieveRequestToken(httpOauthConsumer, callback);
        ctx.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)));
    }

    public void authorize(Activity ctx) throws OAuthMessageSignerException, OAuthNotAuthorizedException,
            OAuthExpectationFailedException, OAuthCommunicationException {
        String verifier = ctx.getIntent().getData().getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER);
        httpOauthprovider.retrieveAccessToken(httpOauthConsumer, verifier);
        accessToken = new Token(httpOauthConsumer.getToken(), httpOauthConsumer.getTokenSecret());
        authentified = true;
    }

    public boolean logout(Context ctx) throws NotAuthentifiedException, SAXException, ParserConfigurationException,
            IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        ReadableResponse response = signedPostRequest(LOGOUT, new ArrayList<NameValuePair>());
        return reader.readResponse(response);
    }

    public boolean authentify(Token accessToken) {
        this.accessToken = accessToken;
        httpOauthConsumer.setTokenWithSecret(accessToken.getToken(), accessToken.getSecret());
        this.authentified = true;
        return true;
    }

    public Token getAccessToken() {
        accessToken = new Token(httpOauthConsumer.getToken(), httpOauthConsumer.getTokenSecret());
        return accessToken;
    }

    public ReadableResponse customRequest(String httpMethod, String request) {
        return customRequest(httpMethod, request, new HashMap<String, String>());
    }

    public ReadableResponse customRequest(String httpMethod, String request, Map<String, String> bodyParams) {
        Request requestObj = new Request(Utils.getScribeVerb(httpMethod), request);
        for (Iterator<String> it = bodyParams.keySet().iterator(); it.hasNext();) {
            String key = it.next();
            requestObj.addBodyParameter(key, bodyParams.get(key));
        }
        return new ScribeResponseWrapper(requestObj.send());
    }

    public ReadableResponse signedCustomRequest(String httpMethod, String request) throws NotAuthentifiedException {
        return signedCustomRequest(httpMethod, request, new HashMap<String, String>());
    }

    public ReadableResponse signedCustomRequest(String httpMethod, String request, Map<String, String> bodyParams)
            throws NotAuthentifiedException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        Request requestObj = new Request(Utils.getScribeVerb(httpMethod), request);
        Utils.addBodyParams(requestObj, bodyParams);
        //scribe.signRequest(requestObj, accessToken);
        return new ScribeResponseWrapper(requestObj.send());
    }

    public ReadableResponse signedCustomRequest(String httpMethod, String request, String body)
            throws NotAuthentifiedException {
        if (!isAuthentified())
            throw new NotAuthentifiedException(NETWORK);
        Request requestObj = new Request(Utils.getScribeVerb(httpMethod), request);
        requestObj.addPayload(body);
        requestObj.addHeader("X-Auth-Service-Provider", "http://api.twitter.com/1/account/verify_credentials.json");
        return new ScribeResponseWrapper(requestObj.send());
    }

    private ReadableResponse signedPostRequest(String request, List<NameValuePair> bodyParams)
            throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException,
            ClientProtocolException, IOException {
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(request);
        post.setEntity(new UrlEncodedFormEntity(bodyParams, HTTP.UTF_8));
        post.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
        httpOauthConsumer.sign(post);
        HttpResponse response = client.execute(post);
        return new HttpResponseWrapper(response);
    }

    private ReadableResponse signedGetRequest(String request) throws OAuthMessageSignerException,
            OAuthExpectationFailedException, OAuthCommunicationException, ClientProtocolException, IOException {
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(request);
        httpOauthConsumer.sign(get);
        HttpResponse response = client.execute(get);
        return new HttpResponseWrapper(response);
    }

    /**
     * Sends a photo to TwitPic
     * @param filePath the path of the picture
     * @param caption a caption associated with the picture
     * @return the url of the picture on TwitPic
     * @throws OAuthMessageSignerException
     * @throws OAuthExpectationFailedException
     * @throws OAuthCommunicationException
     * @throws UnsupportedEncodingException
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    public String sendPhoto(String filePath, String caption)
            throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException,
            UnsupportedEncodingException, IOException, SAXException, ParserConfigurationException {
        Bitmap image = BitmapFactory.decodeFile(filePath);
        ReadableResponse response = Utils.postTwitpic(image, httpOauthConsumer, twitPicKey, caption);
        return reader.readUrl(response);
    }

    /**
     * Sends a photo to TwitPic and tweets it
     * @param tweet the tweet's content
     * @param filePath the path of the picture
     * @param caption a caption associated with the picture
     * @return true if the tweet was successfully posted
     * @throws OAuthMessageSignerException
     * @throws OAuthExpectationFailedException
     * @throws OAuthCommunicationException
     * @throws UnsupportedEncodingException
     * @throws SAXException
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws NotAuthentifiedException
     */
    public boolean sendPhotoAndTweet(String tweet, String filePath, String caption)
            throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException,
            UnsupportedEncodingException, SAXException, ParserConfigurationException, IOException,
            NotAuthentifiedException {
        return tweet(tweet + ' ' + sendPhoto(filePath, caption));
    }
}