I have the following code in which I have one date picker and time picker
When I select that date and time I want to show notification...
It is perfectly working but when I again put notification means if I pu6 multiple notification it will show me only last one...
Means only last notification is showing not all...
NotifyService.java
package com.blundell.tut.service;
import android.R;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import com.blundell.tut.ui.phone.SecondActivity;
public class NotifyService extends Service {
/**
* Class for clients to access
*/
public class ServiceBinder extends Binder {
NotifyService getService() {
return NotifyService.this;
}
}
// Unique id to identify the notification.
public static int NOTIFICATION = 123;
// Name of an intent extra we can use to identify if this service was started to create a notification
public static final String INTENT_NOTIFY = "com.blundell.tut.service.INTENT_NOTIFY";
// The system notification manager
private NotificationManager mNM;
#Override
public void onCreate() {
Log.i("NotifyService", "onCreate()");
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// If this service was started by out AlarmTask intent then we want to show our notification
if(intent.getBooleanExtra(INTENT_NOTIFY, false))
showNotification();
// We don't care if this service is stopped as we have already delivered our notification
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients
private final IBinder mBinder = new ServiceBinder();
/**
* Creates a notification and shows it in the OS drag-down status bar
*/
private void showNotification() {
// This is the 'title' of the notification
CharSequence title = "Alarm!!";
// This is the icon to use on the notification
int icon = R.drawable.ic_dialog_alert;
// This is the scrolling text of the notification
CharSequence text = "Your notification time is upon us.";
// What time to show on the notification
long time = System.currentTimeMillis();
Notification notification = new Notification(icon, text, time);
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, SecondActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, title, text, contentIntent);
// Clear the notification when it is pressed
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
NOTIFICATION++;
Toast.makeText(NotifyService.this, Integer.toString(NOTIFICATION), Toast.LENGTH_SHORT).show();
mNM.notify(NOTIFICATION, notification);
// Stop the service when we are finished
stopSelf();
}
}
ScheduleClient.java
package com.blundell.tut.service;
import java.util.Calendar;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
/**
* This is our service client, it is the 'middle-man' between the
* service and any activity that wants to connect to the service
*
* #author paul.blundell
*/
public class ScheduleClient {
// The hook into our service
private ScheduleService mBoundService;
// The context to start the service in
private Context mContext;
// A flag if we are connected to the service or not
private boolean mIsBound;
public ScheduleClient(Context context) {
mContext = context;
}
/**
* Call this to connect your activity to your service
*/
public void doBindService() {
// Establish a connection with our service
mContext.bindService(new Intent(mContext, ScheduleService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
/**
* When you attempt to connect to the service, this connection will be called with the result.
* If we have successfully connected we instantiate our service object so that we can call methods on it.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with our service has been established,
// giving us the service object we can use to interact with our service.
mBoundService = ((ScheduleService.ServiceBinder) service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mBoundService = null;
}
};
/**
* Tell our service to set an alarm for the given date
* #param c a date to set the notification for
*/
public void setAlarmForNotification(Calendar c){
mBoundService.setAlarm(c);
}
/**
* When you have finished with the service call this method to stop it
* releasing your connection and resources
*/
public void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
mContext.unbindService(mConnection);
mIsBound = false;
}
}
}
ScheduleService.java
package com.blundell.tut.service;
import java.util.Calendar;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import com.blundell.tut.service.task.AlarmTask;
public class ScheduleService extends Service {
/**
* Class for clients to access
*/
NotifyService ns=new NotifyService();
public class ServiceBinder extends Binder {
ScheduleService getService() {
return ScheduleService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("ScheduleService", "Received start id " + ns.NOTIFICATION + ": " + intent);
// We want this service to continue running until it is explicitly stopped, so return sticky.
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients. See
private final IBinder mBinder = new ServiceBinder();
/**
* Show an alarm for a certain date when the alarm is called it will pop up a notification
*/
public void setAlarm(Calendar c) {
// This starts a new thread to set the alarm
// You want to push off your tasks onto a new thread to free up the UI to carry on responding
new AlarmTask(this, c).run();
}
}
AlarmTask.java
package com.blundell.tut.service.task;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import com.blundell.tut.service.NotifyService;
public class AlarmTask implements Runnable{
// The date selected for the alarm
private final Calendar date;
// The android system alarm manager
private final AlarmManager am;
// Your context to retrieve the alarm manager from
private final Context context;
public AlarmTask(Context context, Calendar date) {
this.context = context;
this.am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
this.date = date;
}
#Override
public void run() {
// Request to start are service when the alarm date is upon us
// We don't start an activity as we just want to pop up a notification into the system bar not a full activity
Intent intent = new Intent(context, NotifyService.class);
intent.putExtra(NotifyService.INTENT_NOTIFY, true);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
// Sets an alarm - note this alarm will be lost if the phone is turned off and on again
am.set(AlarmManager.RTC_WAKEUP, date.getTimeInMillis(), pendingIntent);
long firstTime = date.getTimeInMillis();
am.setRepeating(AlarmManager.RTC_WAKEUP, firstTime, am.INTERVAL_DAY * 7, pendingIntent);
}
}
MainActivity.java
package com.blundell.tut.ui.phone;
import java.util.Calendar;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.DatePicker;
import android.widget.TimePicker;
import android.widget.Toast;
import com.blundell.tut.R;
import com.blundell.tut.service.NotifyService;
import com.blundell.tut.service.ScheduleClient;
public class MainActivity extends Activity
{
// This is a handle so that we can call methods on our service
private ScheduleClient scheduleClient;
private DatePicker picker;
NotifyService ns;
private TimePicker tp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scheduleClient = new ScheduleClient(this);
scheduleClient.doBindService();
ns=new NotifyService();
picker = (DatePicker) findViewById(R.id.scheduleTimePicker);
tp=(TimePicker)findViewById(R.id.TimePicker);
tp.setIs24HourView(true);
}
public void onDateSelectedButtonClick(View v){
int day = picker.getDayOfMonth();
int month = picker.getMonth();
int year = picker.getYear();
int hour=tp.getCurrentHour();
int min=tp.getCurrentMinute();
// Create a new calendar set to the date chosen
// we set the time to midnight (i.e. the first minute of that day)
Calendar c = Calendar.getInstance();
c.set(year, month, day,hour,min,0);
scheduleClient.setAlarmForNotification(c);
// Notify the user what they just did
//Toast.makeText(this, Integer.toString(ns.NOTIFICATION), Toast.LENGTH_SHORT).show();
//Toast.makeText(this, "Notification set for: "+ day +"/"+ (month+1) +"/"+ year, Toast.LENGTH_SHORT).show();
}
#Override
protected void onStop()
{
// When our activity is stopped ensure we also stop the connection to the service
// this stops us leaking our activity into the system *bad*
if(scheduleClient != null)
scheduleClient.doUnbindService();
super.onStop();
}
}
SecondActivity.java
package com.blundell.tut.ui.phone;
import android.app.Activity;
import android.os.Bundle;
import com.blundell.tut.R;
/**
* This is the activity that is started when the user presses the notification in the status bar
* #author paul.blundell
*/
public class SecondActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
}
Please suggest me at which place i have to change code...????
In this line,
mNM.notify(NOTIFICATION, notification);
Just make sure that each time the different value of NOTIFICATION is being passed.
at AlarmTask.java, you are hard coded always 0 in PendingIntent.
requestCode must be
UNIQUE INTEGER NUMBER
so change your code,
from
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
to
int random = (int)System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, random, intent, 0);
Just write code like this.
int random = (int)System.currentTimeMillis();
manager.notify(random , activeNotification);
Related
I am attempting to create a background Service so when the application is closed a service is running in the background that will show a notification every 5 seconds to the phone using an AlarmManager.
I currently have my java service file setup as:
package com.racecoursedatatechnologies.rdtstockmanagement;
import android.app.Service;
import android.app.AlarmManager;
import android.content.Intent;
import android.util.Log;
import android.os.Binder;
import android.os.IBinder;
import android.app.PendingIntent;
import android.app.PendingIntent;
public class BackIntentService extends Service {
private PendingIntent pendingIntent;
private AlarmManager manager;
public class LocalBinder extends Binder {
BackIntentService getService() {
return BackIntentService.this;
}
}
#Override
public void onCreate() {
startAlarm();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("LocalService", "Received start id " + startId + ": " + intent);
return START_NOT_STICKY;
}
public void startAlarm()
{
manager = (AlarmManager)getSystemService(this.ALARM_SERVICE);
Intent intent = new Intent(this, BackNotifyAlarm.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
int interval = 1000 * 5;
manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
Toast.makeText(this, "Alarm Started", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
// Tell the user we stopped.
Log.d("LocalService", "Stopped");
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
/**
* Show a notification while this service is running.
*/
private void showNotification() {
//Create a notification and set it's content and display it.
NotificationManager notif=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Notification notify=new Notification.Builder
(getApplicationContext()).setContentTitle("RDT Stock").setContentText("HELLOOO").
setContentTitle("Low Stock Items").setSmallIcon(R.drawable.noticon).build();
notify.flags |= Notification.FLAG_AUTO_CANCEL;
notif.notify(11, notify);
}
}
BackNotifyAlarm Broadcast java file:
public class BackNotifyAlarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
//PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
//wl.acquire();
Toast.makeText(context, "Notification sent!", Toast.LENGTH_LONG).show();
//wl.release();
}
I am starting the service in the MainActivity file. The service starts and the service then runs an Alarm, however the alarm only seems to run once and not repeat, any idea why?
I'm developing android application using local notifications. I was implemented local notifications using Services. In services local notifications work but when I kill the app the service destroyed. Notifications not working. Now I want to implement local notifications using alarm manager how can I do this with alarm manager
Here is Service Class.
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import com.deemsysinc.cyberhealthapp.R;
import com.deemsysinc.cyberhealthapp.weightgoal.WeightGoalActivity;
import com.google.gson.Gson;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
public class NotificationService extends Service{
private IBinder iBinder=new MyBinder();
SharedPreferences prefs;
SharedPreferences.Editor editor;
Handler handler;
// timer handling
NotificationManager manager;
Notification myNotication;
static TimerTask timerTask;
Date date1;
Date date2;
ArrayList<NotificationList> notificationLists;
int temp=0;
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
#Override
public boolean onUnbind(Intent intent) {
return true;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return iBinder;
}
#Override
public void onCreate() {
super.onCreate();
handler=new Handler();
prefs = getSharedPreferences(configuration.AppPrefernce, MODE_PRIVATE);
editor = prefs.edit();
notificationLists=new ArrayList<NotificationList>();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
timerStart();
//Remove();
return Service.START_STICKY;
}
public void showNotifications()
{
Calendar cal = Calendar.getInstance();
Date currentLocalTime = cal.getTime();
DateFormat date = new SimpleDateFormat("hh:mm a");
String localTime = date.format(currentLocalTime);
String converted = localTime.replace("am", "AM").replace("pm", "PM");
Toast.makeText(getApplicationContext(),"Timer Running",Toast.LENGTH_LONG).show();
Log.d("Locals",""+local);
//Toast.makeText(getApplicationContext(),"Service Checked",Toast.LENGTH_SHORT).show();
if(!prefs.getString("weight_hr","").equals("")) {
if (prefs.getString("weight_hr", "").equals(converted)) {
temp++;
Bundle bundle=new Bundle();
//SimpleDateFormat writeformat = new SimpleDateFormat("dd/MM/yyyy");
//String formattedDate = writeformat.format(calendar.getTime());
if(temp==1) {
notificationLists.add(new NotificationList("Weight", "It's time to log your weight today. Click to update weight!", ""));
Gson gson = new Gson();
String json = gson.toJson(notificationLists);
editor.putString("notificationlist", json);
editor.commit();
bundle.putString("fromNotificationCenter","1");
}
else
{
bundle.putString("fromNotificationCenter","0");
}
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(getApplicationContext(), WeightGoalActivity.class);
notificationIntent.putExtras(bundle);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 6, notificationIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setAutoCancel(true);
builder.setContentTitle("Cyberhealths");
builder.setContentText("It's time to log your weight today. Click to update weight!");
builder.setSmallIcon(R.drawable.my_icon);
builder.setContentIntent(pendingIntent);
builder.setOngoing(false);
manager.notify(6, builder.build());
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(6);
Toast.makeText(getApplicationContext(),"Service Destroyed",Toast.LENGTH_LONG).show();
}
private void timerStart() {
timer = new Timer();
timerTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
showNotifications();
} catch (Exception e) {
}
}
});
}
};
timer.scheduleAtFixedRate(timerTask, 0, 65000);
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Intent restartService = new Intent(getApplicationContext(),
this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartServicePI = PendingIntent.getService(
getApplicationContext(), 1, restartService,
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePI);
}
private void runOnUiThread(Runnable runnable) {
handler.post(runnable);
}
public class MyBinder extends Binder {
public NotificationService getService() {
return NotificationService.this;
}
}
}
From the documentation of startForeground():
Make this service run in the foreground, supplying the ongoing
notification to be shown to the user while in this state. By default
services are background, meaning that if the system needs to kill them
to reclaim more memory (such as to display a large page in a web
browser), they can be killed without too much harm. You can set this
flag if killing your service would be disruptive to the user, such as
if your service is performing background music playback, so the user
would notice if their music stopped playing.
In your showNotification() method you need to start service on foreground upon Notification,
int FOREGROUND_ID = 6;
....
builder.setOngoing(false);
Notification notification = builder.build();
manager.notify(FOREGROUND_ID, notification);
startForeground(FOREGROUND_ID, notification);
Once you need to stop the service, simply call:
stopForeground(**false / true**);
Pass false if you don't want Notification to be removed once service stops, or true if you want that Notification should be removed automatically.
I have mainActivity that starts service with START_STICKY onStartCommand, in that service I also use startForeground and alarmManager repeater. When I close the main activity by swiping the app away, service is still running, and the notification icon from the startForeground remains, however, when the alarm from the alarmManager sets off inside service, the service get crashed and restart itself within 5000 ms. Why does the service crash soon as it gets to setting of an alarm?
MainActivity.java:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Messenger;
import android.util.Log;
public class MainActivity extends Activity {
Messenger mService = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CheckIfServiceIsRunning();
}
private void CheckIfServiceIsRunning() {
if (MyService.isRunning()) {
} else {
startService(new Intent(MainActivity.this, MyService.class));
}
}
#Override
protected void onDestroy() {
super.onDestroy();
//stopService(new Intent(MainActivity.this, MyService.class)); //disabled line so that killing UI-app doesn't kill service aswell
}
}
MyService.java:
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
public class MyService extends Service {
public AlarmManager alarmManager;
public PendingIntent pendingIntent;
private Timer timer = new Timer();
private int counter = 0, incrementby = 1;
private static boolean isRunning = false;
final public static int NOTIFICATION_FOREGROUND = 34444;
ArrayList<Messenger> mClients = new ArrayList<Messenger>();
final Messenger mMessenger = new Messenger(new IncomingHandler());
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
#SuppressLint("HandlerLeak")
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
#Override
public void onCreate() {
super.onCreate();
Log.i("MyService", "---- Service Started. ----");
timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 0, 1000L);
isRunning = true;
StartForegroundNotification();
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent broadcast_intent = new Intent(this, MyAlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, broadcast_intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10*1000, pendingIntent);
}
#SuppressWarnings("deprecation")
public void StartForegroundNotification(){
String title = "Service Title";
String message = "Service Message";
Notification notify = new Notification(R.drawable.ic_launcher, null, 0);
Intent notifIntent = new Intent(this, MainActivity.class);
PendingIntent i = PendingIntent.getActivity(this, 0, notifIntent, 0);
notify.setLatestEventInfo(this, title, message, i);
notify.flags |= Notification.FLAG_NO_CLEAR;
startForeground(NOTIFICATION_FOREGROUND, notify);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Received start id " + startId + ": " + intent);
return START_STICKY;
}
public static boolean isRunning()
{
return isRunning;
}
private void onTimerTick() {
Log.i("TimerTick", "Timer doing work." + counter);
try {
counter += incrementby;
} catch (Throwable t) {
Log.e("TimerTick", "Timer Tick Failed.", t);
}
}
#Override
public void onDestroy() {
super.onDestroy();
alarmManager.cancel(pendingIntent);
if (timer != null) {timer.cancel();}
stopForeground(true);
counter=0;
Log.i("MyService", "---- Service Stopped. ----");
isRunning = false;
}
}
MyAlarmReceiver.java:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("alarmer", "I got it");
}
}
and in manifest I used:
<service android:name=".MyService" />
<receiver android:name=".MyAlarmReceiver" />
and the logcat (soon as it hit alarm time - after timer ticks 3 in this case - it crashed if the app is closed, however, after it restarts itself, it will not be crashed again, I guess because it's being started from different context, and not from MainActivity.this, it gets "null" intent in onStartCommand):
12-16 19:08:50.614: I/TimerTick(27069): Timer doing work.1
12-16 19:08:53.614: I/TimerTick(27069): Timer doing work.2
12-16 19:08:56.614: I/TimerTick(27069): Timer doing work.3
12-16 19:08:57.622: I/ActivityManager(395): Killing 27069:com.example.serviceexample/u0a10097: remove task
12-16 19:08:57.629: W/ActivityManager(395): Scheduling restart of crashed service com.example.serviceexample/.MyService in 5000ms
12-16 19:09:02.661: I/ActivityManager(395): Start proc com.example.serviceexample for service com.example.serviceexample/.MyService: pid=27100 uid=10097 gids={50097, 1028}
12-16 19:09:02.715: I/MyService(27100): ---- Service Started. ----
12-16 19:09:02.715: I/TimerTick(27100): Timer doing work.0
12-16 19:09:02.723: I/MyService(27100): Received start id 3: null
In my application I launch another activity (an external activity) using the startActivity method.
I would like to be notified when this second application is started, so I could use startActivityForResult method instead of the startActivity method. Are there other mechanisms to receive such notification?
you can try this, call startService in your first activity at the place where you call the second one.
startService(new Intent(this,NotificationService.class));
create NotificationService.java that consists the following:
package com.sample;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
public class NotificationService extends Service
{
private final int UPDATE_INTERVAL = 10 * 1000;
private Timer timer = new Timer();
private static final int NOTIFICATION_EX = 1;
private static final String TAG = "NotificationService";
private NotificationManager notificationManager;
ArrayList<HashMap<String, String>> currentForecast = new ArrayList<HashMap<String, String>>();
CharSequence tickerText="notifi";
public NotificationService(){}
public IBinder onBind1(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
//code to execute when the service is first created
}
#Override
public void onDestroy() {
if (timer != null){
timer.cancel();
}
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startid) {
notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
int icon = R.drawable.iconToDisplayOnNotification;
long when = System.currentTimeMillis();
final Notification notification = new Notification(icon, tickerText, when);
final Context context = getApplicationContext();
final CharSequence contentTitle = "titleForNotification";
final CharSequence contentText = "TextForNotification";
Intent notificationIntent = new Intent(this, ActivityTobeCalledOnNotificationSelect.class);
final PendingIntent contentIntent = PendingIntent.getActivity(this,0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle,contentText, contentIntent);
notificationManager.notify(NOTIFICATION_EX, notification);
Toast.makeText(this, "Started!", Toast.LENGTH_LONG);
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
// Check if there are updates here and notify if true
Log.w(TAG,"run");
}
}
,10, UPDATE_INTERVAL);
return START_STICKY ;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
I finally got the Local Service Sample to work using the LocalServiceActivities.java and the Basics of Android : Part III – Android Services.
Here's my code Controller.java, LocalService.java, Binding.java, and ILocalService.java all baked together one after another separated by comment headers:
/**************************************************************************************************
* Filename: Controller.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains the primary activity for this application
**************************************************************************************************/
package com.marie.localservicesample;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/*
* Example of explicitly starting and stopping the local service.
* This demonstrates the implementation of a service that runs in the same
* process as the rest of the application, which is explicitly started and stopped
* as desired.
*/
//public static class Controller extends Activity {
public class Controller extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.local_service_controller);
// Watch for button clicks.
Button button = (Button)findViewById(R.id.start);
button.setOnClickListener(mStartListener);
button = (Button)findViewById(R.id.stop);
button.setOnClickListener(mStopListener);
}
private OnClickListener mStartListener = new OnClickListener() {
public void onClick(View v) {
// Make sure the service is started. It will continue running
// until someone calls stopService(). The Intent we use to find
// the service explicitly specifies our service component, because
// we want it running in our own process and don't want other
// applications to replace it.
//startService(new Intent(Controller.this, LocalService.class));
Intent startSvc = new Intent(Controller.this, LocalService.class);
startSvc.putExtra(LocalService.EXTRA_MESSENGER, new Messenger(handler));
startSvc.putExtra(LocalService.EXTRA_SONG, 7);
startService(startSvc);
Intent binding = new Intent(Controller.this, Binding.class);
startActivity(binding);
}
};
private OnClickListener mStopListener = new OnClickListener() {
public void onClick(View v) {
// Cancel a previous call to startService(). Note that the
// service will not actually stop at this point if there are
// still bound clients.
stopService(new Intent(Controller.this,
LocalService.class));
}
};
/*
* This is a handler to be passed to the Service via a Messenger.
*/
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// simple handler test
String obj = (String) msg.obj;
Log.i("handleMessge", "obj: " + obj);
}
};
}
/**************************************************************************************************
* Filename: LocalService.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains a local service
**************************************************************************************************/
package com.marie.localservicesample;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
public class LocalService extends Service {
private NotificationManager mNM;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
//private int NOTIFICATION = R.string.local_service_started;
private int NOTIFICATION = R.string.local_service_started;
private int statusCode = 10;
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Class for clients to access. Because we know this service always
* runs in the same process as its clients, we don't need to deal with
* IPC.
*/
public class LocalBinder extends Binder implements ILocalService {
LocalService getService() {
return LocalService.this;
}
#Override
public int getStatusCode() {
return statusCode;
}
}
public static final String EXTRA_MESSENGER = "com.marie.localservicesample.EXTRA_MESSENGER";
private Messenger messenger;
public static final String EXTRA_SONG = "com.marie.localservicesample.EXTRA_SONG";
private int song;
#Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// Display a notification about us starting. We put an icon in the status bar.
showNotification();
Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService");
thr.start();
}
/*
* This is the ServiceWorker thread that passes messages to the handler defined in
* the MainActivity class.
* NOTE: Instead of passing messages to a handler in MainActivity I would like
* it to pass messages to a handler defined in the RcvMessages activity.
*/
class ServiceWorker implements Runnable
{
public void run() {
// do background processing here... something simple
while (messenger == null);
// send a message to the handler
try {
Message msg = Message.obtain();
msg.obj = "Hello " + "Song " + song;
msg.arg1 = song;
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
// stop the service when done...
// LocalService.this.stopSelf();
// Or use the unbindBtn in the MainActivity class.
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
Bundle extras = intent.getExtras();
messenger = (Messenger)extras.get(EXTRA_MESSENGER);
try {
song = (Integer) extras.get(EXTRA_SONG);
} catch (NullPointerException e) {
e.printStackTrace();
song = 0;
}
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancel(NOTIFICATION);
// Tell the user we stopped.
Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();
}
/**
* Show a notification while this service is running.
*/
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.local_service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.stat_sample, text,
System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this notification
//PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, LocalServiceActivities.Controller.class), 0);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Controller.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.local_service_label),
text, contentIntent);
// Send the notification.
mNM.notify(NOTIFICATION, notification);
}
/* Duplicate added by Eclipse
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
*/
}
/**************************************************************************************************
* Filename: Binding.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains the binding for this application
**************************************************************************************************/
package com.marie.localservicesample;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
/*
* Example of binding and unbinding to the local service.
* This demonstrates the implementation of a service which the client will
* bind to, receiving an object through which it can communicate with the service.
*/
public class Binding extends Activity {
private boolean mIsBound;
private LocalService mBoundService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
mBoundService = ((LocalService.LocalBinder)service).getService();
ILocalService localService = (ILocalService)service;
int statusCode = localService.getStatusCode();
Log.d("Binding","called onServiceConnected. statusCode: " + statusCode);
Toast.makeText(Binding.this, R.string.local_service_connected,
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
mBoundService = null;
Log.d("Binding", "called onServiceDisconnected");
Toast.makeText(Binding.this, R.string.local_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};
void doBindService() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
bindService(new Intent(Binding.this,
LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
private OnClickListener mBindListener = new OnClickListener() {
public void onClick(View v) {
doBindService();
}
};
private OnClickListener mUnbindListener = new OnClickListener() {
public void onClick(View v) {
doUnbindService();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.local_service_binding);
// Watch for button clicks.
Button button = (Button)findViewById(R.id.bind);
button.setOnClickListener(mBindListener);
button = (Button)findViewById(R.id.unbind);
button.setOnClickListener(mUnbindListener);
}
}
/**************************************************************************************************
* Filename: ILocalService.java
* Project name: Local Service Sample
* Application name: Local Service
* Description: This file contains an example interface for LocalService
**************************************************************************************************/
package com.marie.localservicesample;
public interface ILocalService {
// An example method for ILocalService
public int getStatusCode();
}
My question is why would anyone want to provide an ILocalService.java if they already have a startService() with a thread and a handler like I do? My ILocalService.java is a trivial demo which asks for a statusCode. As far as I can tell my ILocalService.java will only consist of getters of status and no setters. So will I only be asking for status info of my local service? What would be an example of a setter to my local service?
Your binder looks like this:
public class LocalBinder extends Binder implements ILocalService {
LocalService getService() {
return LocalService.this;
}
#Override
public int getStatusCode() {
return statusCode;
}
}
The key part of interest is getService. What this means is that any of your Activities that bind to your Service (since this is a local service) can actually obtain the service object and can call ANY functions on that service function, not just getters. You aren't limited to just the narrow communication channel that is startService and the Intent, you have the full method interface for the service object. In the past I've passed BluetoothDevice instances, Handler instances and other complex Java objects through to the service object.