Alarmes et planification des tâches

Afin d’exécuter des tâches répétitives il est possible d’utiliser l’AlarmManager qui permet de planifier des travaux à une heure et/ou date. A partir de l’API 21 un JobScheduler permet de planifier des travaux dépendant de certains états du périphérique (connecté au wifi,…)

AlarmManager :

1°) Définition :

  1. AlarmManager est la classe qui est utilisée pour les alarmes. Elle permet d’exécuter du code et peut être activée en dehors de l’application qui la générée,
  2. Une alarme peut se déclencher même si le périphérique est en veille,
  3. Attention à la consommation de batterie, ne pas créer trop d’alarmes et trop fréquentes,
  4. Once an Alarm Started, this will execute until it is stopped explicitly or until device reboots.
  5. La classe AlarmManger vous permet de lancer un Intent, et peut être utilisée avec des
    broadcast receivers.

2°) Mise en oeuvre :

  1. Android autorise 2 types d’Alarme : Une basée sur le temps réel (RTC) et l’autre sur le temps écoulé,
  2. Le temps écoulé est calculé à partir du dernier boot du périphérique,
  3. RTC est basé sur l’horloge du périphérique.

Pour définir une alarme

L’alarme peut par exemple déclencher un BroadCast :

 package com.andrologiciels.androalarmtest;  
 import android.content.BroadcastReceiver;  
 import android.content.Context;  
 import android.content.Intent;  
 import android.widget.Toast;  
 public class AlarmReceiver extends BroadcastReceiver {  
   @Override  
   public void onReceive(Context context, Intent intent) {  
     // For our recurring task, we'll just display a message  
     Toast.makeText(context, "I'm running", Toast.LENGTH_SHORT).show();  
   }  
 }  

Initialisation de l’Alarme :

a) A un interval précis (en millisecondes ) :

   public void start() {  
     AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);  
     int interval = 8000;  
     manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);  
     Toast.makeText(this, "Alarm Set", Toast.LENGTH_SHORT).show();  
   }  

 

Le fichier manifest (rien de particulier comme permission sauf pour le boot et le broadcast receiver) :

 <?xml version="1.0" encoding="utf-8"?>  
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
   package="com.andrologiciels.androalarmtest"  
   android:versionCode="1"  
   android:versionName="1.0" >  
   <uses-sdk  
     android:minSdkVersion="8"  
     android:targetSdkVersion="21" />  
   <permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  
   <application  
     android:allowBackup="true"  
     android:icon="@drawable/ic_launcher"  
     android:label="@string/app_name"  
     android:theme="@style/AppTheme" >  
     <activity  
       android:name=".MyActivity"  
       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=".AlarmReceiver" >  
     </receiver>  
     <receiver  
       android:name=".DeviceBootReceiver"  
       android:enabled="true"  
       android:exported="true" >  
       <intent-filter>  
         <action android:name="android.intent.action.BOOT_COMPLETED" />  
         <category android:name="android.intent.category.LAUNCHER" />  
         <action android:name="android.intent.action.QUICKBOOT_POWERON" />  
       </intent-filter>  
     </receiver>  
   </application>  
 </manifest>  

 Code source

ATTENTION :

Pour un réveil à un horaire donné avec une répétition sur un interval :

           AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);  
           int interval = 1000 * 30 * 1; // every 30s repeat  
           int nHour = 14;  
           int nMin = 30;  
           Calendar calendar = Calendar.getInstance();  
           calendar.setTimeInMillis(System.currentTimeMillis());  
           calendar.set(Calendar.HOUR_OF_DAY, nHour);  
           calendar.set(Calendar.MINUTE, nMin);  
           // -- Attention, récuparation pour init de l'heure du jour  
           if (calendar.getTimeInMillis() < System.currentTimeMillis()) {  
                calendar.add(Calendar.DAY_OF_YEAR, 1);  
           }  
           Toast.makeText(this, "Alarm Scheduled at " + nHour + ":" + nMin,  
                     Toast.LENGTH_SHORT).show();  
           /* Repeating on an interval */  
           manager.setInexactRepeating(AlarmManager.RTC_WAKEUP,  
                     System.currentTimeMillis(), interval, pendingIntent);  

 

Alarme au démarrage :

Les alarmes sont annulées lorsqu le téléphone est éteinds. Pour lancer une alarme au démarrage il est nécessaire de :

1°) Ajouter au manifest :

<uses-permission android:name= »android.permission.RECEIVE_BOOT_COMPLETED » />
<uses-permission android:name= »android.permission.WAKE_LOCK » />

et

<receiver android:name= ».DeviceBootReceiver » >
<intent-filter>
<action android:name= »android.intent.action.BOOT_COMPLETED » />

<category android:name= »android.intent.category.LAUNCHER » />

<action android:name= »android.intent.action.QUICKBOOT_POWERON » />
</intent-filter>
</receiver>

et

<service android:name= ».serviceAlarm » >
</service>

2°) Ecrire la procédure onBootReceiver :

 public class DeviceBootReceiver extends BroadcastReceiver {  
      @Override  
      public void onReceive(Context context, Intent intent) {  
           WakefulIntentService.acquireStaticLock(context); // --acquire a partial WakeLock                                                                            //   
           context.startService(new Intent(context, serviceAlarm.class)); // --start serviceAlarm 
      }  
 }  

3°) Ajouter un wake lock pour réveiller le téléphone

 package com.andrologiciels.androalarmtest;  
 import android.annotation.SuppressLint;  
 import android.app.IntentService;  
 import android.content.Context;  
 import android.content.Intent;  
 import android.os.PowerManager;  
 /**  
  * Acquires a partial WakeLock, allows Service to keep the CPU alive  
  * until the work is done.  
  */  
 @SuppressLint("Wakelock")  
 public class WakefulIntentService extends IntentService {  
   public static final String  
   LOCK_NAME_STATIC="com.andologiciels.androalarmtest.serviceAlarm.Static";;  
   public static final String  
   LOCK_NAME_LOCAL="com.andologiciels.androalarmtest.serviceAlarm.Local";  
   private static PowerManager.WakeLock lockStatic=null;  
   private PowerManager.WakeLock lockLocal=null;  
   public WakefulIntentService(String name) {  
     super(name);  
   }  
   /**  
    * Acquire a partial static WakeLock, you need too call this within the class  
    * that calls startService()  
    * @param context  
    */  
   public static void acquireStaticLock(Context context) {  
     getLock(context).acquire();  
   }  
   synchronized private static PowerManager.WakeLock getLock(Context context) {  
     if (lockStatic==null) {  
       PowerManager  
       mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE);  
       lockStatic=mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,  
           LOCK_NAME_STATIC);  
       lockStatic.setReferenceCounted(true);  
     }  
     return(lockStatic);  
   }  
   @Override  
   public void onCreate() {  
     super.onCreate();  
     PowerManager mgr=(PowerManager)getSystemService(Context.POWER_SERVICE);  
     lockLocal=mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,  
         LOCK_NAME_LOCAL);  
     lockLocal.setReferenceCounted(true);  
   }  
   @Override  
   public void onStart(Intent intent, final int startId) {  
     lockLocal.acquire();  
     super.onStart(intent, startId);  
     getLock(this).release();  
   }  
   @Override  
   protected void onHandleIntent(Intent intent) {  
     lockLocal.release();  
   }  
 }  

4°) Le service qui lance l’alarme

 package com.andrologiciels.androalarmtest;  
 import android.app.AlarmManager;  
 import android.app.PendingIntent;  
 import android.content.Context;  
 import android.content.Intent;  
 import android.widget.Toast;  
 public class serviceAlarm extends WakefulIntentService {  
      private PendingIntent pendingIntent;  
      public serviceAlarm() {  
           super("serviceAlarm");  
      }  
      @Override  
      protected void onHandleIntent(Intent intent) {  
            /* Retrieve a PendingIntent that will perform a broadcast */  
     Intent alarmIntent = new Intent(serviceAlarm.this, AlarmReceiver.class);  
     pendingIntent = PendingIntent.getBroadcast(serviceAlarm.this, 0, alarmIntent, 0);  
     AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);  
     int interval = 1000 * 30 * 1; //30 secondes  
     manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);  
     Toast.makeText(this, "Alarm Set", Toast.LENGTH_SHORT).show();  
           super.onHandleIntent(intent);  
      }  
 }  

 5°) Et la classe contenant l’action à effectuer au lancement de l’alarme :

 package com.andrologiciels.androalarmtest;  
 import android.content.BroadcastReceiver;  
 import android.content.Context;  
 import android.content.Intent;  
 import android.widget.Toast;  
 public class AlarmReceiver extends BroadcastReceiver {  
   @Override  
   public void onReceive(Context context, Intent intent) {  
     // For our recurring task, we'll just display a message  
     Toast.makeText(context, "Alarm is running...", Toast.LENGTH_SHORT).show();  
   }  
 }  

Liste des alarmes actives :

Branchez le terminale et tapez dans une fenêtre système (cmd) :

..\sdk\platform-tools>adb shell dumpsys alarm > dump.txt

Editez le fichier dump.txt et recherchez le package qui a lancé l’alarme, exemple :

RTC #4: Alarm{41c6dcc0 type 1 com.andrologiciels.andronameday}

type=1 originalType=0 when=+23m37s104ms repeatInterval=3600000 count=1

Ici l’on voit que l’alarme va être lancée dans 23′ et quelle sera répétée toutes les heures (3600000 millisecondes)

https://www.unitjuggler.com/convertir-time-de-ms-en-h.html?val=3600000

Références :

http://blog.masconsult.eu/blog/2014/01/17/scheduling-alarms/

http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent)

http://developer.android.com/reference/android/app/AlarmManager.html#ELAPSED_REALTIME

https://developer.android.com/training/scheduling/alarms.html#type

Alarme : http://javatechig.com/android/repeat-alarm-example-in-android

Scheduler : http://www.vogella.com/tutorials/AndroidTaskScheduling/article.html#schedulestasks_jobscheduler

Liste des alarmes actives : http://stackoverflow.com/questions/6522792/get-list-of-active-pendingintents-in-alarmmanager

http://www.101apps.co.za/articles/scheduling-android-s-repeating-alarms.html

https://dhimitraq.wordpress.com/2012/11/27/using-intentservice-with-alarmmanager-to-schedule-alarms/

http://stackoverflow.com/questions/26380534/broadcastreceiver-vs-wakefulbroadcastreceiver

Et au sujet de wakefull :

https://sufficientlysecure.org/index.php/2012/05/24/execute-service-once-a-day-when-internet-connection-is-available/comment-page-1/

https://randling.wordpress.com/2013/12/29/wakeful-and-repeatable-background-service-on-android/

http://stackoverflow.com/questions/7845660/how-to-run-a-service-every-day-at-noon-and-on-every-boot

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.

Articles récents
Commentaires récents
fatima dans Bienvenue !
AdminDroid dans Bienvenue !
fatima dans Bienvenue !
Archives
Catégories