Alarm manager not pushing data in server periodically for nougat - android

i am using AlarmManager to call the PendingIntent. which triggers the WakefulBroadcastReceiver to push the data in server periodically. but for nougat, its not pushing in the periodic time. and also draining battery too much.
my code is here->
public static void startSyncAlarm(String enteredTime) {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(context, SyncDbToServerAlarmReceiver.class);
intent.putExtra(Constants.ENTERED_TIME, enteredTime);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(context, SyncDbToServerAlarmReceiver.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// alarm needs to be set after 5 minutes of entered time
// convert entered time to milliseconds
// create Date object using string time format with using Simple date format
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss aa");
try {
Date enteredDate = format.parse(enteredTime);
long enteredTimeInMillis = enteredDate.getTime();
long intervalMillis = 30 * 60 * 1000; // 30 minutes gap
long triggerAtMillis = enteredTimeInMillis + intervalMillis;
Log.d(TAG, "start alarm, enteredTimeMillis = " + enteredTimeInMillis + "\ntriggerAtMillis = " + triggerAtMillis);
//long firstMillis = System.currentTimeMillis(); // alarm is set right away
syncDbAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Setup periodic alarm every 5 minutes
syncDbAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis/*firstMillis*/,
intervalMillis, pIntent);
} catch (ParseException e) {
e.printStackTrace();
}
}

Related

Refresh date in Broadcast Receiver Android

I have a broadcast receiver class which I call at the beginning of a new day.
Here is the broadcast receiver onReceive method.
#Override
public void onReceive(Context context, Intent intent) {
context.sendBroadcast(new Intent(NEW_DAY_FROM_RECEIVER));
Log.d(TAG, "Old day passed, new day in!");
DateFormat dateFormat = new SimpleDateFormat("EEE, MMM d");
Date yesterdaysDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000L);
String yesterdaysDateString = dateFormat.format(yesterdaysDate);
// Saving the value
DailyPointsItem yesterdayPointsItem = new DailyPointsItem(yesterdaysDateString, String.valueOf(pointsForToday), notEatenItemsArrayList, DailyPointsItem.DAILY_FOOD_POINT);
Log.d(TAG,"Points: " + yesterdayPointsItem.getTitle() + " : " + yesterdayPointsItem.getDescription());
addDailyPointsItem(context, yesterdayPointsItem);
}
public static void addDailyPointsItem(Context context, DailyPointsItem yesterdayPointsItem) {
ArrayList<DailyPointsItem> dailyPointsDataList = SharedPreferencesManager.getDailyPointsItemsArrayList(context);
dailyPointsDataList.add(0, yesterdayPointsItem);
if(dailyPointsDataList.size()==8){
dailyPointsDataList.remove(7);
}
final SharedPreferences.Editor editor = getSharedPreferences(context).edit();
Gson gson = new Gson();
String jsonDailyPointsArray = gson.toJson(dailyPointsDataList);
editor.putString(JSON_STRING_POINTS_ARRAY, jsonDailyPointsArray);
editor.apply();
}
Here I store the string yesterdaysDateString (which is the string of the previous day that just passed), and display this data some place else.
This broadcast receiver I call at the begining of each day using an AlarmManager, called in my Main Activity when the app starts, like this:
Intent intent = new Intent(this, NewDayReceiver.class);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
if (!calendar.before(Calendar.getInstance())) {
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent); //Repeat every 24 hours
Log.d(TAG, "New day alarm set for:" + calendar.getTime() + " and will repeat every day");
}
Now this works fine, and each day that comes in the date is stored in the string. However the date is only correctly saved if the app is opened each day. If the app isn't opened each day, the AlarmManager works and the broadcast receiver is called, however the date that is saved is the date of the last day the app was open. If for example the app was opened Sun, Mar 25, and not opened for 3 days. then the three dates that are stored are Sun, Mar 25. Why is the Broadcast receiver not saving the current date.
EDITED: It works when the phone is used, but if the phone isn't used and left idle, it doesn't save the correct date. Why would this be so?

AlarmManager shifts time by 12 hours

I'm trying to create periodical notifications.
So, I created a function to reschedule new notification time:
private void rescheduleNotification(Context context) {
long nextNotifTime = System.currentTimeMillis();
// Schedule next notification in 15 minutes
nextNotifTime += 15 * 60 * 1000;
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(nextNotifTime);
// It's an old version with the same result
//calendar.add(Calendar.MINUTE, 15);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm:ss", Locale.ENGLISH);
this.logEvent(" Next notification time is: " + sdf.format(calendar.getTimeInMillis()));
Intent intent = new Intent(context, WordsBcReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager manager = (AlarmManager)context.getSystemService(ALARM_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= 23) {
manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextNotifTime, pendingIntent);
} else {
manager.set(AlarmManager.RTC_WAKEUP, nextNotifTime, pendingIntent);
}
this.logEvent(" Set next notification time: " + sdf.format(nextNotifTime));
}
Sometimes it runs correctly, but sometimes notification time shifts by exactly 12 hours.
I added special function to log all time manipulations, so the log contains:
29/12/17 11:30:36: Next notification time is: 29/12/17 12:00:36
29/12/17 11:30:36: Set next notification time: 29/12/17 12:00:36
seems OK, but adb shell dumpsys alarm says:
type=0 whenElapsed=+11h34m13s906ms when=2017-12-30 00:00:36
I tried to use Calendar (I to exclude some periods later), but result was the same.
Can't find the problem...

Starting alarm after specified days

Hello Below is my code to Start the alarm in my application.
public static void startReferAlarm(Context context,String[] message,String activityToOpen)
{
try {
Log.d("Refer friend Activity", "Alarm On");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
Intent myIntent = new Intent(context, AlarmReciever.class);
myIntent.putExtra("message",message);
myIntent.putExtra("äctivityName",activityToOpen);
final int _id = (int) System.currentTimeMillis();
PendingIntent appIntent = PendingIntent.getBroadcast(context, _id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//48*60*60*1000
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
48*60*60*1000, appIntent);
}catch (Exception e) {
Log.d("MyActivity", "Alarm Off");
e.printStackTrace();
}
}
From my understating above code will start the alarm and will notify on 8 am. and then will repeat after 48 hours.
But I want to start the alarm after 48 hours or lets say after 7 hours and then it repeat after every 48 hours.
Please help me with the logic.Thanks in advance.
Do not use calender.set(Calendar.HOUR, 8) as it will set hours to 8'o clock
Try
//if you want to add 7 hours
calender.add(Calender.HOUR, 7); //this will add 7 hours to current time
//if you want to add 7 days
calender.add(Calender.DAY_OF_MONTH, 7); //this will add 7 days to current time
// interval to repeat alarm after 48hours
int interval = 48 * 60 * 60 * 1000;
Replace Calendar.HOUR with Calendar.HOUR_OF_THE_DAY if you want to use it in 24hours format.
See the answer for repeating alarm issue How to repeat alarm in android 6.0
For any one who is still confuse. Below method will initiate the alarm after 7 days of any particular action it will notify on 9 am and will repeat after 48 hours.
public static void startCreateProfileAlarm(Context context,AlarmManager alarmManager ,String[] message,String activityToOpen) {
try {
//working code
Calendar calendar = Calendar.getInstance();
calendar.add(DAY_OF_MONTH,7);
//calendar.add(Calendar.HOUR_OF_DAY,1);
calendar.set(Calendar.HOUR_OF_DAY, 9);
// we can set any time here
//calendar.set(Calendar.HOUR_OF_DAY, 10);
Intent myIntent = new Intent(context, AlarmReciever.class);
myIntent.putExtra("message",message);
myIntent.putExtra("äctivityName",activityToOpen);
final int _id = (int) System.currentTimeMillis();
createProfileAppIntent = PendingIntent.getBroadcast(context, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//48*60*60*1000
//2*60*1000
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
48*60*60*1000, createProfileAppIntent);
}catch (Exception e) {
Log.d("MyActivity", "Alarm Off");
e.printStackTrace();
}
}

Scheduling multiple future notifications

I am currently debugging an issue with notifications inside my application. For some context, what I'd like to do is schedule notifications that should popup whenever a rocket launch is occurring. What I was doing was, after getting a list of scheduled launches from an API, I would take the launch date (in milliseconds since Jan 1 1970) and subtract the System.currentTimeMillis() from it. I would then use the resulting time to schedule the notification in the future, represented as System.currentTimeMillis() + timeDifference. I noticed that for whatever reason, only 1 notification is ever displayed.
I've tried debugging by scheduling notifications at 2, 4, and 6 minutes in the future, however a notification is only displayed at the 6 minute mark.
Some relevant code is below:
public void scheduleNotifications(List<Launch> launches) {
for(int i = 0; i < launches.size(); i++) {
SimpleDateFormat format = new SimpleDateFormat("MMMM dd, yyyy HH:mm:ss z");
Date date = null;
try {
date = format.parse(launches.get(i).getWindowstart());
} catch (ParseException e) {
e.printStackTrace();
}
long timeBetween = date.getTime() - System.currentTimeMillis();
Integer id = Long.valueOf(date.getTime()).intValue();
Intent notificationIntent = new Intent(this, NotificationPublisher.class);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID, id);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION, getNotification(launches.get(i).getRocket().getName(), launches.get(i).getLocation().getPads().get(0).getName()));
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//Debug. Schedule at 2, 4, 6 minutes.
if (i == 0) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 120000, pendingIntent);
}
if (i == 1) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 240000, pendingIntent);
}
if (i == 2) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 360000, pendingIntent);
}
}
}
private Notification getNotification(String rocketName, String padName) {
Notification.Builder builder = new Notification.Builder(this);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
builder.setContentIntent(pendingIntent);
builder.setContentTitle("Upcoming Launch");
builder.setContentText("A launch of a " + rocketName + " is about to occur at " + padName + ". Click for more info.");
builder.setSmallIcon(R.drawable.rocket_icon);
return builder.build();
}
Broadcast Receiver:
public class NotificationPublisher extends BroadcastReceiver {
public static String NOTIFICATION_ID = "notification_id";
public static String NOTIFICATION = "notification";
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = intent.getParcelableExtra(NOTIFICATION);
int id = intent.getIntExtra(NOTIFICATION_ID, 0);
notificationManager.notify(id, notification);
}
}
I'd like to know why only a single notification is ever presented, as well as what I need to add to achieve the previously stated goal.
When you set an alarm using AlarmManager, it automatically cancels any existing alarm that has a matching PendingIntent. Since all your PendingIntents contain the same components, every time you set an alarm, the previously set ones are automatically cancelled.
If you want to set multiple alarms, you must make sure that each of the PendingIntents is unique. You can do this in one of the following ways:
Use a different requestCode (second parameter to PendingIntent.getBroadcast()) for each PendingIntent
Use a different ACTION in the Intent you pass to PendingIntent.getBroadcast() for each PendingIntent

How to fire off activity when myTime matches with android System time?

I am trying to achieve a task. Here is what's happening. I first save a value in the shared preference in a string from first activity and pass that value to this activity below. Then in my second activity, I call that value. Then I take the current time of the android and convert it to string.
=====================================================
#Lazy Ninja: UPDATED PLEASE CHECK: okay. I got the timings to match Finally! Now just one last thing, how do I keep running this "if statement" in the background so even if the app is closed, the system keeps checking for those two values?
=====================================================
UPDATED CODE:
Intent in = new Intent(Alarm.this, FajrAlarmRecieverActivity.class);
PendingIntent pi = PendingIntent.getActivity(Alarm.this, 2, in, PendingIntent.FLAG_CANCEL_CURRENT);
/*My Time from Shared Preference*/
//SharedPreferences prfs = getSharedPreferences("customeAlarmTimes", Context.MODE_PRIVATE);
//myTime = prfs.getString("Isha", "Isha");
String myTime = "11:15";
SimpleDateFormat formatter = new SimpleDateFormat("K:mm");
Date date = formatter.parse(myTime); // You will need try/catch around this
long millis = date.getTime();
/*My Time from Shared Preference*/
/*System Time*/
Date today = Calendar.getInstance().getTime();
String reportDate = new SimpleDateFormat("K:mm").format(today);
Date swag = formatter.parse(reportDate);
long currentTime= swag.getTime();
Log.d("SystemTime", reportDate);
Log.d("MyTime", myTime);
Log.d("SystemTime in Millis", currentTime+"");
Log.d("MyTime in Millis", millis+"");
if(millis == currentTime){
SendNotification();
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, AlarmManager.INTERVAL_DAY, pi);
}
else if (millis > currentTime){
Toast mtoast = Toast.makeText(getApplicationContext(), "FAJR TIME > CURRENT TIME", Toast.LENGTH_LONG);
mtoast.show();
}
else if (millis < currentTime){
Toast mtoast = Toast.makeText(getApplicationContext(), "FAJR TIME < CURRENT TIME", Toast.LENGTH_LONG);
mtoast.show();
}
}
}
Use repeating Alarm. It will handle the conditions for you
Try the following
Intent i = new Intent(getApplicationContext(), FajrAlarmRecieverActivity.class);
PendingIntent sender = PendingIntent.getActivity(Alarm.this, 0, i, 0);
// Get Time from your sharedpreferences
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour); // set Fajr hour
calendar.set(Calendar.MINUTE, minute); // set Fajr minute
calendar.set(Calendar.SECOND, 0); // set seconds ( well no need for seconds)
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
Dont forget to add FajrAlarmRecieverActivity in your manifest file.
After reading your comment just use set.
After the alarm fires, read from sharedPreferences and and set the alarm again.
EDIT
To get Current time
long currentTime= System.currentTimeMillis();
Get Time from your sharedPrefs, and convert it to milliseconds
if( sharedTimeInMillis < currentTime ){
// your good stuff
}
Convert your String time to milliseconds
myTime = prfs.getString("Isha", "Isha");
SimpleDateFormat formatter = new SimpleDateFormat("K:mm");
Date date = formatter.parse(myTime ); // You will need try/catch around this
long millis = date.getTime();

Categories

Resources