How to create a persistent alarm to notify user of events? - android

I currently have an AlarmManager with BroadcastReceiver implementation as my Alarm. There is one major flaw with this though; it does not go off when force closing the app. I tested out what happens with ICS calendar app, and it goes off even if I force close it. I know some people will say "if the user closes the app in that manner, they do not want it going off." What about task killers? That is the case I am looking for. Its pretty obvious my method cannot accomplish this, and I have looked and looked, but most if not all the examples are like how I implemented it. Any ideas how I can accomplish this?
Edit: So it seems all the research I've done that what I want to do is not possible without having the user install two separate apps, which is not ideal. There is a possibility that Google just made there Calendar app in that way (since they do write the source code), because I tested the top Calendar apps on the market and they all did not go off when the user force closed the app. So this begs the question, simply put, can this even be done in a single application? It is looking slim that it can be done due to Google trying to curb developers from not allowing the user control over random running broadcasts or services, which is understandable. Hopefully this helps others quickly realize there really isn't a real way to actually do this. All you can do is warn the user, that in closing your app in that manner they will not get alarms; enough said.

I would not use a Broadcast Receiver with your alarm
Broadcast Receivers in general provide two functions
1) Listen to broadcasts from the system
2) Allow apps outside of your own to make requests of your app.
Alarm Manager sets up new alarms with:
set(int type, long triggerAtMillis, PendingIntent operation)
Schedule an alarm. (from Android Documentation)
The Pending Intent placed in there is the intent that will be fired when the Alarm is up. You can have this Intent begin a Service by placing the service in the intent.
Ex:
Intent i = new Intent(context, MyService.class)
Where MyService is a class that extends Service. (you can just as easily do an activity, but having activities popping up out of nowhere is terrible design.
A Service is like an Activity that has no UI. Basically you can have it perform some background functions and possibly post a notification to the user that something has occurred.

Related

Kivy--Plyer--Android--sending notification while app is not running

I am writing a python app in kivy.
The idea is to allow the user to make notes of bookings for certain dates, and then the program should send them a notification on that day about the booking.
There's probably a simple way to do this, I am using plyer.
from plyer import notification
notification.notify(title="Kivy Notification",message="Plyer Up and Running!",app_name="Waentjies",app_icon="icon.png",timeout=10)
This works, I get a notification whenever I call that function, however, I can't find any way to send this notification while the app is not running, I do know that there are some other questions that seem to answer this question, but they don't, their simply to run a app in background, which I don't want to do, all I want is something like Clash of Clans notification when your troops are ready for battle, or Facebook's notification when somebody liked your post.
I think you should take a look at the Android AlarmManager. If this is what you need, here is an example for Kivy.
AlarmManager
This class provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running.
On Android, I'm not sure how I would implement it without a background service.
The thing with background services is they also get killed when the application that started the process gets killed.
I know 2-3 ways to prevent that on Android, I consider it hack, but maybe it's a feature.
One is to use the START_STICKY flag. It's implemented in python-for-android, but it seems broken to me.
Another one is to use the a recent feature, setAutoRestartService(). It will make the service restart itself gracefully/programmatically on kill.
Bonus way use a BroadcastReceiver, but this is not implemented in p4a.

Android background Services, Alarms and preserving object reference after application restart

I'm developing a little Android app, that needs to run a background process, used to start a remote connection periodically (for example, to check if there is new data on the server). This process obviously needs to work also if the application activity is not running at the moment.
As I can see in documentation, there are two types of approach to develop a scheduled background process in Android, working also when the application is closed.
Services
Alarms
The first one is not so good for my requirementes, because it can be killed by OS in case of low memory, so it is useless for me. startForeground() is not so good because I want the process is silent.
Alarm is ok, because it can't be killed by the OS, so it can work indefinitely. But... If I schedule an Intent with the AlarmManager, how can I preserve a reference to the Intent, surviving at application restart?
For example, if I want to cancel, or reschedule the Alarm, I need the reference to the initial Intent to cancel it thorugh the "AlarmManager.cancel(Intent i)" method. But if the application was restarted by the user, how can I obtain a reference to the initial Intent that was used to start the alarm?
Is there another way to stop an alarm if the launching application was restarted?
about alarms, you can cancel using the intent characteristics, so you don't need a reference to the original intent. In any case, the alarms mechanism still need you to run something on a service.
In any case, you missed another possible solution: SyncAdapter. Its purpose is to sync with servers, but you can do whatever you wish in the code, and it's unlikely the OS will kill it, as opposed to the other solutions you've mentioned.
Sadly even now it lacks on documentation and samples, but I think it can fulfill your needs. Here's what I've found
yes, note that cancel is looking for a PendingIntent, not an Intent per se.
so
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, R.string.some_string, new Intent(this, InitialIntent.class), 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
gets you where you want to be.
note that I'm not getString'ing that string, that's becasue I want a unique Id/request code for this intent that I'm not going to screw up copypasting; I reference the same number when creating the alarm in InititalIntent.
This question was just answered, here:
How can I get the context of other activity?
Just cancel the intent you scheduled
Your best bet would be to make use to push notification (via GCM), whenever something new is available on the server. I am working on similar application where data can be pushed from one side (producers) and needs to be pushed to the consumer apps.
You need to look at BroadcastReceiver and GCM specific communication model. Hope this helps

Seeking laymans explaination of the pending intent concept

This is a pretty stale question but frankly I'm yet to find it answered in a way that satisfies my curiosity.
Before you, dear reader, leap to the android developer reference to paste me the text, please be aware that I've already read the Intent / Pending Intent documentation and am yet to resolve my confusion.
It strikes me that the Intent model is core to the android system and as such is highly generic. It is because of this that the examples I have seen of its usage tend to be many and varied. This variation obfuscates the concepts I am trying to learn and that is frustrating.
My questions are simply written but perhaps tough to explain in simple terms. I understand that an intent is a message to other activities and that other activities can declare their interest in their manifest. Pending intent, a wrapper for intent, confuses me.
I see documentation referring to permissions and token. I get that, but why is pending intent needed as a separate entity - what behavior does it enable?
What activity / task lifecycle behaviour do pending intents cause?
When is a broadcast receiver required?
What are a broadcast receiver's limitations?
I realise these are seriously newb questions (which I am) but I desperately want to understand these core concepts so I don't have to rely on example / guides / official docs as much.
Any feedback is welcome folks. Thanks.
The main purpose of a PendingIntent is to give another application written permission to do something in your stead. Applications are restricted in what they are allowed to do by, essentially, these two factors:
Visibility. Components like Services or Activities that aren't provided with a publicly visible (or any) intent-filter cannot be called by other applications. They can only be called by your application using explicit intents specifying their package and class name.
Permissions. Each application can request a certain amount of permissions. Those are mostly predefined permissions, but you do have the option to define your own permissions as well, though I never used that. Your application cannot do anything that exceeds those permissions.
Now, with pending intents, you can get past both of those restrictions, if an application that has the required permissions and visibility to do something specifically allows you to do it in her stead. An application could allow you to call one of her private Activities for example, if it gives you a pending intent that contains an explicit intent for said activities.
[edit]
They are used with the alarm manager, for example. It tells the alarm manager what and when to do by giving it a (pending) intent. Since your application probably won't be there any more when the time arrives, the alarm manager will have to send it for you. That would mean that those intents could only do what the alarm manager is allowed to do, not what your application is allowed to do. If the alarm manager was allowed to simply do anything, every application could do anything by using the alarm manager as a proxy. So you have to use pending intents to specifically grant the alarm manager the rights it needs for your particular intent.[/edit]
Apart from that, there isn't too much of a difference to regular intents, at least as far as usage is concerned. It does get a bit more complicated with sticky intents etc, but that's the general gist of it, at least as far as I know.
A broadcast receiver is required when you want to react to certain system events, or events of other applications. A broadcast receiver is invisible, it doesn't create any form of view and doesn't involve any form of user interaction. The advantage is that this can happen irregardless of whether your application (or rather, your activities) are currently running or not.
A broadcast receiver is only granted about 10 seconds to do stuff, after that it gets killed by the system. So if you want to perform any kind of long running processes you'll have to use a background service, or open up an Activity to let your users do stuff.

Start activity using AlarmManager, without Broadcastreceiver

I hope that someone has an answer for me:
I wonder if it is possible (and common) to use the AlarmManager for directly starting an Activity. The documentation does not explain this explicitly. It only describes the usage of Broadcastreceivers.
If it is possible to start my Activity directy, where will I receive the Intent (onNewIntent)?
Many thanks
Jean-Pierre
I wonder if it is possible (and common) to use the AlarmManager for directly starting an Activity.
Yes.
The documentation does not explain this explicitly. It only describes the usage of Broadcastreceivers.
Using a BroadcastReceiver is the most common scenario. It is required for _WAKEUP alarms, if you want the device to reliably wake up when the alarm goes off.
Starting an activity from AlarmManager should be used for "alarm clock"-type applications, and little else. You have no idea what the user might be doing with the phone when your activity comes to the foreground, and they may get very angry with you if they feel that your intrusion is unjustified.
If it is possible to start my Activity directy, where will I receive the Intent (onNewIntent)?
By default, a new instance of the activity will be created. If you use FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP, it will bring forward an existing instance of the activity, and you will get the Intent in onNewIntent().
This sample project demonstrates using AlarmManager this way. This sample project demonstrates user configurable Activity-or-Notification when the alarm goes off. Both of these are relatively deep in a series of tutorials, and so the apps are a bit complex.

Clarification of AlarmManager behavior in Android

I see all the examples of AlarmManager being set by an Activity.
My question is this:
If my application sets a recurring AlarmManager, does that persist even after the application that started is is closed and removed from memory?
If not, how do I start an AlarmManager at a lower level that is started by Android at boot up and if it ever fails or dies or throws an exception is restarted without the user having to do anything?
Lastly, if the action I wish for the BroadcastReceiver to undertake has no visual components, do I still have to create a separate Activity for it? In my case I want there to be a background uploader that wakes up and looks into a folder and if it sees files in that folder, sends them off to the server. I don't need any feedback to the user.
So, my ideal would be to have a magical, OS based AlarmManager that calls an IntentService which just handles the uploading, but I'm unclear on how to get such an AlarmManager running in the first place.
TIA
Yes, AFAIK the alarms "survive" and keeps getting triggered, even after the activity that registered them ends. But they don't survive a phone reboot.
If I understands your problem correctly, I think you can achieve what your looking for by creating a project with a broadcast receiver that listens for android.intent.action.BOOT_COMPLETED intents and then (re-)register a repeating alarm, which in turns starts a (Intent)Service to do the uploading.
You don't need an activity, but you probably would want one anyway, to let the user temporarily disable the upload mechanism by checking off a checkbox, or something. It would probably also be nice to let the user choose the frequency of your alarm, i.e. how often the service should be started and look for new files to upload. This would also be a good place to register your alarm for the first time.
I agree with Nicolai that you'd have 2 broadcast receivers in your application :
one that re-register the alarm on boot
one that starts your service when triggered by the alarm
You could still have an activity but it shouldn't be started by the alarm receiver (hence the service) : instead, maybe launch a notification as you start your service, with the user having the possibility to launch the activity from the expanded message of the notification.
maybe also think about setInexactRepeating (instead of setRepeating) for your alarm, as well as using a worker thread to handle the long uploads (in case the user wants to use your activity in the main thread at the same time).

Categories

Resources