Does anyone have any idea how to mount a multiple alarm system using the Workmanager library?

Asked

Viewed 251 times

-2

I am developing an application that works as "Alarm" to take the medicines at the right time.

I am trying to use the "Alarmmanager" Repeating to run these alarms. However, some problems are happening:,

1 - Multiple alarms. My app allows the user to register multiple users and multiple medications. Always linking a new drug registered to an existing user. This is a problem because at each alarm triggered, one must update an internal database (Update the stock of the medicine the alarm triggered).

*Identifying each alarmManager is a problem for me. Why should the user want to stop the treatment? Or even if the stock runs out? How to identify the alarm regarding the medicine and cancel it?

In addition, multiple alarms can eventually consume a lot of battery, and the alarm Nager, so I’ve been informing myself, in the most recent versions, does not usually fire at the exact times.

My application is for API level 16 and higher and because it is a remedy, it is extremely important that alarms are triggered at the exact time.

2 - Restarting the apparatus (Reboot) One of the problems I have is when I restart my device. That’s because by doing this, all alarms are extinguished.

To try to solve this, I use a Broadcastreceiver that captures the "BOOT COMPLETED" transmission and starts a "Serviceintent" that triggers my alarms again.

But the Broadcast Receiver is not receiving the transmission of "Boot completed" when reboot my device and eventually does not perform my "Service".

I’ve tried everything to solve this problem. GAVE PERMISSION in the application manifest, I used the correct "action" in the receiver Fiter-Intent in the manifest itself and started the application at least once before restarting it. But I still couldn’t get my device to receive the transmission.

To solve this, I did a research and saw that some developers are having problems with this, especially with Android Oreo. Such solutions for me does not meet me since the receiver transmission, by what I’ve been researching, are being "taken out" of the Androids platforms to avoid malware and excessive battery costs (It seems to be a new Google policy).

Even if I could solve the broadcast problem of the Broadcast Receiver, I would have another problem which is the alarm settings in my Serviceintent. How am I supposed to reset the alarms at the right time? That’s why if the user registers 5 medicines as I was going to do to set all alarms independently?

Seen the above problems, for me to use the workmanager solves them. Since I can register several medicines (Through Work) and separate them by Tags for eventual cancellation. In addition to save battery...

The problem is when you restart the device. Because even the work worked after the restart the trigger times of Alarms are affected.

I know workManager is not the ideal tool to do this, but I want so this way seen that the other way, I have much more problems to solve. So I chose to try like this....

While writing this post, I’ve been having some ideas. I’ll put them into practice and if it works I’ll put the answer here. For suddenly my doubt can help someone else.

1 answer

-1

So as promised, I found a solution to use Workmanager as a multiple alarm system (in my application) and decided to share my experience with you.

First of all, although I know that the workManager function is not for this, I see in it the solution of many problems that a multiple alarm system causes in the Android Operating System. This is because several alarms cause excessive battery usage (Alarmmanager). The workmanager lines each job properly and ensures execution. Furthermore, with the workmanager there is no need for the developer to create a Broadcastreceiver to listen to implicit Intents (Action of "BOOT_COMPLETED") and an Intentservice to reprogram alarms every time the user restarts the device, because this the workmanager does automatically. It reads BOOT_COMPLETED transmission from the OS and restarts work.

So without further ado, let’s get the solution.

Recap.... I needed an app that works as an alarm to tell the user when it’s time to take their medicine.

The information about the medicine that alarm was taking into account to trigger:

Starting time

It was left to the user to decide at what time to start the administration of the medicine Ex.: 8:33 am or 17:21 pm

Interval between administrations

It is up to the user to decide what is the interval between administrations

Other information such as stockpile,initial date, whether active or inactive, I will leave out this example for better understanding.

Continuing.... (Solution)

Observing!!!

I noticed that as much as a drug alarm needs to be accurate, I saw that there is no need for the user to have to put in such a precise hour to start a treatment. Ex.: 8:33 am or 17:21 pm.

Dai then I limited the times that the user could initiate a treatment to intervals of 30 every 30 minutes. See the following example for better understanding:

Enter the initial processing time

0:00 in the morning.

0:30 in the morning.

1:00 in the morning.

...

23:00 at night.

23:30 at night.

That is, it is limited in intervals of 30 minutes for the user to choose the beginning of the drug administration.

By doing so, I avoid having to set off alarms in a row at very short intervals such as:

5 different alarms for 5 different medicines (There are people who take medicine cocktail)

1º (17:21) ; 2º (17:22) ; 3º (17:24) ; 4º (17:29) ; 5º (17:30)

The user can now only choose between these two times (17:00) or (17:30) to start the administration of the medicine.

By doing so, I have created a table in my internal database (Sqlitedatabase) called "ALARMES_REGISTRADOS".

This table holds the following columns for each hour range. Example:

//coluna para o horário de "00:00:00"
private static final String COLUNA_000 = "00:00:00"

//coluna para o horário de "00:30:00"
private static final String COLUNA_030 = "00:30:00"

//coluna para o horário de "01:00:00"
private static final String COLUNA_100 = "01:00:00"

//Assim se segue para todos os horários...

These columns serve to receive the names of the medicine that will fire at that time. That is, if I set an alarm a medicine called RIVOTRIL to start at 16:00 every 12 hours, then the following columns in my database are named after the medicine.

COLUNA_1600 = "Rivotril" // 4 da tarde
COLUNA_400 = "Rivotrl" // 4 da madrugada

With this information I can now go to the Workmanager.

First I start a periodicRequest with the interval of 30 in 30 minutes. This is because, the minimum time that one alarm can happen compared to another is 30 minutes.

PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(
                PeriodicWorker.class,30, TimeUnit.MINUTES)
                .build();

        WorkManager.getInstance().enqueueUniquePeriodicWork("VERIFIC_ALARM",
                ExistingPeriodicWorkPolicy.KEEP,periodicWorkRequest);

And inside this periocRequest I do the following:

First I create a String[] that contains all times for comparison to the current system time in a FOR loop. So:

private String[] HOURS = {"00:30:00","01:00:00","01:30:00","02:00:00","02:30:00","03:00:00","03:30:00"
            ,"04:00:00","04:30:00","05:00:00","05:30:00","06:00:00","06:30:00","07:00:00","07:30:00","08:00:00"
            ,"08:30:00","09:00:00","09:30:00","10:00:00","10:30:00","11:00:00","11:30:00","12:00:00"
            ,"12:30:00","13:00:00","13:30:00","14:00:00","14:30:00","15:00:00","15:30:00","16:00:00"
            ,"16:30:00","17:00:00","17:30:00","18:00:00","18:30:00","19:00:00","19:30:00","20:00:00"
            ,"20:30:00","21:00:00","21:30:00","22:00:00","22:30:00","23:00:00","23:30:00","24:00:00"};

Then I get the current system date:

Calendar calendar = Calendar.getInstance();
        Date timeNow = calendar.getTime();

Then I prepare for proper conversion:

SimpleDateFormat date = new SimpleDateFormat("HH:mm:ss", Locale.US);

I convert and make the comparison:

try {

                Date d1 = date.parse(date.format(timeNow));
                Date d2 = date.parse(HOURS[i]);

                long differenceSeconds = TimeUnit.MILLISECONDS.toSeconds(d2.getTime() - d1.getTime());

                if (differenceSeconds <= 1800 && differenceSeconds >= 0) {

                    OneTimeWorkRequest notification=
                            new OneTimeWorkRequest.Builder(NotificationWorker.class)
                                    .setInitialDelay(differenceSeconds, TimeUnit.SECONDS)
                                    .setInputData(inputData)
                                    .build();
                    WorkManager.getInstance().enqueueUniqueWork("NOTIFICATION",
                            ExistingWorkPolicy.KEEP,notification);


                    break;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

Note that the initial Onetimeworkrequest Delay is the difference in seconds from the current system time to the next alarm time. Example:

Current system time - 12:14:30 Time of next alarm (if any) - 12:30:00

Difference in seconds - 930 seconds (Onetimeworkrequest Initialdelay)

All I need to do is manipulate Sqlitedatabase data on my Onetimeworkrequest. That is, take the names of the medicines that are stored in the COLUNA_1230 column that refers to the 12:30 time which is the next alarm. If there is no name there, then nothing will be shown (No alarm/notification).

Good tai as I did and works great on all emulators and smartphone I tested. I thank everyone who read my post. Unfortunately STACKOVERFLOW with the pretext of wanting to maintain the quality of the site, label questions like mine as "No quality", in other words, too stupid. Personally, I think it hurts too much to question people starting in the world of programming, because these people will always have doubts no matter how stupid they are. Perhaps these initiatives also have quality doubts, but because they do not know how to ask in the "right" way end up taking a point against or even a BAM in their accounts. It’s sad!!!

But at last.... Thanks again!!

  • Look man, it’s not hard to ask the right way didn’t you see, as soon as you create the account you get all the rules you should follow, including how to ask questions, and how NOT to ask questions. Just read it. Good luck!

  • Since you read everything from the site then read this here:

  • Comments are used to ask for clarifications or to point out issues in the post. Outdated or outdated comments can be deleted. Learn more about comments... Comments use mini-Markdown formatting: link Italic Bold code. The post Author will Always be notified of your comment. To also notify a Previous commenter, mention their user name: @peter or @Petersmith will Both work. Learn more about formatting...

  • 2

    Wide face the hand of being whiny, if you had read would have understood, and you are right about the comments, you can click on them and signal an administrator to remove if they are not useful. : D

  • Don’t climb up and down and do it.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.