Activity and a Service in same android application - android

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

Related

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

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

AlarmManager - How to set a Notification to appear annually

I want an notification to appear each year depending on the date entered (Birthday). I have everything else working bar how to set a notification annually. As you can see below I have changed the code to say "HERE" where the intervals go. There are intervals for days and I know I could multiply that by 365. But what happens if its a leap year..
int REQUEST_CODE = 7;
Intent intent = new Intent(Activity2.this, Receiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(Activity2.this, REQUEST_CODE, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(am.RTC_WAKEUP, System.currentTimeMillis(), HERE, pendingIntent);
You could replace 'HERE' with a method that determines if the following February from today is in a leap year, and then returns the value 365 or 366 days (in the form of milliseconds mind you) based on those checks.
private long millisUntilNextYear(){
//Set days in a year for Leap and Regular
final int daysInLeapYear = 366;
final int daysInYear = 365;
//Get calendar instance
GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
//Get this year and next year
int thisYear = cal.get(GregorianCalendar.YEAR);
int nextYear = thisYear + 1;
//Get today's month
int thisMonth = cal.get(GregorianCalendar.MONTH);
//Get today's date
int dayOfMonth = cal.get(GregorianCalendar.DAY_OF_MONTH);
//Is today before February? If so then the following February is in THIS year
if (thisMonth < GregorianCalendar.FEBRUARY){
//Check if THIS year is leapYear, and return correct days (converted to millis)
return cal.isLeapYear(thisYear) ? daysToMillis(daysInLeapYear) : daysToMillis(daysInYear);
}
//Is today after February? If so then the following February is NEXT year
else if (thisMonth > GregorianCalendar.FEBRUARY) {
//Check if NEXT year is leapYear, and return correct days (converted to millis)
return cal.isLeapYear(nextYear) ? daysToMillis(daysInLeapYear) : daysToMillis(daysInYear);
}
//Then today must be February.
else {
//Special case: today is February 29
if (dayOfMonth == 29){
return daysToMillis(daysInYear);
} else {
//Check if THIS year is leapYear, and return correct days (converted to millis)
return cal.isLeapYear(thisYear) ? daysToMillis(daysInLeapYear) : daysToMillis(daysInYear);
}
}
}
1) save dates in MM/DD/YY formats.
2) read these dates when you open your app(or at different times)
3) set alerts for single day/today it self.
Plus you can also show birthdays coming in next week/month etc.

Change DateFormat depending on Days passsed

Essentially what I have is a string which contains a files Last Modified Date. To get this I'm using:
Date lastModDate = new Date(file.lastModified());
SimpleDateFormat formatter = new SimpleDateFormat("K:mm a");
String formattedDateString = formatter.format(lastModDate);
The end result is somewhat like 6:12 AM. What I want to do is each time a certain period of time is passed, the dateformat must change. E.g.
After 1 Day has gone by, Last Modified Date = ("Format1");
After a Week has gone by, Last Modified Date = ("Format2");
After 2 Weeks have gone by, Last Modified Date = ("Format3");
Does it make sense? If so is someone please be able to show me how it's done. A good example is the native Messaging App. When a message is created, It will show it's Time then after some days gone by the format changes to the Date it was created then the month etc...
I'm trying to do exactly that.
Calculate the difference in time between the last modified date and now:
long duration = lastModDate.getTimeInMillis() - current.getTimeInMillis();
long sec = TimeUnit.MILLISECONDS.toSeconds(duration);
boolean inFuture = sec > 0;
// Use positive value
if(!inFuture)
sec = -sec;
long minutes = sec / 60 % 60;
long hours = sec / 3600 % 24;
long days = sec / 86400;
if(days > 1 && days < 7)
// Use format 1
else if(days >= 7 && days < 14)
// Use format 2
else
// Use format 3

Scheduling a task for certain days of the week in Android

As the title implies, I'm looking to schedule a task to run on certain days at certain times. For example, I might have it run at 5:00 every Tuesday and Thursday. I've seen several scheduling methods for Android, but all of them seem to operate in the form of "do task after n delay" or "do task every n seconds".
Now I could probably jury-rig it by having it calculate the time to the next execution during the execution of the task itself, but that seems inelegant. Is there some better way to do this?
You've to set an Alarm to perform those tasks. Most probably you will end up calling a Service once the alarm is triggered:
private void setAlarmToCheckUpdates() {
Calendar calendar = Calendar.getInstance();
if (calendar.get(Calendar.HOUR_OF_DAY)<22){
calendar.set(Calendar.HOUR_OF_DAY, 22);
} else {
calendar.add(Calendar.DAY_OF_YEAR, 1);//tomorrow
calendar.set(Calendar.HOUR_OF_DAY, 22); //22.00
}
Intent myIntent = new Intent(this.getApplicationContext(), ReceiverCheckUpdates.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, myIntent,0);
AlarmManager alarmManager = (AlarmManager)this.getApplicationContext().getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
However, if you need to set specifically a day:
int weekday = calendar.get(Calendar.DAY_OF_WEEK);
if (weekday!=Calendar.THURSDAY){//if we're not in thursday
//we calculate how many days till thursday
//days = The limit of the week (its saturday) minus the actual day of the week, plus how many days till desired day (5: sunday, mon, tue, wed, thur). Modulus of it.
int days = (Calendar.SATURDAY - weekday + 5) % 7;
calendar.add(Calendar.DAY_OF_YEAR, days);
}
//now we just set hour to 22.00 and done.
Above code is a little bit tricky and mathematic. If you wan't something stupid aswell as easy:
//dayOfWeekToSet is a constant from the Calendar class
//c is the calendar instance
public static void SetToNextDayOfWeek(int dayOfWeekToSet, Calendar c){
int currentDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
//add 1 day to the current day until we get to the day we want
while(currentDayOfWeek != dayOfWeekToSet){
c.add(Calendar.DAY_OF_WEEK, 1);
currentDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
}
}

Android Get Current Date (with time being 0:00:000) in Milliseconds?

I would like to get the current date with the time zeroed out in milliseconds.
Example, if it's 12:69pm today, I want to get the time in milliseconds for today's date with no time...meaning, the time just after midnight (one millisecond or 0 if that works).
I was using the Calendar object but can't seem to figure out how to zero out the time portion.
Here is how to zero the time of a calendar:
Calendar today = Calendar.getInstance();
today.set(Calendar.MILLISECOND, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.HOUR_OF_DAY, 0);
And without calendar:
long d = new Date().getTime();
int offset = TimeZone.getDefault().getOffset(d);
d = ((d + offset)/ 86400000l) * 86400000l - offset;

Categories

Resources