I am making a personal organizer. From the calendar the user can choose the day and then can make a date with a specific hour. At this date and hour the application should show an other activity, which is the notification. User can make just one note for day. So the pk of each note is YYYYMMDD.
So, I wants to know that what I've done is right or not.
I've a service which is started with application. The onStartCommand of the service checks if in the current date there is a note in the db and, if there is, he calls the Activity Notification. I've a runnable thread which is looping each minute and it update the date if the service, because the date of the onStartCommand is static. If the date getted by the runnable is equal to onStartCommand's date then keep cycling, else I start the service again with:
Intent myIntent = new Intent(Receiver.this, NotificaSuoneria.class);
startActivity(myIntent);
In this way I haven't any troubles, but I want to know if the runnable thread could be killed by android, because if killed I can't check the alarms of the others days.
And, when I restart the service each time update the date, the old runnable thread will be killed or will were a lot of threads?
P.S.
I don't use the AlarmManager for schedule the alarm. If the datenow have some engagement with alarms I calculate the time left and sleep for this time, then I'll start the notification activity. Sorry for my poor english.
You should use AlarmManager for this with a loop like following edited
try {
cntxt = createPackageContext("your.app.package",CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e) {
// handle exception here
e.printStackTrace();
}
Intent myIntent = new Intent(cntxt , yourreciever.class);
PendingIntent pi;
AlarmManager alarmManager;
for(int i=0;i<=timesinday;i++)
{
pi=PendingIntent.getBroadcast(cntxt, i,myIntent, 0);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, currentcal.getTimeInMillis(),pi);
}
Do not forget to add NotificaSuoneria in Android Menifest as a Reciever. If you you want alarm to goes off every day you should use
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,todaycal.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);
#Meesta I am editing the answer you do not have to mention activity here Intent myIntent = new Intent(Receiver.this, here.class); here will be the reciever class from wher you can start your activity also see http://androidword.blogspot.in/2010/10/how-to-use-broadcast-receiver.html and try to add flag_new_activitywhen starting the activity from broadcast reciever
Related
I have a big problem with my app for several days now. I appologize if my english is not so native in advance. I implemented an AlarmManager to give the user of my app the option to start a certain service at any time of the current or the next day. So e.g. the user might choose to set the time for my service to tomorrow at 08:00 a.m. and then starts the service.
The alarm manager should now wait the calculated time from now till the chosen time (i calculated the time also manually and it is correct!) and then start the service. My problem now is that sometimes the alarmmanager is starting my service and somtimes not. It seems that if it has to wait for lets say more than 4 hours it is not working any more and my service is not called. I have set all neccessary permission otherwise it would not work at all. You can have a look at the code of the alarmmanager below:
someIntent = new Intent();
someIntent.setAction("START_SERVICE");
AlarmManager alarams ;
alarmIntent = PendingIntent.getBroadcast(MainActivity.this, 0, someIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarams = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarams.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+delay, alarmIntent);
The broadcast receiver is implemented like this (and it is registered!):
alarmReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(MainActivity.this, MyService.class);
startService(myIntent);
}
};
As I told you, if it is not working it stops before starting the service.
EDIT:
I have an idea. I read something in this thread: Android long running service with alarm manager and inner broadcast receiver
It might be, that my constructor for the intent "someIntent" only works for BroadcastReceivers declared in the manifest file. So in my case I should maybe use someIntent = new Intent("START_SERVICE") instead of someIntent = new Intent(); someIntent.setAction("START_SERVICE"). This effect is called tunneling - i will figure it out, if it works i will post my experience here. Thanks for the well explained answer on the mentioned thread! If you have any other ideas or the same experiences like me please let me know!
eMu
If the device is shutdown and start up then you will not get the alarm maanger broadcast receiver.
Implement OnBootReceiver which will receive the OnBoot completed and there you can start your pending alarms that were not fired.
I want to send data to server at some regular interval. So, I am using AlarmManager for the same. It works fine but the problem is that when I cancel the Alarm on Date/Time change. At that time Alarm fires again before getting cancelled, so that makes my application worse as an extra data is sent to server with irregular interval.
Here is my BroadCastReceiver class with AlarmManager.
public class MyReceiver extends BroadcastReceiver{
AlarmManager mgr;
PendingIntent pi;
Intent intent;
public static boolean flag = false;
#Override
public void onReceive(final Context arg0, Intent arg1) {
if(arg1.getAction().equals("android.intent.action.TIME_SET")){
Log.d("MyReceiver", "Time set");
mgr = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
intent = new Intent(arg0, TestService.class);
intent.putExtra("test", "testvalue");
pi = PendingIntent.getService(arg0, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if(!flag){
mgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, 5000, pi);
flag = true;
}
else{
mgr.cancel(pi);
pi.cancel();
flag = false;
}
}
}
}
Below is the Screen Shot with Logcat output that explains that after cancelling the Alarm it fires once more time just after cancelling.
As you can see in the Logcat output black arrow shows where I changed that time to cancel the Alarm and red arrow shows that after cancelling the Alarm once again it fired just before cancelling which should not happen. So, can anyone give my idea why that is happening and what should I do to restrict Alarm getting fired again before cancelling.
NOTE:- This only happens when I tried to increase date/time say from 10:00 to 11:00, works perfect when I decrease time say 10:00 to 9:00.
Not able to see the LogCat at my end, but looking at the code, I am not sure, how is the Service which gets invoked (TestService) gets killed / stopped ? I think you would need to stop it somehow. Also, its not recommended to do long running tasks within the broadcast receiver.
Have you verified that you service stop event is occuring after the mgr.cancel(pi) is fired?
Just try with some unique code with pending intent within activity and then cancel that intent using the same code.
setting pending intent in activity
PendingIntent.getBroadcast(this, code, intent, PendingIntent.FLAG_UPDATE_CURRENT);
for stopping that broadcast receiver
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), code, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
why that is happening
First Thing is that you are using Intent Action android.intent.action.TIME_SET so It does mean that Everytime any how if the System date/time gets Changed your BroadcastReceiver will ne called Automatically.
Second you have used one static boolean flag in your Receiver class.
Now what is happening is Whenever you change your System timings the flag toggles it's state from false to true and from true to false.
That is what exactly happening in your code and logcat also shows the same that everything is working as per the code written.
So according to me there is nothing Wrong happening in the code and it's output.
what should I do to restrict Alarm getting fired again before cancelling
First thing as I think, you should not use Action TIME_SET like that to toggle flag on/off as users and developers might not remember for what they are changing time either to turn FLAG On or Off,
Better way is that,
you should handle the Service yourself by an Activity and show one ToggleButton there to manage the State of the FLAG and set and cancel the PendingIntent.
OR
And If you want to do the task of your service automatically then you just simply use the AlarmManager and set your Alarm Triggering time and Interval there only once say time is currenttime and Interval is 50000 miliseconds..
so it will obviously call the service from now onwards after every 5mins, then in your App you will only require one ToggelButton to indciate the Sync to ther server is On or Off , if user Toggle it on or off then write your AlarmManager code there in your Activity only in the toggleButtontb.setOnCheckedChangeListener(listener) , I suppose this is the better way then what you are actually implementing.
I don't understand what need to set the receiver for date change if your goal is only to send the data on server in some regular interval .
change date and time of device does not mean that your alarm wont work
at that time which you already have set before those changes .Alarmmanager work on that given duration of time which is excluding from local current date and time of device .
Hi i have written reminder code in service onstart().and when user insert date-time and insert record at that time service called by startservice() function,but only service is starting when i insert record i.e i am getting reminder when it get call from my activity.but i want reminder after 3days or something so how should i keep service always on so that i can get reminder in future? or how should i make connection of service keep alive?should i called bindservice() frunction from my any activity or what?
thanks in advance---
Don't let your Service run all the time. It consumes battery and memory when not neccessary¹.
Rather schedule a PendingIntent via the AlarmManager thats starts the service at the relevant point in time to do it's work. When done, kill the service again.
In general androids services are used different then services/daemons on a "normal" computer. They have a task that they execute, then they quit (usually via Service.stopSelf()) until someone starts them again to do more work.
Here is a small example how the AlarmManager is used:
// get a calendar with the current time
Calendar cal = Calendar.getInstance();
// add 15 minutes to the calendar object
cal.add(Calendar.MINUTE, 15);
Intent intent = new Intent(ctx, YourService.class);
PendingIntent pi = PendingIntent.getService(this, 123, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);
This launches the intent to start YourService in 15 minutes from now. There is plenty of documentation for sending intents this way, search a bit around.
¹ Which will eventually frustrate your users: "Why does this app waste my battery?" is a pretty common question
Firstly no need of service,you can useAlarManagerClass Link Alarmanger class for schedule events and show alert at specific time and date. If you want show messages after some long duration then schedule a Pending-intent via the AlarmManager thats starts the service at the relevant point in time to do it's work. When done, kill the service again as per tell by above answers . In addition you can store your data into shared preferences for permanently. You can retrieve it at any time for resheulding it on device reboot or for other purpose.
Sometimes, it may be necessary for your android app to complete a task sometime in the future. In order to do this, you must schedule an activity (can also be a service) to be run using Android’s AlarmManager. This post will show:
* How to set up a receiver for the scheduled event
* How to create an activity from this receiver
* Using the AlarmManager and the created classes to successfully receive and process a scheduled event
Creating a BroadcastReceiver
The first thing you will need is a receiver to receive the event. There are several key aspects to have for the receiver to work properly. First create a class that extends BroadcastReceiver and override and implement the necessary onReceive(Context context, Intent intent) method. The following is a basic example using a Toast message:
package com.justcallmebrian.alarmexample;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
import android.os.Bundle;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
Bundle bundle = intent.getExtras();
String message = bundle.getString("alarm_message");
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(context, "There was an error somewhere, but we still received an alarm", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
In the previous example, we are simply just printing out the message supplied by the String passed in under the name of alarm_message. For those who are not familiar with Toast, it is basically a short and quick message given to the user. Here you can find more information on Toast.
Besides actually creating the class to receive the event, you must also declare it within AndroidManifest.xml. The following is the line that should be added before the closing of the application tag (before ).
Basically this states that the class AlarmReceiver is available and will start a private process. Once that is done, your BroadcastReceiver is ready to go.
Setting up an Event using AlarmManager
In order to receive an event, you obviously must schedule the event. There are three ways of scheduling an event (a one time event using the set method, a repeating event using the setRepeating method and finally using the setInexactRepeating). This tutorial will cover the one time alarm using the set method. For more information regarding the other events, you can view AlarmManager.
The following code snippet will get the AlarmManager and set an event to occur 5 minutes from the current time:
// get a Calendar object with current time
Calendar cal = Calendar.getInstance();
// add 5 minutes to the calendar object
cal.add(Calendar.MINUTE, 5);
Intent intent = new Intent(ctx, AlarmReceiver.class);
intent.putExtra("alarm_message", "O'Doyle Rules!");
// In reality, you would want to have a static variable for the request code instead of 192837
PendingIntent sender = PendingIntent.getBroadcast(this, 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Get the AlarmManager service
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
This code snippet basically obtains a new Calendar object and adds 5 minutes to it. An Intent is created with the AlarmReceiver which we created earlier. The more important piece of the code is setting the FLAG_UPDATE_CURRENT flag. Without this flag, the message being passed as an Extra will be lost and not obtained by the receiver.
With these code snippets you should be able to create and run some tasks in the BroadcastReceiver. However, sometimes you may wish to start a new activity (or service) on the alarm event. In order to do this, you would want to have the AlarmReceiver create and start the new Activity.
Starting an Activity from BroadcastReceiver
Starting an activity within a Receiver has an extra flag that is needed. We will change the previous onReceive for AlarmReceiver to get this done:
#Override
public void onReceive(Context context, Intent intent) {
try {
Bundle bundle = intent.getExtras();
String message = bundle.getString("alarm_message");
Intent newIntent = new Intent(context, AlarmActivity.class);
newIntent.putExtra("alarm_message", message);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
} catch (Exception e) {
Toast.makeText(context, "There was an error somewhere, but we still received an alarm", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
Now you would only have to create the new AlarmActivity as you would do any other Activity. Don’t forget to include the newly created activity in the AndroidManifest.xml file.
I have a service that runs every hour by a shot in my AlarmManager startAPP.class (main activity) in onCreate, as follows:
Intent it = new Intent("SINC");
PendingIntent p = PendingIntent.getBroadcast(StartAPP.this, 0, it, 0);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
c.add(Calendar.SECOND, inicio);
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
long time = c.getTimeInMillis();
alarm.setRepeating(AlarmManager.RTC_WAKEUP, time, repetir, p);
Everything ok. The service is triggered exactly as it should. But how is that a download is done execution is somewhat slow (minutes) 1 or 2. And this time the android triggers a dialog stating that the application stopped responding and asks if I want to close or wait.
How do I get this service does not display this message (dialog). Because from what I read services are used for processing time consuming and downloading files.
The service extends BroadcastReceiver
public class Sinc extends BroadcastReceiver
Note: if I tell the dialog I want to wait, the whole service process is successfully completed. (all files are downloaded)
Thanks
You should have your Sinc class inherit from IntentService instead of BroadcastReceiver and modify your PendingIntent to be a service intent instead of a broadcast intent.
I need to have a process run whenever the end-user clicks on a Submit button. The application needs to try to process the data on the screen every X minutes, Y times, even if the the application is down. So, it will need to attempt to do some processing until one of the following occurs:
1) The processing is successful for the data that was submitted
2) The processing has been retried Y times and still never succeeded
3) The application is terminated by the OS or the phone is turned off.
If the end-user's phone is still on but the application has stopped,
what's the correct interface to use to accomplish this?
If I use Handler/Runnable, that only works as long as the application stays active.
AlarmManager looks like it's used when you want processing to run at a specific time.
Any suggestions will be greatly appreciated!
I use this method to set an alarm.
private void setAlarm(){
Context context = getApplicationContext();
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, OnAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
myCal = Calendar.getInstance();
myCal.setTimeInMillis(myPrefs.getLong("time", 0));
mgr.set(AlarmManager.RTC_WAKEUP, myCal.getTimeInMillis(), pi);
Log.i(myTag, "alarm set for " + myCal.getTime().toLocaleString());
Toast.makeText(getApplicationContext(),"Alarm set for " + myCal.getTime().toLocaleString(), Toast.LENGTH_LONG).show();
}
inside my onAlarmReciever onRecieve method is this:
Intent i = new Intent(context, AlarmActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
So basically when the intent fires it starts the AlarmActivity. Inside that activity you could have it try what ever you are doing and if it fails call the setAlarm() again
You have two options: a Service, or set up an alarm with AlarmManager. Which one you pick will depend mostly how often do you want to retry. A minute? Use a service. An hour? A day? set up an alarm so you don't waste the phone resources keeping the service alive.
http://developer.android.com/reference/android/app/Service.html
http://developer.android.com/reference/android/app/AlarmManager.html
Write an Android Service