Archive

Posts Tagged ‘Basics of Android’

Setting up Android Application Development With Eclipse

January 12th, 2009

We will see how to setup Android development environment on a Windows machine.

To develop Android applications Android SDK is required. Currently released SDK version is 1.0r2. The latest SDK can be downloaded from this URL

Download the android-sdk-windows-1.0_r2.zip file.

Unzip the downloaded archive file to say c drive in C:\android-sdk-windows-1.0_r2 folder on your disk.

We are going to use Eclipse for developing Android applications. So let’s see how to configure the Eclipse to use Android SDK.

To develop Android application in Eclipse an eclipse plug-in ‘Android Development Tools’ (ADT) is required. Let’s see how to install the ADT plug-in for eclipse 3.3:

Steps to install ADT plug-in:

1. Start eclipse. Go to Help > Software Update > Find and install

2. Choose option Search for new feature to install.

3. Click on the button as New Remote Site. Add the name of the remote site as ‘Android Plug-in’ and put the URL, as shown in the image:

https://dl-ssl.google.com/android/eclipse/

01_addremotesite1

4. Check the newly added Remote Site also check the Discovery Site option, as shown in the image. Also select the Automatically select mirrors option.

02_updateoptions

Selecting the Discovery site is useful incase your eclipse environment does not have required plug-ins for the ADT plug-in.

5. Click on Finish.

6. The update window will show Android Plugin and Discovery site option.

7. Expand the Discovery site option so that content of the discovery site will be loaded.

8. Select (check) the android plug-in option. Sometimes this may show error as
‘ Android Editors (0.8.0.v200809220836-110569) requires plug-in “org.eclipse.wst.sse.ui”‘

9. Click on the ‘Select Required’ button. The required plug-ins will be selected from the Discovery site. Click next.

selectrequired

10. License agreement will be shown. To install plug-in select Accept terms and click Next.

11. Click Finish.

12. A warning message will be shown as plug-in is not signed. But you can safely install the plug-in by clicking Install All option.

13. Restart Eclipse.

Now your plug-in is installed. You have to initialize the plug-in to use the Android SDK that we downloaded earlier.

1. Go to the android Windows > Preferences menu. Eclipse Preference window will be opened.
2. Select Android from the left hand size menu (you can use the filter box to search quickly).
3. Click on the Browse button and select the location of the SDK in our case C:\android-sdk-windows-1.0_r2.
4. Click Apply and then Ok.

Now the plug-in is completely installed and you can start with the application development.

Creating an Android Project
Following are the steps to create Android project in eclipse

1. Select File > New > Android Project.

2. Select ‘Create a new Project in workspace’ option to create a new project. Provide the project name, base Package name, application main Launcher activity and Application Name as shown.
04_createandroidproject2

3. A new Eclipse Android project will be created. The project will have main activity class and Resource (R) class defined. A res folder containing application resources and AndroidManifest.xml file will also be generated.

Running the application:
To run the application Open the Run dialog. In the Run dialog select the Android Application and click on New Configuration.
Provide the configuration name and project name as follows (use default values for rest of the fields).

05_createlauchconf

Click on apply and click run.

The emulator will be started and the application’s main activity will call.

Debugging the application
To run the application in debug mode, choose eclipse Debug button and select the application launch configuration.
The application will go into the debug mode when the application reaches any breakpoints.

Using Logcat:
ADT provide a window called LogCat. The window can be opened from Window > Show view > LogCat. (You may have to click on others to see the complete list of available views).
The logcat view show system log messages as shown,

06_androidlogcatview

The application can also log message that will be shown in the Logcat view. The application can Log message with ‘Log’ class. Use methods Log.v (verbose), Log.d (debug), Log.i (info), Log.w (warning) and Log.e (error) as per the required log levels.

DDMS Perspective:
ADT come with an eclipse perspective called as DDMS perspective. Go to Windows > Open Perspective > DDMS.
The DDMS perspective shows windows like Devices, Emulator Control, File Explorer, Heap Status, and Thread Status.

07_eclipseddms-perspective

Devices window shows the currently running emulator instance. The window also shows the information about the application processes running on the emulator along with their pids. The window also provide options like ‘Debug Selected Process’, Update Process Thread and Heap status, Stop process and Capture Emulator screen. When Update Thread and Heap status option is selected the process Thread and Heap status can be seen in Head and Thread windows.

The Emulator Control Window provide functionality like sending SMS or Voice message to the emulator, Setting the emulator location co-ordinates etc.

The File Explorer shows the files and folders present on the emulator. The window also provides functionality to push a file on Device (emulator), Pull file from Emulator, Delete Selected files. The controls are present at the upper right corner.

The Logcat window is also shown as part of the DDMS perspective.

Now your Android development environment is all set and you also how to use the android tools. So now start developing Android Applications!

Android Tools , ,

Basics of Android : Part IV – Android Content Providers

January 9th, 2009

The last post in the series, which talks about basic Android development concepts. Android application can use a file or SqlLite database to store data. Content provider provides the way by which you can share the data between multiple applications. For example contact data is used by multiple applications and must be stored in Content Provider to have common access. A content provider is a class that implements a standard set of methods to let other applications store and retrieve the type of data that is handled by that content provider. If you want your data to be public and handle by many applications create your own content provider. Application can perform following operations on content provider -

  1. Querying data
  2. Modifying records
  3. Adding records
  4. Deleting records

Standard Content Provider: Android provide some standard content provider, which are already implemented in Android e.g. contacts, images on device etc. Using these content providers the application can access contact information, images available on the device etc. Querying data: The query string in content provider is different than standard sql query. For any operation like select, add, delete, modify we required content provider URI. The URI consist of three parts, the string “content://”, segment representing kind of data to retrieve and optional ID of specific item of the specified content provider. Here are some examples of query string:

content://media/internal/images URI return the list of all internal images on the device.

content://contacts/people/ URI return the list of all contact names on the device.

content://contacts/people/45 URI return the single result row, the contact with ID=45.

Although this is the general form of the query, query URIs are somewhat arbitrary and confusing. For this android provide list of helper classes in android.provider package that define these query strings so you should not need to know the actual URI value for different data types. So it will be easy to query data. Above URIs can be represented as:

MediaStore.Images.Media.INTERNAL_CONTENT_URI
Contacts.People.CONTENT_URI

To query about specific record we have to use same CONTENT_URI, but must append specific ID. So third URI becomes

Uri person = ContentUris.withAppendedId(People.CONTENT_URI, 23);

Here is how we can query for data:

Cursor cur = managedQuery(person, null, null, null);

This query returns the cursor which contains the fields, we can iterate through cursor to retrieve all data. Let’s see an example now, which will make concept clearer:

package com.wissen.testApp;

public class ContentProviderDemo extends Activity {

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

    private void displayRecords() {
        // An array specifying which columns to return.

        String columns[] = new String[] { People.NAME, People.NUMBER };
        Uri mContacts = People.CONTENT_URI;
        Cursor cur = managedQuery(mContacts, columns, // Which columns to return
                null, // WHERE clause; which rows to return(all rows)
                null, // WHERE clause selection arguments (none)
                null // Order-by clause (ascending by name)

        );
        if (cur.moveToFirst()) {
            String name = null;
            String phoneNo = null;
            do {
                // Get the field values
                name = cur.getString(cur.getColumnIndex(People.NAME));
                phoneNo = cur.getString(cur.getColumnIndex(People.NUMBER));
                Toast.makeText(this, name + " " + phoneNo, Toast.LENGTH_LONG).show();
            } while (cur.moveToNext());
        }
    }
}

In above example we are retrieving only specific columns contact name, number and displaying the contact records one by one. Modifying Records: To modify the set of records call the method ContentResolver.update() with columns and value to be changed. You can select the columns to be updated in Content query string or in method itself. Here is how it can be done:

private void updateRecord(int recNo, String name) {
        //appending recNo, record to be updated
        Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, recNo);
        ContentValues values = new ContentValues();
        values.put(People.NAME, name);
        getContentResolver().update(uri, values, null, null);
    }

You can call above method to modify any record by specifying record number and name.

updateRecord(10,"XYZ");

This will change the name to “XYZ” of record number 10. Adding Records: To add a new record, call ContentResolver.insert() with the URI of the type of item to add, and a Map of any values you want to set immediately on the new record. This will return the full URI of the new record, including record number, which you can then use to query and get a Cursor over the new record. In above example what we have used is standard Content Provider, Contacts. We can add records in contacts also. Continuing our previous example, let us create insertRecord() method that will do the work of insertion.

private void insertRecords(String name, String phoneNo) {
        ContentValues values = new ContentValues();
        values.put(People.NAME, name);
        Uri uri = getContentResolver().insert(People.CONTENT_URI, values);
        Log.d("ANDROID", uri.toString());
        Uri numberUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY);
        values.clear();
        values.put(Contacts.Phones.TYPE, People.Phones.TYPE_MOBILE);
        values.put(People.NUMBER, phoneNo);
        getContentResolver().insert(numberUri, values);
    }

To insert record in contacts just call insertRecords(name, phoneNo). Deleting records: To delete record/records from content provider use getContextResolver.delete(). Following example deletes all contacts from device as no where condition is specified.

 private void deleteRecords() {
        Uri uri = People.CONTENT_URI;
        getContentResolver().delete(uri, null, null);
    }

You can delete specific records by specifying where condition in method as parameter. This will give you an idea, how to delete specific records:

getContentResolver().delete(uri, "NAME=" + "'XYZ XYZ'", null);

This will delete records whose name is ‘XYZ XYZ’. Creating Content Provider: We now know how to use the content Provider; let’s now see how to create a content provider. To create own Content Provider in android following steps needs to be followed: 1. Create a class that will extend ContentProvider. 2. Define a public static final Uri named CONTENT_URI. This is the string that represents the full “content://” URI that your content provider handles. You must define a unique string for this value; the best solution is to use the fully-qualified class name of your content provider (lowercase). So, for example:

public static final Uri CONTENT_URI = Uri.parse( "content://com.google.android.MyContentProvider");

3. Create your system for storing data. Most content providers store their data using Android’s file storage methods or SQLite databases, but you can store your data any way you want, so long as you follow the calling and return value conventions. 4. Define column names that you will return to client. If you are using android database the column will be same as database. But you database must include one column call as _id, which identify each record in database uniquely. 5. If you are exposing byte data, such as a bitmap file, the field that stores this data should actually be a string field with a content:// URI for that specific file. This is the field that clients will call to retrieve this data. The content provider for that content type (it can be the same content provider or another content provider – for example, if you’re storing a photo you would use the media content provider) should implement a field named _data for that record. The _data field lists the exact file path on the device for that file. This field is not intended to be read by the client, but by the ContentResolver. The client will call ContentResolver.openOutputStream() on the user-facing field holding the URI for the item (for example, the column named photo might have value content://media/images/4453). The ContentResolver will request the _data field for that record, and because it has higher permissions than a client, it should be able to access that file directly and return a read wrapper for that file to the client. 6. Declare public static String for client to specify which column to return or to specify field value from cursor. 7. Return a Cursor object in response to query. This means write down all the overridden methods such as insert(), update() and delete() those will perform operations on underlying database. We may notify the listeners about updated information by using ContentResover().notifyChange(). 8. Add <provider> tag to AndroidMenifest.xml and set its authorities to define the authority part of the content type it should handle. 9. If you are handling a new data type, you must define a new MIME type to return for your implementation of android.ContentProvider.geType(url). This type corresponds to the content:// URI submitted to getType(), which will be one of the content types handled by the provider. The MIME type for each content type has two forms: one for a specific record, and one for multiple records. Use the Uri methods to help determine what is being requested. Here is the general format for each:

vnd.android.cursor.item/vnd.yourcompanyname.contenttype for a single row.

For example, a request for train record 122 using content://com.example.transportationprovider/trains/122 might return the MIME type vnd.android.cursor.item/vnd.example.rail

vnd.android.cursor.dir/vnd.yourcompanyname.contenttype for multiple rows.

For example, a request for all train records using content://com.example.transportationprovider/trains might return the MIME type vnd.android.cursor.dir/vnd.example.rail Here is the code that creates a content provider. The example just store user name and display the user names of all the users. SQLLite database is used to store the user data.

package com.wissen.testApp;

public class MyUsers {

    public static final String AUTHORITY = "com.wissen.MyContentProvider";

    // BaseColumn contains _id.
    public static final class User implements BaseColumns {

        public static final Uri    CONTENT_URI = Uri.parse("content://com.wissen.MyContentProvider");

        // Table column
        public static final String USER_NAME   = "USER_NAME";
    }
}

The above class defines the CONTENT_URI of the content provider, it also defines the columns of the content provider. Next we will define the actual content provider class that will use the above defined class.

package com.wissen.testApp.android;

public class MyContentProvider extends ContentProvider {

    private SQLiteDatabase      sqlDB;

    private DatabaseHelper      dbHelper;

    private static final String DATABASE_NAME    = "Users.db";

    private static final int    DATABASE_VERSION = 1;

    private static final String TABLE_NAME       = "User";

    private static final String TAG              = "MyContentProvider";

    private static class DatabaseHelper extends SQLiteOpenHelper {

        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            //create table to store user names
            db.execSQL("Create table " + TABLE_NAME + "( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
            onCreate(db);
        }
    }

    @Override
    public int delete(Uri uri, String s, String[] as) {
        return 0;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues contentvalues) {
        // get database to insert records
        sqlDB = dbHelper.getWritableDatabase();
        // insert record in user table and get the row number of recently inserted record
        long rowId = sqlDB.insert(TABLE_NAME, "", contentvalues);
        if (rowId > 0) {
            Uri rowUri = ContentUris.appendId(MyUsers.User.CONTENT_URI.buildUpon(), rowId).build();
            getContext().getContentResolver().notifyChange(rowUri, null);
            return rowUri;
        }
        throw new SQLException("Failed to insert row into " + uri);
    }

    @Override
    public boolean onCreate() {
        dbHelper = new DatabaseHelper(getContext());
        return (dbHelper == null) ? false : true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        qb.setTables(TABLE_NAME);
        Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder);
        c.setNotificationUri(getContext().getContentResolver(), uri);
        return c;
    }

    @Override
    public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
        return 0;
    }
}

So we created a content Provider class as MyContentProvider and wrote code for insertion and retrieving records from Sqlite database. The content provider entry has to be added in the AndroidManifest.xml file as follows:

<provider android:name="MyContentProvider" android:authorities="com.wissen.MyContentProvider" />

Now Lets use the above defined content provider:

package com.wissen.testApp;

public class MyContentDemo extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        insertRecord("MyUser");
        displayRecords();
    }

    private void insertRecord(String userName) {
        ContentValues values = new ContentValues();
        values.put(MyUsers.User.USER_NAME, userName);
        getContentResolver().insert(MyUsers.User.CONTENT_URI, values);
    }

    private void displayRecords() {
        // An array specifying which columns to return.
        String columns[] = new String[] { MyUsers.User._ID, MyUsers.User.USER_NAME };
        Uri myUri = MyUsers.User.CONTENT_URI;
        Cursor cur = managedQuery(myUri, columns, // Which columns to return
                null, // WHERE clause; which rows to return(all rows)
                null, // WHERE clause selection arguments (none)
                null // Order-by clause (ascending by name)
        );
        if (cur.moveToFirst()) {
            String id = null;
            String userName = null;
            do {
                // Get the field values
                id = cur.getString(cur.getColumnIndex(MyUsers.User._ID));
                userName = cur.getString(cur.getColumnIndex(MyUsers.User.USER_NAME));
                Toast.makeText(this, id + " " + userName, Toast.LENGTH_LONG).show();
            } while (cur.moveToNext());
        }
    }
}

The above class first adds a user entry in the database and then displays all the usernames available in the db. So we saw how to user the content providers and how to create our own content provider. From this post on wards we will be diving deep into specific APIs like Android Media API, Android Communications API, Accelarometer and lots of other stuff.

Android Basics , , ,

Basics of Android : Part III – Android Services

January 8th, 2009

Many a times the application needs to do some tasks in the background for which user interventions is not required (or very less intervention is required). These background processes keeps working even if user is using some other application on the phone.

To define such background processes android has a concept of Services. Service in android is long lived application component. Service doesn’t implement any User Interface. Common example of service is Media Player application that keeps playing song in the background, file download application that can download the file in the background.

Let’s see how to create a service.

Creating a service

Android has defined a base class for all services as ‘Service’. All the services have to extend from this Service class. Service class defines service lifecycle methods like onCreate(), onStart(), onDestroy(). Here is the example a service class

package com.wissen.testApp.service;
public class MyService extends Service {
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
	@Override
	public void onCreate() {
		super.onCreate();
		Toast.makeText(this, "Service created...", Toast.LENGTH_LONG).show();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
	}
}

The above service is notifying the user when the service is created and service is destroyed.

Like every thing else in android, Service in android are also associated with the intents. This intent is required while using the service.

The service entry has to be done in the AndroidManifest.xml file along with the service intent as shown below:

<service class=".service.MyService">
<intent-filter>
<action android:value="com.wissen.testApp.service.MY_SERVICE" />
</intent-filter>
</service>

Now our service is created and can be used by the application code.

Using the service:

The application can start the service with the help of Context.startService method. The method will call the onCreate method of the service if service is not already created; else onStart method will be called. Here is the code to start the MyService

..

Intent serviceIntent = new Intent();
serviceIntent.setAction("com.wissen.testApp.service.MY_SERVICE");
startService(serviceIntent);

The service started with startService method will keep on running until stopService() is called or stopSelf() method is called.

Another way to use service is to bind to the service. The service contented this way will be considered required by the system only for as long as the calling context exists. To bind to the service a service connection object need to be created. The service connection object tell the application when the service is connected or disconnected. Here is how you can bind to the service.

ServiceConnection conn = new ServiceConnection() {
	@Override
	public void onServiceConnected(ComponentName name, IBinder service) {
	Log.i("INFO", "Service bound ");
	@Override
	public void onServiceDisconnected(ComponentName arg0) {
	Log.i("INFO", "Service Unbound ");
	}
	}

	bindService(new Intent("com.wissen.testApp.service.MY_SERVICE"), conn, Context.BIND_AUTO_CREATE);
}

The application can communicate with the service when application is connected with the service. Generally the service communicate is done with the help of Service Interface. Service interface defines methods for which service can provider implementation. For example here is some interface:

package com.wissen.testApp;
public interface IMyService {
public int getStatusCode();
}

Using this interface the application can ask the Service about its status. Lets see how the service can support this interface. Previously we saw a method called onBind which return IBinder object, the method gets called when some client of the service binds to the service. This is the same object that is passed to the onServiceConnected method. The application can communicate with the service using this IBinder object. Here is how this can be done:

 

public class MyService extends Service {
	private int statusCode;
	private MyServiceBinder myServiceBinder = new MyServiceBinder();
	@Override
	public IBinder onBind(Intent intent) {
		return myServiceBinder; // object of the class that implements Service
								// interface.
	}
	public class MyServiceBinder extends Binder implements IMyService {

		public int getStatusCode() {
			return statusCode;
		}
	}
	// .......
}

 

And here is how application can call getStatusCode method:

 

	ServiceConnection conn = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			IMyService myService = (IMyService) service;
			statusCode = myService.getStatusCode();
			Log.i("INFO", "Service bound ");
		}
		// ........
	};

You can also define ServiceListener interface which the client of the service has to be implemented to gets update from the service. In that case the service interface will have to define methods to register and unregister the ServiceListener objects.

Communication with Remote Service:

The services that we defined until now run in the application processes, you can define service that can run in their own process. For two processes to communicate with each other they need to marshal the object to sent to other process.

Android provide an AIDL tool (Android Interface definition Language) to handle all marshalling and communication part.

 

The service has to provide the Service interface as an aidl file. The AIDL tool will create a java interface corresponding for the aidl Service Interface. The AIDL tool also defines a stub class in the generated service interface, which implements the Service Interface (as abstract methods) and also provides some other required functionality. The service interface implementation class has to extend this stub class and define the service interface methods. The service onBind method will return object of this implementation class so that the client application can use the service methods. Here is the how the communication can be done:

Create a file as IMyRemoteService.aidl as follows:

 

package com.wissen.testApp;

interface IMyRemoteService {
int getStatusCode();
}

The eclipse android plug-in will create a Java interface for the aidl file created above as the part of build process.

The interface generated above will have a Stub inner class. Define a class that extends this stub class. Here is the code for the RemoteService class:

package com.wissen.testApp;
class RemoteService implements Service {
	int statusCode;

	@Override
	public IBinder onBind(Intent arg0) {
		return myRemoteServiceStub;
	}
	private IMyRemoteService.Stub myRemoteServiceStub = new IMyRemoteService.Stub() {
		public int getStatusCode() throws RemoteException {
			return 0;
		}
	};
	// ........
}

When the client application connect to the service the onServiceConnected method will be called and client will get the IBinder object of the service. The Stub class also provides a method to obtain the Service Interface object from the IBinder object. Here is the client onServiceConnected code

 

	ServiceConnection conn = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			IMyRemoteService myRemoteService = IMyRemoteService.Stub
					.asInterface(service);

			try {

				statusCode = myRemoteService.getStatusCode();
			} catch (RemoteException e) {

				// handle exception

			}

			Log.i("INFO", "Service bound ");
		}
		// .........
	};

Permissions:

Service may specify required user permissions in the AndroidManifest.xml in <service> tag like this,

<service class=".service.MyService" android:permission="com.wissen.permission.MY_SERVICE_PERMISSION">
<intent-filter>
<action android:value="com.wissen.testApp.service.MY_SERVICE" />
</intent-filter>
</service>

Then to use above service the application has to ask for permission with the help of <user-permission> tag as follows:

<uses-permission android:name="com.wissen.permission.MY_SERVICE_PERMISSION"></uses-permission>

So in today’s post we saw how to create service and use it. In the next post we will see how to use ContentProviders. 

Android Basics , ,

Basics of Android : Part II – Intent Receivers

January 7th, 2009

In the last post we see about the Android activities and how to use them.

In this post we will see about the IntentReceivers.

Android Intent receivers are part of the event handling mechanism. The intent receiver can handle the broadcaste intents and thus can be used as event handler.

Creating Intent Receivers:

Android has defined a ‘BroadcastReceiver’ class. All the intent receivers have to inherit from this class. Following is the example of the intent receiver

package com.wissen.testApp.receiver;

public class MyIntentReceiver extends BroadcastReceiver {

/**

* @see adroid.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)

*/

@Override

public void onReceive(Context context, Intent intent) {

...

}

}

The intent receiver has to override the method onReceive as shown above. The onReceive method gets called when intent receiver’s intent is broadcasted, and thus onReceive() method is the entry point for the intent receiver.

The intent receiver entry has to be done in the AndroidManifest.xml file. The intent receiver can be defined in manifest xml as follows:

<receiver android:name=”.receiver.MyIntentReceiver” android:enabled=”true”>
<intent-filter>
<action android:name=”com.wissen.testApp.MY_INTENT_RECEIVER” />
</intent-filter>
</receiver>

The intent receiver can also be registered dynamically with the help of Context.registerReceiver() method as follows:

..


MyIntentReceiver intentReceiver = new MyIntentReceiver();

IntentFilter intentFilter = new IntentFilter("com.wissen.testApp.MY_INTENT_RECEIVER");

registerReceiver(intentReceiver, intentFilter);

..

Broadcasting Intent:

The intent can be broadcasted with the help of sendBroadcast() and sendOrderedBroadcast() method of the Context class. The sendBroadcast method will send the broadcast to all the registered Intent Receivers, on the other hand sendOrderedBroadcast() method calls the intent receivers one at a time. This gives the intent receivers ability to exchange result of previous intent receiver or to abort the broadcast. The order of execution is controls by the android:priority attribute defined in the <intent-filter> tag of AndroidManifext.xml file.

Receiver Lifecycle:

There is only one lifecycle method for the intent receiver as onReceive(). The method gets called when intent is broadcasted. The receiver object is only valid for the duration of the onReceive() method, after the method ends the object is considered to be non-active and can be garbage collected. Because of this the intent receiver onReceive() method should not handle any asynchronous operation.

To receiver an intent by the intent receiver the application does not need to be running. When the intent is broadcasted the system will start the application to call the intent receiver.

Permissions:

Sometimes for defining intent receivers for some intent, permissions need to be specified by the intent receiver. The intent receiver can specify the required permission in the AndroidManifest.xml file with the help of <user-permission> tag. While registering the intent receiver dynamically, the permission can be specified as the parameter of the registerReceiver method.

To enforce a permission while broadcasting an intent, a non-null permission argument need to be specified for the sendBroadcast() or sendOrderedBroadcast() method.

This is all on the intent receivers. In next post we will see android services and content providers.

Android Basics ,

Basics of Android : Part I – Android Activities

January 4th, 2009

There are four basic building blocks of an Android Application -

1. Activity

2. Intent Receivers

3. Service

4. Content Providers

In this post we will go in details of the activity. Activities represent the application screens in Android. Android platform define a class ‘Activity’, all the activities have to extend from Activity class.

Android platform is designed in such way that all applications can expose interfaces using above mentioned 4 building blocks through which they can interact with each other. There fore defining screens in XML is major feature required in developing such no-boundary application.

Designing user screen in XML:

The activity (screen) consists of views and viewgroups. Views are the standard screen components like TextView (Label), Buttons, CheckBox, EditText (textbox) etc. The viewgroups are special views that can contain other views and thus viewgroups can be used as panels to arrange the views on the screen. Viewgroups examples are LinearLayout, RelativeLayout, AbsoluteLayout etc.

Android supports XML syntax for designing application screens. Let’s develop an xml layout of screen which takes user’s first name and last name.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/widget28"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/firstNameLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="First Name:">
</TextView>
<EditText
android:id="@+id/firstName"
android:layout_width="319px"
android:layout_height="wrap_content"
android:textSize="18sp">
</EditText>
<TextView
android:id="@+id/lastNameLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Last Name:">
</TextView>
<EditText
android:id="@+id/lastName"
android:layout_width="320px"
android:layout_height="wrap_content"
android:textSize="18sp">
</EditText>
<Button
android:id="@+id/submitButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Submit"
android:layout_gravity="center_horizontal">
</Button>
</LinearLayout>

There are visual tools available for creating android XML screen layout. Try out droiddraw.

The above activity layout shows two textboxes for user’s first Name and last Name. Each view controls is assigned an id to identify and access the control. Activity layouts are stored under resources directory as layouts (in res/layout dir).

Activity intents:

Each activity is associated with intents which specify what the Activity can do. Activity intent consists of action and data required by the activity. The activity intents are specified in the application AndroidManifest.xml file as intent filters. Activity can support multiple actions. See the example below:

<activity class=".SomeActivity" android:label="@string/activityTitle">
<intent-filter>
<action android:value="android.intent.action.VIEW" />
<category android:value="android.intent.category.DEFAULT" />
<type android:value="content://contacts" />
</intent-filter>
</activity>

The above activity supports the view action for contact data. That means the activity display the phone contacts. There are some standard intent actions defined by the android platform like VIEW, EDIT, MAIN etc. But custom intent actions can also be specified as shown below:

<activity class=".TestActivity" android:label="@string/activityTitle">
<intent-filter>
<action android:value="com.wissen.testApp.activities.TEST_ACTIVITY" />
<category android:value="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

This activity can be used by using the TEST_ACTIVITY intent. We will see how to create activity with intents in following part of post.

Application Launcher Activity:

Every android application has a Launcher activity. The launcher activity is the activity that gets control when the application starts.

Launcher activity must support predefined intent ‘android.intent.action.MAIN’ and has category ‘android.intent.category.LAUNCHER’.

The launcher activity can be specified in the AndroidManifest.xml as follows:

<activity class=".WelcomeActivity" android:label="@string/app_name">
<intent-filter>
<action android:value="android.intent.action.MAIN" />
<category android:value="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Creating an Activity:

All the activity must extend android ‘Activity’ class. onCreate() method gets called when an activity is created.

Let create an activity for the layout we defined earlier. Here is the code…

package com.wissen.testApp;

public class UserInfoActivity extends Activity {

		private EditText firstName;

		private EditText lastName;

		/** Called when the activity is first created. */

		@Override

		public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);

		setContentView(R.layout.main);

		firstName = (EditText) findViewById(R.id.firstName);<

		lastName = (EditText) findViewById(R.id.lastName);

		submitButton = (Button) findViewById(R.id.saveButton);

		}
	}

The above activity class overrides the onCreate method. The onCreate is the activity lifecycle method and as name suggests it gets call when activity is created. So the onCreate method is the entry point for an activity.

Activity calls the setContentView method to assign the layout that we defined earlier. The Resource class is used to refer to the xml layout main (the xml file name is main.xml).

As we saw in the xml layout all the view controls as assigned id's to them. The activity can refer to the view with the help of these defined ids by using the findViewById method.

So now our activity is using layout that we defined and also has access to the firstName, lastName and button controls.

Lets define an onClick event handler for the submit button. The event handler will just show user provide firstName and LastName in a notification.

public class UserInfoActivity extends Activity implements View.OnClickListener {

		private EditText firstName;

		private EditText lastName;

		/** Called when the activity is first created. */

		@Override

		public void onCreate(Bundle savedInstanceState) {
		 //.......
		}<

		public void onClick(View view) {

		if(view.getId() == R.id.submitButton) {

		Toast.makeText(context, "Hi " + firstName.getText() + " " + lastName.getText().toString(), Toast.LENGTH_LONG).show();

		}
		}
		}

Define the above activity as the launcher activity in the AndroidManifest.xml file and the activity will be called when the application will start.

Activity Lifecycle:

Let see what the lifecycle of the android activity is. Activity class supports following lifecycle methods,

onCreate(): Called when the activity is first created. This is where setting up views is done. This method also provides you with a Bundle containing the activity's previous state (if any).

onRestart(): Called just before activity is being started after it has been stopped.

onStart(): Called when the activity is becoming visible to the user. Followed by onResume() if the activity is at the top of the activity stack.

onResume(): Called when the activity will start interacting with the user, i.e. activity is at the top of the activity stack.

onPause(): Called just before some other activity become active and user start interacting with the new activity. This method can be used to save unsaved changes.

onStop(): Called when the activity is no longer visible to the user. This may happen either because a new activity become visible, or this one is being destroyed.

onDestroy(): This method is called just before the activity is destroyed. The activity can be destroyed by calling finish() method.

Starting an Activity:

We have seen how to create and show a launcher activity. To show other activities in the application the activities has to be started.

Support you have defined an as activity as follows:

package com.wissen.testApp;

public class TestActivity extends Activity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		// ........
	}
}

AndroidManifest.xml contains:


<activity class=".TestActivity" android:label="@string/activityTitle">

<intent-filter>

<action android:value="com.wissen.testApp.activities.TEST_ACTIVITY" />

<category android:value="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

To show this activity to the user, the activity must be started (this can happen on some event). Here is show the activity can be started

Intent testActivityIntent = new Intent();

testActivityIntent.setAction("com.wissen.testApp.activities.TEST_ACTIVITY");

startActivity(myProfileIntent);

The activity can also be started by setting the Activity class name in the intent. Like

intent.setClass(context, TestActivity.class);

Sometimes the caller activity need some return value from the called activity. In that case the caller will start the activity with the help of startActivityForResult() method. The caller will get the result onActivityResult() method as follows:

public class MyActivity extends Activity {

	// ...

	static final int REQUEST_CODE = 0;

	protected boolean onKeyDown(int keyCode, KeyEvent event) {

		startActivityForResult(

		new Intent("activity.Action"),

		REQUEST_CODE);

		return true;

	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {

		if (requestCode == REQUEST_CODE) {

			if (resultCode == RESULT_OK) {

				// .. do something with the result

			}

		}

	}

}

The REQUEST_CODE will be return back by the called activity to identify the request.

This is all on the activities. In subsequent posts we will see other building blocks of the android platform.

Android Basics , , ,