chronometer in home screen widget - wrong count down format - android

I have home screen widget which have one chronometer as RemoteViews item.
I need this chronometer to countdown from some time in the future. Chronometer works, but I have noticed some strange time formatings on some devices.
For example, if there is 10 minutes and 5 seconds remaining, I have following outputs:
Huawei Mate 10 Lite (Android Oreo - API 26)
-10:05
Huawei G7, with Lollipop (API 22)
00:-605 - total remaining time here is displayed as number of seconds.
My question: is there any way that I can provide my formating, so that result be same on all devices.
NOTE: I need this for chronometer in homescreen widget, not inside of an activity or a fragment.
Edit: Widget is refreshed from AlarmManager. On BroadcastReceiver I have following code to update widget.
protected void updateCountdownTimer(RemoteViews remoteViews, int index) {
Calendar calendar = Calendar.getInstance();
List<Time> timeList;
if (index == -1) {
calendar.add(Calendar.DATE, 1);
TimesProvider.getProvider().setCurrentDate(calendar);
index = 0;
}
timeList = TimesProvider.getProvider().getTimes();
Time time = timeList.get(index);
calendar.set(Calendar.HOUR_OF_DAY, time.getHour());
calendar.set(Calendar.MINUTE, time.getMinute());
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
remoteViews.setChronometer(R.id.chronometer, SystemClock.elapsedRealtime() + calendar.getTimeInMillis() - System.currentTimeMillis(), null, true);
remoteViews.setTextColor(R.id.chronometer, Color.CYAN);
}

Related

AlarmManager time not being set correctly

I am developing an app where I use an AlarmManager to schedule a time to open an Activity.
The chosen time is picked by a TimePicker.
Despite the time being the expected one when I call the method when.getTime , my activity doesn't open at the specified time.
Getting the time
int hour = tp.getCurrentHour();
int min = tp.getCurrentMinute();
MedicationReminder mr = new MedicationReminder(getApplicationContext());
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR, hour);
c.set(Calendar.MINUTE, min);
if (hour > 12) {
c.add(Calendar.HOUR, 12);
}
mr.setReminder(new Medication(name, quant_aux, time), c);
Setting alarm
Intent i = new Intent(mContext, MedicationReceiver.class);
i.putExtra("medName",medication.getName());
i.putExtra("medQuant",medication.getQuantity());
PendingIntent pi=PendingIntent.getBroadcast(mContext,0,i,0);
mAlarmManager.set(AlarmManager.RTC_WAKEUP,when.getTimeInMillis(),pi);
I tried replacing when.getTimeInMillis by 2000 and the activity opened , so the problem is not on my broadcast receiver.
Why is this happening?
Edit: I tried to schedule for the following minute and the acitivity opened.
I tried for the next 2 minutes and the activity opened with a delay of 12-15 seconds. Tried with 5 minutes and the activity didn't open
Try using setExact instead of set
...
mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), pi);
https://developer.android.com/training/scheduling/alarms

Android multiple alarms not working

public static boolean setupAlarm(String flightName, long columnId, int time,int requestCode, Context context) {
AlarmManager alarmManager;
FlightTimeObject timeObject = DataCheckingUtils.getConvertedTime(time);
try {
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context.getApplicationContext(), ProcessAlarmReceiver.class);
intent.putExtra(IntentActions.INTENT_REQUEST_CODE, requestCode);
intent.putExtra(IntentActions.INTENT_SEND_STRING_FLIGHT, flightName);
intent.putExtra(IntentActions.INTENT_SEND_FLIGHT_COLUMN_ID, columnId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent,0);
//Get calendar instance
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
//get hour
if (timeObject.getHour()!= -1) {
int hour = timeObject.getHour();
calendar.set(Calendar.HOUR_OF_DAY, hour);
}
//get minute
if (timeObject.getMinute()!=-1){
int minute = timeObject.getMinute();
calendar.set(Calendar.MINUTE, minute);
}
calendar.set(Calendar.SECOND, 0);
assert alarmManager != null;
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
pendingIntent);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
Hello everyone. The above code gets called within a for loop, underneath.
private static void setupAlarmToFlight(ArrayList<FlightObject> flightArray, Context context) {
int numberOfAlarms = 0;
int requestCode = 0;
for (int i = 0; i < flightArray.size(); i++){
FlightObject flight = flightArray.get(i);
String name = flight.getFlightName();
long flightColumnId = flight.getColumnId();
int flightActualTime = flight.getActualArrivalTime();
int scheduledTime = flight.getFlightScheduledTime();
int timeToParse = -2;
if (flightActualTime == -2){
timeToParse = scheduledTime;
}else{
timeToParse = flightActualTime;
}
boolean alarmSet = ExtractFlightUtilities.setupAlarm(
name,
flightColumnId,
timeToParse,
requestCode,
context);
if (alarmSet){
numberOfAlarms++;
requestCode++;
}
}
Intent intent = new Intent(IntentActions.ALARM_SET);
intent.putExtra(IntentActions.INTENT_SEND_INT, numberOfAlarms);
context.sendBroadcast(intent);
}
This code basically sets alarms for different flight arrival times from an arraylist that will start a service. The first alarm always fires right on time, but the rest never fire. I even stopped the service so it would just get to the receiver, but only the first fires. I also stopped the for loop at 2-3 alarms, but nothing.
I made sure that the hours and minutes are set correctly, and used another loop that would just set alarm in one minute after each but no luck.
Any help would be greatly appreciated.
EDITED:
I tried the suggestion and still not firing the alarms.
Something interesting I noticed, when setting breakpoints, the debugger gives preview values, and the first alarm that goes off okay, it's values, such as the requestCode and the Calendar values are green. All other following alarms are red.
For the first alarm.
The request code is green.
The pending intent looks all green.
The calendar value looks all green.
For all the other alarms.
The request code is red.
The pending intent request code red:
The calendar value is red
Again thank you for your time.
Since you set exact time, it might be because you did not check if the alarm time set is not passed already. E.g. consider the current date/time is 1-Jan-2018 11:30PM. If you set alarm for 01:00AM, based on your code, the alarm will be set for 1-Jan-2018 01:00AM since you used:
calendar.setTimeInMillis(System.currentTimeMillis())
which returns 1-Jan-2018 11:30PM and the you set time to 01:00AM which change the date to 1-Jan-2018 01:00AM which is passed. In this case you should add to alarm date one day. Something like this:
/**
* adjust time and date of alarm (alarms set in some previous years, will updated to today).
* if time is passed in today, date will +1
*
* #param alarmTimeCalendar time which may need adjustments
* #return adjusted time for alarm
*/
public static Calendar adjustAlarmTime(Calendar alarmTimeCalendar) {
Calendar adjustedDateCalendar = Calendar.getInstance();
int hour = alarmTimeCalendar.get(Calendar.HOUR_OF_DAY);
int minute = alarmTimeCalendar.get(Calendar.MINUTE);
adjustedDateCalendar.set(Calendar.HOUR_OF_DAY, hour);
adjustedDateCalendar.set(Calendar.MINUTE, minute);
adjustedDateCalendar.set(Calendar.SECOND, 0);
Date currentDate = adjustedDateCalendar.getTime();
Date alarmDate = adjustedDateCalendar.getTime();
long difference = alarmDate.getTime() - currentDate.getTime();
if (difference < 0) {
adjustedDateCalendar.add(Calendar.DATE, 1);
}
return adjustedDateCalendar;
}
So after trying multiple ways of approaching the problem, I solved it by setting the alarm as only RTC and not RTC_WAKEUP. Now all the alarms are firing right on time.
Thank you all.

Understanding My AlarmManager Logic

I need help in understanding the logic that I have implemented in my app using AlarmManager, since the logic is not working as I expected. I am new to Android development and a self-learner.
The Logic :
User selects a time in Main Activity using a button.
That time value is used for setting repeating alarm in Another activity.
When the alarm goes of A dialog box appears.
Main Activity:
static long ATfrom_to_millisec;
case R.id.ATfrom:
final Calendar ATfromC = Calendar.getInstance();
ATfromHour = ATfromC.get(Calendar.HOUR_OF_DAY);
ATfromMinute = ATfromC.get(Calendar.MINUTE);
// Launch Time Picker Dialog
TimePickerDialog ATfromtpd = new TimePickerDialog(MainActivity.this,
new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
//Converting to milli seconds to use in AlarmManager
ATfrom_to_millisec = ((hourOfDay * 60 * 60 * 1000) + (minute * 60 * 1000));
String AM_PM;
if (hourOfDay < 12) {
AM_PM = "AM";
} else {
AM_PM = "PM";
if (hourOfDay > 12) {
hourOfDay = hourOfDay - 12;
}
}
if (minute < 10) {
ATfrom.setText(hourOfDay + ":0" + minute + " " + AM_PM);
} else {
ATfrom.setText(hourOfDay + ":" + minute + " " + AM_PM);
}
In the above logic the time selected by the user is converted to milliseconds and stored in a public static variable so that it can be used by other activities.
Alarm Activity :
public void onClick(View arg0) {
// TODO Auto-generated method stub
switch (arg0.getId()){
case R.id.bReminder:
try {
//Receiving the static variable's value from MainActivity
long AT_from = MainActivity.ATfrom_to_millisec;
float cov = (float)(AT_from/1000/60/60);
//Toast to check if the time value is passed correctly
toast.makeText(getApplicationContext(), String.valueOf(cov), toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, Notifier.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this.getApplicationContext(),
12345, intent, 0);
//Logic for Repeating Alarm that uses the time value from MainActivty as starting time and repeating it every 10 seconds.
// i.e. the alarm should go off after 10 seconds from the use selected time and repeat after 10 seconds.
AlarmManager am =
(AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, AT_from + (10*1000), 10*1000, pendingIntent);
} catch (Exception e) {}
break;
case R.id.bReminderStop:
AlarmManager am =
(AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am.cancel(pendingIntent);
break;
}
}
When alarm is set with the above implemented logic , The alarm goes of immediately once it is set and repeats with an interval of 1 minute.
But I implemented my logic expecting the alarm to go of 10 seconds from the time set by user and repeat after every 10 seconds
I am not able to understand the mistake implemented in my logic.
Also in the toast I am not getting the decimal value of float cov
(eg : 11:30 PM must be displayed as 23.5 .But it is displayed as 23.0)
Dialog Activity when Alarm goes off :
public class Notifier extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("HydrateTime");
alertDialogBuilder.setMessage("Enter the amount of water");
alertDialogBuilder.setPositiveButton("Update", null);
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
I want the above Activity to be invoked when the Alarm goes off. Is the above implemented logic enough to make a Dialog window appear when an activity goes of?
Note : I am using a general activity definition in the Android Manifest.
like :
<activity
android:name=".Notifier"
android:label="#string/app_name">
</activity
Kindly request answers for the below questions :
Am I passing the time value set in the MainActivity to the AlarmManager in another activity correctly?
What is the mistake in my Alarm logic and how to rectify it such that the alarm goes of as per my requirement?
Is the definition for the dialog box correct? should there any more definitions in Manifest? should I create any layout file for the dialog activity? Should I extend my Notifier class with Dialog class instead of Activity class?
The logic has a minor flaw. You see, with alarms if the time to fire has already passed, then the alarm will fire immediately. For eg: if I set an alarm with milli seconds for 2 Jan 1983, it would fire immediately. If you notice, you are doing something similar.
To fix it, simply add this in your Alarm Activity:
// Will trigger after 10 secs from set time
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + AT_from + (10*1000), 10*1000, pendingIntent);
I am not sure what is causing the interval problem though. It seems fine to me.

MonoDroid - Daily scheduled service using alarm manager?

I am trying to schedule a service to run daily at a user specified time. I am using a timepicker to give the user control over what time of day the service is run.
Each time the user changes the time of day for the service to run I am updating the alarm manager.
Here is my code to do this:
void RescheduleOpeningRatesRetriever (string strTime)
{
var i = new Intent (this.ApplicationContext, typeof (OpenRatesService));
var src = PendingIntent.GetService (this.ApplicationContext, 0, i, PendingIntentFlags.UpdateCurrent);
var am = (AlarmManager)this.ApplicationContext.GetSystemService (Context.AlarmService);
var hour = TimePickerPreference.GetHour (strTime);
var minute = TimePickerPreference.GetMinute (strTime);
var cal = Java.Util.Calendar.GetInstance (Java.Util.TimeZone.Default);
cal.Set (Java.Util.CalendarField.HourOfDay, hour);
cal.Set (Java.Util.CalendarField.Minute, minute);
am.SetRepeating (AlarmType.RtcWakeup, cal.TimeInMillis, AlarmManager.IntervalDay, src);
}
I am not 100% sure if the code is scheduling the service to run properly as I have had mixed results from my tests.
The problem that I am experiencing now is each time I re-schedule the service to run with the above code, the service is started instantly.... I don't want to start the service until the configured time of day.
How can I schedule and update the service to run at a specified time of day without running the service instantly upon scheduling it with the alarm manager?
If the time for which you are setting the alarm is in the past then the alarm will goes off instantly. so first check whether the time is in past, if it is then set it for next day.
like::
Calendar rightNow = Calendar.getInstance()
if( cal.after( rightNow ) )
{
am.SetRepeating (AlarmType.RtcWakeup, cal.TimeInMillis, AlarmManager.IntervalDay, src);
}
else
{
cal.roll(Java.Util.CalendarField.DAY_OF_MONTH, 1);
SetRepeating (AlarmType.RtcWakeup, cal.TimeInMillis, AlarmManager.IntervalDay, src);
}

Time in Milliseconds Alarm

Okay, So I'm working on having an alarm that gives a notification at, lets say 3:00 PM daily, but I want this to be selectable by the user, between AM/PM, and Hours/Min freely changeable. I will probably use a TimePicker, and this is my code I have so far:
public void startAlarm() {
Intent intent = new Intent(currentDay.this, AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(currentDay.this,0, intent,0);
long firstTime = SystemClock.elapsedRealtime();
firstTime += 15*1000;
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,firstTime,AlarmManager.INTERVAL_DAY, sender);
}
So, I figure I'm going to be using something along the lines of:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 19);
cal.set(Calendar.MINUTE, 45);
and then using
cal.getTimeInMillis()
But this doesn't work, any ideas? Thanks!
EDIT: So, long story short, I know how to get the current time, then add lets say 15 seconds to it, but I want to have a definite time that WORKS for example 5:14 PM, and everything I've tried doesn't work
As far as I can tell you are getting a Calendar instance with the current date/time and then you are adding 19 hours and 45 minutes to it, NOT setting the time of the Calendar instance explicitly to 19:45. Is that what you are meaning to do? You need to use the Calendar set() method to set an explicit time.
From the API reference for Calendar
Calendar's getInstance method returns a calendar whose locale is based on system settings and whose time fields have been initialized with the current date and time:
Calendar rightNow = Calendar.getInstance()
public abstract void add (int field, int value)
Since: API Level 1
Adds the specified amount to a Calendar field.
Parameters
field the Calendar field to modify.
value the amount to add to the field.
Throws IllegalArgumentException if field is DST_OFFSET or ZONE_OFFSET.
EDIT: To convert local time to UTC...
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 19);
cal.set(Calendar.MINUTE, 45);
int offset = cal.getTimeZone().getOffset(cal.getTimeInMillis());
firstTime = cal.getTimeInMillis() + offset;
NOTE: I haven't tried the above and there may be an easier way but it should work. It's hard for me to test stuff like this as my timezone is GMT/UTC.

Categories

Resources