Friday, August 17, 2012

Simple Collision Detection in 2D

The title of this post starts with "simple" because we can complicate it a lot. This is a very simple explanation of the collision detection.

The collision detection is used in graphical applications like games to know whether an object hit another object, like the character of the game against a wall or against other object. If this happens the character should stop, die, exploit...

It's quite important to make this part of the game precise and efficient, because it can ruin a game if it's not precise (the game loose a lot of of reality) and also if it's not efficient (it will slow the game).

Let's start by the shapes. We are going to use simple shapes. Points (x,y), Rectangles and Circles.

To define a rectangle we could use 2 points: the lower left and the upper right

Or 1 point (lower left) and the width and height


To define a circle we will use the center point and the radius.


If we have 2 circles how could we know if they are overlapping one each other?
Just checking the distance between the two centers. If the distance is minor than the addition of the two radius, is because we have an overlap. If it's bigger we don't have overlap.

It seems easy, but how can we calculate the distance between two points?
Remembering the vectors of the math class, if we have two points:

A-------------------------->B

distance is the square root of the square of the difference of each coordinate.??

difX = B.x - A.x
difY = B.y - A.y

Dist = sqrt(difX*difX + difY*difY)

So we just have to check if this distance is minor than the addition of the radius. Easy. But we can do it better cos we know that the sqrt function is very expensive. So we can avoid it checking if the squared distance is minor than the square of the addition of the radius.

public float distanceSquare(Point a, Point b){
  //use distance square to avoid use square root cos is expensive
  float x = b.x - a.x;
  float y = b.y - a.y;
  return x*x + y*y;
 }

public boolean circle2cirlce(Circle a, Circle b){
  float sumRad = a.radius + b.radius;
  return distanceSquare(a.center, b.center) < sumRad*sumRad;
 }

That was really easy, but what if we have two rectangles? If we think a little about it, we can find a solution. But there is the Separating Axis Theorem SAT to help us. The theorem says that if two convex polygons are not overlapping, we can draw a line between them. Then using an axis that will be the normal of this line we can get the projection of the shapes in the axis and see that the projections do not overlap. Well is a quick explanation. If you want to know more about it just search Separating Axis Theorem on the Internet.

That theorem is very good to check collisions between polygons, because you just have to check the projections on the axis. One polygon has the same number of axis that of  vertices's. And when you find two projections that don't overlap, you can finish the check. That makes this method very efficient.
But we are using a simple version of polygon. We are using rectangles. And they are always aligned with the axis X and Y.  So for us should be much more easy. We just need 2 axis cos the projections are the same in the other two.


In this image we can see the projections in the axis. In this concrete case we could use x and y.

So one first approximation to the method to check if two rectangles are overlapping could be:

public boolean rectWithRectProjection(Rectangle a, Rectangle b){
  float minX, maxX, minY, maxY;
  
  //axis x (1,0)
  minX = Math.min(a.downLeft.x, b.downLeft.x);
 
  maxX = Math.max(a.downLeft.x+a.width, b.downLeft.x +b.width);
  
  if(a.width + b.width < maxX - minX)
   return false;
  //axis y (0,1)
  minY = Math.min(a.downLeft.y , b.downLeft.y);
  
  maxY = Math.max(a.downLeft.y+a.height, b.downLeft.y+b.height);
  
  if (a.height+b.height < maxY - minY)
   return false;
  
  return true;
  
 }

In this case we are used the version that gives the width and the height of the rectangle.
This method is slow because uses the min and max functions that are very expensive. We can do it better just getting the points that can be overlapped in each case. Let's see how two rectangles can be overlapped. Depending on the side that is each one.





To avoid using max and min functions, we can just check this 4 possibilities. One for each axis of the rectangle. If we use the 2 points version of the rectangles we can write it like:

public static boolean rectWithRect(Rectangle2Points a, Rectangle2Points b){
  return (a.downLeft.x <= b.upRight.x && 
   a.upRight.x >= b.downLeft.x && 
   a.downLeft.y <= b.upRight.y &&
   a.upRight.y >= b.downLeft.y);
  
 }

In this case we just check two points in each condition. This version is much more efficient. In each condition we are checking one axis (one side of the rectangle) left, right, bottom, top. Notice that all the conditions must be true. If one of this conditions is false we can assure that the rectangles are not colliding. So knowing this we can make this checking faster in some cases:

public static boolean rectWithRectCut(Rectangle2Points a, Rectangle2Points b){
  if(a.downLeft.x > b.upRight.x)
   return false;
  if(a.upRight.x < b.downLeft.x)
   return false;
  if(a.downLeft.y > b.upRight.y)
   return false;
  if(a.upRight.y < b.downLeft.y)
   return false;
  
  return true;
 }

We need to invert the major/minor operators cos now we are checking if not meet the condition. You can use NOT (!) instead if you want, of course.

Using the other version of rectangle it would be:

public static boolean rectWithRect(RectanglePointWH a, RectanglePointWH b){
  return (a.downLeft.x <= b.downLeft.x + b.width && a.downLeft.x + a.width >= b.downLeft.x &&
    a.downLeft.y <= b.downLeft.y + b.height && a.downLeft.y + a.height >= b.downLeft.y);
  
 }
 
 
 //FASTEST
 public static boolean rectWithRectCut(RectanglePointWH a, RectanglePointWH b){
  if(a.downLeft.x > b.downLeft.x + b.width)
   return false;
  if(a.downLeft.x + a.width < b.downLeft.x)
   return false;
  if(a.downLeft.y > b.downLeft.y + b.height)
   return false;
  if(a.downLeft.y + a.height < b.downLeft.y)
   return false;
  return true;
 }


Getting the time of these algorithms with two rectangles not overlapping

PROJECTION
 COLLISION NOT FOUND
Time:166993

NOT CUT
 COLLISION NOT FOUND
Time:18404

CUT
 COLLISION NOT FOUND
Time:2170

We can see that it's a big difference. Of course this difference between the NOT CUT algorithm and the CUT will only happen when the rectangles are not colliding, cos when we find that the rectangles are not colliding we finish the algorithm. But the good news are that in a game we usually have lots of objects and very few colliding. So considering this difference for every object in the game on every frame... it could be important.



If we want to check if a single point is overlapping a rectangle, the logic is quite similar. I'm not going to write the code here.


Now let's think how can we detect collisions between circles and rectangles. The first attempt is to use a similar algorithm than the one used to check two rectangles. And it could work in most of the cases, but not in all of them. Why? Because if we use the same algorithm we are treating the circle as if it  were a square with the diameter as a side. Think in this case



Here we can see that if we consider the circle as a square, we have a collision. But it's a fake collision. Its cos this algorithm is not precise. So we need to change the algorithm to check this. One way to do this is find the closest point of the rectangle to the circle, and then check if the distance from this point to the center of the circle is bigger than the radius. But how can we find this closest point? 


Yes, another time we have to check the axis. If the Y coordinate of the center of the circle is into the space used by the rectangle (look at the right circle), we have to use the Y coordinate of the circle to the Y of the closest point. Otherwise we will use the biggest or the fewest Y coord of the rectangle (depending if the circle is up or down). The same with the X. Once we have the X and Y of the closest point we can check the distance. Ah, remember that if we check the distance squared is more efficient.

public static boolean colisioCercleRectangle(Circle c, Rectangle2Points r) {
      Point closest;
         float closestX = c.center.x;
         float closestY = c.center.y;
         
         if(c.center.x < r.downLeft.x) {
             closestX = r.downLeft.x; 
         } 
         else if(c.center.x > r.upRight.x) {
             closestX = r.upRight.x;
         }
           
         if(c.center.y < r.downLeft.y) {
             closestY = r.downLeft.y;
         } 
         else if(c.center.y > r.upRight.y) {
             closestY = r.upRight.y;
         }
         
         System.out.println(" closest x:"+closestX+" closesty:"+closestY);
         closest = new Point(closestX,closestY);
         
         
         return distanceSquare(c.center,closest) < c.radius * c.radius;           
     }

Well I think that's all. I just want to say that this is a very simple way to do this. We are using circles and rectangles, and the rectangles are always parallel to the axis X and Y. And of course in 3D the things are much more difficult. But this can work for a simple 2D game.

Wednesday, August 15, 2012

REST ATHENTICATION AND SIGN REQUEST USING OAUTH

In this post I'm going to explain a little how to use OAuth to Authenticate for using a REST API. In former post we used the twitter API to make a REST client application in android, but without authenticate. We need authentication to make some request, like send a tweet.

There are some ways to authenticate but Twitter uses Oauth version 1. Using OAuth we don't need to store any user/password. The user allows our app to make some things in his/her account. And our app delegates the authentication and authorization to a trusted location (in this case Twitter). Our app just has to store two tokens and sign each request to the API. The authorization has a life time in OAuth, but Twitter authorizations are unlimited, but, of course, the user can always revoke the using twitter web page.

To help us with all the authorization flow with OAuth we are going to use signpost library. 
So we will need to add signpost-commons-http4-1.2.1.2.jar (cos we are going to work with apache libraries in android) and signpost-core1.2.1.2.jar.

So the flow to authorize an application using signpost is:
  • First we need to create the twitter application on the twitter developers site. Once created we should have some information:
  • Consumer key
  • Consumer secret
  • Request token URL
  • Authorize URL
  • Access Token URL
  • Callback URL   (is the URL to redirect once authorized, but don' worry about that, use what you want, we will pass another through the flow)
  • With the key and the secret we can create an OAuthConsumer object wich will represent our application. With the URLs we can create an OAuthProvider object which will represent Twitter in this case.
  • With these two objects we can get retrieve a request token. This is the URL where the user has to authenticate and authorizate. 
  • Using that URL we have to pop the browser and wait until the user authorize the app.
  • Then we will intercept the callback from twitter and get some information (oauth verifier).
  • With the verifier we can get retrieve the access token (token and tokensecret) from twitter and store them (in Shared Preferences) to be able to sign further requests to the API.
As usual, each task that means download information from the Internet shouldn't be executed in the UI thread. To do this we can use AsyncTasks.

Well, knowing the "simple" OAuth flow and with the application created on the twitter developers site we can start to write.

The main activity will show a TextView to see if the user is authenticated or not, a button to erase the credentials, a button to send a tweet, a EditText to write the text to send and a TextView to see the result of the send (OK or KO). The send button and the edit text should are invisible if the user is not authenticated. The layout looks like this when the user is authenticated.



The main activity will check the Shared Preferences to see if we already have the tokens in onResume(). If we don't have tokens yet, we will launch an Activity to start the authorization flow. If we have tokens we have to put these tokens in our OAuthConsumer object and we can sign requests (later we'll see how).

private void checkTokens() {
  String token = shPref.getString(TwitterOauthKeys.TOKEN_KEY, "isnull");
   String tokensecret = shPref.getString(TwitterOauthKeys.TOKEN_SECRET_KEY, "isnull");
   
   if(token.equals("isnull")){
    text.setText("User NOT Authenticated");
    //disable buttonsend and company
    buttonsend.setVisibility(View.GONE);
    texttweet.setVisibility(View.GONE);
    //launch activity NewTwitterClientActivity to get tokens
    try {
    Intent NewClientIntent = new Intent(this, Class.forName("com.vidaltech.rest.oauth.NewTwitterClientActivity"));
    startActivity(NewClientIntent);
   } catch (ClassNotFoundException e) {
    Log.e(TAG,"Activity class not found");
   }
   }
   else{
    text.setText("User Authenticated!");
    //enable button send and edittext
    buttonsend.setVisibility(View.VISIBLE);
    texttweet.setVisibility(View.VISIBLE);
    
    //put tokens in OauthConsumer to sign requests
    consumer.setTokenWithSecret(token, tokensecret);
    
    
   }
   
 }


In the New Twitter Client Activity we need to create the OAuth objects and launch the task to retrieve the request token passing the objects to the task, as we've seen on the flow.

/*
    * Start a task to retrieve request token and launch browser/webview
    */
   new RetrieveRequestTokenTask(this, oauthConsumer, oauthProvider).execute();

This task simply retrieve the URL using the signpost library and launch a browser. Here we can see the doInBackground method of the task

protected Void doInBackground(Void... params) {
  try{
   /*
    * Getting the URL to redirect the user to authorize the application (request Token URL)
    */
  String url = oauthProvider.retrieveRequestToken(oauthConsumer, TwitterOauthKeys.CALLBACK_URL);
  Log.d(TAG,"Retrieved request token url "+url);
  /*
   * Redirecting user:
   * -creating a intent to launch browser
   * We use operator or to set various flags in the same int
   * flag no history to mark the new activity to be finished inmediately after user ends
   * flag from background to indicate that is launched from a background task, not from the interaction with user
   */
  Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_FROM_BACKGROUND);
  context.startActivity(browserIntent);
  
  }
  catch(Exception e){
   Log.e(TAG, "Error retrieving request token.");
   
  }
  return null;
 }

Now the browser should open and show the page to authenticate (if the user is not already logged in) and the page to authorize.

There is another possibility for doing this. We can use a WebView to show the Authentication/Authorization page in our application without launching the browser. At the end of the post you can see the details.

After that, we have to intercept the callback in our application. To do this we need to create a intent-filter. Each filter describes a capability of the component, a set of intents that the component is willing to receive. Check the android developer page to get more information about this.

<activity android:configChanges="keyboard|keyboardHidden|orientation" android:name="NewTwitterClientActivity" android:launchMode="singleInstance">
            <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:scheme="vidaltech" android:host="twitter"/>
            </intent-filter>
        </activity>

In the data tag, scheme and host must be the same that the callback URL we used in our app. The one that we used to build the OAuthProvider object. For example in this case is "vidaltech://twitter".

Now, following the flow, we can override the method onNewIntent(Intent intent) in that activity to get the URI and use it to retrieve the access token (in a separate task).

@Override
 protected void onNewIntent(Intent intent) {
  super.onNewIntent(intent);
  Log.d(TAGLIFE, "NEWCLIENTACTIVITY ONNEWINTENT");
  Log.d(TAG, "enter onNewIntent");
  final Uri uri = intent.getData();
  Log.d(TAG, "enter onNewIntent"+uri.getScheme());
  if(uri != null && TwitterOauthKeys.CALLBACK_URL.startsWith(uri.getScheme())){
   /*
    * launch the task to retrieve access token
    */
   new RetrieveAccesTokenTask(this,oauthConsumer, oauthProvider, shPref).execute(uri);
  }
  finish();
  
 }

In the retrieve acces token task we have to retrieve the tokens and store them in Shared Preferences.

@Override
 protected Void doInBackground(Uri... params) {
  Uri uri = params[0];
  //extract the oauth verifier from Uri using the static strings from OAuth class
  String oauthVerifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
  //launch the method to retrieve access token
  try {
   oauthProvider.retrieveAccessToken(oauthConsumer, oauthVerifier);
   /*
    * now we should have the token and tokensecret in oauthConsumer
    * Let's store them in shared preferences: we should use a Editor to write in sharedpreferences
    * with putString and then commit
    */
   Editor shPrefEditor = shPref.edit();
   shPrefEditor.putString(TwitterOauthKeys.TOKEN_KEY, oauthConsumer.getToken());
   shPrefEditor.putString(TwitterOauthKeys.TOKEN_SECRET_KEY, oauthConsumer.getTokenSecret());
   shPrefEditor.commit();
   
  } catch (OAuthMessageSignerException e) {
   Log.e(TAG, "Signer execption");
  } catch (OAuthNotAuthorizedException e) {
   Log.e(TAG, "Not autorized");
  } catch (OAuthExpectationFailedException e) {
   Log.e(TAG, "Expectation failed");
  } catch (OAuthCommunicationException e) {
   Log.e(TAG, "Communication error");
  }
  return null;
 }

In this moment we have our application authorized. Now let's see how to sign a request. To do this let's tweet somewhat. First we can check the twitter developers page to see which request we need to do. To tweet we have to do this POST request: POST statuses/update. 
Following the link we can see that the URL is http://api.twitter.com/1/statuses/update.format and we only have one required parameter: "status". This parameter is the message we want to send URL encoded.

So, do you remember that we have a send button and a edit text field in our layout? Let's use them. When the authenticated user push the button, we have to launch a task to make the REST request. And we already know how to do this with a GET method. Now we are going to use POST method, but is quite similar. Ah! And remember to sign the request before execute it!

First we have to create the HttpPost object with the URL. Then we have to add the data (message) using a NameValuePair object (from Apache library). Then sign the request (using our OAuthConsumer object) and that's all.

this.hPost = new HttpPost(uri);
  
  //put the data in a namevaluepair (from apache library)
  List dataToAdd = new ArrayList(1);
  
  dataToAdd.add(new BasicNameValuePair("status",data));
  
 
   hPost.setEntity(new UrlEncodedFormEntity(dataToAdd));
   
   /*
    * Before send we have to SING the request
    */
   
    consumer.sign(hPost);
   
   
   HttpResponse response = this.httpClient.execute(hPost);
   
   
   StatusLine statusLine = response.getStatusLine();
   if (statusLine.getStatusCode() == 200){
    Log.d(TAG, "post return OK");
    return true;
   }
   else{
    Log.d(TAG, "post return KO");
    return false;
   }

Take care with the Exceptions! Of course that is executed in an asynchronous task and at the end it will update the UI showing wether the tweet has been sent or not.


USING A WEBVIEW INSTEAD OF LAUNCHING A BROWSER

A WebView is a widget that allows to load web pages in our application.
Using a webview our app will be more clean and we will have more control on the authorization process.

So let's go.

First of all we don't need anymore the intent-filter and the method onNewIntent of the New Client Activity. In fact we don't need that activity, cos now we are going to intercept the callback using a WebViewClient.

A WebViewClient allows to control the events happening in a WebView. So we are going to use this to know when is loading a page. We will check if the page loaded is our CALLBACK URL and then we get the params from the URL to pass them to the RetrieveAccesTask.

So now, the RetrieveRequestTask won't launch a browser. Now will launch an activity which has a WebView in the layout. And we are going to pas the url to load using the method puExtra if the Intent.

Intent webViewIntent = new Intent(this.context, Class.forName("com.vidaltech.oauth.webview.WebViewActivity"));
  webViewIntent.putExtra("url", url);
  context.startActivity(webViewIntent);
  

We get the url from the intent.
Intent intent = getIntent();
        url = intent.getStringExtra("url");

This activity will have a WebView object and we will set a ClientWebView to be able to call to onPageStarted method. In this method we will get the url and call the Retrieve Acces Task
 webView = (WebView) findViewById(R.id.webview);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        //webSettings.setBuiltInZoomControls(false);
        
        
        webView.setWebViewClient(new WebViewClient(){//Web client allow us to get control of the events

         /*
          * We have to use onPageStarted. Is called once.
          * onResource
          */

   @Override
   public void onPageStarted(WebView view, String url, Bitmap favicon) {
    Log.d(TAG," on pagestarted url "+url);
    
    if(url != null && url.startsWith(TwitterOauthKeys.CALLBACK_URL)){

     /*
      * here we have in the url with oauth_verifier
      * We just need to encode and use the task already created
      */

     Log.d(TAG," on pagestarted into if");
     
     Uri uri = Uri.parse(url);
     new RetrieveAccesTokenTask(context,TwitterOauthKeys.oauthConsumer, TwitterOauthKeys.oauthProvider, shPref).execute(uri);
     
     callFinish();//finish the activity
    }
    else{
      //Check if we already have the tokens cos always is called onPageStarted
      String token = shPref.getString(TwitterOauthKeys.TOKEN_KEY, "isnull");
     
      //if we have the tokens we can close this activity and go back to the main activity
      if(!token.equals("isnull")){
       callFinish();//finish the activity
      }
     }
    
   }
         
        });
        
        webView.loadUrl(url);
 
As we can see, we need to check if we have the tokens in this activity (also in the main activity) in the method onPageStarted. If we have the tokens we can finish the activity to go back to the main activity and send tweets.

We have also to store the OAuthObjects in another class to be able to acces them from the differents activities.


Sunday, August 12, 2012

Asyncronous tasks in android

Hi there, in this entry I'm going to talk about the famous AsyncTasks.

If you want to do some process that could take a while (like download something) and you are using the User Interface thread to do that, your UI will be blocked while doing that process, and that is very annoying for the user. That's not a good design. When the application is doing some process at least it should show some kind of information about what is happening, like a progress dialog showing how long it will take. To do that we have to use threads so while the UI is showing something, the thread is doing his work and updating the UI (for example with the percentage of the process or adding information).

The problem in Android is that the UI thread doesn't allow calls from other threads (for security matters?). So if you are in other thread and you need to update something you cannot simply call a method.

There are some methods to do this (use a Handler, runOnUiThread, AsyncTask) but the most used is AsyncTask because is simple and easy.

An AsyncTask uses three generic types

public class MyAsyncTask extends AsyncTask<Params, Process, Result>  

Params is the type of data that we are going to pass to the task.
Process is the type of data that we are going to pass to the update process method.
Result is the type of data that the task is going to return.

If we are not going to use one of them we have to use the Void type.

The AsynkTask has one method that you have to override

protected Object doInBackground(Object... params) 

This method is launched in other thread. Here we have to do the long process.

The other methods that you can override will help you to update information between threads. They are

@Override
 protected void onPostExecute(Object result) {
  
 }

 @Override
 protected void onPreExecute() {
  
 }

 @Override
 protected void onProgressUpdate(Object... values) {
  
 }

 @Override
 protected void onCancelled() {

 }

onPreExecute is executed before doInBackground and you can use it for make some changes to UI, like show a dialog or disable some views.

onProgressUpdate is the method used to update the progress. It will be called from doInBackground.

onPostExecute will be executed once finished doInBackground. We can use it to dismiss the dialog or to update the information in the UI.

onCancelled will be executed if the task is cancelled.

Knowing how AsyncTask works we can make an asyncronous task that download information from a REST resource to take advantage of the example in the former entry.

We are not going to use the onProgressUpdate method in this example, and we have to pass the URI (a String) to access to the REST service and the task will return the information in a String.

public class MainTwitterClientActivity extends Activity implements OnClickListener{
 private static final String URI = "http://twitter.com/statuses/user_timeline.json?id=xxxxxx";
 private HttpRestConnector restConnector;
 
 private TextView text;
 private Button buttonSend;
 
 
 
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        restConnector = new HttpRestConnectorJson();
        
        buttonSend = (Button) findViewById(R.id.button1);
        
        text = (TextView) findViewById(R.id.editText1);
        
        buttonSend.setOnClickListener(this);
  
    }



 public void onClick(View v) {
  
  new DialogProgressTask(this).execute(URI);
  
 }
 
 public void setText(String t){
  text.setText(t);
 }
    
 private class DialogProgressTask extends AsyncTask{
  private ProgressDialog dialog;
  private Context context;
 
  
  public DialogProgressTask(Context context){
   this.context = context;
  }
  @Override
  protected void onPreExecute() {
   dialog = ProgressDialog.show(this.context, "Downloading", "Downloading information from Twitter...",true);
  }

  @Override
  protected String doInBackground(String... uri) {
   
   return JsonParserTwitter.getInfFromArray(restConnector.execGetConnection(uri[0]));
  }

  
  @Override
  protected void onPostExecute(String result) {
   
   dialog.dismiss();
   setText(result);   
  }

 }

}


In the doInBackground method we just call the REST service using the custom class RestConnector and pass the result to a JSON parser class to get the information in String. Then we use this String in onPostExecute method to call the method "setText" to update the UI showing the information downloaded.

As we can see AsyncTask is simple and very useful.

REST with JSON - part 1

In this entry of the blog I want to explain how to consume RESTful web services from an Android application using the format JSON for the information.

The term REST stands for Representational State Transfer. REST is not a technology, and many tools available on the market might not support REST directly because of the lack of a specific standard. What makes REST the best choice in many scenarios, is its ease of implementation and the fact that REST is not tied to any particular system, language or tool. If you can send an HTTP request to a web server, you can use REST.

To define what should be done on a specific resource, REST uses the intrinsic meaning of the verbs of the http protocol. Here are the five main verbs that are commonly used in RESTful systems:
  • GET - Retrieve a resource
  • PUT - Create a resource
  • POST - Update a resource
  • DELETE - Delete a resource
  • HEAD - Retrieve the metadata that defines a resource

If we don't want to create our REST service in a web/application server we can use one of the thousands of services available on the Internet. For instance Twitter.

To retrieve the user timeline of  Joel Comm the author of the book Twitter Power, we can access the uri:
http://twitter.com/statuses/user_timeline/joelcomm.json

And it will return the user timeline in JSON format. You can try it in your browser. If you are using Firefox there is a tool called RESTClient that helps you viewing the information of the REST services.

Of course Twitter has much more resources published. You can see them here.
Some of the resources are not accessible without authentication, but in this part we are going to use only resources that don't need authentication.

To make this in android we need to have an application with INTERNET permission. In the manifest:
<uses-permission android:name="android.permission.INTERNET"/>

This application has to create a Http Get method, execute it and get the response. The information will be in a HttpEntity object.

                
StringBUilder sBuffer = new StringBuilder();
HttpClient httpClient = new DefaultHttpClient();
  HttpGet hget = new HttpGet(URI);
  hget.addHeader("accept", FORMAT);
  
  try {
   HttpResponse response = httpClient.execute(hget);
   StatusLine statusLine = response.getStatusLine();
   if (statusLine.getStatusCode() == 200){
    //deal with the entity
    HttpEntity entity = response.getEntity();
    InputStream content = entity.getContent();
    BufferedReader bReader = new BufferedReader(new InputStreamReader(content));
    String line;
    while((line = bReader.readLine()) != null)
     sBuffer.append(line);
    
   }
   else{
    Log.e(TAG,"Error downloading data ");
    
   }
   
  } catch (ClientProtocolException e) {
   Log.e(TAG, "Error client protocol bad");
   e.printStackTrace();
   
   
  } catch (IOException e) {
   Log.e(TAG, "Error io execption");
   e.printStackTrace();
   
  }
  
  String resultInJsonFormat = sBuffer.toString();
 

To extract the information from the Entity we can use alternatively the toString(HttpEntity) method of EntityUtils

String resultInJsonFormat = EntityUtils.toString(entity);

As you know, if you get information from the Internet, it could be a little slow. So you shouldn't use the User Interface thread to do this kind of things because while is downloading information the UI will remain blocked (and it doesn't likes to the users). But we'll see how to do that in a further entry...

Now that we have the information in JSON format let's see what's that. Wikipedia says that JSON , or JavaScript Object Notation, is a text-based open standard designed for human-readable data interchange. It is derived from the JavaScript scripting language for representing simple data structures and associative arrays, called objects. Despite its relationship to JavaScript, it is language-independent, with parsers available for many languages.

The JSON format is often used for serializing and transmitting structured data over a network connection. It is used primarily to transmit data between a server and web application, serving as an alternative to XML.

Note that the information could come as a JSON Object or as a JSON Array. In this concrete case is a JSONArray.  To parse this formats in Java we have the package org.json.* and is easy to use. Let's see the simple code:


JSONArray jsonArray = new JSONArray(jsonRaw);
   int length = jsonArray.length();
   builder.append("Length: "+length+"\n");
   JSONObject jObject;
   for(int i=0; i < length;i++ ){
    jObject = jsonArray.getJSONObject(i);
    builder.append(jObject.getString("text")+"\n");
   }

In this case we are getting the String from the field text of each JSONObject in the array. There are lots of fields in each object.

Well that's a simple example of using REST and JSON in android. In further entries we'll see how to authenticate.