Scheduling local notifications using Alarm Manager android - android

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.

Related

Android Notification showing only once

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);

background services stop when the app is closed via the BACK button

A background service in Android stops running when the user exits the app using the BACK button. The same service works fine if the app is in foreground or in background (clicking the HOME button).
there are 3 cases:
Keep the app running: every 15 seconds a notification is shown (OK).
Put the app in background by clicking the HOME button: notifications keep showing (OK)
Click the BACK button (this closes the app): the background service is stopped and no more notifications are shown (BUG)
Expected behavior
Also in case #3, the notifications should keep running every 15 seconds.
my entire source is below
MainActivity.java
package com.example.service_demo;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private TextView timerValue;
private Button startTimer;
private Button cancleTimer;
Intent i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapview();
}
private void mapview() {
timerValue = (TextView) findViewById(R.id.timertext);
startTimer = (Button) findViewById(R.id.starttimer);
cancleTimer = (Button) findViewById(R.id.cancletimer);
startTimer.setOnClickListener(this);
cancleTimer.setOnClickListener(this);
}
#Override
protected void onResume() {
super.onResume();
i = new Intent(this, SimpleService.class);
if (isMyServiceRunning()) {
Toast.makeText(getBaseContext(), "Service is running,",
Toast.LENGTH_SHORT).show();
registerReceiver(broadcastReceiver, new IntentFilter(
SimpleService.BROADCAST_ACTION));
startTimer.setEnabled(false);
} else {
Toast.makeText(getBaseContext(), "There is no service running",
Toast.LENGTH_SHORT).show();
}
}
#Override
public void onClick(View v) {
if (v == startTimer) {
startTimer.setEnabled(false);
i = new Intent(this, SimpleService.class);
startService(i);
registerReceiver(broadcastReceiver, new IntentFilter(
SimpleService.BROADCAST_ACTION));
} else if (v == cancleTimer) {
i = new Intent(this, SimpleService.class);
stopService(i);
timerValue.setText("00:00:00");
startTimer.setEnabled(true);
}
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
private void updateUI(Intent intent) {
String str = intent.getStringExtra("textval");
timerValue.setText(str);
}
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager
.getRunningServices(Integer.MAX_VALUE)) {
if (SimpleService.class.getName().equals(
service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
i = new Intent(this, SimpleService.class);
startService(i);
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
System.exit(0); // system.exit(0) is mendatory for my app so it can't be
// removed
}
}
SimpleService
package com.example.service_demo;
import java.util.Timer;
import java.util.TimerTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class SimpleService extends Service {
private NotificationManager mNM;
private long startTime = 0L;
long timeInMilliseconds = 0L;
long timeSwapBuff = 0L;
long updatedTime = 0L;
long basestart = System.currentTimeMillis();
Timer timer = new Timer();
long timeswap = 0L;
int secs = 0;
int mins = 0;
int hour = 0;
Intent intent;
String s;
public static final String BROADCAST_ACTION = "com.example.service_demo.MainActivity";
private int NOTIFICATION = 1;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
intent = new Intent(BROADCAST_ACTION);
Toast.makeText(this, "Service Started", 2000).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
timer.schedule(new RemindTask(), 0, 1000);
}
});
t.start();
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mNM.cancel(NOTIFICATION);
if (timer != null) {
timer.cancel();
timer.purge();
timer = null;
}
Toast.makeText(this, "Service Stoped", 2000).show();
}
class RemindTask extends TimerTask {
#Override
public void run() {
timeInMilliseconds = System.currentTimeMillis() - basestart;
timeSwapBuff = timeswap;
updatedTime = timeSwapBuff + timeInMilliseconds;
secs = (int) (updatedTime / 1000);
mins = secs / 60;
hour = mins / 60;
secs = secs % 60;
mins = mins % 60;
s = "" + String.format("%02d", hour) + ":" + ""
+ String.format("%02d", mins) + ":"
+ String.format("%02d", secs);
if (s.equalsIgnoreCase("00:00:15")) {
showNotification();
}
intent.putExtra("textval", s);
sendBroadcast(intent);
}
}
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = s;
// Set the icon, scrolling text and timestamp
#SuppressWarnings("deprecation")
Notification notification = new Notification(R.drawable.ic_launcher,
text, System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this
// notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, "Notification Label", text,
contentIntent);
// Send the notification.
mNM.notify(NOTIFICATION, notification);
}
}
In the method onStartCommand() of the service, return START_STICKY.
The service will continue to run until you explicitly call stopSelf() in the service or call stopService() from your activity.
Try implementing foreground service. foreground service
Foreground service displays notification and is never stopped.
Implement this code snippet in your service's onCreate().
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
This works for me:
notifyIntent.setAction(Intent.ACTION_MAIN);
notifyIntent.addCategory(Intent.CATEGORY_LAUNCHER);

Service crash, even with startForeground when the activity gets shut down and the alarmManager sets off

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

How to receive a notification that an application has been started?

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;
}
}

Creating an android service

I'm trying to create a service which will start by the user request in the application.
After the user will choose an update interval, the service will run in the operation system background, and will send a non-relevant message.
I've tried to write the service according to the example for Service class API.
For some reason, I figured in debug (when running doBindService() method) that mUpdateBoundService is getting null.
My second question is whether I can use "Toast" inform message outside an application ? (As kind of a desktop notification).
Can anyone help ? Here is my short code:
UpdateService.java
package android.update;
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.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class UpdateService extends Service {
private NotificationManager mNM;
private final IBinder mBinder = new UpdateBinder();
private int updateInterval;
public class UpdateBinder extends Binder {
UpdateService getService() {
return UpdateService.this;
}
}
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Timer timer = new Timer();
timer.schedule(new UpdateTimeTask(), 100, updateInterval);
}
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
class UpdateTimeTask extends TimerTask {
public void run() {
showNotification();
}
}
public void showNotification() {
Toast.makeText(this, "Hi", 10);
}
#Override
public IBinder onBind(Intent intent) {
updateInterval = intent.getExtras().getInt(getString(R.string.keyUpdateInterval));
return mBinder;
}
}
UpdateActivity.java
package android.update;
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.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class UpdateActivity extends Activity {
private UpdateService mUpdateBoundService;
private boolean mIsBound = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onClickStartUpdateService(View view) {
switch (view.getId()) {
case R.id.btnStartUpdateService:
doBindService();
//Toast.makeText(this,"Service Started",Toast.LENGTH_LONG).show();
mUpdateBoundService.showNotification();
break;
}
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mUpdateBoundService = ((UpdateService.UpdateBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mUpdateBoundService = null;
}
};
private void doBindService() {
Intent updateActivityIntent = new Intent(UpdateActivity.this,
UpdateService.class);
EditText txtUpdateInterval = (EditText) findViewById(R.id.txtUpdateInterval);
int interval = Integer.parseInt(txtUpdateInterval.getText().toString());
updateActivityIntent.putExtra(getString(R.string.keyUpdateInterval), interval);
bindService(updateActivityIntent, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
}
Your toast is not showing because you are not telling it to. Try:
public void showNotification() {
Toast.makeText(this, "Hi", 10).show();
}
For your service issue, I think that you do not properly understand how services & activities work together. A service can run independently of a service, or you can have a service whose lifecycle matches that of a given activity. From your code, it is not clear which of these models you are following. Your implementation will cause the service to wake periodically, but only while your activity is running. If the user switches to another activity, your service will no longer be woken.
If you want a service to wake periodically independently of the activity, then you need to run your timer event in the service itself. Better still use an Alarm to wake your service: Register an Alarm with AlarmManager which will fire an Intent at a future point (or regular intervals, if you prefer), and extend your service from IntentService, override onHandleIntent() and add the necessary Intent Filter to your Service entry in the manifest.

Categories

Resources