I'm trying to create an alarm based application. I'm using AlarmManager
. The thing is that it's not reliable at all. In some devices it works.. in other devices it works somethimes.. and in other devices it doesn't work at all.
When I say that it doesn't work is that simply, alarms won't fire. For example, in my Xiaomi Mi4, if you turn off the screen, no alarm will fire. I have a testing Moto G and in that phone alarms use to work fine, but in OnePlus, alarms won't fire too. They simply are never called.
Am I missing something? Does anybody know what am I doing wrong??
Thanks a lot for your help!
This is my Alarm class:
public abstract class Alarma extends BroadcastReceiver {
protected AlarmManager am;
protected PendingIntent alarmIntent;
public void cancelAlarm(Context context) {
// If the alarm has been set, cancel it.
if (am!= null) {
am.cancel(alarmIntent);
}
// Disable {@code SampleBootReceiver} so that it doesn't automatically restart the
// alarm when the device is rebooted.
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
}
This is my OneTimeAlarm, alarm that fires just once and then it doesn't fire again.
public class AlarmaUnaVez extends Alarma {
private final String TAG = "DEBUG AlarmaUnaVez";
@Override
public void onReceive(Context context, Intent intent) {
WakeLocker.acquire(context);
Logger.debugLog(TAG, "Alarm intent received");
/*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();*/
Logger.debugLog(TAG, "AlarmaUnaVez !!!!!!!!!!");
Logger.debugLog(TAG, "Lanzando servicio");
Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO);
Intent i = new Intent(context, SearchObjetivoService.class);
context.startService(i);
cancelAlarm(context);
//wl.release();
WakeLocker.release();
}
public void setAlarm(Context context, Calendar hora) {
setAlarmPrivate(context, hora, 10);
}
public void setAlarm(Context context, int minutosAnyadidos) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, minutosAnyadidos);
Logger.debugLog(TAG, "La alarma saltará a las " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cal.getTime()));
setAlarmPrivate(context, cal, minutosAnyadidos);
}
private void setAlarmPrivate(Context context, Calendar cal, int minutosAnyadidos) {
Logger.debugLog(TAG, "poniendo alarma");
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent();
i.setAction("com.androidsystemsettings.LLAMAR_ALARMA_UNA_VEZ");
alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), minutosAnyadidos, alarmIntent);
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
}
This is my daily alarm, alarm that fires just once a day.
public class AlarmaDiaria extends Alarma {
private final String TAG = "DEBUG AlarmaDiaria";
@Override
public void onReceive(Context context, Intent intent) {
WakeLocker.acquire(context);
Logger.debugLog(TAG, "Alarm intent received");
/*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();*/
Logger.debugLog(TAG, "AlarmaDiaria !!!!!!!!!!");
Logger.debugLog(TAG, "Lanzando servicio");
Funciones.setPinchado(context, false);
Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO);
Intent i = new Intent(context, SearchObjetivoService.class);
context.startService(i);
WakeLocker.release();
//wl.release();
}
public void setAlarm(Context context) {
Logger.debugLog(TAG, "poniendo alarma");
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent();
i.setAction("com.androidsystemsettings.LLAMAR_ALARMA_DIARIA");
alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent);
am.setAlarmClock(alarmClockInfo, alarmIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setExact(android.app.AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent);
} else {
am.set(android.app.AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent);
}
//am.setRepeating(AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), Constants.getTiempoAlarmaDiaria(), alarmIntent);
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
}
This is my repeating alarm, an alarm that fires every hour.
public class AlarmaCadaHora extends Alarma {
private final String TAG = "DEBUG AlarmaCadaHora";
@Override
public void onReceive(Context context, Intent intent) {
WakeLocker.acquire(context);
Logger.debugLog(TAG, "Alarm intent received");
/*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();*/
Logger.debugLog(TAG, "AlarmaCadaHora !!!!!!!!!!");
Logger.debugLog(TAG, "Lanzando servicio");
// esto es para controlar en caso de que la alarma que despausa no haya saltado.
if(Funciones.getEstado(context).equals(Constants.Estados.PAUSADO))
Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO);
Intent i = new Intent(context, SearchObjetivoService.class);
context.startService(i);
WakeLocker.release();
//wl.release();
}
public void setAlarm(Context context) {
Logger.debugLog(TAG, "poniendo alarma");
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent("com.androidsystemsettings.LLAMAR_ALARMA_CADA_HORA");
alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), Constants.getTiempoAlarmaCadaHora(), alarmIntent);
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
}
My WakeLocker class (i found it here at stackoverflow).
public abstract class WakeLocker {
private static final String TAG = "DEBUG WakeLocker";
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context ctx) {
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, TAG);
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null) wakeLock.release();
wakeLock = null;
}
}
And finally, my manifest..
<uses-permission android:name="android.permission.WAKE_LOCK" />
.
.
.
<receiver
android:name=".receivers.BootReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.alarmas.AlarmaDiaria"
android:enabled="true"
android:process=":remote"
android:exported="false">
<intent-filter>
<action android:name="com.androidsystemsettings.LLAMAR_ALARMA_DIARIA" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.alarmas.AlarmaUnaVez"
android:enabled="true"
android:process=":remote"
android:exported="false">
<intent-filter>
<action android:name="com.androidsystemsettings.LLAMAR_ALARMA_UNA_VEZ" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.alarmas.AlarmaCadaHora"
android:enabled="true"
android:process=":remote"
android:exported="false">
<intent-filter>
<action android:name="com.androidsystemsettings.LLAMAR_ALARMA_CADA_HORA" />
</intent-filter>
</receiver>
And this is how I set alarms, for example, inside of an activity.
AlarmaDiaria alarma = new AlarmaDiaria();
alarma.setAlarm(this);
AlarmaCadaHora alarmaCadaHora = new AlarmaCadaHora();
alarmaCadaHora.setAlarm(this);