Friday, March 25, 2011

Notifications

By Magesh Kumar   Posted at  2:20 AM   Android No comments

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

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

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

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

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

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

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

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

The code is explained below:

Step 1: Procure a handle to the NotificationManager:

            private NotificationManager mNotificationManager;
      …
mNotificationManager = 
      (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

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

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

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

Context context = getApplicationContext();
      
CharSequence contentTitle = "Notification Details...";
      
CharSequence contentText = "Browse Android Official Site by clicking me";
Intent notifyIntent = newIntent(android.content.Intent.ACTION_VIEW,Uri.parse("http://www.android.com"));
      
PendingIntent intent = 
      PendingIntent.getActivity(SimpleNotification.this, 0, 
      notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intent);
Step 4: Now the stage is set. Notify. 
       
      mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);

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

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

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

Gallery View

By Magesh Kumar   Posted at  2:08 AM   Android No comments


Continuing on the Views, I have taken up the Gallery View that helps in showing Images as in a gallery. As per the android documentation, this is the definition: “A Gallery is a View commonly used to display items in a horizontally scrolling list that locks the current selection at the center.”


For this the layout xml in this case, the main.xml will have a ‘Gallery’ element as shown below:

<Gallery 
    android:id="@+id/Gallery01" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"></Gallery>
<ImageView android:id="@+id/ImageView01" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"></ImageView>

It also has an ImageView element which is used to show the selected Image in a larger ImageView. Here is how it would look when executed.



Now, I create a GalleryView Activity. To view a set of images of Antartica, I have created small sized images of antartica and stored them in the res/drawable-ldpi folder starting formantartica1.png to antartica10.png.

I create an array of these resources/images in my activity with the following code:

Integer[] pics = {
R.drawable.antartica1,
R.drawable.antartica2,
R.drawable.antartica3,
R.drawable.antartica4,
R.drawable.antartica5,
R.drawable.antartica6,
R.drawable.antartica7,
R.drawable.antartica8,
R.drawable.antartica9,
R.drawable.antartica10
};

As we have seen with all the other views so far, we need to have an adapter that associates the view with the data. Here the view is Gallery and the data is the above mentioned 10 images. An Adapter plays the role of linking the two as shown below:

Gallery ga = (Gallery)findViewById(R.id.Gallery01);
ga.setAdapter(new ImageAdapter(this));

However, we do not have a readymade implementation of the ImageAdapter. We have to create our own implementation of the same by extending the BaseAdapter class. This is the core of the code in this example. The moment we extend the BaseAdapter, we have to override 4 methods. They aregetCount(), getItem(), getItemId() and getView().

Before we go to each of them, let us see the constructor of the ImageAdpater:

public class ImageAdapter extends BaseAdapter {

private Context ctx;
int imageBackground;

public ImageAdapter(Context c) {
    ctx = c;
    TypedArray ta = obtainStyledAttributes(R.styleable.Gallery1);
    imageBackground = ta.getResourceId(R.styleable.Gallery1_android_galleryItemBackground, 1);
    ta.recycle();
}
}

It takes the context that is passed to the constructor. We need to examine this code a little. First, we can define our own resources or attributes in an XML file. Those attributes can be retrieved through the method obtainStyledAttributes. This is a method on the Context object. The returned value needs to be stored in a TypedArray object. A TypedArray is nothing but a container for an array of values that are returned by obtainStyledAttributes.

So, in my example, I have created an xml file by name attributes.xml in the res/values folder with the following content:

<resources>
     <declare-styleable name="Gallery1">
    <attr name="android:galleryItemBackground"/>
     </declare-styleable>
</resources>

Here Gallery1 is a custom name for a style defined by us. In this style, we are trying to say what should be the background of our images. For that we are using a pre-defined backgournd in R.attrclass as galleryItemBackground.

So, this is accessed in the ImageAdapter contructor through the line

ta.getResourceId(R.styleable.Gallery1_android_galleryItemBackground, 1);
ta.recycle();

The number 1 is to say that it is the first element in the attributes.xml file under the styelableGallery1.

The rest of the over ridden methods are simple:

@Override
public int getCount() {
    return pics.length;
}

@Override
public Object getItem(int arg0) {
    return arg0;
}

@Override
public long getItemId(int arg0) {
    return arg0;
}

@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
    ImageView iv = new ImageView(ctx);
    iv.setImageResource(pics[arg0]);
    iv.setScaleType(ImageView.ScaleType.FIT_XY);
    iv.setLayoutParams(new Gallery.LayoutParams(150,120));
    iv.setBackgroundResource(imageBackground);
    return iv;
}

The getView actually returns a View object when called. Here I have overridden it to return aImageView object with the selected image inside it alosn with some scale, layout paramaters and the image background set.

Finally in the onCreate() method of the activity I have captured the onClick event on a Gallery item and within that I have toasted a message as well as displayed the image in a bigger manner below the gallery:

ga.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
    Toast.makeText(getBaseContext(), "You have selected picture " + (arg2+1) + " of Antartica", 
        Toast.LENGTH_SHORT).show();
    imageView.setImageResource(pics[arg2]);
}
});


Tuesday, March 15, 2011

Creating and Using Databases in Android

By Magesh Kumar   Posted at  11:42 PM   Android No comments

Every application uses data, and Android applications are no exception. Android uses the open-source, stand-alone SQL database, SQLite. Learn how to create and manipulate a SQLite database for your Android app.

Creating the DBAdapter Helper Class
A good practice for dealing with databases is to create a helper class to encapsulate all the complexities of accessing the database so that it's transparent to the calling code. So, create a helper class called DBAdapter that creates, opens, closes, and uses a SQLite database.
First, add a DBAdapter.java file to the src/<package_name> folder
In the DBAdapter.java file, import all the various namespaces that you will need:

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DBAdapter
{

}

Next, create a database named bookstitles with the fields shown in

Define the following constants in the DBAdapter.java file.

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DBAdapter
{
    public static final String KEY_ROWID = "_id";
    public static final String KEY_ISBN = "isbn";
    public static final String KEY_TITLE = "title";
    public static final String KEY_PUBLISHER = "publisher";   
    private static final String TAG = "DBAdapter";
   
    private static final String DATABASE_NAME = "books";
    private static final String DATABASE_TABLE = "titles";
    private static final int DATABASE_VERSION = 1;

    private static final String DATABASE_CREATE =
        "create table titles (_id integer primary key autoincrement, "
        + "isbn text not null, title text not null, "
        + "publisher text not null);";
       
    private final Context context; 
}

The DATABASE_CREATE constant contains the SQL statement for creating the titles table within the books database.
Within the DBAdapter class, you extend the SQLiteOpenHelper class—an Android helper class for database creation and versioning management. In particular, you override the onCreate() and onUpgrade() methods
In the DBAdapter class, extend the SQLiteOpenHelper class and override the onCreate() and onUpgrade() methods.

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DBAdapter
{
    public static final String KEY_ROWID = "_id";
    public static final String KEY_ISBN = "isbn";
    public static final String KEY_TITLE = "title";
    public static final String KEY_PUBLISHER = "publisher";   
    private static final String TAG = "DBAdapter";
   
    private static final String DATABASE_NAME = "books";
    private static final String DATABASE_TABLE = "titles";
    private static final int DATABASE_VERSION = 1;

    private static final String DATABASE_CREATE =
        "create table titles (_id integer primary key autoincrement, "
        + "isbn text not null, title text not null, "
        + "publisher text not null);";
       
    private final Context context;
   
    private DatabaseHelper DBHelper;
    private SQLiteDatabase db;

    public DBAdapter(Context ctx)
    {
        this.context = ctx;
        DBHelper = new DatabaseHelper(context);
    }
       
    private static class DatabaseHelper extends SQLiteOpenHelper
    {
        DatabaseHelper(Context context)
        {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db)
        {
            db.execSQL(DATABASE_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion,
                              int newVersion)
        {
            Log.w(TAG, "Upgrading database from version " + oldVersion
                  + " to "
                  + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS titles");
            onCreate(db);
        }
    }   
}

The onCreate() method creates a new database if the required database is not present. The onUpgrade() method is called when the database needs to be upgraded. This is achieved by checking the value defined in the DATABASE_VERSION constant. For this implementation of the onUpgrade() method, you will simply drop the table and create the table again.
Defining the various methods for opening and closing the database, as well as the methods for adding/editing/deleting rows in the table.
public class DBAdapter
{
    //...
    //...

   //---opens the database---
    public DBAdapter open() throws SQLException
    {
        db = DBHelper.getWritableDatabase();
        return this;
    }

    //---closes the database---   
    public void close()
    {
        DBHelper.close();
    }
   
    //---insert a title into the database---
    public long insertTitle(String isbn, String title, String publisher)
    {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_ISBN, isbn);
        initialValues.put(KEY_TITLE, title);
        initialValues.put(KEY_PUBLISHER, publisher);
        return db.insert(DATABASE_TABLE, null, initialValues);
    }

    //---deletes a particular title---
    public boolean deleteTitle(long rowId)
    {
        return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
    }

    //---retrieves all the titles---
    public Cursor getAllTitles()
    {
        return db.query(DATABASE_TABLE, new String[] {
                        KEY_ROWID,
                        KEY_ISBN,
                        KEY_TITLE,
                KEY_PUBLISHER},
                null,
                null,
                null,
                null,
                null);
    }

    //---retrieves a particular title---
    public Cursor getTitle(long rowId) throws SQLException
    {
        Cursor mCursor =
                db.query(true, DATABASE_TABLE, new String[] {
                                     KEY_ROWID,
                                     KEY_ISBN,
                                     KEY_TITLE,
                                     KEY_PUBLISHER
                                     },
                                     KEY_ROWID + "=" + rowId,
                                     null,
                                     null,
                                     null,
                                     null,
                                     null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;
    }

    //---updates a title---
    public boolean updateTitle(long rowId, String isbn,
    String title, String publisher)
    {
        ContentValues args = new ContentValues();
        args.put(KEY_ISBN, isbn);
        args.put(KEY_TITLE, title);
        args.put(KEY_PUBLISHER, publisher);
        return db.update(DATABASE_TABLE, args,
                         KEY_ROWID + "=" + rowId, null) > 0;
    }
}

Notice that Android uses the Cursor class as a return value for queries. Think of the Cursor as a pointer to the result set from a database query. Using Cursor allows Android to more efficiently manage rows and columns as and when needed. You use a ContentValues object to store key/value pairs. Its put() method allows you to insert keys with values of different data types.
The full source listing of DBAdapter.java class.
package net.learn2develop.Database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DBAdapter
{
    public static final String KEY_ROWID = "_id";
    public static final String KEY_ISBN = "isbn";
    public static final String KEY_TITLE = "title";
    public static final String KEY_PUBLISHER = "publisher";   
    private static final String TAG = "DBAdapter";
    
    private static final String DATABASE_NAME = "books";
    private static final String DATABASE_TABLE = "titles";
    private static final int DATABASE_VERSION = 1;

    private static final String DATABASE_CREATE =
        "create table titles (_id integer primary key autoincrement, "
        + "isbn text not null, title text not null, "
        + "publisher text not null);";
       
    private final Context context;
   
    private DatabaseHelper DBHelper;
    private SQLiteDatabase db;

    public DBAdapter(Context ctx)
    {
        this.context = ctx;
        DBHelper = new DatabaseHelper(context);
    }
       
    private static class DatabaseHelper extends SQLiteOpenHelper
    {
        DatabaseHelper(Context context)
        {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db)
        {
            db.execSQL(DATABASE_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion,
        int newVersion)
        {
            Log.w(TAG, "Upgrading database from version " + oldVersion
                    + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS titles");
            onCreate(db);
        }
    }   
   
    //---opens the database---
    public DBAdapter open() throws SQLException
    {
        db = DBHelper.getWritableDatabase();
        return this;
    }

    //---closes the database---   
    public void close()
    {
        DBHelper.close();
    }
   
    //---insert a title into the database---
    public long insertTitle(String isbn, String title, String publisher)
    {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_ISBN, isbn);
        initialValues.put(KEY_TITLE, title);
        initialValues.put(KEY_PUBLISHER, publisher);
        return db.insert(DATABASE_TABLE, null, initialValues);
    }

    //---deletes a particular title---
    public boolean deleteTitle(long rowId)
    {
        return db.delete(DATABASE_TABLE, KEY_ROWID +
                        "=" + rowId, null) > 0;
    }

    //---retrieves all the titles---
    public Cursor getAllTitles()
    {
        return db.query(DATABASE_TABLE, new String[] {
                        KEY_ROWID,
                        KEY_ISBN,
                        KEY_TITLE,
                KEY_PUBLISHER},
                null,
                null,
                null,
                null,
                null);
    }

    //---retrieves a particular title---
    public Cursor getTitle(long rowId) throws SQLException
    {
        Cursor mCursor =
                db.query(true, DATABASE_TABLE, new String[] {
                                     KEY_ROWID,
                                     KEY_ISBN,
                                     KEY_TITLE,
                                     KEY_PUBLISHER
                                     },
                                     KEY_ROWID + "=" + rowId,
                                     null,
                                     null,
                                     null,
                                     null,
                                     null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;
    }

    //---updates a title---
    public boolean updateTitle(long rowId, String isbn,
    String title, String publisher)
    {
        ContentValues args = new ContentValues();
        args.put(KEY_ISBN, isbn);
        args.put(KEY_TITLE, title);
        args.put(KEY_PUBLISHER, publisher);
        return db.update(DATABASE_TABLE, args,
                         KEY_ROWID + "=" + rowId, null) > 0;
    }
}

Using the Database
You are now ready to use the database along with the helper class you've created. In the DatabaseActivity.java file, create an instance of the DBAdapter class:


import android.app.Activity;
import android.os.Bundle;

public class DatabaseActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DBAdapter db = new DBAdapter(this);
    }
}
Adding a Title
To add a title into the titles table, use the insertTitle() method of the DBAdapter class:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        DBAdapter db = new DBAdapter(this);

        //---add 2 titles---
        db.open();       
        long id;
        id = db.insertTitle(
                        "0470285818",
                        "C# 2008 Programmer's Reference",
                        "Wrox");       
        id = db.insertTitle(
                        "047017661X",
                        "Professional Windows Vista Gadgets Programming",
                        "Wrox");
        db.close();
    }
The insertTitle() method returns the ID of the inserted row. If an error occurs during the adding, it returns -1.
If you examine the file system of the Android device/emulator, you can observe that the books database is created under the databases folder

Retrieving All the Titles
Retrieving all the titles in the titles table with the DBAdapter class' getAllTitles() method:

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.Toast;

public class DatabaseActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DBAdapter db = new DBAdapter(this);

        //---get all titles---
        db.open();
        Cursor c = db.getAllTitles();
        if (c.moveToFirst())
        {
            do {         
                DisplayTitle(c);
            } while (c.moveToNext());
        }
        db.close();
    }   
}

The result is returned as a Cursor object. To display all the titles, you first need to call the Cursor object's moveToFirst() method. If it succeeds (which means there is at least one row available), display the details of the title using the DisplayTitle() method (defined below). To move to the next title, call the Cursor object's moveToNext() method:
 
    public void DisplayTitle(Cursor c)
    {
        Toast.makeText(this, 
                "id: " + c.getString(0) + "\n" +
                "ISBN: " + c.getString(1) + "\n" +
                "TITLE: " + c.getString(2) + "\n" +
                "PUBLISHER:  " + c.getString(3),
                Toast.LENGTH_LONG).show();        
    } 

It shows the Toast class displaying one of the titles retrieved from the database.



Retrieving a Single Title
To retrieve a single title using its ID, call the getTitle() method of the DBAdapter class with the ID of the title:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DBAdapter db = new DBAdapter(this);

        //---get a title---
        db.open();
        Cursor c = db.getTitle(2);
        if (c.moveToFirst())       
            DisplayTitle(c);
        else
            Toast.makeText(this, "No title found",
                                     Toast.LENGTH_LONG).show();
        db.close();
    }
The result is returned as a Cursor object. If a row is returned, display the details of the title using the DisplayTitle() method, else display an error message using the Toast class.

Updating a Title
Update a particular title by calling the DBAdapter class' updateTitle() method and passing the ID of the title you want to update as well as the values of the new fields.
@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DBAdapter db = new DBAdapter(this);

        //---update title---
        db.open();
        if (db.updateTitle(1,
                        "0470285818",
                        "C# 2008 Programmer's Reference",
                        "Wrox Press"))
            Toast.makeText(this, "Update successful.",
                Toast.LENGTH_LONG).show();
        else
            Toast.makeText(this, "Update failed.",
                Toast.LENGTH_LONG).show();
        //-------------------
       
        //---retrieve the same title to verify---
        Cursor c = db.getTitle(1);
        if (c.moveToFirst())       
            DisplayTitle(c);
        else
            Toast.makeText(this, "No title found",
                                     Toast.LENGTH_LONG).show();       
        //-------------------       
        db.close();
    }
A message is displayed to indicate if the update is successful. At the same time, you retrieve the title that you have just updated to verify that the update is indeed correct.
Deleting a Title
To delete a title, use the deleteTitle() method in the DBAdapter class by passing the ID of the title you want to delete:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DBAdapter db = new DBAdapter(this);

        //---delete a title---
        db.open();
        if (db.deleteTitle(1))
            Toast.makeText(this, "Delete successful.",
                Toast.LENGTH_LONG).show();
        else
            Toast.makeText(this, "Delete failed.",
                Toast.LENGTH_LONG).show();           
        db.close();
    }
A message is displayed to indicate if the deletion is successful.

Back to top ↑
Connect with Us

What they says

© 2013 MaGeSH 2 help. WP Mythemeshop Converted by BloggerTheme9
Blogger templates. Proudly Powered by Blogger.