Long running background process - android

What i want: To run a background service that would communicate with our server via RESTFUL webservice after regular interval of 1 minute (Its a strict project requirement. So cannot increase it.)
What i have: I tried various approaches using simple BroadcastReceivers with a simple Service AND WakefulBroadcastReceivers using WakefulIntentService etc..
Main Problem: The main issue is when device screen is ON, everything is working fine on regular/fixed intervals but when the screen goes off OR devices gets locked, then the alarm Manager triggers service with a minimum interval of 5 Minutes.. Thats exactly what i dont want. I want the same 1 minute interval while device is locked/screen off.
Below is my code:
Manifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver android:name=".MyScheduledReceiver" />
<service android:name=".BackgroundService" />
Activity.java
MyScheduledReceiver.scheduleAlarms(MainActivity.this);
gradle
// Background long running process
compile 'com.commonsware.cwac:wakeful:1.0.+'
repositories {
maven {
url "https://s3.amazonaws.com/repo.commonsware.com"
}
}
BroadcastReceiver
public class MyScheduledReceiver extends WakefulBroadcastReceiver {
private static final int PERIOD = 60 * 1000;
private static final int INITIAL_DELAY = 2000; // 5 seconds
#Override
public void onReceive(Context context, Intent i) {
try {
if (i.getAction() == null) {
WakefulIntentService.sendWakefulWork(context, BackgroundService.class);
} else {
scheduleAlarms(context);
}
} catch (Exception e) {
e.printStackTrace();
}
}
static void scheduleAlarms(Context ctxt) {
AlarmManager mgr = (AlarmManager) ctxt.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ctxt, MyScheduledReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(ctxt, 0, i, 0);
mgr.setRepeating(AlarmManager.RTC_WAKEUP, INITIAL_DELAY, PERIOD, pi);
}
}
BackgroundService
public class BackgroundService extends WakefulIntentService {
public BackgroundService() {
super("BackgroundService");
}
#Override
protected void doWakefulWork(Intent intent) {
sendNotification("HELLOO");
stopSelf();
}
#Override
public void onTaskRemoved(Intent rootIntent) {
MyScheduledReceiver.scheduleAlarms(BackgroundService.this);
super.onTaskRemoved(rootIntent);
}
private void sendNotification(String message) {
try {
Intent intent = intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Notification notification;
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("test")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
notification = notificationBuilder.build();
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Currently i am simply showing a notification with a sound in the notification bar from my BackgroundService.
I would really appreciate your help. Thanks !

What you want is not supported on Android 6.0 anyway. Android 6.0 will not issue alarms every minute, to any application, thanks to Doze mode.
The closest thing that will work is:
Have a service that uses a ScheduledExecutorService to get control every minute to do your work
Have that service acquire a WakeLock and keep the CPU on all the time
Have that service use startForeground() and START_STICKY to minimize the amount of time that it is not around and therefore incapable of doing this work
Make sure that application is added to the "ignore battery optimizations" whitelist in Settings
Ignore the cries of anguish from users, complaining that their battery life is atrocious

Try using like this
public static void scheduleAlarms(Context ctxt) {
AlarmManager mgr = (AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ctxt, MyScheduledReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(ctxt,REQUEST_CODE, i, 0);
// We want the alarm to go off 3 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
firstTime += 3 * 1000;//start 3 seconds after first register.
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,
600000, sender);//10min interval
}

Have you tried using a Handler to obtain this goal? AlarmManager will typically work on a battery friendly rhythm when possible. Whereas Handlers are much more exact.
For example, you could run this code in your Service:
// Store this as a member variable
private Handler mHandler = new Handler();
// This can be a member variable or local
private Runnable runnable = new Runnable() {
#Override
public void run() {
// Do stuff
// Tell the Handler to call itself again
mHandler.postDelayed(this, 60000);
}
};
// Put this at the start of `Service`
mHandler.postDelayed(runnable, 60000);
As Commonsware points out, having the Handler declared as it is above would cause the Handler to run on the Main Thread. Here is some documentation on how to get a Handler to run in the background:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}

Related

Run a method daily after a fixed time

I have functionality in my app where a user will select the time when he wants to get notifications from the application. In this case, I am taking the input from user in this format 12:00 AM. I wrote a method for creating notifications in my app which is working fine but I want to call that method every day at a user-selected time. Also, if app is completely destroyed not even running in the background will this method be called at the user-selected time daily?
String user_time=tinyDB.getString("app_check_time"); // This is user selected time e.g, 12:00 PM
Calendar calendar = Calendar.getInstance();
Date date1 = null;
try {
date1=new SimpleDateFormat("h:m a").parse(user_time);
} catch (ParseException e) {
e.printStackTrace();
}
calendar.set(Calendar.HOUR_OF_DAY, date1.getHours());
calendar.set(Calendar.MINUTE, date1.getMinutes());
Date time = calendar.getTime();
System.out.println("hourr "+time);
timer = new Timer();
timer.schedule(new createNotification(), time);
You can use WorkManager for this. And yes, it'll run even if your app is completely dead.
From Android Docs:
WorkManager is a library used to enqueue deferrable work that is guaranteed to execute sometime after its Constraints are met.
You can see the guide here https://developer.android.com/topic/libraries/architecture/workmanager
The WorkManager API makes it easy to schedule deferrable, asynchronous tasks that are expected to run even if the app exits or device restarts.
Hope it helps!
Have you considered using something like Quartz Scheduler? This library has a mechanism for scheduling tasks to run at a set period of time every day using a cron like expression (take a look at CronScheduleBuilder).
Some example code (not tested):
public class GetDatabaseJob implements InterruptableJob
{
public void execute(JobExecutionContext arg0) throws JobExecutionException
{
getFromDatabase();
}
}
public class Example
{
public static void main(String[] args)
{
JobDetails job = JobBuilder.newJob(GetDatabaseJob.class);
// Schedule to run at 5 AM every day
ScheduleBuilder scheduleBuilder =
CronScheduleBuilder.cronSchedule("0 0 5 * * ?");
Trigger trigger = TriggerBuilder.newTrigger().
withSchedule(scheduleBuilder).build();
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(job, trigger);
scheduler.start();
}
}
There's a bit more work upfront, and you may need to rewrite your job execution code, but it should give you more control over how you want you job to run. Also it would be easier to change the schedule should you need to
Creating a long running service for this task
Intent intent = new Intent(this, ReminderService.class);
startService(intent);
Creating a reminderservice which extends service
public class ReminderService extends Service {
#Override
public void onCreate() {
Calendar calendar = Calendar.getInstance();
calendar.set(calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH),
6,
0,
0);
setAlarm(calendar.getTimeInMillis());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// If we get killed, after returning from here, restart
return START_STICKY;
}
public void setAlarm(long timeInMillis) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, ReminderReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
0, intent, 0);
if (alarmManager != null) {
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, timeInMillis,
2 * 60 * 1000 , pendingIntent); //AlarmManager.INTERVAL_DAY //2 * 60 * 1000 (2 minutes)
}
}
}
creating ReminderReceiver which extends BroadcastReceiver
public class ReminderReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//do task to show notification
ShowNotification showNotification = new ShowNotification(context);
showNotification.showNotification("Method called");
}
}
create ShowNotification class
public class ShowNotification {
private static final int NOTIFICATION = 0;
private static final String NOTIFICATION_CHANNEL_ID = "100";
private Context context;
private NotificationManager notificationManager;
private ConnectivityManager conManager;
public ShowNotification(Context context) {
this.context = context;
if (notificationManager == null) {
notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
}
if (conManager == null) {
conManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
}
}
/**
* Show a notification while this service is running.
*
* #param key
*/
void showNotification(String key) {
String NOTIFICATION_CHANNEL_NAME = "NOTIFICATION_CHANNEL_NAME";
// In this sample, we'll use the same text for the ticker and the expanded notification
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME, importance);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
notificationManager.createNotificationChannel(notificationChannel);
}
final Intent notificationIntent = new Intent(context, SplashActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
// Set the info for the views that show in the notification panel.
Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setWhen(System.currentTimeMillis())
.setContentTitle("Method Called")
.setContentText(key)
.setContentIntent(contentIntent)
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
.build();
// Send the notification.
notificationManager.cancel(NOTIFICATION);
notificationManager.notify(NOTIFICATION, notification);
}
}
In manifest file
<service
android:name=".ReminderService"
android:enabled="true"
android:exported="false" />
<receiver android:name=".ReminderReceiver" />

alarm manager/ service/ broadcast receiver is not working after app is closed or swiped away from the recent app

I know there are so many questions about this.
I tried most of them and spent so much time on it.
but not getting any solution
Actually, I want a background process to run to infinite time even app is removed from recent app
I want to take GPS location of user repetitively after 15 minute
so first I had tried with following
TRY 1******
I have created broadcast receiver who will call my service
name of that broadcast receiver is LocationServiceRestarter
I am initiating alarm repeater who will call LocationServiceRestarter at regular interval of 5 seconds
Intent intent = new Intent("com.lmf.overduereport.gpstimer.LocationServiceRestarter");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am =
(AlarmManager)getSystemService(Activity.ALARM_SERVICE);
alarm_manager.setRepeating(AlarmManager.RTC_WAKEUP,SystemClock.elapsedRealtime()+5*1000,5*1000,pendingIntent);
it works fine if I don't remove app from recent apps
I have added a log inside broadcast receiver who writes log in my folder about if broadcast receiver called or not.
in this case broadcast receiver itself is not called from alarm manager then it will obviously not call service that i want to be called to record location.
TRY 2******
I have also tried services who can run infinitely. but it also stops working after app closes
TRY 3******
This time I will not call repetitive alarm manager instead of that I did following
Intent intent = new Intent("com.lmf.overduereport.gpstimer.LocationServiceRestarter");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am =
(AlarmManager)getSystemService(Activity.ALARM_SERVICE);
//--
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 5000, pendingIntent);
above will call broadcast receiver and in broadcast receiver I have added alarm manager as follows
LocationServiceM.appendLog("Got Reciever******");
intent = new Intent("com.lmf.overduereport.gpstimer.LocationServiceRestarter");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
12345, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am =
(AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 5000, pendingIntent);
above will reinitiate broadcast receiver with new schedule time so chain will continue.
but sadly that also don't work. it works fine if app is not removed from the recent app.
even I had tried same above thing with service and intent service with no luck.
Conclusion: alarm manager or Broadcast receiver is not called after app is removed from the recent app.
but I have seen many app that runs in background even app is closed from recent app.
you can use START_STICKY which tells the OS to recreate the service after it has enough memory and call onStartCommand() again with a null intent. START_NOT_STICKY tells the OS to not bother recreating the service again.
you can use a service to fired when app is closed or kill from the task:
public class SensorService extends Service {
public int counter=0;
public SensorService(Context applicationContext) {
super();
Log.i("HERE", "here I am!");
}
public SensorService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
Intent broadcastIntent = new Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
stoptimertask();
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 1000, 1000); //
}
/**
* it sets the timer to print the counter every x seconds
*/
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
Log.i("in timer", "in timer ++++ "+ (counter++));
}
};
}
/**
* not needed
*/
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
you also need a BroadcastReceiver which will receive a signal when someone or something kills the service; its role is to restart the service.
public class SensorRestarterBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(SensorRestarterBroadcastReceiver.class.getSimpleName(), "Service Stops! Oooooooooooooppppssssss!!!!");
context.startService(new Intent(context, SensorService.class));;
}
}
For full implementation see this link
http://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android

Alarm manager for background services

I have implemented the alarm manager to wake up the background services every 15 mins periodically. It is working fine, but since the inclusion of DOZE mode Android 6.0, the seems like behaving strange and not waking up in every 15 mins. Although, I am using the method alarm.setExactAndAllowWhileIdle(), but still not working in Idle state
here is my method for implementing Alarm Manager
private void serviceRunningBackground()
{
final Intent restartIntent = new Intent(this, service.class);
restartIntent.putExtra("ALARM_RESTART_SERVICE_DIED", true);
alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Handler restartServiceHandler;
restartServiceHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
pintent = PendingIntent.getService(getApplicationContext(), 0, restartIntent, 0);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
Log.d(TAG, " Marshmellow "+ TIMER_START_TIME);
alarmMgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, 900000, pintent);
} else {
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 900000, pintent);
}
sendEmptyMessageDelayed(0, TIMER_START_TIME);
}
};
restartServiceHandler.sendEmptyMessageDelayed(0, 0);
}
Any help would be appreciated..thanks
Try this:
public class PollReceiver extends WakefulBroadcastReceiver{
static final String PERIOD = "period";
#Override
public void onReceive(Context context, Intent intent){
startWakefulService(context,new Intent(context,MyService.class));
long period = intent.getLongExtra(PERIOD,-1);
if(period>0){
scheduleExactAlarm(context,(AlarmManager)context.getSystemService(Context.ALARM_SERVICE),period)
}
}
static void scheduleExactAlarm(Context context,AlarmManager alarms, long period){
Intent i = new Intent(context,PollReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context,0,i,0);
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1){
alarms.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + period,pi);
}
}
Ive tested scheduling alarms in this way in Doze and it works. They go off every 15 minutes. Check out https://commonsware.com , thats where I found this method of scheduling a repeating alarm.

Android service gets killed on swiping out the application

I have an Android Service class the code for which is as follows:
public class LoginService extends Service {
BroadcastReceiver wifiStateChangeReciever;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("AndroidLearning", "Service onStartCommand Started.");
return Service.START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("AndroidLearning", "Service Started.");
final IntentFilter intentFilter = new IntentFilter();
// intentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
intentFilter.addAction("android.net.wifi.STATE_CHANGE");
wifiStateChangeReciever = new WifiStateChangeReciever();
this.registerReceiver(wifiStateChangeReciever, intentFilter, null, null);
Log.i("AndroidLearning", "Reciever Registered.");
}
#Override
public void onDestroy() {
Log.i("AndroidLearning", "Service Destroyed.");
this.unregisterReceiver(wifiStateChangeReciever);
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.w("AndroidLearning", "On Task Remove: FLAG_STOP_WITH_TASK - "
+ ServiceInfo.FLAG_STOP_WITH_TASK);
this.unregisterReceiver(wifiStateChangeReciever);
Intent restartServiceIntent = new Intent(getApplicationContext(),
this.getClass()); restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(
getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarmService.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent);
Log.w("AndroidLearning", "End on task removed");
super.onTaskRemoved(rootIntent);
}
}
It registers a BroadcastReciever. The Activity which starts this service has the following code:
Intent intent = new Intent(this, LoginService.class);
startService(intent);
However whenever the Activity is swiped out from the task list (recent) the service is also stopped. I over rode the onTaskRemoved to remedy it but it still does not seem to work and the AlarmManager never starts the pendingIntent. I have tries using both method: set and setExact for the AlarmManager.
I also tried adding the following options to <service> tags
android:stopWithTask="false"
android:process=":remote"
but to no avail.
What am I doing wrong here? Thanks for the help.
I finally found the answer to my own problem. It seems this was a problem with the particular flavor of android that I was running on my phone (Mi UI). There was a separate setting regarding each application whether it needed to be allowed to be restarted or not.
Unless this setting is configured no amount of changing permissions and setting Alarms helped me.
This is a different approach from you but I recently fixed this by adding a notification when the service was running
private void showNotification(){
NotificationCompat.Builder builer = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo)
.setContentTitle("Service active")
.setContentText("Your service keeps running")
.setOngoing(true);
mNotificationManager.notify(NOTIFICATION_ID, builer.build());
}
The notification is shown in onStartCommand and dismissed in the service ondestroy method.
You need to start service in foreground if you don't want android to shut it down.
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);
http://developer.android.com/guide/components/services.html#Foreground
If you try this on some devices, sadly, it won't work.
Some OEMs decided to change the normal behavior of what happens when you remove an app from the recent tasks, so they become semi-disabled:
https://issuetracker.google.com/issues/122098785
https://dontkillmyapp.com/

Android Notification with AlarmManager, Broadcast and Service

this is my code for menage a single notification:
myActivity.java
public class myActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
cal = Calendar.getInstance();
// it is set to 10.30
cal.set(Calendar.HOUR, 10);
cal.set(Calendar.MINUTE, 30);
cal.set(Calendar.SECOND, 0);
long start = cal.getTimeInMillis();
if(cal.before(Calendar.getInstance())) {
start += AlarmManager.INTERVAL_FIFTEEN_MINUTES;
}
Intent mainIntent = new Intent(this, myReceiver.class);
pIntent = PendingIntent.getBroadcast(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager myAlarm = (AlarmManager)getSystemService(ALARM_SERVICE);
myAlarm.setRepeating(AlarmManager.RTC_WAKEUP, start, AlarmManager.INTERVAL_FIFTEEN_MINUTES, pIntent);
}
}
myReceiver.java
public class myReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent i) {
Intent myService1 = new Intent(c, myAlarmService.class);
c.startService(myService1);
}
}
myAlarmService.java
public class myAlarmService extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
displayNotification();
}
#Override
public void onDestroy() {
super.onDestroy();
}
public void displayNotification() {
Intent mainIntent = new Intent(this, myActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(pIntent)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_noti)
.setTicker(getString(R.string.notifmsg))
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.notifmsg));
nm.notify(0, builder.build());
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
...
...
...
<service android:name=".myAlarmService" android:enabled="true" />
<receiver android:name=".myReceiver"/>
IF the time has NOT past yet everything works perfectly. The notification appears when it must appear.
BUT if the time HAS past (let's assume it is 10.31 AM) the notification fires every time... when I close and re-open the app, when I click on the notification... it has a really strange behavior.
I can't figure out what's wrong in it. Can you help me please (and explain why, if you find a solution), thanks in advance :)
Place display notification inside an if statement , such that compare the current time with the notification set time and if the current time is before the set time then display notification, else do nothing.
int temp = calTemp.getTime().compareTo(calendar.getTime());
if(temp > 0){
}else{
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(),
pendingIntent1);
}
here calTemp gives current time and calender gives the time i want to fire the alarm. So according to above code if the time has already past then the notification will not fire for sure .
Hi I've had the same problem and found a solution in this SO post, basically the idea is to rely on AlarmManager, Receiver but avoid usage of Service.
Since you are using the Service just to build and display the notification you may find useful my approach.
Let me know.

Categories

Resources