Tuesday, April 12, 2011

Start a service to send Notification

Last exercise show how to "send a Notification" in activity. In this exercise, main activity start a service, and notification is sent in service run in background.

Start a service to send Notification

main.xml to have buttons to start and stop service.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/startservice"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start Service to send Notification"
/>
<Button
android:id="@+id/stopservice"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Stop Service"
/>
</LinearLayout>

main activity, AndroidNotifyService.java simple start and stop the service.
package com.exercise.AndroidNotifyService;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class AndroidNotifyService extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonStartService = (Button)findViewById(R.id.startservice);
Button buttonStopService = (Button)findViewById(R.id.stopservice);

buttonStartService.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(AndroidNotifyService.this, com.exercise.AndroidNotifyService.NotifyService.class);
AndroidNotifyService.this.startService(intent);
}});

buttonStopService.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setAction(NotifyService.ACTION);
intent.putExtra("RQS", NotifyService.STOP_SERVICE);
sendBroadcast(intent);
}});

}
}
[================================================
Correction@2011-0424: Please change the code
intent.putExtra("RQS", NotifyService.STOP_SERVICE);
to
intent.putExtra("RQS", NotifyService.RQS_STOP_SERVICE);
================================================]

NotifyService.java, our service to send notification.
package com.exercise.AndroidNotifyService;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.IBinder;

public class NotifyService extends Service {

final static String ACTION = "NotifyServiceAction";
final static String STOP_SERVICE = "";
final static int RQS_STOP_SERVICE = 1;

NotifyServiceReceiver notifyServiceReceiver;

private static final int MY_NOTIFICATION_ID=1;
private NotificationManager notificationManager;
private Notification myNotification;
private final String myBlog = "http://android-er.blogspot.com/";

@Override
public void onCreate() {
// TODO Auto-generated method stub
notifyServiceReceiver = new NotifyServiceReceiver();
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION);
registerReceiver(notifyServiceReceiver, intentFilter);

// Send Notification
notificationManager =
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
myNotification = new Notification(R.drawable.icon,
"Notification!",
System.currentTimeMillis());
Context context = getApplicationContext();
String notificationTitle = "Exercise of Notification!";
String notificationText = "http://android-er.blogspot.com/";
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(myBlog));
PendingIntent pendingIntent
= PendingIntent.getActivity(getBaseContext(),
0, myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);
myNotification.defaults |= Notification.DEFAULT_SOUND;
myNotification.flags |= Notification.FLAG_AUTO_CANCEL;
myNotification.setLatestEventInfo(context,
notificationTitle,
notificationText,
pendingIntent);
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);

return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
// TODO Auto-generated method stub
this.unregisterReceiver(notifyServiceReceiver);
super.onDestroy();
}

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}

public class NotifyServiceReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
int rqs = arg1.getIntExtra("RQS", 0);
if (rqs == RQS_STOP_SERVICE){
stopSelf();
}
}
}

}


Modify AndroidManifest.xml to add our service.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidNotifyService"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidNotifyService"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".NotifyService"/>
</application>
</manifest>


Download the files.

Related:
- Auto start a service with Intent of "android.intent.action.BOOT_COMPLETED" action
- Send Notification inside background Thread
- Update Notification

8 comments:

WILL said...

Nice example. I tried to improve it adding a little more logic in the onStartCommand method.Depending no the intent, now you can create the notification or update it.The problem? It doesn't work.It tells me:
object not locked by thread before notify()

I have tried to put the notificationManager.notify calls inside a synchronized method but it doesn't work. I will apreciate if you improve this example a little and explain how to modify a notification created in a different call.

Thank you very much.

Android Er said...

hello WILL,

I can't catch your question, sorry!

Do you means how to send Notification inside background Thread? If yes, please refer Send Notification inside background Thread

WILL said...

No, forgive me you, my English is too poor :(.Well, I have seen your new post but I don't know if that is what I need.

I will try to explain my problem.
I want my program to create an status bar notification in a particular moment.After that moment (with the notification in the status bar created), I want to update it(no create another one) with other messages and from other activities.
One of my problem was. What is the best way to do this?

_ ¿Share notification between activities?

_ Create a thread that is always listening to update the notification. _

_ Create a service that will manage the notification status bar when receiving intents.

I thought that the last one could be the better one. But this is what happens to me:

_ First call to MyService (very similar to your example) goes fine and it creates the notification as it is suppose to do.
_ Second call to MyService if check it the notification is not null, then updates it and after that when calling
MyNotificationManager.notify() it causes a: object not locked by thread before notify().

I wish this time I have explained it a little better. It it is necessary I can't post some code but I don't know the right tags, May I use be code tag?

Android Er said...

hello WILL,

That means you want Update Notification, is it?

wilcome said...

Yes thats it! Thank you so much for open my eyes ;). I misunderstood the android developer documentation when it tells to call Notification Manager notify() for update and I called it without parameters, so it didn't work at all. Thank you.

CaptainSparrow said...

using alarm manger i want to send predefined msg....with notification.....

In Service interface class, i created a Notification manager and Sms Manager in OnStartCommand()..But when i run this apps i got a force to close alert..

please help me...

rythmal said...

Hey thanks for the very helpful post u have made.I have this question.hope ull be able to help me.I want to start a new activity when the user clicks the notification icon.so put i put,

Intent notificationIntent = new Intent(this, MyClass.class);

where you put your blog address....
but dat activity with the name MyClass doesn't show wat it is supposed to show.i did put it in the manifest as-well..please help me with this..it would be a real big help.i need this to complete my project.
Thank you very much.

Anand Krish said...

coding is ok brother, but please give some explanation about what is going on. only coding is there. when you are free plese give the explanaiton about your code.