Working repeating alarmmanager doesn't work, receiver doesn't start - android

public void schedule()
{
Long time = new GregorianCalendar().getTimeInMillis()+10*1000;
Intent intent = new Intent(getActivity(), AlarmReceiver.class);
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, time, 10*1000, PendingIntent.getBroadcast(getActivity(), 1, intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
Above this is my method in a Fragment. Also tried in Activity. Weirdly this code works on an empty test project. The problem as I've seen here is that the last part, alarmManager.setInexactRepeating() does not start the AlarmReceiver.class at all.
What am I doing wrong here?
my Manifest file:
<receiver android:name=".AlarmReceiver"/>
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
also my receiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
Toast.makeText(context, "Alarm Triggered and SMS Sent", Toast.LENGTH_LONG).show();
}
}

Because of setInexactRepeating. Use setRepeating and it will be processed at the right time.
Instead of:
setInexactRepeating
use
setRepeating
setInexactRepeating, is OS and battery friendly, it batches together all the work to be done on Alarm receive and works through one by one, while as setRepeating instantly fires the alarm
Also a note: Alarms are wiped off once phone is rebooted, you might have to implement a boot broadcast receiver to make it persistent. Make sure you dont do that runtime, you need to implement it in the Manifest else when your app is not in background you will not receive any broadcasts.
A small example:
This is working code. It wakes CPU every 10 minutes until the phone turns off.
Add to Manifest.xml:
...
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
...
<receiver android:process=":remote" android:name="Alarm"></receiver>
...
Code:
package YourPackage;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.widget.Toast;
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
wl.release();
}
public void SetAlarm(Context context)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, 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);
}
}
Set Alarm from Service:
package YourPackage;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
public class YourService extends Service
{
Alarm alarm = new Alarm();
public void onCreate()
{
super.onCreate();
}
public void onStart(Context context,Intent intent, int startId)
{
alarm.SetAlarm(context);
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
If you want set alarm repeating at phone boot time:
Add permission to Manifest.xml:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
...
<receiver android:name=".AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
...
And create new class:
package YourPackage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AutoStart extends BroadcastReceiver
{
Alarm alarm = new Alarm();
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
{
alarm.SetAlarm(context);
}
}
}

Related

AlarmManager is not repeating

I can't make AlarmManager repeating. I have tried a lot of examples, but for me they don't work. Alarm always fires only once, then nothing happens.
I ran all examples on my device (android 4.4.2) and all the examples work completely the same. Just one fire, and then nothing.
Can anybody tell me what I'm doing wrong?
Here is the code of the last example:
Receiver:
package net.desme.alarmtest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.widget.Toast;
public class Alarm extends BroadcastReceiver {
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();
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_SHORT).show(); // For example
wl.release();
}
public void setAlarm(Context context)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 6, 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);
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.desme.alarmtest" >
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".AlarmManagerActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".Alarm" android:process=":remote" />
</application>
</manifest>
Activity:
package net.desme.alarmtest;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
public class AlarmManagerActivity extends Activity {
Alarm alarm = new Alarm();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm_manager);
findViewById(R.id.start_repeating).setOnClickListener(mStartRepeatingListener);
findViewById(R.id.stop_repeating).setOnClickListener(mStopRepeatingListener);
}
private View.OnClickListener mStartRepeatingListener = new View.OnClickListener() {
public void onClick(View v) {
alarm.setAlarm(getApplicationContext());
}
};
private View.OnClickListener mStopRepeatingListener = new View.OnClickListener() {
public void onClick(View v) {
alarm.cancelAlarm(getApplicationContext());
}
};
}
Also i tried these:
https://developer.android.com/training/scheduling/alarms.html
http://www.coderzheaven.com/2011/07/31/how-to-setup-a-repeating-alarm-in-android/
and much more but i cant post it because the red tip says that i need at least 10 reputation
EDIT
The problem was that in API 19+ all alarms are inexact. Here is what the documentation says:
Note: as of API 19, all repeating alarms are inexact. If your
application needs precise delivery times then it must use one-time
exact alarms, rescheduling each time as described above. Legacy
applications whose targetSdkVersion is earlier than API 19 will
continue to have all of their alarms, including repeating alarms,
treated as exact.
And possible solutions:
Note: for timing operations (ticks, timeouts, etc) > it is easier and much more efficient to use Handler
If your application wants to allow the delivery times to drift in order to guarantee that at least a certain time interval always elapses between alarms, then the approach to take is to use one-time alarms, scheduling the next one yourself when handling each alarm delivery.
this is the solution for starting an alarm for repeating with 10 seconds interval, but it's pending intent is different, because i used this method to start service after 10 seconds interval, therefore use it according to your requirement,
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(Main.this, Service_class.class);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
36000 * 1000, pintent);
Thanks
Your code works fine in Android 4.4.2 API 22. Maybe the AlarmManager on your device/API is acting differently; perhaps overriding the frequency since it's so short. Do you really need 6 seconds interval? Try increasing the frequency over a minute, i.e. > 60000.

AlarmManager fires alarms at wrong time

I managed everything all right to create a notification service used to fire a notification as a result of an alarm. Unfortunately, setting the alarm using AlarmManager doesn't work right. It fires several minutes later (not exactly hours, which would indicate a timezone problem). The recurring period is 1 week, so I used the constant INTERVAL_DAY and multiplied it with 7. In order to make sure that one PendingIntent doesn't replace the other, I pass the dayOfWeek as second parameter to PendingIntent.getService(). I check the correctness of the time for the alarm to fire by logging it:
Log.d(TAG, "next alarm " + df.format(cal.getTime()));
Is there really no way to list all alarms set - at least those from my own app? I believe this is the only way to track down the error.
My code:
cal.setTimeInMillis(System.currentTimeMillis());
cal.add(Calendar.DATE, 1);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
Log.d(TAG, "next alarm " + df.format(cal.getTime()));
Intent showNotificationIntent = new Intent(context, NotificationService.class);
dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
alarmIntent = PendingIntent.getService(context, dayOfWeek, showNotificationIntent, 0);
getAlarmManager(context).setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
INTERVAL_WEEK, alarmIntent);
I want to offer to have an alarm every day, but at various times, which can be set by the user. So I use up to 7 alarms, which should fire on a weekly basis.
Even after reading the numerous answers to similar questions (I don't intend to create a duplicate question), I haven't managed to find the problem.
For api levels below 19 you should use AlarmManager.setRepeating() and your alarms will trigger exactly at specified time. Thou on api levels 19 and above this will no longer work. There was change in android so that all repeating alarms are inexact. So if you would like to achieve exact repeating alarm you should schedule alarm with AlarmManager.setExact() and then when alarm triggers do it again for next week and so on every week.
Because of setInexactRepeating. Use setRepeating and it will be processed at the right time.
Instead of:
setInexactRepeating
use
setRepeating
setInexactRepeating, is OS and battery friendly, it batches together all the work to be done on Alarm receive and works through one by one, while as setRepeating instantly fires the alarm
Also a note: Alarms are wiped off once phone is rebooted, you might have to implement a boot broadcast receiver to make it persistent. Make sure you dont do that runtime, you need to implement it in the Manifest else when your app is not in background you will not receive any broadcasts.
A small example:
This is working code. It wakes CPU every 10 minutes until the phone turns off.
Add to Manifest.xml:
...
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
...
<receiver android:process=":remote" android:name="Alarm"></receiver>
...
Code:
package YourPackage;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.widget.Toast;
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
wl.release();
}
public void SetAlarm(Context context)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, 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);
}
}
Set Alarm from Service:
package YourPackage;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
public class YourService extends Service
{
Alarm alarm = new Alarm();
public void onCreate()
{
super.onCreate();
}
public void onStart(Context context,Intent intent, int startId)
{
alarm.SetAlarm(context);
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
If you want set alarm repeating at phone boot time:
Add permission to Manifest.xml:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
...
<receiver android:name=".AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
...
And create new class:
package YourPackage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AutoStart extends BroadcastReceiver
{
Alarm alarm = new Alarm();
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
{
alarm.SetAlarm(context);
}
}
}

How to start an activity using AlarmManager etc

I am trying to start code inside an activity at regular intervals using Alarm manager. I have looked at various examples on here but they have not really helped.
For testing purposes, all I am trying to do is pop up a toast at 10 second intervals, but nothing seems to be happening at all. Please help guys!
I have this in the manifest (also declarations for all three activities):
<receiver android:name=".receiver.AlarmReceiver"></receiver>
Code from main activity, in OnCreate:
//
// Setting up the Alarm Manager
//
Intent myIntent = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
long timerInterval = 10 * 1000;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), timerInterval, pendingIntent);
//finish();
AlarmReceiver.java:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context," onRecieve() test" , Toast.LENGTH_LONG).show();
Intent scheduledIntent = new Intent(context, MyService.class);
scheduledIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scheduledIntent);
}
}
MyService.java:
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
public void onCreate(Bundle savedInstanceState) {
super.onCreate();
Toast.makeText(getBaseContext(),"test message.",
Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
Your activity is not showing, because you are calling startActivity() on an Intent that identifies a Service. You should see warnings related to this in LogCat.
I humbly suggest that you use LogCat yourself, via the Log class, for logging background operations, rather than attempting to use a Toast.
test this code:
private void establecerAlarmaClick(int when){
AlarmManager manager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(MainActivityAlarmita.this, MainActivityAlarmita.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivityAlarmita.this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
((AlarmManager) getSystemService(ALARM_SERVICE)).set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + when * 1000, pendingIntent);
}

Starting a service via Alarm does not work

I have the following broadcast reciever that gets called when the phone boots up (Bootreciever.java) and I'm trying to start a service that runs intermittently using a repeating alarm.
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Inside onRecieve() :D" , Toast.LENGTH_LONG).show();
Log.d(getClass().getName(), "Inside onRecieve() :D");
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyService.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 3000, 1000, pi);
}
Basically, I'm setting a repeating alarm to trigger 3 seconds and on every second after that. The bootup complete broadcast is received just fine - but the service does not start. MyService.java looks like this:
public class MyService extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Hello from MyService!", Toast.LENGTH_LONG);
Log.d(getClass().getName(), "Hello from MyService!");
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
What am I doing wrong when starting the service?
Logcat does not tell me anything and I have the service defined in my manifest. On its own this service works when called using startService() but seem to fail when used within a PendingIntent.
Instead of PendingIntent.getBroadcast() use PendingIntent.getService()
I think you should check your duration because android gets a bit picky with alarms that trigger too often. In order to start a service the best way is to set the alarm to broadcast the intent to a broacast receiver and then get it to start your services.
Example 1 the receiver:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class QoutesReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// log instruction
Log.d("SomeService", "Receiving Broadcast, starting service");
// start the qoute service
Intent newService = new Intent(context, SomeService.class);
context.startService(newService);
}
}
Example 2 the Function that sets the alarm (this example runs every 2 mins):
public void setAlarm(Context context) {
// Get the current time
Calendar currTime = Calendar.getInstance();
// Get the intent (start the receiver)
Intent startReceiver = new Intent(context, MyReceiver.class);
PendingIntent pendReceiver = PendingIntent.getBroadcast(context, 0,
startReceiver, PendingIntent.FLAG_CANCEL_CURRENT);
// call the Alarm service
AlarmManager alarms = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
//Setup the alarm
alarms.setRepeating(AlarmManager.RTC_WAKEUP,
currTime.getTimeInMillis() + (2 * 60 * 1000), 2 * 60 * 1000,
pendReceiver);
}

Using a broadcast receiver to start AlarmManager in Android?

I am writing a program that fires off an intent to start a service periodically, to do this I have decided to use alarmmanager, I was able to make this do what I wanted in an activity fairly easily but I'm getting an error when attempting to do it in a receiver that I'm unable to figure out.
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
tells me that ALARM_SERVICE can't be resolved to a variable
here is my complete code for that receiver:
package com.testapp21.second.activities;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
public class PhoneOnReceiver extends BroadcastReceiver {
private PendingIntent mAlarmSender;
#Override
public void onReceive(Context context, Intent intent) {
mAlarmSender = PendingIntent.getService(context,
0, new Intent(context, StatsCheckerService.class), 0);
// We want the alarm to go off 30 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, 30*1000, mAlarmSender);
}
}
Try
AlarmManager am = (AlarmManager)context.getSystemService(Service.ALARM_SERVICE);
I found that if you are in a fragment you can do this
AlarmManager am = (AlarmManager)getActivity().getSystemService(Service.ALARM_SERVICE);

Categories

Resources