Using Room with Kotlin

If I was really exited to hear about Android Architecture Components in Google I/O 2017. In particular Room Persistence Library. I had pleasure talking with folks working on it in person during I/O! I want to try it for my own.

I had been using Kotlin prior to the I/O announcement. Having google fully commit it to as a first class citizen on Android was very encouraging.

In this post, I wanted to show how you can start using Room with Kotlin.

I started with a shell project with Dagger 2 setup. We will implement Room in Kotlin project using Dagger2, later will also integrate it with RxJava2.

I am going to use a simple “ToDoList” app, that allows users to add a Task in the application. So first off, lets include the library.

Including Room

In your build.gradle file, include the room dependency. (1.0.0-alpha1 was the latest version at the time of this writing)

Defining Entities

Let’s now create `Task` entity. For now we will make it simple with id, description and boolean flag to indicate if the task is completed.

If you notice, it is for the most part just a regular “data class“. We are just adding annotation for Room to make sense of it.

@Entity(tableName = “task”) as it denotes, is using the table name called “task”. If name is not specified, by default class name is used as the Table name.

@ColumnInfo annotation on  a field relating it to the column on the table. e.g. in this example you can see that on the db column name uses “_”.

@PrimaryKey(autoGenerate = true) is applied to “id” field. which in this case is autogenerated. An entity must have at least 1 PrimaryKey.

Defining Dao

Dao is where Room does its magic. We just need to define a interface along with the SQL queries. Room at compile time generates the actual implementation of this class for us to use. This may remind you of Retrofit, This is exactly what happening here.

As you can see, we have an interface which is annotated with @Dao, in there we can see multiple functions annotated with various other annotations.

Lets look at one of them, “fun getAllTasks(): List”, this function returns list of all tasks from the database. This function is annotated with @Query annotation. In there we have the sql query specified. This query is validated at compile time. If the query is malformed it will fail the build. With this you can feel confident that if it compiles, it will work.

Now let’s look at the little more complex one. “fun findTaskById(id: Long): Task”. This function is annotated with @Query(“select * from task where id = :p0”).

There is a currently a bug where kotlin converts the parameters to p0, arg0 etc. Hence, the query above specified “:p0”. Ideally we should be able to say “:id”. This will be fixed in the near future. Until then, pay close attention to compile errors to identify this type of mismatch.

Defining Database

We define our database by creating an abstract class that extends RoomDatabase.

Class is annotated with @Database which defines the all the entities(table) it contains, its version. If you look closely, “exportSchema” is set to false here. If you do not, it defaults to “true” which generates a compile time warning as you can see blow:

warning: Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide `room.schemaLocation` annotation processor argument OR set exportSchema to false.

This is class pretty much like dagger component, this exposes Dao we defined above. Here we are exposing “TaskDao”

Configuring in Dagger

Like dagger, we will build the room database. Note, this is an expensive operation so, we would want a singleton object. Lets look at the configuration here:

We are building Room database using the application context, We point to the abstract class we defined above, database file name we want.

We are calling following function so that we can run queries in main thread.

.allowMainThreadQueries()

If we did not call this, we would see an exception indicating that we cannot access database on main thread.

Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long periods of time.

In the later part we will be using RxJava and we will get rid of this. For now, lets move on. We are using Dagger to provide the TaskDao also.

Getting Entities in Presenter

In this example we are using MVP pattern. Lets see how we can get the entities and show it in a recycler view.

Thats it! At this point we are able to define Task entity, use Room to fetch the entities and display them on a Recycler view.

Using Room with RxJava/RxAndroid with Kotlin

Let’s take this up a notch by introducing RxJava/RxAndroid. Add the RxJava/RxAndroid dependency in our build file by adding the following.

compile "io.reactivex.rxjava2:rxjava:2.1.0"
compile "io.reactivex.rxjava2:rxandroid:2.0.1"

We would also need to add one more dependency

compile "android.arch.persistence.room:rxjava2:1.0.0-alpha1"

With this we can now start using Room with RxJava.
Let’s change our function that returned list of Task to return a Flowable.

 @Query("select * from task")
 fun getAllTasks(): Flowable<List<Task>>

With this we can now remove “allowMainThreadQueries()”. Our Module would simply do

<pre>@Provides fun providesAppDatabase(context: Context): AppDatabase =
Room.databaseBuilder(context, AppDatabase::class.java, "my-todo-db").build()

We will then need to modify our presenter to use the updated function. Here is the full presenter.

todolist

And that is it!, At this point you have Room, Dagger, RxJava all working together using Kotlin!

You can find completed sample at https://github.com/manijshrestha/ToDoList

Using Android Beam/NFC to transfer Data

Most of the Android devices have NFC reader built in. NFC can be used to transfer data between two devices, trigger actions on device etc.
In this post I am going to build a simple app that transfers data between two devices using NFC.

It is important to understand how NFC works. I am not going to explain those in detail as there are many resources on the internet that does a really good job of explaining the technology.

Goal of this post is to build a simple Android application that will send some text data over to another NFC capable Android Device. To test this you will need two android devices with NFC. You will need to deploy the application to both the devices.

So to enable NFC on you app, the very first thing you would need to do is setup permission in AndroidManifest.xml

Permissions

Add the following tag to the AndroidManifest.xml to access the NFC hardware.

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

Also add uses-feature tag to specify the feature used by the application. If the Application must have the NFC, you would want to add android:required=”true” attribute to it.

<uses-feature android:name="android.hardware.nfc" />

We would need to use SDK level 14+ to be able to use Android Beam. SDK level 9 has very limited support so you would want to use SDK level 10 at minimum for good NFC support.

<uses-sdk android:minSdkVersion="16"/>

Message Sender Activity

We will simply implement NfcAdapter.CreateNdefMessageCallback interface. This will require us to implement NdefMessage createNdefMessage(NfcEvent nfcEvent)
This method will be called when Android Beam is invoked. Here is the method implementation.

   @Override
    public NdefMessage createNdefMessage(NfcEvent nfcEvent) {
        String message = mEditText.getText().toString();
        NdefRecord ndefRecord = NdefRecord.createMime("text/plain", message.getBytes());
        NdefMessage ndefMessage = new NdefMessage(ndefRecord);
        return ndefMessage;
    }

In our onCreate method we need to get NfcAdapter and set the callback to this class. Here is the snippet.

.. ..
 @Override
    protected void onCreate(Bundle savedInstanceState) {
.. ..
       NfcAdapter mAdapter = NfcAdapter.getDefaultAdapter(this);
        if (mAdapter == null) {
            mEditText.setText("Sorry this device does not have NFC.");
            return;
        }

        if (!mAdapter.isEnabled()) {
            Toast.makeText(this, "Please enable NFC via Settings.", Toast.LENGTH_LONG).show();
        }

        mAdapter.setNdefPushMessageCallback(this, this);
.. ..
    }
.. ..

So that’s all to it to be able to send a NFC NDEF message.

NFC Intent

Lets create another Activity that will be respond to the NDEF message and display the message.
In the activity we just need to inspect “Intent” and pull NDEF message.
In this demo we will name this activity as NFCDisplayActivity. We will check for the info onResume() as such

   @Override
    protected void onResume(){
        super.onResume();
        Intent intent = getIntent();
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            Parcelable[] rawMessages = intent.getParcelableArrayExtra(
                    NfcAdapter.EXTRA_NDEF_MESSAGES);

            NdefMessage message = (NdefMessage) rawMessages[0]; // only one message transferred
            mTextView.setText(new String(message.getRecords()[0].getPayload()));

        } else
            mTextView.setText("Waiting for NDEF Message");

    }

Here we are verifying that, this activity was triggered by NDEF_DISCOVERED action. (There are 3 possible actions, NDEF_DISCOVERED, TECH_DISCOVERED and TAG_DISCOVERED)
We then extract the Parcelable extra message from the intent and put that in a text view.

You will need to configure this Activity in your AndroidManifest.xml like below

  <activity
            android:name=".NFCDisplayActivity"
            android:label="NFC Data Display">
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="text/plain" />
            </intent-filter>
        </activity>

With that when NFC message comes with mimeType of “text/plain”, it will start our Display Activity.

You can find my the entire project in github https://github.com/manijshrestha/AndroidNFCDemo.

Here is the Video of the app.

Dynamic Image View Flipper using Ion

There are instances where you would want to load images from the internet into a viewflipper. In this post we will build a viewflipper in which images will be loaded dynamically using a library called Ion. This library does lot more than loading images. Ion takes over previous library called UrlImageViewHelper.

I am using Android Studio to build this example. If you are using Eclipse steps will be the same except for how you would import the library.

Create an android project in Android studio or Eclipse. then,

Importing Library

Android Studio: Open build.gradle, add the following line.

dependencies {
    compile 'com.koushikdutta.ion:ion:1.1.5'
}

This will add ion as a dependency. When the project is being built, it will download the dependency for you.

Eclipse: Download the ion.jar from github. Include the jar in your project build path.

AndroidManifest.xml

Since we are going to be getting the image from the internet we will need to add the internet permission in the manifest file.
Add the following permission in AndroidManifest.xml

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

Layout

For this demo we are going to create a layout with viewflipper and two buttons that will let us go “next” and “previous”.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".DynamicImageFlipperActivity">

    <ViewFlipper
        android:id="@+id/viewFlipper"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:layout_width="match_parent">

    </ViewFlipper>


    <RelativeLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_weight="0">

        <Button
            android:id="@+id/previousButton"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_alignParentLeft="true"
            android:text="<< Previous" />

        <Button
            android:id="@+id/nextButton"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_toRightOf="@id/previousButton"
            android:layout_alignParentRight="true"
            android:text="Next >>" />

    </RelativeLayout>

</LinearLayout>

Activity

We will create a ImageView programatically and load it with image from the internet. To do so lets create a helper method in your Activity.

  protected ImageView getNewImageView() {
        ImageView image = new ImageView(getApplicationContext());
        image.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        return image;
    }

Only thing this method will do is create a ImageView.
Now the way we use Ion is as follows.

Ion.with(imageView)
   .placeholder(R.drawable.loading)
   .load(URL_TO_IMAGE);

This will load the “imageView” with placeholder image while the image is being downloaded from the internet. “load” method takes a string parameter which is the URL to the image. We can also provide animations etc if you would like you can get more info from Ion documentation.

Here is the completed Activity:

public class DynamicImageFlipperActivity extends Activity {

    private List<String> imageURLs = Arrays.asList(new String[]{
            "http://manijshrestha.github.io/android-icon.png",
            "http://manijshrestha.github.io/iPhone-icon.png",
            "http://manijshrestha.github.io/windows-icon.png"});

    private int index = 0;

    private ViewFlipper mViewFlipper;
    private Button mPreviousButton;
    private Button mNextButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dynamicimageflipper);
        mViewFlipper = (ViewFlipper) findViewById(R.id.viewFlipper);
        mPreviousButton = (Button) findViewById(R.id.previousButton);
        mNextButton = (Button) findViewById(R.id.nextButton);

        ImageView image = getNewImageView();
        image.setImageResource(R.drawable.ic_launcher);

        mViewFlipper.addView(image);
        mNextButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                ImageView imageView = getNewImageView(); // Where we will place the image
                Ion.with(imageView)
                        .placeholder(R.drawable.loading)
                        .load(getNextImage());

                mViewFlipper.addView(imageView); // Adding the image to the flipper
                mViewFlipper.showNext();
            }
        });

        mPreviousButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mViewFlipper.showPrevious();
            }
        });

    }

    protected ImageView getNewImageView() {
        ImageView image = new ImageView(getApplicationContext());
        image.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        return image;
    }

    protected String getNextImage() {
        if (index == imageURLs.size())
            index = 0;
        return imageURLs.get(index++);
    }
}

At the end the app will look like image below:
device-2013-12-21-093810

device-2013-12-21-093856

You can find the complete project in my github repo:
https://github.com/manijshrestha/DynamicImageViewFlipperProject

Moving on from Linux to OSX

I recently started using a mac. Being a long time Ubuntu user, I thought it was going to be a smooth transition. I found it otherwise. I didn’t think it would be this hard. Things I never thought would have bothered me, for instance being able to tap, “Ctrl + X” to “cut” within the Finder window and paste it elsewhere. Being able to install tools via command line etc.
So here is the list of things I setup, which helped me to be more productive and IMHO more intuitive user experience.

1. Brew http://mxcl.github.io/homebrew/
Coming from Ubuntu, I got used to “apt-get” package manager. It made it very easy to manage software via command line. On mac, going through the App store and or manual install felt so old school. Luckily there were many alternatives around. One of them is Homebrew. It truly is the missing package manager for OSX.
It installs the packages in “/usr/local/Cellar”, so its easy to locate things that were installed via brew.

2. XtraFinder http://www.trankynam.com/xtrafinder/
If you come from Windows or Ubuntu, you probably are used to “cut”, “paste” either by keyboard shortcut or via context menu. On Mac, context menu in Finder, did not include this option. Furthermore, I could not simply ctrl+x, ctrl+p a directory or a file within finder. I heard about TotalFinder. But I wanted to see if there was any other alternative and I did find XtraFinder.
XtraFinder is a free plugin that adds these missing features to Finder. It allows you to customize other behaviors such as open the file/directory when you press “enter”. Also has snappy side by side dual pane and also tabs.
XtraFinder

3. MenuCalendar Clock http://www.objectpark.net/mcc.html
I really liked the Ubuntu’s pull down calendar. I am so used to pick on the time in menu bar see the month. MenuCalendar clock solved this one. This is a paid app if you want to use all its features. Unregistered version gives you basic feature which is good enough for general use. Clicking on a date opens iCal, which is very neat.
MenuCalendar

4. Menu Meters http://www.ragingmenace.com/software/menumeters/index.html
As a developer I constantly find myself looking at the system resource usage. Menu Meters provides memory, CPU, disk and network usage graph right on the menu bar. It is customizable to your needs. You can configure things you want to monitor and choose colors in the graph etc.
MenuMeters

5. Size Up http://www.irradiatedsoftware.com/sizeup/
SizeUp allows you to quickly resize and position your windows with keyboard shortcuts or a handy menu bar icon. You can move windows between workspaces, maximize, minimize, stick window to right or left etc.
https://i2.wp.com/www.irradiatedsoftware.com/images/sizeup/mainfeature-actions.png

6. ClipMenu http://www.clipmenu.com/
ClipMenu is a freeware tool that manages your clipboard history. It also allows you to have snippets of frequently used items.
ClipMenu

7. Mounting NTFS with full read/write access http://crosstown.coolestguyplanettech.com/os-x/44-how-to-write-to-a-ntfs-drive-from-os-x
By default OSX mounts NTFS formatted drives in read mode. It does not allow you to write to NTFS formatted device. This is a pain if you have external drives that you use with your Windows machine etc. My search on the internet, suggested to format the drive to FAT32, which OSX does support r/w natively. But I really didn’t like that idea. There are some paid applications out there that allows you to write to NTFS formatted drives on OSX. However, I found this blog entry to be very effective. This allows you to read write to your NTFS drives, and the good thing is, its completely free!
NTFS

8. Natural Keyboard on Mac http://david.rothlis.net/keyboards/microsoft_natural_osx/
I am used to the Natural keyboard, and found typing on a mac keyboard is not the most comfortable experience. Blog linked above walks through the steps of setting up the Microsoft Natural Keyboard on a mac.
keyboard

If you are trying to setup your mac to be more user friendly hopefully this post helped. Please feel free to post about any tools you may find helpful to you in the comments section.

Thats it for today.

Hola NodeJS, chat client using socket io

It was about time to play with NodeJS. It definitely WOW’ed me interms of performance and simplicity. Today I am going to share my experience building a chat client using NodeJS. This is one of the famous “Hello World” type application demo’ed.
If you haven’t already, you can setup node js by following the steps outlined on their website.

Creating simple http server
Let me demonstrate how easy it is to create a simple http server with node.
Create a js file and name it “server.js” and put the contents below:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'}); + '\n'
  res.end('Hello World\n');
}).listen(8080, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8080/');

What we are doing above is that, we are requiring http module and listening on port 8080.
When a request comes, we are responding with the famous “Hello World” text.

To start the server simply run the following command:

$ node server.js

Now on your browser, navigate to “http://localhost:8080 ” , walla.. “Hello World”! (Note: you can go to any url on that port will respond back with same response, like http://localhost:8080/foo/bar will still resolve to same response.)

“npm” – Node Packaged Modules
Node comes with a really nice package manager called npm. If you are familier with package managers such as apt-get, yum, brew etc, you will find it right at home.

To install any package just type “npm install ”
For instance, to install “socket.io” module we would run the following:

  $   npm install socket.io

This will create a directory named “node_modules” and the requested module is pulled in there.
Alright, now we have enough arsenal to get started with the our topic.

Let’s Chat, shall we?
To start, lets create a directory so we can put our resources in there. Lets name it “NodeChat”.
Inside the directory let’s create a file with name, ‘server.js’. We will edit this in a bit.
On the command line run the following commands to install modules required by our program.

$ npm install socket.io
$ npm install node-static

socket.io is used for the websocket communication we will have between server and the browser.
node-static will let us serve static files via nodejs.

Now we have that lets hack-away our server.js.
To start lets say that we will just “post message” to the server and server will broadcast it to all the clients.

To start, let’s build a web server component. As we did in above example we will do the following:

var app = require('http').createServer(handler),
io = require ('socket.io').listen(app),
static = require('node-static');

Here we are building a web server. The “handler” is a function I will show in a bit. The “socket.io” will listen on the http server we just created.

Now, we can add the following:

// Make all the files in the current directory accessible
var fileServer = new static.Server('./');

app.listen(8080);

That piece is self explanatory. Now to the important piece, we will add the handler and the socket.io stuff.
Below is the complete contents of the file when we will be done.

//Node.js Chat client Server

var app = require('http').createServer(handler),
io = require ('socket.io').listen(app),
static = require('node-static');

// Make all the files in the current directory accessible
var fileServer = new static.Server('./');

app.listen(8080);

function handler(request, response) {
	request.addListener('end', function () {
		fileServer.serve(request, response);
	});
}

io.sockets.on('connection', function(socket) {
	socket.on('postMessage', function(data){
		socket.broadcast.emit('message', data);
		socket.emit('message', data);
	});
});

Here, the function handler is simply delegating to serve the static content requested.
Important part is the io.sockets piece. When a client fires the ‘postMessage’ event, we will run the closure attached to the event on the server. In this case, we simply trigger the ‘message’ event along with the data on all the active clients except for the socket that trigged it. To echo the message back, we trigger the ‘message’ event on the socket itself with the data.

Now we have the backend ready lets work on the Front-end.

Create “index.html” and paste the following html code.

<!DOCTYPE HTML>
<html>
<head>
	<title>Live Chat Powered by Node.js</title>
	<script src="/socket.io/socket.io.js"></script>
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
	<script>
	$(document).ready(function () {
		var socket = io.connect('http://localhost:8080');

    	//Bind the "send" button to do a post
    	$("#send-btn").bind('click', function() {
    		socket.emit('postMessage', {text: $("#message-box").val()});
    		$("#message-box").val('');
    	});

    	//on socket message from server
    	socket.on('message', function(data) {
    		$("#message-board").append( data.text + "<br/>");
    	});

    });
	</script>
	<style>
	#message-board {
		width: 500px;
		height: 400px;
	}
	</style>
</head>
<body>
	<div id="content">
		<div id="message-board"></div>
		<input id="message-box" type="text" size="100" placeholder="Type a message..."/>
		<button id="send-btn">send</button>
	</div>
</body>
</html>

Here we have simple page with one text box and one button.
Using jQuery, when the page is loaded, we create a socket connection to the server.
When ‘click’ event is fired, we fire the ‘postMessage’ event with the text value from the ‘message-box’ input. and we clear the box for user to type new message.
When the server fires the ‘message’ event on our local client script will simply append the text on the “message-board” div.
Here you go we have a very simple Chat client.

I have added some flare to it, you can find the code at https://github.com/manijshrestha/NodeChat

Setting up VIM with better color scheme while working via dark console.

I spend a lot of time working in the console window as I manage multiple EC2 instances.
At work I use cygwin and at home I use gold old linux terminal. Depending on the configuration, vim color scheme might not be as terminal color friendly.
Look at the image below.
vim1

I could hardly read the comments on this shell script. Luckily vim does provides multiple color schemes to work with.
You can try different color scheme by running “:colorscheme” in vim.

:colorscheme delek

Instead of doing it every time, We can manage the default vim setting by creating a “.vimrc” file on the home directory.
Lets do that:

$ vi ~/.vimrc

Add following lines in the file


syntax on
colorscheme delek

I have selected have the syntax highlighting on and selected “delek” color scheme so its easier to read on my terminal.

vimrc

Now lets look at the same shell script:

vim2

And the output is much readable on the dark console.

You can select other color scheme depending on your preference. You can find the installed schemes at

/usr/share/vim/vim72/colors

Some of the default ones you may find are

blue.vim
darkblue.vim
default.vim
delek.vim
desert.vim
elflord.vim
evening.vim
koehler.vim
morning.vim
murphy.vim
pablo.vim
peachpuff.vim
README.txt
ron.vim
shine.vim
slate.vim
torte.vim
zellner.vim

You can download more online http://www.vimninjas.com/2012/08/26/10-vim-color-schemes-you-need-to-own/.

Implementing Android Status bar notification in phonegap/cordova app.

This is a quick write up to demonstrate phonegap statusbar notification plugin in a cordova (formally phonegap) app.
I am going to run through steps for creating an android application utilizing phonegap.

Creating a Project
I am going to assume that you already have android SDK and Eclipse plugin installed. If not, please follow the developer guide to do so.
We will create an sample application, we are going to name it “phonegapstatusnotificationdemo”.

Importing Cordova
At this point we should have a sample android application. Now, we are going to import the cordova(phonegap) libraries in our application. At the time of this writing Cordova 2.2.0 is the latest version. You can download the library form their website.

After you download the zip file, open and locate “lib/android”, and extract the cordova-2.2.0.jar.

  • Place the jar file into “lib” folder in your Android project. This folder should already be in your class path. If not you may need to do it manually via project properties.
  • Also, find the “xml” folder in the zip file and place it under “res” folder in the android project. The xml folder contains the config.xml that has the phonegap configuration.
  • Create a folder named “www” inside “assets” folder in the android project as well.
  • Place the cordova-2.2.0.js file from the zip into the www folder you just created.

You are now set to use phonegap.

Updating the Activity
Since phonegap places the html as the view in the application, we have to do 2 things.
1. create the html file
2. Update the Activity to extend DroidGap and local the html from step 1.

We are going to do just that. Lets create a html file and place it in the “www” folder inside the “assets” folder in the android project.

  <html>
	<head>
		<script type="text/javascript" charset="utf-8" src="cordova-2.2.0.js"></script>
	</head>

	<body>
		Hello World!
	</body>

</html> 

In your main activity, update it to extend the DroidGap.

import org.apache.cordova.DroidGap;

import android.os.Bundle;

public class MainActivity extends DroidGap {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		super.loadUrl("file:///android_asset/www/index.html");
	}

}

Now you can run your phonegap application on your device or emulator. You should see the “Hello World” text on a blank screen.

Using Statusbar Notification plugin
Now, lets use a Status notification plugin. These steps will be same for implementing other phonegap plugins also.
Phonegap plugin work in 2 parts.
1. Javascript: Plugin will have a javascript code that your application can call form your html or js.
The provided js will invoke the back end java code. You shouldn’t need to worry much about the inner workings of the plugin js code. But it is import to understand the framework so you can debug issues.

2. Java code: This is the code that phonegap plugin framework will call when this method is called from the javascript library code.

Today we are going to use the statusbar notificaiton plugin.
Lets grab the plug in code from github.
https://github.com/phonegap/phonegap-plugins/tree/master/Android/StatusBarNotification

README provides steps to import this plugin in your application. We are going to do just that.

Importing Plugin files
place the “.java” files into your android project src package. At the time of this writing there are two files (StatusBarNotification.java and StatusNotificationIntent.java). Make sure you update the package appropriately. I would encourage to use the package name used in these java files for simplicity.

Now, place the statusbarnotification.js into your “www” folder. At this time you can include this script in your index.html by placing the html below in the portion of the html

<script type="text/javascript" charset="utf-8" src="statusbarnotification.js"></script> 

In your res/xml/config.xml file, place the following script inside the section.

<plugin name="StatusBarNotification" value="com.phonegap.plugins.statusBarNotification.StatusBarNotification"/>

If you had placed the java files above in different package structure, be sure to change the value filed to appropriate location.
Since phonegap provides a default icons for notification, which is used in the java code, you will have to copy the png files from the plugin into your res/drawable folder. If you want different icon, just be sure to have those icons in the folder and change the reference in the java file. (Watch for “int icon = R.drawable.notification;” references, in StatusNotificationIntent.java)

So in your html file, whenever you want to show a notification, you can call the following javascript function.

window.plugins.statusBarNotification.notify("Put your title here", "Put your sticky message here");

.

You can checkout out my sample application on github (https://github.com/manijshrestha/PhonegapStatusNotificationDemo) that uses this plugin. If you have any questions/ enhancement request to this plugin feel free to PM me.

Thank you,