AlarmManager inside BroadcastReceiver when BOOT_COMPLETED - android

I have a Service "GroupsTaskAlarmChecker" that is called every 20 seconds by AlarmManager in onCreate of Groups.class activity this way:
int seconds = 20;
Intent myIntent = new Intent(Groups.this, GroupsTaskAlarmChecker.class);
pendingIntent = PendingIntent.getService(Groups.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), seconds * 1000, pendingIntent);
This works perfectly. But I need to do that when device boot.
Then I know I have to make AndroidManifest like this:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".ReceiverBoot">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED">
<category android:name="android.intent.category.HOME">
</category></action></intent-filter>
</receiver>
and then mi broadcastReceiver like this:
public class ReceiverBoot extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int seconds = 20;
Intent myIntent = new Intent(context, GroupsTaskAlarmChecker.class);
pendingIntent = PendingIntent.getService(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), seconds * 1000, pendingIntent);
}
}
but inside this onReceive I dont know how can I do the same that I did before (with intent and alarmManager to start the service each 20 seconds).
Error in this line:
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Is possible that I can't make an AlarmManager inside BroadcastReceiver?
I thank you all, I am an Android begginer and I need your help. Sorry for my english ;)

To summarize the answers and comments above: the onReceive handler receives a context which can be used to access getSystemService and ALARM_SERVICE. Sample code:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Start periodic service.
Calendar cal = Calendar.getInstance();
Intent srvIntent = new Intent(context, MyService.class);
PendingIntent pIntent = PendingIntent.getService(context, 0, srvIntent, 0);
// Use context argument to access service
AlarmManager alarm =
(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
// Repeat every 5 seconds
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
5000, pIntent);
}
}
}
Create a new class with this code and of course change MyReceiver and MyService to the names in your implementation.

ALARM_SERVICE is neither defined in the class ReceiverBoot nor in BroadcastReceiver.
You should reference Context.ALARM_SERVICE as the argument for getSystemService(String).

Here is a little contribution, which I believe that can add a more complete vision about achieving the goal of this question.
First: configure a "receiver" inside of the AndroidManifest from your app.
<receiver
android:name=".AlarmBroadcastReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Second: with a Class that EXTENDS the Abstract Class BroadcastReceiver, you should determine if the Intent Action was "BOOT_COMPLETED". If the condition is satisfied, you can call a method from your class which has all the construction to your Alarm.
See the following snippet bellow.
public class AlarmBroadcastReceiver extends BroadcastReceiver {
String TAG = "ALARMS";
String CLASS = this.getClass().getSimpleName() + ": ";
Context alarmContext;
#Override
public void onReceive(final Context context, Intent intent) {
Log.d(TAG, CLASS + "[START] onReceive()... ");
alarmContext = context;
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Log.d(TAG, CLASS + "BOOT_COMPLETED action has been received.");
setAlarmOnBoot();
}
Log.d(TAG, CLASS + "[END] onReceive()... ");
}
public void setAlarmOnBoot() {
Log.d(TAG, CLASS + "[START] - setAlarmOnBoot()");
final long beginAt = SystemClock.elapsedRealtime() + 60 * 1000;
final long interval = 300000; // 5 minutes
try {
AlarmManager alarm = (AlarmManager) alarmContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(alarmContext, AlarmBroadcastReceiver.class);
PendingIntent pIntent = PendingIntent.getService(alarmContext, 0, intent, 0);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, beginAt, interval, pIntent);
Log.d(TAG, CLASS + "the Alarm has been configured successfully (5 minutes) of interval.");
} catch (Exception e) {
Log.d(TAG, CLASS + "an exception has ocurred while setting the Alarm...");
e.printStackTrace();
}
Log.d(TAG, CLASS + "[END] - setAlarmOnBoot()");
}
}

in your onReceive:
if ("android.intent.action.BOOT_COMPLETED".equals (intent.getAction())){
//start it again here
}

Related

Alarmmanager going off on reboot...but its set for 7 days ahead?

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.

Generating alarm at specific day each week at a specified time android

I am using the following code to trigger an alarm at 08:45 am on every monday.
Calendar cl1 = Calendar.getInstance();
cl1.set(Calendar.DAY_OF_WEEK, 2);
cl1.set(Calendar.HOUR, 8);
cl1.set(Calendar.MINUTE, 45);
cl1.set(Calendar.SECOND, 0);
long tme = cl1.getTimeInMillis();
Intent intent = newIntent(Mondayentry.this,Alarmreceiver.class);
PendingIntent pendingintent = PendingIntent.getBroadcast(Mondayentry.this,0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager al = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
al.setRepeating(AlarmManager.RTC_WAKEUP, tme,7*1440*60000, pendingintent);
And I have used the following broadcast class
public class Alarmreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Alarm generated", Toast.LENGTH_SHORT).show();
}
}
I have also added in the manifest file
<receiver android:name=".Alarmreceiver"> </receiver>
There is no error but the alarm is not triggered at all.
Please help me.

Service is started via BroadcastReceiver "randomly"

I want to have an Notification on an specified Time each day.
For that I implemented an Broadcast receiver and an AlarmManager.
My doubt is that the receiver is reacting to every broadcast of the system.
Cause if I setup the alarmManager it is working fine for a while but than I got an notification nearly every hour (approximately).
And an other strange behaviour, if i go in airplane mode, the notifications doesn't show up.
public class MyReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Intent service1 = new Intent(context, MyAlarmService.class);
context.startService(service1);
}
}
in the main activity
long REPEATE_TIME_MS=86400000 /*24h*/;
/* notification handling */
String syncConnPref = this.sharedPref.getString("notificationTime", "12:00");
String[] pieces=syncConnPref.split(":");
/* setup the start time for the alarm */
Calendar calendar = Calendar.getInstance();
long nowInMillisecs = calendar.getTimeInMillis();
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(pieces[0], 10));
calendar.set(Calendar.MINUTE, Integer.parseInt(pieces[1], 10));
long alarmStartTimeUnMillisecs = calendar.getTimeInMillis();
if(alarmStartTimeUnMillisecs<=nowInMillisecs)
{
calendar.add(Calendar.DAY_OF_YEAR, 1);
alarmStartTimeUnMillisecs = calendar.getTimeInMillis();
}
Intent myIntent = new Intent(this.notificationContext, MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.notificationContext, 0, myIntent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)this.notificationContext.getSystemService(Service.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), REPEATE_TIME_MS, pendingIntent);
Log.d(TAG, "Alarm setup with :"+ calendar.get(Calendar.HOUR_OF_DAY)+":"+ calendar.get(Calendar.MINUTE));
manifest.xml
<receiver android:name="com.example.whoseturn.MyReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

Avoid alarm firing after each reboot

My apps alarm fires directly after each reboot, not at the specified time and it's not repeating. The alarm I set is ignored.
InitializeAlarm:
public class InitialisiereAlarm extends Activity {
private static final String TAG = "InitialisiereAlarm";
private static AlarmManager am;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm);
aktiviereAlarmDownload();
finish();
}
private void aktiviereAlarmDownload() {
Calendar calAkt = Calendar.getInstance();
calAkt.setTimeInMillis(System.currentTimeMillis());
calAkt.set(Calendar.DAY_OF_WEEK, 2);
calAkt.set(Calendar.HOUR_OF_DAY, 10);
calAkt.set(Calendar.MINUTE, 15);
Intent intent = new Intent(this, StartAlarm.class);
intent.putExtra("alarmCode", "12345");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 12345,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calAkt.getTimeInMillis(),
AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
}
}
StartAlarm extends BroadcastReceiver, actually the same plus starting another activity:
public class StartAlarm extends BroadcastReceiver {
private static final String TAG = "StartAlarm";
private WakeLock wl;
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context
.getSystemService(Activity.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SomeTag");
wl.acquire();
Intent intent2 = new Intent();
intent2.setClassName("com.test.testApp",
"com.test.testApp.DoThings");
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent2);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 12345,
intent2, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calAkt = Calendar.getInstance();
calAkt.setTimeInMillis(System.currentTimeMillis());
calAkt.set(Calendar.DAY_OF_WEEK, 2);
calAkt.set(Calendar.HOUR_OF_DAY, 10);
calAkt.set(Calendar.MINUTE, 15);
AlarmManager am = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calAkt.getTimeInMillis(),
AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
}
StartAlarm in the Manifest:
<receiver
android:name=".timer.StartAlarm"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I don't see what I'm doing wrong. Guess there's something I didn't understand... Any help is apprechiated!
Edit:
The problem was, that the alarm layed in the past. Solved it by setting the alarm to a future date by inserting
Calendar cal = Calendar.getInstance();
if (calAkt.compareTo(cal) <= 0) {
calAkt.add(Calendar.MINUTE, 8);
}
Thanks #CommonsWare for the hint
My apps alarm fires directly after each reboot
No, it does not. However, your StartAlarm BroadcastReceiver is getting control at boot time, because that is what you put in your manifest. If you do not want StartAlarm to get control at boot time, then get rid of its <intent-filter> in the manifest.

BroadcastReceiver is not called

I have to following code to call the BroadcastReceiver:
public class WorkItemAlarmManager {
...
public void initAlarm(HelpMe helpMe, String delay,String period,WorkItem workItem){
//HelpMe = Activity
helpMe.registerReceiver(new WorkItemAlarmHandler() , new IntentFilter("WORK_ITEM_ALARM"));
Intent intent = new Intent("WORK_ITEM_ALARM");
intent.setClass(helpMe, WorkItemAlarmManager.class);
intent.putExtra("work_item", workItem);
PendingIntent mAlarmSender = PendingIntent.getService(helpMe, 0,intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
//System.out.println("START"+System.currentTimeMillis());
calendar.add(Calendar.SECOND, calcDelayMillis(delay));
//System.out.println("END"+calendar.getTimeInMillis());
AlarmManager am = (AlarmManager) helpMe.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), mAlarmSender);
}
...
}
and the BroadcastReceiver:
public class WorkItemAlarmHandler extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
....
}
}
But the WorkItemAlarmHandler is never called.
Update:
I tried to register the BroadcastReceiver in the manifest at first. But that didn't work:
<receiver
android:name="de.helpme.alarm.WorkItemAlarmHandler"
android:enabled="true"
android:label="WorkItemAlarmHandler" >
<intent-filter>
<action android:name="WORK_ITEM_ALARM" />
</intent-filter>
</receiver>
Thanks for your answers :). Now it works - but i dont yet know which one is the correct because i implemented both answers at once. If a figure out which was the right one i mark the right as answer.
Update:
The cause of the problem as i see it was:
PendingIntent mAlarmSender = PendingIntent.getService(helpMe, 0,intent, 0);
With this code it works fine:
PendingIntent mAlarmSender = PendingIntent.getBroadcast(helpMe, 0, intent, 0);
Thanks again for all your help!
try this :
In WorkItemAlarmManager ;
public class WorkItemAlarmManager {
...
public void initAlarm(HelpMe helpMe, String delay,String period,WorkItem workItem){
Intent intent =new Intent(helpMe, WorkItemAlarmHandler.class);
intent.setAction("WORK_ITEM_ALARM");
intent.putExtra("work_item", workItem);
PendingIntent mAlarmSender=
PendingIntent.getBroadcast(helpMe, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
//System.out.println("START"+System.currentTimeMillis());
calendar.add(Calendar.SECOND, calcDelayMillis(delay));
//System.out.println("END"+calendar.getTimeInMillis());
AlarmManager am = (AlarmManager) helpMe.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), mAlarmSender);
}
...
}
and in WorkItemAlarmHandler:
public class WorkItemAlarmHandler extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("WORK_ITEM_ALARM")){
Toast.makeText(context, "WORK_ITEM_ALARM", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(context, "repeating alarm",
Toast.LENGTH_LONG).show();
}
}
}
Your code uses:
intent.setClass(helpMe, WorkItemAlarmManager.class);
but with the setClass(...) method you specify the class that should finally handle the intent.
Therefore you should write:
intent.setClass(helpMe, WorkItemAlarmHandler.class);
As far as I remember, if you specify the class or component manually (eg. with the setClass() method) this object has to be specified in the manifest, so make sure the receiver is mentioned there.

Categories

Resources