Archive

Archive for January, 2009

Sony Ericssons losses, Androids gain?

January 17th, 2009

As per latest news, Sony Ericsson has taken a hit in its yearly revenues and filed losses of more than 70 million Euros. With this news the rumours of split between Sony Ericsson and its parent company Sony starts to grow even stronger. But for Android community, there is that silver lining around all these bad news coming in. We already talked here, about how Motorola is going to focus on Android to help itself come out of these negative results and same will happen with Sony Ericsson too. 

Essentially companies are looking to cut costs by using Android open operating system and save costs of licensing costly proprietary solutions avaialble. It will be interesting to see how Windows Mobile and Symbian tackle this contuning shift by handset manufacturers in year 2009. If the way things are going, and industry experts believes things to get even worse for mobile manufacturers, we might see a altogether different market situation by end of this year.

Mobile Market, News

Android Location API

January 16th, 2009

Android support Location based service APIs. Location service allows to find out the device current location. The application can ask for periodic update of the device location. The application can also register a intent receiver for proximity alerts like when the device is entering and existing from an area of given longitude, latitude and radius.

Let’s check the important classes present in the android.location package.

Android Location API:

Following are the some important classes present under the android location package.

LocationManager: The class provides access to the location service. It also provides facility to get the best Location Provider as per the criteria. Proximity alerts can be set (as said above) with help of this class.

LocationProvider: It’s an abstract superclass for location providers. A location provider provides periodic reports on the geographical location of the device.

LocationListener: Provides callback methods which are called when location gets changed. The listener object has to be registered with the location manager.

Criteria: The class provides the application to choose suitable Location Provider by providing access to set of required properties of the LocationProvider.

Android also provide an API to access the Google MAPs. So with the help of the Google MAPs and the location APIs the application can show required places to the user on the MAP. Let’s see Android support for the Google APIs.

Google Map API

Android defines a package called com.google.android.maps. The package contains classes related to rendering, controlling and overlaying information on the Google maps on the android devices. Let’s see the most important classes defined in the package:

MapActivity: It is the spacing activity defined to show the Google MAPs. The MapActivity takes care of the low-level networking.

MapView: MapView is the view that supports and displays the map. This must be contained by a MapActivity.

MapController : MapController is the object used to move the map around the screen.

Overlay: It’s a drawable object that can be shown on top of the map.

GeoPoint: It’s a position in latitude-longitude.

Now we have some basic knowledge of the Location and Map APIs, so let’s create some application and see them in action.

Application:

Let’s develop an application that shown the Google MAP on the screen and shows the user’s current position on the MAP. We will use Google MAP APIs to show map on the device and then use location APIs to get the device current location to show it on the MAP. The user location will gets updated if the user moved from the current location.

Application Activity:

To use map in an activity that activity has to be extended by the MapActivity as shown..

class MyGPSActivity extends MapActivity {
...
}

To use the Google MAP APIs, application AndroidManifest.xml file must define following XML element, as a child of the application element:

<uses-library android:name=”com.google.android.maps” />

Using the MapView:

To display Map we need to add MapView to the application. Add following in the activity’s layout file (main.xml).

<com.google.android.maps.MapView
android:id="@+id/myGMap"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:enabled="true"
android:clickable="true"
android:apiKey="API_Key_String"
/>

To use the Google Map service an API key is needed. The API key can obtained as follows:

1) Get debug.keystore file. You will get this under USER_HOME\Local Settings\Application Data\Android directory.

2) Use keytool tool to generate Certificate fingerprint (MD5). Use following command on command prompt

keytool -list -alias androiddebugkey -keystore <path_to_debug_keystore>.keystore -storepass android -keypass android

3) Go to ‘Sign Up for the Android Maps API‘ page.  Put your Certificate fingerprint (MD5) And get your API key for android GMap application.

4) Replace “API_Key_String” with your API key.

Update the MyGPSActivity class to use the MapView

class MyGPSActivity extends MapActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
// Creating and initializing Map
gMapView = (MapView) findViewById(R.id.myGMap);
GeoPoint p = new GeoPoint((int) (lat * 1000000), (int) (long * 1000000));
gMapView.setSatellite(true);
//get MapController that helps to set/get location, zoom etc.
mc = gMapView.getController();
mc.setCenter(p);
mc.setZoom(14);
}
...
}

Certain permission has to be set in the AndroidManifest.xml file to use location information.

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

Using Location Manager:

The location manage object can be obtained with Context.getSystemService method with Context.LOCATION_SERVICE parameter.

LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

Update the GPSActivity to implement the LocationListener interface so that the activity can listener to the location changes.

class MyGPSActivity extends MapActivity implements LocationListener {
...
/* This method is called when use position will get changed */
public void onLocationChanged(Location location) {
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
protected boolean isRouteDisplayed() {
return false;
}

}

Lets add code to initialize the LocationManager and register the Location Listener with the location manager in the onCreate() method

@Override

public void onCreate(Bundle savedInstanceState) {
...
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, this);

}

Now the onLocationChanged method of the GPSActivity method will be called if the user changes its position by 500m. A “gps” (GSP_PROVIDER) provider is used here but you can obtain a provider object as per your needs with the getBestProvider method of the LocationManger and the Criteria object.

Here is the implementation of the onLocationChanged method

public void onLocationChanged(Location location) {
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
p = new GeoPoint((int) lat * 1000000, (int) lng * 1000000);
mc.animateTo(p);
}

}

The code changes the map location to the new updated location.

We can add extra things in our application like Zoom controls, Marker and Text to show current location etc.

Adding Zoom control:

The MAP api provides facility to add zoom control to the map display. Following code add zoom control to your application:

// Adding zoom controls to Map

ZoomControls zoomControls = (ZoomControls) gMapView.getZoomControls();

zoomControls.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,

LayoutParams.WRAP_CONTENT));

gMapView.addView(zoomControls);

gMapView.displayZoomControls(true);

Adding Map Overlay:

A map overlay can be added showing the user’s current location. To add an overlay, define a class that will extend Overlay class.

class MyLocationOverlay extends com.google.android.maps.Overlay {
@Override

public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {

super.draw(canvas, mapView, shadow);
Paint paint = new Paint();
// Converts lat/lng-Point to OUR coordinates on the screen.
Point myScreenCoords = new Point();
mapView.getProjection().toPixels(p, myScreenCoords);
paint.setStrokeWidth(1);
paint.setARGB(255, 255, 255, 255);
paint.setStyle(Paint.Style.STROKE);
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.marker);
canvas.drawBitmap(bmp, myScreenCoords.x, myScreenCoords.y, paint);
canvas.drawText("Here I am...", myScreenCoords.x, myScreenCoords.y, paint);
return true;

} }

The overlay display a text “Here I am..” on the map at user location.

Let’s add this overlay to our map view

// Add a location mark

MyLocationOverlay myLocationOverlay = new MyLocationOverlay();

List<Overlay> list = gMapView.getOverlays();

list.add(myLocationOverlay);

Running application on Emulator:

Run the emulator instance. The latitude and longitude values can be supplied to the emulator with the help of ‘Emulator Control’ window present in the DDMS eclipse perspective. According to latitude and longitude application will display location of user.

gpsapp

Download the sample code here

Android API , , ,

Android gains momentum : Motorola to focus on Android

January 15th, 2009

Chicago Tribune has confirmed the rumours that have been flying about Motorola and its focus on Android going forward. Moto has trimmed staffs by 4000 and most hit area is mobile development with around 3000 people being laid off from that division.

This essentially means that Moto’s smart phones will be powered with Android, through which company is hoping to give boost to its positioning in smartphone market.

Though laying off people is always a bad news, but for Android developers and enthusiast there is some thing to look forward to in this. We should see similar moves by other biggies in the field given the current economic situation. Working on open source technologies will catch momentum in mobile markets too.

News , , , ,

Android Application Lifecycle

January 14th, 2009

In Android, the applications are run as a separate Linux process. So the application lifecycle is closely related to the process lifecycle. The application process lifecycle is handled by the system depending on the current system memory state.

In case of low memory, the Android system kills some less important process. The process importance is decided depending on the state of the process components.

The process types depending on the importance are as follows (from most important to least important):

1. Foreground process: A foreground process is the application process with which the user is currently interacting. The process is considered to be foreground if its Activity is at the top of the Activity stack (its onResume() has been called) or BroadcastReceiver is currently running (onReceive() method is currently getting executed) or its Service is executing callback functions like onCreate(), onStart() or onDestroy() methods.

2. Visible Process: A visible process is the process which has an Activity visible to the user (its onPause() method has been called).

3. Service Process: Service process contains a Service for which startService method is called and the service is running.

4. Background Process: The background process does not have any visible activities to the user. (Activity onStop() method has been called).

5. Empty Process: Empty process is the one that does not have any active application components. These processes are kept on for caching purpose.

It is important that application developers understand lifecycle of the application process. Not using these correctly can result in the system killing the application’s process while it is doing important work.

Android Basics , , ,

Android Hierarchy Viewer

January 13th, 2009

Android Hierarchy viewer is added in 0.9 SDK. The Hierarchy Viewer tool allows you to optimize your user interface. It provides a visual representation of your layout’s hierarchy of Views and a pixel view of the current display.

 

To start the hierarchy View first start an emulator instance and then run hierarchyviewer.exe from android SDK tools/ directory.

The Hierarchy View will be started as shown:

01_hierarchyviewerdevices

 

The devices list on the left shows the currently running devices (or emulators). And on the right the list of currently active windows is displayed of the selected device.

 

To see the window’s View hierarchy select that window and click on the Load view hierarchy.

02_layoutview

 

The view hierarchy view shows the windows view and viewgroups as a hierarchy, depending on parent child relationship. The window’s wire frame view is also shown on the right side.

 

On selecting any view the property window shows the properties of that view. The property values are not editable. Clicking on the display view shows the selected element.

 

The Invalidate and Request Layout buttons executes the invalidate() and requestLayout() methods of the selected view. If you are running the application in debug mode, you can debug the view functionality with the help of these buttons.

 

To refresh the view hierarchy to reflect the changes as per the device current stage, ‘Load View Hierarchy’ can be used.

 

The hierarchy viewer tool also provides a Pixel Perfect view for the window. You can switch to the Pixel Perfect view by clicking on the second button at the bottom left corner.

 

Pixel Perfect View:

The pixel perfect view shows following 3 views:

Explorer View: It shows the view hierarchy as a list (left hand side view)

Normal View: View of the device window (middle view)

Loupe View: A magnified, pixel-grid view of the device window, on the right.

03_pixelperfectview

 

 

 

The normal and Loupe view refreshes after sometime to show the current device window.

 

A very useful feature is that you can overlay an image on top of the normal and Loupe Views. Support you have an already designed screen layout as an image. You can overlay that image on the device window by clicking on the Load button and selecting the file from file system. You can adjust the opacity of the image and match your screen components with the image to check whether they match.

 

So the hierarchy viewer is really useful to design the application screens (views) and debug the application.

 

Android Tools ,

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 , ,

Android Powers Netbook

January 9th, 2009

Today Qualcomm said it is using Android to power the latest netbook from its offerings. Industry experts have been speculating that Android will not merely remain a mobile operating system but soon will become operating system powering other, essentially, mobile devices like Netbooks, laptops.
Move was expected but this will happen so soon, with in 2 years of Android announcement is definitely a little surprising. We think that it will take another 2 years for Android to start dominating the entire range of mobile and slim devices market.
As developers, this means more and more enterprises will be porting applications to Android.
Overall momentum around Android is definitely picking up!

Android

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 ,