Thursday 23 February 2012

Implementing Remote Interface Using AIDL in Android

Each application in Android runs in its own process. An application cannot directly access another application's memory space. This is called application sandboxing.

In order to allow cross-application communication, Android provides an implementation of interprocess communication (IPC) protocol. IPC protocols tend to get complicated because of all the marshaling/un marshaling of data that is necessary.

To help with this, Android provides Android Interface Definition Language, or AIDL. It is a lightweight implementation of IPC using a syntax that is very familiar to Java developers, and a tool that automates the stub creation.

In order to allow for one application to call into another, we typically have to:

1. Define the AIDL interface
2. Implement the Stub for the remote service
3. Expose the remote service to the local client


Defining the AIDL

The AIDL syntax is very similar to regular Java interface. You simply define the method signature. The datatypes supported by AIDL are somewhat different than regular Java interfaces. For one, all Java primitive datatypes are supported. So are StringListMap, and CharSequence classes. Also, all other AIDL datatypes that you defined are supported. In addition to that, all Parcelable classes are supported, but this is not going to be covered in this example. I'm trying to keep this example somewhat simpler to start with.


/src/com.sourav/IAdditionService.aidl


Code:
package com.sourav;

// Declare the interface.
interface IAdditionService {
    // You can pass values in, out, or inout. 
    // Primitive datatypes (such as int, boolean, etc.) can only be passed in.
    int add(in int value1, in int value2);
}



Implementing the Remote Service

Once you create your AIDL file and put it in the right place, the Eclipse+AIDL tool will generate a file with the same name, but .java extension. So I now have /gen/com.sourav.com/IAdditionService.java file. This is an auto-generated file so you don't want to edit it. What is important is that it contains a Stub class that we'll want to implement for our remote service.

To implement our remote service, we'll return the IBinder from onBind() method in our service class,AdditionService. The IBinder represents the implementation of the remote service. To implementIBinder, we subclass IAddtionService.Stub class from the auto-generated Java code, and provide implementation for our AIDL-defined methods, in this case add().

/src/com.sourav/AdditionService.java


Code:
package com.sourav;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

/**
 * This class exposes the remote service to the client
 */
public class AdditionService extends Service {
  private static final String TAG = "AdditionService";
  
  @Override
  public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate()");
  }
  
  @Override
  public IBinder onBind(Intent intent) {

    return new IAdditionService.Stub() {
      /**
       * Implementation of the add() method
       */
      public int add(int value1, int value2) throws RemoteException {
        Log.d(TAG, String.format("AdditionService.add(%d, %d)",value1, value2));
        return value1 + value2;
      }

    };
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "onDestroy()");
  }
}

Exposing the Service Locally

Once we have the service implement the onBind() properly, we are ready to connect to that service from our client. In this case, we have AIDLDemo activity connecting to that service. To establish the connection, we need to implement ServiceConnection class. Our activity in this example provides this implementation in AdditionServiceConnection inner class by implementing onServiceConnected() and onServiceDiconnected() methods. Those callbacks will get the stub implementation of the remote service upon connection. We need to cast them from stubs to our AIDL service implementation. To do that, we use the IAdditionService.Stub.asInterface((IBinder) boundService) helper method.

From that point on, we have a local service object that we can use to make calls against the remote service.

/src/com.sourav/AIDLDemo.java


Code:
package com.sourav;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class AIDLDemo extends Activity {
  private static final String TAG = "AIDLDemo";
  IAdditionService service;
  AdditionServiceConnection connection;

  /**
   * This class represents the actual service connection. It casts the bound
   * stub implementation of the service to the AIDL interface.
   */
  class AdditionServiceConnection implements ServiceConnection {

    public void onServiceConnected(ComponentName name, IBinder boundService) {
      service = IAdditionService.Stub.asInterface((IBinder) boundService);
      Log.d(AIDLDemo.TAG, "onServiceConnected() connected");
      Toast.makeText(AIDLDemo.this, "Service connected", Toast.LENGTH_LONG)
          .show();
    }

    public void onServiceDisconnected(ComponentName name) {
      service = null;
      Log.d(AIDLDemo.TAG, "onServiceDisconnected() disconnected");
      Toast.makeText(AIDLDemo.this, "Service connected", Toast.LENGTH_LONG)
          .show();
    }
  }

  /** Binds this activity to the service. */
  private void initService() {
    connection = new AdditionServiceConnection();
    Intent i = new Intent();
    i.setClassName("com.sourav", com.sourav.AdditionService.class.getName());
    boolean ret = bindService(i, connection, Context.BIND_AUTO_CREATE);
    Log.d(TAG, "initService() bound with " + ret);
  }

  /** Unbinds this activity from the service. */
  private void releaseService() {
    unbindService(connection);
    connection = null;
    Log.d(TAG, "releaseService() unbound.");
  }

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    initService();

    // Setup the UI
    Button buttonCalc = (Button) findViewById(R.id.buttonCalc);

    buttonCalc.setOnClickListener(new OnClickListener() {
      TextView result = (TextView) findViewById(R.id.result);
      EditText value1 = (EditText) findViewById(R.id.value1);
      EditText value2 = (EditText) findViewById(R.id.value2);

      public void onClick(View v) {
        int v1, v2, res = -1;
        v1 = Integer.parseInt(value1.getText().toString());
        v2 = Integer.parseInt(value2.getText().toString());

        try {
          res = service.add(v1, v2);
        } catch (RemoteException e) {
          Log.d(AIDLDemo.TAG, "onClick failed with: " + e);
          e.printStackTrace();
        }
        result.setText(new Integer(res).toString());
      }
    });
  }

  /** Called when the activity is about to be destroyed. */
  @Override
  protected void onDestroy() {
    releaseService();
  }

}



The UI in this case is very simple. There are couple of TextViews and EditText fields and a button The button handles its events in an anonymous inner class OnClickListener. The button simply invokes theadd() method on the service as if it was a local call.


The layout for this example is not that significant, but I'm including it here for completeness purposes.

/res/layout/main.xml


Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical" android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView android:layout_width="fill_parent"
    android:layout_height="wrap_content" android:text="AIDL Demo"
    android:textSize="22sp" />
  <EditText android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:id="@+id/value1"
    android:hint="Value 1"></EditText>
  <TextView android:id="@+id/TextView01" android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:text="+"
    android:textSize="36sp"></TextView>
  <EditText android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:id="@+id/value2"
    android:hint="Value 2"></EditText>
  <Button android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:id="@+id/buttonCalc"
    android:text="="></Button>
  <TextView android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:text="result"
    android:textSize="36sp" android:id="@+id/result"></TextView>
</LinearLayout>



The output of your code should look like this:


Additional Resources
I highly recommend getting the details on AIDL from Designing a Remote Interface Using AIDL.

Enjoy.... 
Do post your doubts, queries or suggestions in this blog.


Friday 17 February 2012

All about 9-patch image in android.

While I was working on my Android App I found 9-patch (aka 9.png) to be confusing and poorly documented. After a little while, I finally picked up on how it works and decided to throw together something to help others figure it out. As Android devices come in many shapes and sizes, often making it very difficult for developers to design applications that look great on all the various screen sizes and orientations. For addressing this challenge,9-patch  can be indispensable. In this article, I will discuss what the 9-patch graphics format is, how it works, and when to use it.
What is the 9-patch  !!! 
Android supports 9-patch Stretchable Graphics for the controlled scaling of images. 9-patch graphics uses .png transparency to do an advanced form of 9-slice or scale9  that have patches, or regions of the image, defined to scale and stretch in the appropriate areas instead of scaling the entire image as one unit, which often obscures the details of the graphic. Generally, the center patch is transparent or solid, With  parts of the edges set to remain fixed, other edge parts set to stretch, and the corners set to remain fixed.


Here’s a basic guide map:


As you can see, you have guides on each side of your image. The TOP and LEFT guides are for scaling your image (i.e. 9-slice), while the RIGHT and BOTTOM guides define the fill area.
The black guide lines are cut-off/removed from your image – they won’t show in the app.  Guides must only be one pixel wide, so if you want a 48×48 button, your png will actually be 50×50. Anything thicker than one pixel will remain part of your image. (My examples have 4-pixel wide guides for better visibility. They should really be only 1-pixel).
Your guides must be solid black (#000000). Even a slight difference in color (#000001) or alpha will cause it to fail and stretch normally. This failure won’t be obvious either*, it fails silently! Yes. Really. Now you know.
Also you should keep in mind that remaining area of the one-pixel outline must be completely transparent. This includes the four corners of the image – those should always be clear. This can be a bigger problem than you realize. For example, if you scale an image in Photoshop it will add anti-aliased pixels which may include almost-invisible pixels which will also cause it to fail*. If you must scale in Photoshop, use the Nearest Neighbor setting in the Resample Image pull down menu (at the bottom of the Image Size pop-up menu) to keep sharp edges on your guides. This is actually a “fix” in the latest dev kit. Previously it would manifest itself as all of your other images and resources suddenly breaking, not the actually broken 9-patch image.
The TOP and LEFT guides are used to define the scalable portion of your image – LEFT for scaling height, TOP for scaling width. Using a button image as an example, this means the button can stretch horizontally and vertically within the black portion and everything else, such as the corners, will remain the same size. This allows you to have buttons that can scale to any size and maintain a uniform look.
It’s important to note that 9-patch images don’t scale down – they only scale up. So it’s best to start as small as possible.
Also, you can leave out portions in the middle of the scale line. So for example, if you have a button with a sharp glossy edge across the middle, you can leave out a few pixels in the middle of the LEFT guide. The center horizontal axis of your image won’t scale, just the parts above and below it, so your sharp gloss won’t get anti-aliased or fuzzy.

Fill area guides are optional and provide a way define the area for stuff like your text label. Fill determines how much room there is within your image to place text, or an icon, or other things. 9-patch isn’t just for buttons; it works for background images as well.
The above button & label example is exaggerated simply to explain the idea of fill – the label isn’t completely accurate. To be honest, I haven’t experienced how Android does multi-line labels, but there’s a good explanation of how to do them on Stack Overflow. Usually, a button label is usually a single row of text.
Finally, here’s a good demonstration of how scale and fill guides can vary, such as a LinearLayout with a background image & fully rounded sides:
Creating 9-patch Graphics
Let's give it a try. I've created a really basic PNG file called bluenotstretchy.png. To create a NinePatch graphic from this PNG file using the Draw 9-patch tool, perform the following steps:
1.       Launch Draw 9-patch.bat in your Android SDK /tools directory.
2.       Drag the PNG file into the left-hand pane (or use File -> Open NinePatch…)
3.       Click the "Show Patches" checkbox at the bottom of the left pane.
4.       Set your Patch Scale appropriately (higher to see more obvious results).
5.       To set a horizontal patch guide, click along the right edge of your graphic.
6.       To set a vertical patch guide, click along the top edge of your graphic.
7.       View the results in the right pane, and move patch guides until the graphic stretches the way you intend it. 
8.       If you need to delete a patch guide, press Shift and click on the guide pixel (black).
9.       Save your graphic with the extension .9.png (e.g., blue.9.png).

Loading 9-patch Graphic Resources from java file :
9-patch resources are simply another kind of Drawable subclass called NinePatchDrawable. Most of the time, you'll need only the resource ID of the image, to set as an attribute of View or layout. Occasionally you might need to act on the resource programmetically.
To create a NinePatchDrawable object from a NinePatch drawable resource, use the resource'sgetDrawable() method. If the drawable is a NinePatch, the getDrawable() method will return a NinePatchDrawable instead of a generic BitmapDrawable object.
For example, to load a NinePatch drawable resource called blue.9.png, you could use the following code:
import android.graphics.drawable.NinePatchDrawable;
NinePatchDrawable myNinePatchDrawable = (NinePatchDrawable) getResources().getDrawable(R.drawable.blue);
You can then use the NinePatchDrawable object much as you would any BitmapDrawable.

Enjoy.... 
Do post your doubts, queries or suggestions in this blog.