Android Calendar.getInstance() does not get today after midnight - android

I have the following code:
Calendar nextSchedule = Calendar.getInstance();
nextSchedule.set(Calendar.HOUR_OF_DAY, 0);
nextSchedule.set(Calendar.MINUTE, 0);
nextSchedule.set(Calendar.SECOND, 10);
nextSchedule.set(Calendar.MILLISECOND, 0);
nextSchedule.add(Calendar.DAY_OF_YEAR, 1);
Calendar cal = Calendar.getInstance();
long diff = nextSchedule.getTimeInMillis() - cal.getTimeInMillis();
long seconds = diff / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
As expected, around 11am it gave me 13/12hours but when doing the following in a widget:
Calendar nextSchedule = Calendar.getInstance();
nextSchedule.set(Calendar.HOUR_OF_DAY, 0);
nextSchedule.set(Calendar.MINUTE, 0);
nextSchedule.set(Calendar.SECOND, 10);
nextSchedule.set(Calendar.MILLISECOND, 0);
nextSchedule.add(Calendar.DAY_OF_YEAR, 1);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextSchedule.getTimeInMillis(), pendingIntent);
Around 1:30am, it was still not updated. Only somewhen between 2am and 9am (I was asleep) it got updated.
A similar strange thing happens elsewhere. I have a calendar view (applandeo) with the following code: cvCalendar.setOnDayClickListener(eventDay -> showDateItems(eventDay,lvCalendar));
private void showDateItems(EventDay eventDay, ListView lvCalendar) {
Calendar cal = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal.set(eventDay.getCalendar().get(Calendar.YEAR),eventDay.getCalendar().get(Calendar.MONTH),eventDay.getCalendar().get(Calendar.DATE));
cal2.set(eventDay.getCalendar().get(Calendar.YEAR),eventDay.getCalendar().get(Calendar.MONTH),1);
cal2.add(Calendar.MONTH, -1);
ArrayList<String> items = new ArrayList<>();
String line;
for (ItemsHistoryItem item: Utils.getInstance().itemsHistory) {
if (item.getxDay() < Utils.getInstance().calenderToEpoch(cal2) && item.getyDay() < Utils.getInstance().calenderToEpoch(cal2)) break;
if (item.getxDay() != Utils.getInstance().calenderToEpoch(cal) && item.getyDay() != Utils.getInstance().calenderToEpoch(cal)) continue;
line = item.getItemId() + ": $" + item.getAmount();
if (item.getxDay() == Utils.getInstance().calenderToEpoch(cal))
line += " (x day)";
else
line += " (y day)";
items.add(line);
}
ArrayAdapter<String> lcAdapter = new ArrayAdapter<>(requireActivity(), android.R.layout.simple_list_item_1, items);
lvCalendar.setAdapter(lcAdapter);
}
long calenderToEpoch(Calendar cal2) {
return TimeUnit.MILLISECONDS.toDays(cal2.getTimeInMillis());
}
Basically, the above code scans dates of items and when the user select a certain date, he gets a list of items which dates (x and y) are of that date. When doing so during the day, it works. When doing so in 1:30am (for example), it shifts one day ahead so if the user clicks on 12-oct, he gets the items of 11-oct. Somwhen between 2am and 9am it "shifts" back and works as expected.
Any idea what's wrong here?

I have a suggestion for using alarmmanager properly if you want it to fire exactly at the time you want else it does not fire on time when device is in deep sleep mode and gets delayed:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// use setAlarmClock function of AlarmManager
// but this function will show an alarm icon on statusbar
// if you dont want to show that icon you can use
// setExactAndAllowWhileIdle function but that will not be
// perfectly exact
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// use setExact function of AlarmManager
}
else {
// use set function of AlarmManager
}

Apparently the default timezone for Calendar.getInstance() in my case was GMT+3 so at 3am the items were shown for their dates and the widget was updated. to fix it, I simply did the following:
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));

Related

queryUsageStats interval duration

I'm using UsageStatsManager API to get usage statistics for a certain time interval. All works fine if I use the predefined intervals i.e. INTERVAL_DAILY, INTERVAL_WEEKLY, INTERVAL_MONTHLY, INTERVAL_YEARLY. But if I want to view the data for the past 2 or 3 hours, I am getting today's data for the whole day. I have tried using Calendars and System.currentTimeMillis() but that didn't give me filtered results.
Calendar approach :
Calendar startCalendar = Calendar.getInstance();
startCalendar.add(Calendar.HOUR_OF_DAY, -2);
Calendar endCalendar = Calendar.getInstance();
And pass this to queryUsageStats method like this:
usageList = usm.queryUsageStats(interval, startCalendar.getTimeInMillis(), endCalendar.getTimeInMillis());
where interval is INTERVAL_BEST.
System.currentTimeMillis() approach :
long startTime = System.currentTimeMillis() - 7200*1000 // 7200 seconds i.e. 2 hrs
long endTime = System.currentTimeMillis();
Pass this to queryUsageStats just like above :
usageList = usm.queryUsageStats(interval, startTime, endTime);
where interval is again INTERVAL_BEST.
I'd like to know whether it's possible to get data for this duration i.e. less than a day, as the INTERVAL_BEST hasn't been documented properly to include this information. Any help would be appreciated as I'm stuck on this problem.
As UsageStatsManager doc says:
A request for data in the middle of a time interval will include that interval.
It seems that usage data is stored in buckets, and minimum bucket is a day, so you can't query usage stats for period less than a day. Even if you query a one-hour interval for a particular day, usage stats for the whole day is returned.
A little late to the party, but I think this might be useful to some.
You could use the queryEvents(long startTime, long endTime) from UsageStatsManager for achieving the desired result. The method could look like this (inspired by this post):
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public HashMap<String, AppUsageInfo> queryUsageStatistics(Context context, long startTime, long endTime) {
UsageEvents.Event currentEvent;
List<UsageEvents.Event> allEvents = new ArrayList<>();
HashMap<String, AppUsageInfo> map = new HashMap<>();
UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
assert mUsageStatsManager != null;
// Here we query the events from startTime till endTime.
UsageEvents usageEvents = mUsageStatsManager.queryEvents(startTime, endTime);
// go over all events.
while (usageEvents.hasNextEvent()) {
currentEvent = new UsageEvents.Event();
usageEvents.getNextEvent(currentEvent);
String packageName = currentEvent.getPackageName();
if (currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED || currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED ||
currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_STOPPED) {
allEvents.add(currentEvent); // an extra event is found, add to all events list.
// taking it into a collection to access by package name
if (!map.containsKey(packageName)) {
map.put(packageName, new AppUsageInfo());
}
}
}
// iterate through all events.
for (int i = 0; i < allEvents.size() - 1; i++) {
UsageEvents.Event event0 = allEvents.get(i);
UsageEvents.Event event1 = allEvents.get(i + 1);
//for launchCount of apps in time range
if (!event0.getPackageName().equals(event1.getPackageName()) && event1.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED) {
// if true, E1 (launch event of an app) app launched
Objects.requireNonNull(map.get(event1.getPackageName())).launchCount++;
}
//for UsageTime of apps in time range
if (event0.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED &&
(event1.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED || event1.getEventType() == UsageEvents.Event.ACTIVITY_STOPPED)
&& event0.getPackageName().equals(event1.getPackageName())) {
long diff = event1.getTimeStamp() - event0.getTimeStamp();
Objects.requireNonNull(map.get(event0.getPackageName())).timeInForeground += diff;
}
}
// and return the map.
return map;
}
The AppUsageInfo class would be:
public class AppUsageInfo {
public long timeInForeground;
public int launchCount;
AppUsageInfo() {
this.timeInForeground = 0;
this.launchCount = 0;
}
}
To then get the usage stats for the last two hours, simply call
Calendar startCalendar = Calendar.getInstance();
startCalendar.add(Calendar.HOUR_OF_DAY, -2);
Calendar endCalendar = Calendar.getInstance();
HashMap<String, AppUsageInfo> result = queryUsageStatistics(context, startCalendar.getTimeInMillis(), endCalendar.getTimeInMillis();

Calculating the trigger time for an alarm when today set time passed in android?

In my Alarm application i have the following function for calculating the trigger time for the alarm , and its working perfect if the alarm time > current time , but if the alarm time is passed " Today Set time passed" current time > alarm time the alarm should fires tomorrow but in my function it fires in the same day after a few hours or minutes based on the difference amount . How can i fix this problem? what is the condition i should add to my function to wait 24 hours to tomorrow if the alarm set time is passed ? please help me
private long getTriggerTime(int hour,int minute)
{
long triggerTime = System.currentTimeMillis() ;
Calendar calendarNow = Calendar.getInstance();
int currentHour = calendarNow.get(Calendar.HOUR_OF_DAY);
int currentMinute = calendarNow.get(Calendar.MINUTE);
int HourDifference = currentHour-hour;
int MinuteDifference = currentMinute -minute;
if(HourDifference < 0 ){ HourDifference = HourDifference*(-1); }
if(MinuteDifference < 0){ MinuteDifference = MinuteDifference*(-1); }
triggerTime = triggerTime + ( HourDifference*60*60*1000) + (MinuteDifference*60*1000 );
return triggerTime;
}
Here how i use this function
am.setRepeating(AlarmManager.RTC_WAKEUP, getTriggerTime(hour,min),AlarmManager.INTERVAL_DAY ,sender);
Note : hour , min in 24hour format
here is the sample code for alarm to fire if the alarm time > current time ,else it will for 24 hours.....
private long getAlarmTimeInMillis(int hour,int minute){
Calendar calendar=Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);//
calendar.set(Calendar.SECOND, 0);
if (calendar.getTimeInMillis() < System
.currentTimeMillis()) {
calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH)+ 1);
// add 24 hours to the calender.getTimeMillis
}
return calendar.getTimeInMillis();
}
try this.....
Use this:
Calendar calendarNow = Calendar.getInstance();
calendarNow.set(calendarNow.get(Calendar.YEAR), calendarNow.get(Calendar.MONTH),
calendarNow.get(Calendar.DAY_OF_MONTH),
calendarNow.get(Calendar.HOUR_OF_DAY),
calendarNow.get(Calendar.MINUTE), 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendarNow.getTimeInMillis(),
24 * 60 * 60 * 1000, pendingIntent);

Android: Subtract minutes to my alarm

I'm making an alarm, get the current time as follows:
public String getAlarmTimeStringFive2db() {
String timef2db = "";
if (alarmTime.get(Calendar.HOUR_OF_DAY) <= 9)
timef2db += "0";
timef2db += String.valueOf(alarmTime.get(Calendar.HOUR_OF_DAY));
timef2db += ":";
if (alarmTime.get(Calendar.MINUTE) <= 9)
timef2db += "0";
timef2db += String.valueOf(alarmTime.get(Calendar.MINUTE));
return timef2db;
}
...
public static long create(Alarm alarm) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_ALARM_ACTIVE, alarm.getAlarmActive());
cv.put(COLUMN_ALARM_TIME, alarm.getAlarmTimeStringFive2db());
...
public void setAlarmTime(String alarmTime) {
String[] timePieces = alarmTime.split(":");
Calendar newAlarmTime = Calendar.getInstance();
newAlarmTime.set(Calendar.HOUR_OF_DAY,
Integer.parseInt(timePieces[0]));
newAlarmTime.set(Calendar.MINUTE, Integer.parseInt(timePieces[1]));
newAlarmTime.set(Calendar.SECOND, 0);
setAlarmTime(newAlarmTime);
}
...
This works fine, for example returns 5:35 ... all right.
My problem is I want to subtract 5 minutes always on time. If the time is 5:35, I want the alarm time starts at 5:30.
My problem is I do not know how to subtract those 5 minutes.
I tried
Calendar.MINUTE, Integer.parseInt(timePieces[1],5)
Calendar.MINUTE, -5)
...but nothing works
I read this link
Set Alarm To Alert 5 Minutes Before a certian Time
.. but I could not apply it to my code
Can anyone tell me as subtracting 5 minutes of my alarm?
thanks in advance
Regards
I'm not sure if you are using the Calendar instance in the right way, but here is an example shows that time changes when use add -5 to the current calendar
Calendar cal = Calendar.getInstance();
System.out.println("Before :" + cal.get(Calendar.MINUTE));
cal.add(Calendar.MINUTE, -5);
System.out.println("After :" + cal.get(Calendar.MINUTE));
and the result will be something like this:
Before :37
After :32

Android - checking if time is between certain hours of the day

in my app I'm updating some stuff if the time is between certain hours of the day which the user choose. It works fine if the user chooses something like "07-21", but not with "21-07" which is over the night.
How I'm doing to check the time is I'm getting the current hour and converting it into milliseconds. Then I check if the current milli is between the chosen hours (those are also converted into milliseconds).
Like this:
if (currentMilli >= startHourMilli && currentMilli <= endHourMilli)
The problem: It doesn't work if the user chooses anything that is over midnight (19-08 for example).
I've tried a lot of stuff but I just can't figure out how to do this.
Any help is appreciated!
Do you increase the day of the year by 1 when you're passing midnight? Otherwise your
startHourMilli might be greater than endHourMilli and your if-clause will always be false.
The solution is to use the add-method of the Calendar class. Therefore I calculate the interval's length in hours and add this value to our Calendar instance.
int start = 21; // let's take your failing example: 21-07
int end = 7;
int hours = (end - start) % 24; // here hours will be 14
Calendar cal = Calendar.getInstance();
// set calendar to TODAY 21:00:00.000
cal.set(Calendar.HOUR_OF_DAY, start);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long startHourMilli = cal.getTimeInMillis();
// add 14 hours = TOMORROW 07:00:00.000
cal.add(Calendar.HOUR_OF_DAY, hours);
long endHourMilli = cal.getTimeInMillis();
Let me know if this helps :)
Simplest way to check..
val isDayTime : Boolean
get() {
val cal = Calendar.getInstance()
val hour = cal.get(Calendar.HOUR_OF_DAY)
return hour in 8..20
}
Date has the functions before and after for comparing two dates.
Hope this documentation helps you:
http://developer.android.com/reference/java/util/Date.html#after(java.util.Date)
http://developer.android.com/reference/java/util/Date.html#before(java.util.Date)
Best regards.
I'm answering my own question because I think I came up with something that might work for what I'm trying to do:
if(endHourMilli < startHourMilli){
if(currentMilli >= startHourMilli && currentMilli <= 23*3600000 || currentMilli >= 0 && currentMilli <= endHourMilli){
//Do whatever
}
}else{
if (currentMilli >= startHourMilli && currentMilli <= endHourMilli) {
//Do whatever
}
}
It should work even if endMilli is less than startMilli, or have I screwed something up here?
I know I'm a little late to the party, but recently I developed android app that needed to work within given timeframe, and since I didn't like working with Calendar I ended up using something like this:
// if start hour is later than end hour
// example: start = 21, end = 07
int startHourMilli = 21, endHourMilli = 07;
// just add one day (in your case in millis)
if (startHourMilli > endHourMilli) endHourMilli += 24 * 60 * 60 * 1000;
// now here you can check without any problems
if(currentMilli >= startHourMilli && currentMilli < endHourMilli){
// within timeframe, do stuff you need
} else {
// not in timeframe, find solution
}
Now I know that you found yourself a solution, but I think that my approach may be a little more understandable (at least to newbies that might get confused).
You can always use simple if / else for 24 hour format, without using functions or additional calculations:
For Example1: Full time period from StartHour to StopHour(stop hour include all minutes)
int StartHour = 23; //start from 23:00
int StopHour = 9; // until current hour is 9 that will include until 9:59
int CurrentHour = 2;
if (StartHour > StopHour)
{
if (CurrentHour < StartHour && StopHour < CurrentHour)
{Inside = false;}
else
{Inside = true;}
}
else
{
if (CurrentHour >= StartHour && StopHour >= CurrentHour)
{Inside = true;}
else
{Inside = false;}
}
At the end if Inside == true CurrentHour is in time range StartHour - StopHour(full stop hour)
And do something else if both equal:
if (StartHour == StopHour) {..............};
For Example2: If you want to stop at this exact StopHour hour, you need some changes:
int StartHour = 23; //start from 23:00
int StopHour = 9; // this will stop after 8:59
int CurrentHour = 2;
if (StartHour2 > StopHour2)
{
if (Hr24 < StartHour2 && StopHour2 <= Hr24)
{Quiet = false;}
else
{Quiet = true;}
}
else
{
if (Hr24 >= StartHour2 && StopHour2 > Hr24)
{Quiet = true;}
else
{Quiet = false;}
}
At the end if Inside == true CurrentHour is in time range StartHour - StopHour(exact)
I think that ottel142 is almost ok but it shoud be:
public static boolean checkIfNight() {
int start = 21;
int end = 7;
int hours = 24 - start + end;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, start);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long startHourMilli = cal.getTimeInMillis();
KLog.e(cal.getTime());
cal.add(Calendar.HOUR_OF_DAY, hours);
long endHourMilli = cal.getTimeInMillis();
long currentMilli = Calendar.getInstance().getTimeInMillis();
if (currentMilli >= startHourMilli && currentMilli <= endHourMilli)
return true;
else return false;
}

Activity and a Service in same android application

I am developing an application in which user would first be presented a simple UI with days and timings. user would select timings against each day. and click a button "Done". Now this would start alarm services to trigger on every day as per selected timings. (and will turn the bluetooth device off/on those timings). right now i am using separate service for each day (beginner's instinct). The application is working fine. Now what i want is that when the user click on the "Done" button, the application should keep running in background and when the user again click the application icon and click on the "Default" button, it should stop all the services. How can i achieve that ? Code for triggering service every sunday is as follows
time interval of 7 x days for the alarm to repeat every 7 days
long interval = 1000 * 60 * 60 * 24 * 7; // to make the alarm repeat at every 7 days
//getting values for hours, mins and AM/PM from the spinner boxes for sunday
index = sunHr.getSelectedItemPosition();
int sunHrInt = Integer.parseInt(hrList[index]);
index = spinnerSunMin.getSelectedItemPosition();
int sunMinInt = Integer.parseInt(minList[index]);
index = spinnerSunAmPm.getSelectedItemPosition();
//conversion of time to 24 hrs format
if (ampmList[index] == "AM") //(convert to 24 hr format)
{
if (sunHrInt == 12)
{
sunHrInt = 0;
}
else
{
if (sunHrInt != 12)
sunHrInt = sunHrInt + 12;
}
}
//setting current calender
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar
//setting calender for sunday
Calendar calSun = new GregorianCalendar();
calSun.add(Calendar.DAY_OF_YEAR, cur_cal.get(Calendar.DAY_OF_YEAR));
calSun.set(Calendar.HOUR_OF_DAY, sunHrInt);
calSun.set(Calendar.MINUTE,sunMinInt);
calSun.set(Calendar.SECOND, 0);
calSun.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND));
calSun.set(Calendar.DATE, cur_cal.get(Calendar.DATE));
calSun.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH));
//finding out when the sunday is to occur from today
days = 8 - calSun.get(Calendar.DAY_OF_WEEK); // how many days until Sunday
if (days >= 7)
{
days = days - 7;
}
calSun.add(Calendar.DATE, days);
//finally triggering the intent
Intent myIntentSun = new Intent(AndroidAlarmService.this, SunOffAlarmService.class);
pendingIntentSun = PendingIntent.getService(AndroidAlarmService.this, 0, myIntentSun, 0);
AlarmManager alarmManagerSun = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManagerSun.set(AlarmManager.RTC_WAKEUP, calSun.getTimeInMillis(), pendingIntentSun);
Use Preferences to store values and try it. it may help you

Categories

Resources