So far, in all my examples, I have been using the declarative way of creating an Android UI using XML. However, there could arise certain situations when you may have to create UI programmatically. Sincere advice would be to avoid such a design since android has a wonderful architecture where the UI and the program are well separated. However, for those few exceptional cases where we may need too… here is how we do it.
Every single view or viewgroup element has an equivalent java class in the SDK. The structure and naming of the classes and methods is very similar to the XML vocabulary that we are used to so far.
Let us start with a LinearLayout. How would we declare it in an XML?
<?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="@string/hello"
    />
</LinearLayout>
This just contains a TextView embedded in a LinearLayout. A very trivial example. But serves the purpose intended. Let me show how almost every single element here corresponds to a class or a method call in the class.  So the equivalent code in the onCreate(…)  method of an activity would be like this:
         super.onCreate(savedInstanceState);
      
        lLayout = new LinearLayout(this);
        lLayout.setOrientation(LinearLayout.VERTICAL);
        //-1(LayoutParams.MATCH_PARENT) is fill_parent or match_parent since API level 8
        //-2(LayoutParams.WRAP_CONTENT) is wrap_content
        lLayout.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,

LayoutParams.MATCH_PARENT));
        tView = new TextView(this);
        tView.setText("Hello, This is a view created programmatically! " +
                  "You CANNOT change me that easily :-)");
        tView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
        lLayout.addView(tView);
        setContentView(lLayout);



Like this any layout view can be created. But from this small example you can notice two outstanding things – very tedious to code for every attribute of the view. And any simple change in the view, you need to change the code, compile, deploy and only then you see the effect of the change – unlike in a layout editor. 









Your Ad Here

We have seen that we can declare User Interface in Android through XML or we can even create the UI Programmatically. Now, we will see how we can mix the two and use it for building dynamic User Interfaces. One example of such a case would be when on a particular action of the user on one of the UI elements, you need more UI elements to appear on the same screen. How do we achieve this?
You can do it in two ways:
1.       The dynamic part of the UI can be created programmatically. However we saw in my earlier tutorial that it is not a very good way to mix UI and code.  So, we can
2.       Define the dynamic UI too as an XML and use XML inflation to include it into the existing UI.
We will see how to do the 2nd way, which probably is a good practice too.
As always, again a very simple example. Assume I have a very simple linear layout. In that I want to include a button. I can do it as part of the mail XML itself. However, assume that this button is supposed to be reused in many activities and hence I have defined it as a separate XML. How do I include it into the main XML?
So, here is the main.xml
<?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"
    android:id="@+id/layout1"
    >
</LinearLayout>
Here is the buttons.xml that is also created in the res/layout folder:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/button_small_left"
 style="?android:attr/buttonStyleSmall"
        android:text="Press to close"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
And here is the Activity’s onCreate(…) method of the InflateView class:
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        final LayoutInflater  inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        Button b = (Button)inflater.inflate(R.layout.buttons,
                null);
       
        lLayout = (LinearLayout)findViewById(R.id.layout1);
        lLayout.addView(b);
First 3 lines must be familiar. In the 4th line, I am getting a handle to the LayoutInflater through the getSystemService(…) method.  This inflater has a method inflate to which I pass the buttons.xml by passing the parameter R.layout.buttons. Then, I try to append this button to the Linear Layout that already exists and is set as the view in line 2 setContentView(R.layout.main). How to append? I get a handle to the LinearLayout lLayout and add the new button to it in the last line!
That simple to inflate an XML and append it to an existing view!
However, I have gone ahead and added another bit to this program as shown below:
        b.setOnClickListener(new OnClickListener() {
           
            public void onClick(View v) {
                  //restrict to adding only 1 textview child element
                  if (lLayout.getChildAt(2) == null)
                  {
                  TextView tv = (TextView)inflater.inflate(R.layout.text, null);
                  lLayout.addView(tv);
                  }
            }
        });
On the click of this dynamically added button, I am showing how we can add more to the UI dynamically through inflation. Assume, on the click of the button, you want to show some new text. This TextView is defined in another XML called text.xml which is also in the res/layout folder.
So, I am inflating from this XML and appending it to the LinearLayout view. So, a lot can be achieved for dynamic UI through inflation.
The concept of Broadcast Receivers, one of the fundamental blocks of Android, is very simple. These are applications that will respond to any intent that is broadcast by other applications. Provided the broadcast intent matches the intent specified against the receiver in the AndroidManifest.xml


This goes to automatically imply that many activities, events, services or the like can broadcast intents expecting the appropriate action to be automatically taken. So, to begin with, let us see the various Broadcast events that are given by the platform itself. Here is a standard list obtained from the android documentation:


·         ACTION_TIME_TICK
·         ACTION_TIME_CHANGED
·         ACTION_TIMEZONE_CHANGED
·         ACTION_BOOT_COMPLETED
·         ACTION_PACKAGE_ADDED
·         ACTION_PACKAGE_CHANGED
·         ACTION_PACKAGE_REMOVED
·         ACTION_PACKAGE_RESTARTED
·         ACTION_PACKAGE_DATA_CLEARED
·         ACTION_UID_REMOVED
·         ACTION_BATTERY_CHANGED
·         ACTION_POWER_CONNECTED
·         ACTION_POWER_DISCONNECTED
·         ACTION_SHUTDOWN


For details on when each of these intents get broadcasted, please see the android documentation. I have chosen the BROADCAST event ACTION_TIME_CHANGED as I can simulate a time change in the emulator. How to simulate the time change from adb shell is given at the end of this tutorial.


Now let us get on to the example of a broadcast receiver. You can download the complete code here.


Any activity that intends to respond to broadcasts has to extend the android.content.BroadcastReceiver class and implement the single method onReceive().


In my example, I just notify on the status bar that the time has changed and the moment the user clicks on the status bar and sees the details, clicks on the details, the notification is removed from the status bar.


When the user clicks on the detailed portion, I take the user to the contacts application, just for anything better. Ideally this should take to an activity relevant to the application. So, if you see the onReceive() method, it is nothing but a notification example. That is all.


      private NotificationManager mNotificationManager;
      private int SIMPLE_NOTFICATION_ID;
     
      @Override
      public void onReceive(Context context, Intent intent) {

        mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
      Notification notifyDetails = new Notification(R.drawable.android,"Time Reset!",System.currentTimeMillis());
      PendingIntent myIntent = PendingIntent.getActivity(context, 0, new Intent(Intent.ACTION_VIEW, People.CONTENT_URI), 0);
      notifyDetails.setLatestEventInfo(context, "Time has been Reset", "Click on me to view Contacts", myIntent);
      notifyDetails.flags |= Notification.FLAG_AUTO_CANCEL;
      mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);
            Log.i(getClass().getSimpleName(),"Sucessfully Changed Time");

      }


Once this class is ready, start the android emulator in eclipse. Then, simulate a time changed from the command prompt as given below. You will see the notification come up.


Simulating a time change in the emulator:


To start the adb shell type (in windows, assuming the path has been set to the tools folder of android sdk installation):


C:\> adb shell
#date –- 2009-10-01 14:24:59
20070325.123456
#date –s 20070325.123456


The first step date –- gives the time in seconds since Jan 1st 1970. Take the result and give it as a parameter to date –s, the time is reset in adb and within a minute on the android emulator. This broadcasts the event that time has been changed in the emulator and kicks off the Broadcast Receiver program that has been executed.
A few days ago bhushan made an article about communicating between activites. 

I'm currently working on a pet project that uses Oauth with the google data api, where

I had to get a response from the browser, so let's take a look at communicating between 
an activity and a browser.

All the tutorials that I found on the net use onResume to get the response, 
but I can't recommend that, because onResume runs even on the first run 
of the app (see lifecycle) which is unnecessary in this case.


To sum up the logic:
  • open the browser with a callback url provided
  • user enters credentials
  • the callback will take the result info back to the app that called the browser.
Opening the browser:
We need to use a service that uses browser callback, for example Google data api (Oauth) via Signpost.



  1. ...
  2. String url = provider.retrieveRequestToken(consumer, "putyourappnamehere:///&quot;);
  3. startActivity(new Intent(Intent.ACTION_VIEW, url));  
  4. ...
    1. protected void onNewIntent(Intent intent) {
    2.   super.onNewIntent(intent);
    3.   setIntent(intent);//must store the new intent so getIntent() won't return the old one
    4.   processResponse()
    5. }
    6. private void processResponse(){
    7.   Intent intent = getIntent();
    8.   Uri uri = this.getIntent().getData();  //get your data here
    9. }
    You also need an intent filter in the manifest, that will "catch" the response.


  1. ...
  2. <intent-filter>  
  3. <action android:name="android.intent.action.VIEW"></action>  
  4. <category android:name="android.intent.category.DEFAULT"></category>  
  5. <category android:name="android.intent.category.BROWSABLE"></category>  
  6. <data android:scheme="putyourappnamehere"></data>
  7. </intent-filter>
  8. ...
Your class has to extend TabActivity:

  1. public class YourClass extends TabActivity {
  2. ...
  3. ...
  4. }



    After that, here's how to configure a Tab:
     
    1. Create a LinearLayout in your main.xml, with the  id: "TabOne"  

    2. Paste these lines after onCreate() :


    1. /* TAB  #1 */
    2. TabSpec tsTabOne = mTabHost.newTabSpec("TabOne");
    3. tsBrand.setIndicator("Tab One"), getResources().getDrawable(R.drawable.tab_one));          
    4. tsTabOne.setContent(R.id.TabOne);
        


      3. You have to create tab_one.xml in /res/drawable folder, with the following:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3.     <!-- When selected, use this -->
  4.     <item android:drawable="@drawable/tab_one_icon&quot;
  5.           android:state_selected="true" />
  6.     <!-- When not selected, use that-->
  7.     <item android:drawable="@drawable/tab_one_iconfaded" />
  8. </selector>


    As you can see, you'll need 2 icons/tab, a normal, and a faded one.
    Copy those images to "/res/drawables/" folder too, with a name like "tab_one_icon.png", or "tab_one_iconfaded.png".

    4. Ok, now repeat these 3 steps above, as manytimes, as many Tabs you would like to have.
    5. Final Step, paste the following:



    1. /* Create TabHost */
    2. TabHost mTabHost;
    3. mTabHost = getTabHost();
    4. /* Add Tabs to TabHost */
    5. mTabHost.addTab(tsTabOne);
    6. ... /* If you have more ... */
    7. mTabHost.setCurrentTab(0);


Location Manager | Android Developer Tutorial

Location-based service is another key functionality that gets used by mobile applications. IT is often combined with maps to give a good user experience. We have already see how to use the external Google Maps API in tutorial Part 14. Here I will build upon the same to show how changes in location can be displayed on the map.
The location services are provided in the android.location package.


In order to use location services, our activity needs to implement the LocationManager Interface.
What does a LocationManager provide?


It is through this interface that an application can access the system’s location services. These services basically allow the application to obtain periodic updates of the device’s geographical location. It also helps in firing an application specific intent when the device comes within the proximity of a specified location.
Since in my example I want to simulate a location change and make my activity respond to the same, I am implementing this interface.


In order to make it an effective application, I have shown my location (hard-coded) on the google map. Then, I have used the location manager to handle any change in the location. The change in location needs to be simulated on the emulator by connecting through telnet. How to simulate location change is given at the end of this tutorial.


Now, dive into the code.


NOTE: I am adding the LocationManager implementation to the same MapActivity class created in the earlier tutorial (Part 14) and hence will not be explaining anything related to the maps API here.


Step 1: Obtain the LocationManager instance:


LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, this);


After getting the location manager, I am setting default GPS provider and asking to be notified if the location changes by more than 500 meters from the current location, the frequency of updation being 1 sec.


Step 2: Override the onLocationChanged() method in order to respond to changes in location.


public void onLocationChanged(Location location) {
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
String currentLocation = "The location is changed to Lat: " + lat + " Lng: " + lng;
myLoc.setText(currentLocation);
geoPoint = new GeoPoint((int) lat * 1000000, (int) lng * 1000000);
myMC.animateTo(geoPoint);
}
}


This method gets invoked when we change the location through the telnet connection to the emulator as described at the end of the tutorial. Based on the latitude and the longitude settings sent, the GeoPoint is changed to display the new location.


That is it. I have not overridden any of the other methods provided by the locationManager. Complete code is downloadable here.



How to simulate location change in the emulator?
Start the Emulator from eclipse
Start a command prompt
Start telnet
Then, type, o localhost 5554
This connects the telnet client to the android emulator (assuming emulator is running locally listening on port 5554. Else this connection fails)
Now type
geo fix 79.000000 13.000000 (or your latitude and longitude)
This sends the location change signal to the emulator.

Notifications - Android Tutorial for Beginners


We have seen Activities and Intents. Now we need to move on to services. However, since services mostly interact with a user through notifications, I felt the need to introduce a simple program to deal with Notifications.


What are Notifications? The name itself implies their functionality. They are a way of alerting a user about an event that he needs to be informed about or even take some action on getting that information.


Notification on Android can be done in any of the following ways:
  • · Status Bar Notification
  • · Vibrate
  • · Flash lights
  • · Play a sound

From the Notification, you can allow the user to launch a new activity as well. Now we will look at status bar notification as this can be easily tested on the emulator.


To create a status bar notification, you will need to use two classes: Notification and NotificationManager.
  • · Notification – defines the properties of the status bar notification like the icon to display, the test to display when the notification first appears on the status bar and the time to display.
  • · NotificationManager is an android system service that executes and manages all notifications. Hence you cannot create an instance of the NotificationManager but you can retrieve a reference to it by calling the getSystemService() method.

Once you procure this handle, you invoke the notify() method on it by passing the notification object created.


So far, you have all the information to display on the status bar. However, when the user clicks the notification icon on the status bar, what detailed information should you show the user? This is yet to be created. This is done by calling the method setLatestEventInfo() on the notification object. What needs to be passed to this method, we will see with an example.


You can download the code for a very simple Notification example here:


The code is explained below:


Step 1: Procure a handle to the NotificationManager:


private NotificationManager mNotificationManager;

mNotificationManager =
(NotificationManager)getSystemService(NOTIFICATION_SERVICE);


Step 2: Create a notification object along with properties to display on the status bar


final Notification notifyDetails =
new Notification(R.drawable.android,"New Alert, Click Me!",System.currentTimeMillis());



Step 3: Add the details that need to get displayed when the user clicks on the notification. In this case, I have created an intent to invoke the browser to show the website http://www.android.com


Context context = getApplicationContext();

CharSequence contentTitle = "Notification Details...";

CharSequence contentText = "Browse Android Official Site by clicking me";
Intent notifyIntent = new Intent(android.content.Intent.ACTION_VIEW,Uri.parse("http://www.android.com"));

PendingIntent intent =
PendingIntent.getActivity(SimpleNotification.this, 0,
notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intent);
Step 4: Now the stage is set. Notify.

mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);


Note that all of the above actions(except getting a handle to the NotificationManager) are done on the click of a button “Start Notification”. So all the details go into the setOnClickListener() method of the button.
Similarly, the notification, for the example sake is stopped by clicking a cancel notification button. And the code there is :
mNotificationManager.cancel(SIMPLE_NOTFICATION_ID);


Now, you may realize that the constant SIMPLE_NOTIFICATION_ID becomes the way of controlling, updating, stopping a current notification that is started with the same ID.


For more options like canceling the notification once the user clicks on the notification or to ensure that it does not get cleared on clicking the “Clear notifications” button, please see the android reference documentation.


Remote Service | Android Developer Tutorial


Services typically are required to run for a long time and hence should run in their own thread. Such services can be invoked by any number of clients who want to connect to the service, invoke a few methods on the service and finally release the service, probably to serve more clients or close down.

Here, I would like to introduce you to the concept of connecting to a remote service and the kind of support provided by the android platform for the same.

We have earlier seen how local services can be created and used. The difference between the two mainly is that the local service runs in the same process as the application that started it and hence the life of the local service is dependent on the life of the said application while remote service can run in its own process. This causes a challenge of inter-process communication. If one process wants to communicate with another process, the object that is passed between the two needs to be marshaled.

For this purpose, Android provides the AIDL (Android Interface Definition Language) tool that handles the marshaling as well as the communication.

The service has to declare a service interface in an aidl file and the AIDL tool will automatically create a java interface corresponding to the aidl file. The AIDL tool also generates a stub class that provides an abstract implementation of the service interface methods. The actual service class will have to extend this stub class to provide the real implementation of the methods exposed through the interface.

The service clients will have to invoke the onBind() method on the service to be able to connect to the service. The onBind() method returns an object of the stub class to the client. Here are the code related code snippets:

The AIDL file:
package com.collabera.labs.sai;

interface IMyRemoteService {

int getCounter();
}

Once you write this AIDL file (.aidl) in eclipse, it will automatically generate the Remote interface corresponding to this file. The remote interface will also provide a stub inner class which has to have an implementation provided by the RemoteService class. The stub class implementation within the service class is as given here:

private IMyRemoteService.Stub myRemoteServiceStub = new IMyRemoteService.Stub() {
public int getCounter() throws RemoteException {
return counter;
}
};
The onBind() method in the service class:
public IBinder onBind(Intent arg0) {
Log.d(getClass().getSimpleName(), "onBind()");
return myRemoteServiceStub;
}

Now, let us quickly look at the meat of the service class before we move on to how the client connects to this service class. My RemoteService class is just incrementing a counter in a separate thread. This thread is created in the onStart() method as this gets certainly called whether the service is connected to by a call to startService(intent). Please read the lifecycle of a service if this needs more clarity. Here are the over-ridden onCreate(), onStart() and onDestroy() methods. Note that the resources are all released in the onDestroy() method.

public void onCreate() {
super.onCreate();
Log.d(getClass().getSimpleName(),"onCreate()");
}
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
serviceHandler = new Handler();
serviceHandler.postDelayed(myTask, 1000L);
Log.d(getClass().getSimpleName(), "onStart()");
}
public void onDestroy() {
super.onDestroy();
serviceHandler.removeCallbacks(myTask);
serviceHandler = null;
Log.d(getClass().getSimpleName(),"onDestroy()");
}

A little explanation: In the onStart() method, I created a new Handler object that will spawn out a new task that implements the Runnable interface. This thread does the job of incrementing the counter. Here is the code for the Task class – an inner class of the RemoteService class.

class Task implements Runnable {
public void run() {
++counter;
serviceHandler.postDelayed(this,1000L);
Log.i(getClass().getSimpleName(), "Incrementing counter in the run method");
}
}

An object of this Task class is passed to the serviceHandler object as a message that needs to be executed after 1 second. The Task class implements the run() method in which we repeatedly post the same message to the serviceHandler. Thus, this becomes a repeated task till all the messages in the serviceHandler queue are deleted by calling the removeCallbacks() method on the serviceHandler in the destroy() method of the RemoteService class.

Note that the onDestroy() method thus stops this thread and set the serviceHandler to null. This completes the implementation of the RemoteService class. The complete code is downloadable here.
Now coming to the client class - Here, for simplicity sake, I have put the start, stop, bind, release and invoke methods all in the same client. While in reality, one client may start and another can bind to the already started service.

There are 5 buttons one each for start, stop, bind, release and invoke actions. A client needs to bind to a service before it can invoke any method on the service.
Here are the start and the bind methods.

private void startService(){
if (started) {
Toast.makeText(RemoteServiceClient.this, "Service already started", Toast.LENGTH_SHORT).show();
} else {
Intent i = new Intent();
i.setClassName("com.collabera.labs.sai", "com.collabera.labs.sai.RemoteService");
startService(i);
started = true;
updateServiceStatus();
Log.d( getClass().getSimpleName(), "startService()" );
}
}

An explicit intent is created and the service is started with the Context.startService(i) method.
Rest of the code is to update some status on the UI. There is nothing specific to a remote service invocation here. It is on the bindService() method that we see the difference from a local service.

private void bindService() {
if(conn == null) {
conn = new RemoteServiceConnection();
Intent i = new Intent();
i.setClassName("com.collabera.labs.sai", "com.collabera.labs.sai.RemoteService");
bindService(i, conn, Context.BIND_AUTO_CREATE);
updateServiceStatus();
Log.d( getClass().getSimpleName(), "bindService()" );
} else {
Toast.makeText(RemoteServiceClient.this, "Cannot bind - service already bound", Toast.LENGTH_SHORT).show();
}
}

Here we get a connection to the remote service through the RemoteServiceConnection class which implements ServiceConnection Interface. The connection object is required by the bindService() method – an intent, connection object and the type of binding are to be specified. So, how do we create a connection to the RemoteService? Here is the implementation:

class RemoteServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className,
IBinder boundService ) {
remoteService = IMyRemoteService.Stub.asInterface((IBinder)boundService);
Log.d( getClass().getSimpleName(), "onServiceConnected()" );
}

public void onServiceDisconnected(ComponentName className) {
remoteService = null;
updateServiceStatus();
Log.d( getClass().getSimpleName(), "onServiceDisconnected" );
}
};

The Context.BIND_AUTO_CREATE ensures that a service is created if one did not exist although the onstart() will be called only on explicit start of the service.

Once the client is bound to the service and the service has already started, we can invoke any of the methods that are exposed by the service. Here we have only one method and that is getCounter(). In this example, the invocation is done by clicking the invoke button. That would update the counter text that is below the button.

Let us see the invoke method:

private void invokeService() {
if(conn == null) {
Toast.makeText(RemoteServiceClient.this, "Cannot invoke - service not bound", Toast.LENGTH_SHORT).show();
} else {
try {
int counter = remoteService.getCounter();
TextView t = (TextView)findViewById(R.id.notApplicable);
t.setText( "Counter value: "+Integer.toString( counter ) );
Log.d( getClass().getSimpleName(), "invokeService()" );
} catch (RemoteException re) {
Log.e( getClass().getSimpleName(), "RemoteException" );
}
}
}

Once we use the service methods, we can release the service. This is done as follows (by clicking the release button):

private void releaseService() {
if(conn != null) {
unbindService(conn);
conn = null;
updateServiceStatus();
Log.d( getClass().getSimpleName(), "releaseService()" );
} else {
Toast.makeText(RemoteServiceClient.this, "Cannot unbind - service not bound", Toast.LENGTH_SHORT).show();
}
}

Finally we can stop the service by clicking the stop button. After this point no client can invoke this service.

private void stopService() {
if (!started) {
Toast.makeText(RemoteServiceClient.this, "Service not yet started", Toast.LENGTH_SHORT).show();
} else {
Intent i = new Intent();
i.setClassName("com.collabera.labs.sai", "com.collabera.labs.sai.RemoteService");
stopService(i);
started = false;
updateServiceStatus();
Log.d( getClass().getSimpleName(), "stopService()" );
}
}
These are the basics of working with a remote service on Android platform. All the best!