I am developing an Android app which must perform 2 periodic tasks in background:
download files from server every 24 hours.
perform file operations each week on phone sd card.
How do i do this?
Firstly you need to use AlarmManager. When the registered alarm e.g. 24 hours case, will trigger, you can call service from the broadcast receiver of AlarmManager. You need to study a bit about AlarmManager if you don't already know. For further help you can get some idea from code below:
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());
Calendar cal = new GregorianCalendar();
cal.set(Calendar.DAY_OF_YEAR, cal.get(Calendar.DAY_OF_YEAR) + 1); //+1 For Next day (24 hours or so...)
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, cur_cal.get(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND));
cal.set(Calendar.DATE, cur_cal.get(Calendar.DATE));
cal.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH));
AlarmManager am = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
am.cancel(pendingIntent);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
Here is how you can set your Alarm. Now when Alarm will be triggered, you will call your service like this:
public class AlarmReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context arg0, Intent arg1)
{
// Call you service or any task here
}
}
Last thing, don't forget to mention your broadcast receiver and service in AndroidManifest.xml
<receiver android:name=".AlarmReceiver">
</receiver>
<service android:name=".MyService"/>
Here's what official android docs says about AlarmManager
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.
Handler documentation.
Related
Hello i want to make a background service to update the data of my app and repeat it once a day, also i want the service to start onboot. I have the following code:
public class OnBoot extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Create Intent
context.startService(new Intent(context, BackgroundServiceHandler.class));
}
}
I have a settings menu so the user can choose the hour of the repeating alarm.
How can i reset the time of the alarmmanager? Where i have to put the code of the alarm manager? Do i have to use service or intentservice? How to check if service is running?
Alarm manager code:
Intent intent = new Intent(MainActivity.this, AlarmService.class);
intent.putExtra("i", 3);
PendingIntent pi = PendingIntent.getService(MainActivity.this, 9, intent, 0);
// every day at 9 am
Calendar calendar = Calendar.getInstance();
// if it's after or equal 9 am schedule for next day
if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) >= 9) {
calendar.add(Calendar.DAY_OF_YEAR, 1); // add, not set!
}
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pi);
How can i reset the time of the alarmmanager?
How to edit/reset Alarm Manager?
Where i have to put the code of the alarm manager?
For example you can place that code in static method and call it from place where user set time and from OnBootReceiver. How to implement class which will receive event OnBoot please check that answer.
Do i have to use service or intentservice?
Service vs IntentService
How to check if service is running?
Check if service is running on Android?
I'm trying to update fragment on clock time, say for example 8PM, with below logic. Unfortunately, it doesn't update the fragment. Any help/reference would be appreciated.
What I did:
registered an AlarmManager in app's Application class as below:
alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent().setAction(AppConstants.INTENT_ACTION_UPDATE_DASHBOARD);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
// Set the alarm to start at Consulting start time
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
alarmMgr.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);
Listens for AlarmManager in Fragment as below:
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mDashboardUpdateReceiver, new IntentFilter
(AppConstants.INTENT_ACTION_UPDATE_DASHBOARD));
and performs actions if broadcast receives:
private BroadcastReceiver mDashboardUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Dashboard updating...");
updateCounters();
}
First, a PendingIntent does not trigger a local broadcast. You cannot use LocalBroadcastManager here.
Second, using AlarmManager to update a UI is rather odd. If your UI exists, you have a process running, so you could use something in-process (e.g., ScheduledExecutorService) rather than fussing with AlarmManager.
Third, you are not taking into account that set(Calendar.HOUR_OF_DAY, hour) and calendar.set(Calendar.MINUTE, minute) might change the Calendar to be in the past. Imagine if you execute your first code snippet at 23:00, with hour set to be 22 and minute set to be 0. The Calendar object that you create will be for today, but for 22:00 today, which was an hour before now (23:00). You need to check the Calendar, see if it is in the past, and if so, add() a day or otherwise adjust it to some future time.
I am following Android developers documentation and some other tuts to create an Alarm manager which fires and wakes up the CPU at 4pm everyday, following is my code:
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
BroadcastReceiver br;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 16);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
}
public void setup() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent i) {
Toast.makeText(c, "Rise and Shine!", Toast.LENGTH_LONG).show();
//Invoke the service here Put the wake lock and initiate bind service
}
};
registerReceiver(br, new IntentFilter("com.testrtc") );
alarmIntent = PendingIntent.getBroadcast( this, 0, new Intent("com.testrtc"),
0 );
alarmMgr = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
}
}
Manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
However I dont get any errors, but the alarm (Toast message) wont fire.
EDIT from the developer docs:
RTC examples
Here are some examples of using RTC_WAKEUP.
Wake up the device to fire the alarm at approximately 2:00 p.m., and repeat once a day at the same time:
// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
This one for set Repeating, says that if I want my alarm to fire at 8:30 and then repeat after each 20 minutes, however I just want to fire my alarm at a specific time but I dont want to repeat it.
Wake up the device to fire the alarm at precisely 8:30 a.m., and every 20 minutes thereafter:
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 20, alarmIntent);
Decide how precise your alarm needs to be
Choosing the alarm type is often the first step in creating an alarm. A further distinction is how precise you need your alarm to be. For most apps, setInexactRepeating() is the right choice. When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. This reduces the drain on the battery.
For the rare app that has rigid time requirements like yours, the alarm needs to fire precisely at 4:00 p.m. everyday then use setRepeating().
Reference: Decide how precise your alarm needs to be
Solution :
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
// Set the alarm to start at approximately 4:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 16);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000*60*60*24, alarmIntent);
Edited Testing : (Fire alarm at every 10seconds)
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime(),
1000*10, alarmIntent);
Conclusion :
setup() method was not called before dealing with alarms.
Update for API 19+
setRepeating is inexact when targeting api level 19 or higher. For exact repating you can now use setExact() and manage repeating yourself.
reference: AlarmManager documentation
Instead of using setInexactRepeating() I suggest you to use setRepeating()
from the docs,
setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour.
setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
Schedule a repeating alarm.
Documentation is quite clear:
public void setInexactRepeating (...)
triggerAtMillis time in milliseconds that the alarm should first go
off, using the appropriate clock (depending on the alarm type). This
is inexact: the alarm will not fire before this time, but there may be
a delay of almost an entire alarm interval before the first invocation
of the alarm.
so to my understanding but there may be a delay of almost an entire alarm interval means you may have one day delay, because u use AlarmManager.INTERVAL_DAY.
set minutes and seconds also to calendar ..
calendar.set(Calendar.HOUR, 16); // At the hour you wanna fire
calendar.set(Calendar.MINUTE, 0); // Particular minute
calendar.set(Calendar.SECOND, 0);
and use
alarmManager.setRepeating(AlarmManager.RTC,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY,
alarmIntent);
I had your same problem (usually is an Huawei issue) and I resolved by enabling the app in the PowerManager or Protected Apps.
Try to create a receiver that extends WakefulBroadcastReceiver:
public class MyReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myService = new Intent(context, MyService.class);
context.startService(myService);
}
}
In your service, you can put your toast, or try to write a log in a file to be sure that it works. Then, in your activity:
Intent myAlarm = new Intent(context.getApplicationContext(), MyReceiver.class);
PendingIntent recurringAlarm = PendingIntent.getBroadcast(context.getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), 4 * 1000 * 60, recurringAlarm);
// Alarm every 4 minutes
I've an intent that starts a new class at fixed time (and date). This intents start at fixed date BUT also at every reboot (also after the date and time are are in the past). In my code the New.class starts at 26/12/12 - 21.30 but if I reboot emulator after that time, New.class starts automatically. Why? Thanks!
PS: this code is within an Autostart class (public void onReceive(Context context, Intent intent) {)
Calendar cal = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
cal.set(Calendar.DATE,26);
cal.set(Calendar.MONTH,Calendar.DECEMBER);
cal.set(Calendar.YEAR,2012);
cal.set(Calendar.HOUR_OF_DAY, 21);
cal.set(Calendar.MINUTE, 30);
cal.set(Calendar.SECOND, 00);
Intent intent3 = new Intent(context, New.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,intent3, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
That's by design. See the documentation of the set() method:
"If the time occurs in the past, the alarm will be triggered immediately."
If you do not want this to happen, you shouldn't schedule the Alarm. That is, you should check yourself whether to call set() within the BroadcastReceiver.
I need to prompt alarm according to the time values in DB. I came through lot of examples but confusing me. Could any body help to set a repeating alarm for given time like 2011-07-03 02:00:00:000 . and it should repeat for 5mints interval.
I suggest you create a service. The service can read the database and set the alarm using AlarmManager class. You can use the AlarmManager's set() or setRepeating() methods based on your use. http://developer.android.com/reference/android/app/AlarmManager.html#set%28int,%20long,%20android.app.PendingIntent%29
here is a sample of AlarmManager usage.
long triggerAtTime = SystemClock.elapsedRealtime() + triggerAfterTime;
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, YourAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
YourAlarmReceiver class (usually) can be a BroadcastReceiver where your logic goes on what happens when the alarm is triggered.
There is no public API for the Calendar application, though since it is a native UI for a Google Calendar, you could push an event over to the Google Calendar via its GData API.
You can use AlarmManager class
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);