Wednesday, 27 March 2013

How to log in to Reddit using Java (for Android)

Note: This article is outdated. Reddit now uses OAuth 2.0. If you are interested in how to use it, you must read my new tutorial about Reddit OAuth instead.

You might have already read my previous tutorials on how to create an Android client for Reddit here and here. To fetch a user's front-page and to allow the user to up-vote or down-vote posts, you will need a mechanism to first allow the user to log in to Reddit.

The Reddit API makes this a fairly simple process. In this tutorial, I will be creating a class that logs a user in to Reddit. You can read about the login API here.

Let us start now. Let us name this class Login.java.

We first need to create a connection to Reddit that allows us to POST data. To allow POST data, all we need to do is use the setDoOutput() method of the HttpURLConnection class.

Here is the complete method for it,
// This method creates a connection that allows
// you to POST data
private HttpURLConnection getConnection(String url){        
    URL u = null;
    try{
        u = new URL(url);
    }catch(MalformedURLException e){
        Log.d("Invalid URL", url);
        return null;
    }
    HttpURLConnection connection = null;
    try {
        connection = (HttpURLConnection)u.openConnection();
    } catch (IOException e) {
        Log.d("Unable to connect", url);
        return null;
    }
    // Timeout after 30 seconds
    connection.setReadTimeout(30000);
    // Allow POST data
    connection.setDoOutput(true);
    return connection;
}
Next, we create a method that allows us to write data to the connection. This method will accept a HttpURLConnection and a String as parameters. All it does is write that string to the connection. Here it is,
// This method lets you POST data to the URL.
private boolean writeToConnection(HttpURLConnection con, String data){
    try{
        PrintWriter pw=new PrintWriter(
                         new OutputStreamWriter(
                            con.getOutputStream()
                         )
                       );
        pw.write(data);
        pw.close();
        return true;
    }catch(IOException e){
        Log.d("Unable to write", e.toString());
        return false;
    }
}
Finally, we create the method to actually log in to Reddit. It sends the data to the Reddit API and checks the type of cookie returned. The Reddit API returns,
  1. In case of a successful login, a reddit_session cookie
  2. In case of a failed login, a reddit_first cookie
Here is the method,
// The login API URL
private final String REDDIT_LOGIN_URL = "https://ssl.reddit.com/api/login";

// The Reddit cookie string
// This should be used by other methods after a successful login.
private String redditCookie = "";

// This method lets you log in to Reddit.
// It fetches the cookie which can be used in subsequent calls
// to the Reddit API.
private boolean login(String username, String password){
    HttpURLConnection connection = getConnection(REDDIT_LOGIN_URL);

    if(connection == null)
        return false;
    
    //Parameters that the API needs
    String data="user="+username+"&passwd="+password;
    
    if(!writeToConnection(connection, data))
        return false;
    
    String cookie=connection.getHeaderField("set-cookie");
    
    if(cookie==null)
        return false;
    
    cookie=cookie.split(";")[0];
    if(cookie.startsWith("reddit_first")){
        // Login failed
        Log.d("Error", "Unable to login.");
        return false;
    }else if(cookie.startsWith("reddit_session")){
        // Login success
        Log.d("Success", cookie);
        redditCookie = cookie;
        return true;
    }                
    return false;
}
After a successful login, just pass the cookie along with every request you make to the Reddit API to fetch data that is personalized for the user. You can pass the cookie using,
connection.setRequestProperty("Cookie", redditCookie);
Put all these methods together in a class, and you will have added Reddit login functionality to your application. Thank you for reading, and please do comment if you have any feedback or questions.

No comments:

Post a Comment