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.
Related
I am almost finished with this game I have been making. It is a toy app and is only serving to teach me. So I call it toyapp.
I am trying to use what I learned about alarmmanager, intent, and broadcast to kill my application. I figured out how to get my alarm to go 10 seconds and then print a message to a widget. This was based on the following tutorial here.
It was my thinking that I could just call this up, warn the user I am about to kill this application and then close it out. However, it appears that the AlarmReceiver is not being called at all? My game just keeps playing.
The code I have modified is below for my toyapp.
public void timingService(Context context, Activity activity){
// get a Calendar object with current time
Calendar cal = Calendar.getInstance();
// add 5 minutes to the calendar object
cal.add(Calendar.SECOND, 5);
Intent intent = new Intent(context, AlarmReciever.class);
intent.putExtra("alarm_message", "Game will exit soon");
// In reality, you would want to have a static variable for the request code instead of 192837
PendingIntent sender = PendingIntent.getBroadcast(context, 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Get the AlarmManager service
AlarmManager am = (AlarmManager) activity.getSystemService(context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
}
Now, put my Receiver code in my activity class. Which is as follows:
public class AlarmReciever 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_LONG).show(); //Give message
toyappActivity.this.finish(); //Exit the game
}catch(Exception e){
Toast.makeText(context, "There was an error somewhere", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
}//End of AlarmReciever
My inspiration for this approach was the following that I read here.
What I eventually want to do is simple. I will have an option to play the game with or without the alarm. I plan on reseting the alarmmanager with the accelerometer sensor if movement is detected. Otherwise, it will just countdown and then cancel the game.
I suspect I am not understanding intents directly, but this is my crashing point. I am so sorry if this seems stupid, but I have a rather bad cold right now and this seems like it should work to me. However, computers never lie, only our minds.
As always, you are all the best group of coders and developers. I learn so much from you all and your help is so much appreciated. Any dumb mistakes are my own, but I hope you let me off on that technicality.
Warm Regards,
GeekyOmega
The Alarm is set properly: am.set(...), it should be called only once.
But you would expect a message on you screen with:
Toast.makeText(context, message, Toast.LENGTH_LONG).show(); //Give message
The proces will refer to a :remote not sure the context what will be, as I remmeber the appContext. It seems you are trying to show a message from background and your GUI may block it. Try to remove (comment) that maeesage and let the
toyappActivity.this.finish(); //Exit the game
code run, just do a Log.d() if you want.
The AlarmManager class isn't designed for simple timeouts.
From the documentation in the link above...
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
See the Handler class to do what you want more efficiently.
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
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 .
I have created an On Boot Receiver to repeatedly call a wakeful intent service every 5 minutes but cannot figure out how to start the service immediately when the app is installed..? I do not want to rely on the user rebooting their device before it starts to run!
Here is my code so far :
public class OnBootReceiver extends BroadcastReceiver {
private static final int PERIOD = 300000; // check every 5 minutes
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, OnAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60000, PERIOD, pi);
}}
Can anyone help me out pls? :)
If you want to set an alarmmanager to start your service when the app is installed, then it's not possible. It's a OS limitation, security if you will. But if you want to start the service in the moment the app starts, just call it, it will keep runing.
Essentially, since the Application object is created when the application is started and when the BOOT_COMPLETED Intent is received, you could register with the AlarmManager in the onCreate method in your custom Application class. Just be aware that the Application object is instantiated every time the process starts, which includes cases where the process is temporarily killed to save resources. But if you don't change the PendingIntent in any way, it should be no problem to register over and over again.
However, it is not possible to start the application when it is installed, there has to be some user interaction first.