2016-03-31 17 views
5

Sto provando a creare un'applicazione basata su allarme. Sto usando AlarmManager. Il fatto è che non è affatto affidabile. In alcuni dispositivi funziona .. in altri dispositivi funziona a volte .. e in altri dispositivi non funziona affatto.AlarmManager non funziona correttamente

Quando dico che non funziona è che semplicemente, gli allarmi non sparano. Ad esempio, nel mio Xiaomi Mi4, se si spegne lo schermo, nessun allarme scatterà. Ho un Moto G di test e in quel telefono gli allarmi funzionano bene, ma in OnePlus gli allarmi non vengono attivati. Semplicemente non vengono mai chiamati.

Mi manca qualcosa? Qualcuno sa cosa sto facendo male ??

Grazie mille per il vostro aiuto!

Questa è la mia classe di allarme:

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); 
    } 

} 

Questo è il mio OneTimeAlarm, allarme che spara solo una volta e poi non si attiva di nuovo.

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); 
    } 
} 

Questo è il mio allarme giornaliero, allarme che spara solo una volta al giorno.

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); 
    } 
} 

Questo è il mio allarme ripetuto, un allarme che spara ogni ora.

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); 
    } 
} 

La mia classe WakeLocker (l'ho trovata qui su 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; 
    } 

} 

E, infine, il mio manifesto ..

<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> 

Ed è così che ho impostato gli allarmi, ad esempio, all'interno di un'attività.

AlarmaDiaria alarma = new AlarmaDiaria(); 
    alarma.setAlarm(this); 

    AlarmaCadaHora alarmaCadaHora = new AlarmaCadaHora(); 
    alarmaCadaHora.setAlarm(this); 
+0

potresti per favore essere più chiaro su cosa non funziona? è attivo l'allarme una tantum? l'allarme giornaliero funziona? sta funzionando l'allarme ripetuto? In quali circostanze non funziona? mai o qualche volta o solo se il dispositivo è in modalità di sospensione? – Opiatefuchs

+0

Non vedo nemmeno come vengono impostati –

+0

Ho modificato il mio commento per rispondere a @Opiatefuchs. – JFValdes

risposta

2

C'è un cambiamento nel modo in cui AlarmManager funziona in API19. Quindi presumo che funzioni "su pre API19 ma" non funziona "sui dispositivi più recenti. Here's why:

Nota: Cominciando con API 19 (KitKat) consegna allarme è inesatta: il sistema operativo si sposterà gli allarmi al fine di minimizzare wakeups e l'uso della batteria. Lì sono nuove API per supportare le applicazioni che richiedono rigorose garanzie di consegna ; vedere setWindow (int, long, long, PendingIntent) e setExact (int, long, PendingIntent). Le applicazioni la cui target targetSdkVersion è precedente all'API 19 continueranno a vedere il comportamento precedente di in cui tutti gli allarmi vengono recapitati esattamente quando è richiesto .

3

Oltre alla risposta di Marcin, un altro motivo potrebbe essere una build in task-manager/energy-manager. Se scrivi, la sveglia funziona bene su alcuni dispositivi e, in alcuni casi, potrebbe essere a causa di API inferiori/superiori come suggerito da Marcin. Ma c'è un'altra cosa che ho esplorato sul mio Huawei Ascend Mate 7: alcuni dispositivi hanno un sistema di controllo dell'energia all'interno che chiude completamente l'applicazione dopo lo spegnimento dello schermo.Ho avuto lo stesso problema con una delle mie app con un gestore di allarmi e nulla ha aiutato, sia che si tratti di un servizio normale o di un servizio in primo piano, né di alcuna altra soluzione di programmazione. Era semplicemente semplice: dovevo andare a settings-->energy saving mode-->protected apps. Qui devi abilitare la protezione della tua app.

Può darsi che questa non sia la soluzione nel tuo caso, ma è in molti altri dispositivi e questa spiegazione è troppo lunga per un commento, quindi devo metterla come risposta.

+0

Sì, sono completamente d'accordo con te. Penso che questo sia il vero problema .. – JFValdes

Problemi correlati