I'm trying to write code that will run in the background and call server APIs. Googling led me to use AlarmManager, here is my code:
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval = 4000;
Intent alarmIntent = new Intent(getApplicationContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmIntent, 0);
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
The problem here though, is when my app is on the foreground (currently in android main menu, or on another app), whenever the alarm fires, it sends my activity to the front.
Anyone know why this happens and how I can avoid this? I have a service that is started by the AlarmReceiver class, and I want it to run on the background.
AlarmReceiver.class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, LogService.class);
i.putExtra("param1", "index.html");
i.putExtra("param2",
"http://www.vogella.com/index.html");
context.startService(i);
}
}
LogService.class
public class LogService extends IntentService{
public LogService() {
super("LogService");
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent intent) {
String param1 = intent.getStringExtra("param1");
String param2 = intent.getStringExtra("param2");
Log.i("Hello from logservice!", "!!! -- " + param1 + " - " + param2);
}
}
Added stuff to manifest:
<receiver android:name="com.example.app.alarm.AlarmReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service android:name="com.example.app.alarm.LogService" >
</service>
Thanks in advance!
After reading around, I've found out that since API 19, all repeating alarms are inexact. After knowing about this, I tried using the setRepeating function. I don't know why it behaves differently, but all is working as intended now.
Related
I want to do some network job periodically even when app if force closed.
Now it works until it's force closed.
What i am missing?
Also if i add to manifest this: android:process=":remote" - it's not triggering onReceive method (like app is force closed), but in logs i found that:
V/AlarmManager: triggered: cmp=com.cryptorulezz.cryptosignals/.Code.Alarm Pkg: com.cryptorulezz.cryptosignals
My code:
public class Alarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
// Put here YOUR code.
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example
System.out.println("ALARM !!!!!!!!!!!!!!!!!!!!");
wl.release();
}
public void setAlarm(Context context)
{
AlarmManager am =(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
//Intent i = new Intent(context, Alarm.class);
Intent i = new Intent("Coinsider.START_ALARM");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 1, pi); // Millisec * Second * Minute
}
public void cancelAlarm(Context context)
{
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
How i set alarm in MainActivity:
Alarm alarm = new Alarm();
alarm.setAlarm(this);
Manifest:
<receiver android:name=".Code.Alarm" android:exported="false">
<intent-filter>
<action android:name="Coinsider.START_ALARM" >
</action>
</intent-filter>
</receiver>
Once the app gets force killed, it won't receive the intent and the intent filter won't be triggered. To overcome this, I suggest a sort of watchDog, that relies on some system events (like android.intent.action.BOOT_COMPLETED), that simply checks if one of your process is alive, and fires it if not. In the manifest, you 'd have something like this:
<receiver
android:name="it.angelic.receivers.WatchDogSetupReceiver"
android:process=":souliss_process">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.USER_PRESENT"/>
</intent-filter>
</receiver>
The class WatchDogSetupReceiver would then check if the dog is alive, and fire a new one if needed:
Intent i = new Intent(ctx, WatchDogEventReceiver.class); // explicit intent
PendingIntent patTheDog = PendingIntent.getBroadcast(ctx, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, now.getTimeInMillis(), 5000,
patTheDog);
Last, WatchDogEventReceiver would simply do the required un-killable job. It is important that the watchdog stays light, as it will be fired upon every screen on event. This solution is non-optimal, but works even after force-kill:
public class WatchDogEventReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context ctx, final Intent intent) {
Log.d(Constants.TAG + ":WatchDog", "WatchDog.onReceive() called, looking for Dataservice:");
ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
//Fire Service
Intent eventService = new Intent(ctx, YourDamnService.class);
ctx.startService(eventService);//sempre, ci pensa poi lui
}
im trying to do somekind of auto GoogleDrive backup(uploading a file) timer, but i cant set the specific time, even if i set to 5 seconds(testing purpouse, it just run every 1minute) and when the user reboot the phone, it only RUN one time (the Alarm is not called =/, so the application has to be opened one time after the boot)
Manifest Configuration:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application...>
<receiver
android:name=".Tools.AutoBackupAlarmBroadCast"
android:process=":remote" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".Tools.AutoBackupService"
android:exported="false" />
</application>
and with this WakeBroadCast:
public class AutoBackupBootStarter extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, AutoBackupService.class);
context.startService(startServiceIntent);
}
}
make sure that the AutoBackupAlarm is called on boot, but it only happens ONE time, i need it to start the trigger to repeat by the user setted time(will get it from shared Preferences)
the service:
AutoBackupService:
public class AutoBackupService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
*/
public AutoBackupService() {
super("AutoBackup");
}
#Override
protected void onHandleIntent(Intent intent) {
WakefulBroadcastReceiver.completeWakefulIntent(intent);
//HERE i must start the Async to make the GoogleDrive Backup
//the next doubt will be how can i get sharedpreferences and activity to pass to the async from HERE?
Log.d("BACKUP", "AutoBackupLogTest");
}
}
the broadcast
public class AutoBackupAlarmBroadCast extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AutoBackupService.class);
i.putExtra("foo", "bar");
context.startService(i);
}
}
the AlarmFunction called on onCreate, that almost works how i want, it cant repeat every 5 seconds like the time below, it only show every 1 minute
public void scheduleAlarm() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), AutoBackupAlarmBroadCast.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, AutoBackupAlarmBroadCast.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 5 seconds
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
// Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
1 * 5 * 1000, pIntent);
}
Try below code to repeat task after particular time interval
boolean alarmUp = (PendingIntent.getBroadcast(this, 444, new Intent(this, AlarmReceiver.class), PendingIntent.FLAG_NO_CREATE) != null);
if(!alarmUp){
AlarmManager alarmManager = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
Intent DataSyncIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 444, DataSyncIntent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime(),
15 * 60000, // 60000 = 1 minute,
pendingIntent);
}
I'm failing to see why this alarm is going off on a reboot...I am setting it 7 days ahead here -
Intent intent = new Intent(MainActivity.this, Reminder.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MainActivity.this, 1, intent, 1);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
try {
am.cancel(pendingIntent);
} catch (Exception e) {
System.out.println("Derp");
}
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 7);
long time = calendar.getTimeInMillis();
am.set(AlarmManager.RTC_WAKEUP, time,
pendingIntent);
Here is my manifest that I have set for alarm to stick around on a reboot - Reminder is the class receiving the alarm-
<receiver android:name="com.practicum.notifications.Reminder" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
By default, all alarms are canceled when a device shuts down. To prevent this from happening, you can design your application to automatically restart a repeating alarm if the user reboots the device. This ensures that the AlarmManager will continue doing its task without the user needing to manually restart the alarm.
You have to manually reset the alarm once again in Bootup Receiver
public class SampleBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
// Set the alarm here.
}
}
All alarms are shut off when you power off the Android device.
You need to call setRepeating method
public class AlarmReceiver extends BroadcastReceiver {
private static final int PERIOD=5000;
#Override
public void onReceive(Context ctxt, Intent i) {
scheduleAlarms(ctxt);
}
static void scheduleAlarms(Context ctxt) {
AlarmManager am = (AlarmManager) ctxt.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ctxt, YourService.class);
PendingIntent pi = PendingIntent.getService(ctxt, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + PERIOD, PERIOD, pi);
}
}
Check this answer from CommonsWare.
For future reference, I misunderstood how receving the boot complete action worked. I had the intent filter in both of my receiver classes so they were both running, when instead I needed an intent filter on a new broadcastreceiver class to RESET my alarmmanagers.
I've seen several examples on how to make some event to be repeated even when the app isnt running, but still I'm not sure if I got it.
With AlarmManager you can make your app to wake up to do something in some fixed interval without it consuming system resources between the periods, right?
But can it be to show up a toast over your current activity instead of having an Activity with a layout for it?
AlarmReceiver class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this is where to start activity or service to launch toast message
}
}
In activity or boot receiver:
private static final int PERIOD = 60000; //or whatever you need for repeating alarm
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent alIntent = new Intent(context, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, alIntent, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60000, PERIOD, pi);
In AndroidManifest, add:
<receiver android:name=".AlarmReceiver"></receiver>
I am creating an android application which obtains the local weather forecast from a weather api as well as twitter updates on the aurora borealis and correlates the two. I was wondering what is the best way for me to continually update the data and compare it, even when the user does not have the application open on their device? So essentially I want my app to run in the background. Any help would be great!
The task you want to repeat periodically may be implemented in a IntentService.
public class MyService extends IntentService {
public MyService () {
super("MyService ");
}
#Override
protected void onHandleIntent(Intent intent) {
new MyTask().execute();
Log.d("MyService", "About to execute MyTask");
}
private class MyTask extends AsyncTask<String, Void, Boolean> {
#Override
protected Boolean doInBackground(String... strings) {
Log.d("MyService", "Calling doInBackground within MyTask");
return false;
}
}
}
You need to set a periodic alarm through the AlarmManager, that allow you to decide when to start the IntentService using a PendingIntent; for example, in an activity:
...
int interval =10*1000;//every 10 seconds
AlarmManager alarm = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(this, MyAlarmReceiver.class);
PendingIntent pendingIntent =PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
interval, pendingIntent);
...
The PendingIntent will be sent to an BroadcastReceiver listening for the alarm:
public class MyAlarmReceiver extends BroadcastReceiver {
public MyAlarmReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent);
Log.d("MyAlarmReceiver", "Called context.startService");
}
}
Everytime phone is turned off, the alarms you set are automatically canceled, so you need a BroadcastReceiver listening for boot_completed e setting again the alarm:
public class MyBootReceiver extends BroadcastReceiver {
public MyBootReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("MyBootReceiver ", "Boot completed");
int interval =10*1000;//every 10 second
AlarmManager alarm =
(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(context, MyAlarmReceiver.class);
PendingIntent pendingIntent =
PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(),
interval, pendingIntent);
}
}
In AndroidManifest.xml you need to add the RECEIVE_BOOT_COMPLETED permission and the BOOT_COMPLETED intent-filter for the BroadcastReceiver :
<application ...>
...
<receiver
android:name=".services.MyBootReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter android:priority="500" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
...
</application>
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
More detail here