Ce tutoriel est réalisé et proposé par bunjix, développeur d’application sous Android. Vous pouvez voir son blog surhttp://bunjix.fr.
Dans ce tuto je vais créer un réveil simple. Le but est de montrer comment se passe l’activation d’une alarme à une heure voulue.
D’abord mon fichier XML pour l’affichage de mes informations (très simple)
01.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
02.
<
RelativeLayout
android:id
=
"@+id/RelativeLayout01"
03.
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
04.
xmlns:android
=
"http://schemas.android.com/apk/res/android"
05.
android:gravity
=
"center"
>
06.
<
CheckBox
android:layout_height
=
"wrap_content"
07.
android:layout_width
=
"fill_parent"
android:text
=
"07:00"
android:id
=
"@+id/heure"
08.
android:textSize
=
"40dip"
android:gravity
=
"center"
android:onClick
=
"changeHeure"
/>
09.
</
RelativeLayout
>
Pour réaliser ce réveil j’utilise la classe AlarmManager. Dans ma méthode onCreate j’ai 3 étapes:
1. Je charge les informations du réveil (voir plus bas pour l’explication).
2. Je gère l’affichage
3. Je planifie l’alarme.
2. Je gère l’affichage
3. Je planifie l’alarme.
01.
@Override
02.
public
void
onCreate(Bundle savedInstanceState) {
03.
//Chargement des informations du reveil
04.
charger();
05.
06.
super
.onCreate(savedInstanceState);
07.
setContentView(R.layout.main);
08.
09.
//Affichage
10.
affichage();
11.
12.
//Planification
13.
planifierAlarm();
14.
}
Pour que le réveil soit fonctionnel, je souhaite qu’il se réactive si je reboot mon téléphone. Il faut donc que je sauvegarde l’heure de mon réveil et ses informations. Pour cela j’ai créé une classe Alarm qui implémente Serializable
Code classe Alarm
01.
import
java.io.Serializable;
02.
import
android.text.format.Time;
03.
04.
public
class
Alarm
implements
Serializable{
05.
private
static
final
long
serialVersionUID = 1L;
06.
private
Time heure;
07.
private
boolean
active;
08.
public
Time getHeure() {
09.
return
heure;
10.
}
11.
public
void
setHeure(Time heure) {
12.
this
.heure = heure;
13.
}
14.
public
boolean
isActive() {
15.
return
active;
16.
}
17.
public
void
setActive(
boolean
active) {
18.
this
.active = active;
19.
}
20.
}
Pour charger les informations du réveil, j’ai donc la fonction charger. La fonction tente de charger l’objet Alarm Serialisé dans le fichier alarm.serial. Si ce fichier n’existe pas encore, on créer une alarm activé avec une heure fixée à 7h30.
01.
public
void
charger(){
02.
alarm =
null
;
03.
try
{
04.
ObjectInputStream alarmOIS=
new
ObjectInputStream(openFileInput(
"alarm.serial"
));
05.
alarm = (Alarm) alarmOIS.readObject();
06.
alarmOIS.close();
07.
}
08.
catch
(FileNotFoundException fnfe){
09.
alarm =
new
Alarm();
10.
alarm.setActive(
true
);
11.
Time t =
new
Time();
12.
t.hour =
7
;
13.
t.minute =
30
;
14.
alarm.setHeure(t);
15.
}
16.
catch
(IOException ioe) {
17.
ioe.printStackTrace();
18.
}
19.
catch
(ClassNotFoundException cnfe) {
20.
cnfe.printStackTrace();
21.
}
22.
}
Pour sauver les infos du réveil j’implémente la méthode sauver() :
01.
public
void
sauver(){
02.
try
{
03.
ObjectOutputStream alarmOOS=
new
ObjectOutputStream(openFileOutput(
"alarm.serial"
,MODE_WORLD_WRITEABLE));
04.
alarmOOS.writeObject(alarm);
05.
alarmOOS.flush();
06.
alarmOOS.close();
07.
}
08.
catch
(IOException ioe) {
09.
ioe.printStackTrace();
10.
}
11.
}
Toujours dans mon Activity j’ai ma fonction affichage qui affiche simplement les informations du réveil (l’heure et l’état : activé/désactivé)
01.
private
void
affichage() {
02.
//Ici on a juste voulu créer un affichage de l'heure qui soit au format hh:mm.
03.
String heureReveil =
""
;
04.
heureReveil += alarm.getHeure().hour >
10
? alarm.getHeure().hour :
"0"
+ alarm.getHeure().hour;
05.
heureReveil +=
":"
;
06.
heureReveil += alarm.getHeure().minute >
10
? alarm.getHeure().minute :
"0"
+ alarm.getHeure().minute;
07.
CheckBox ck_alarm = (CheckBox)findViewById(R.id.heure);
08.
ck_alarm.setText(heureReveil);
09.
ck_alarm.setChecked(alarm.isActive());
10.
}
Dans le fichier layout.xml qu’on peut voir au début, vous constaterez que pour la CheckBox, j’ai réglé l’attribut onClick (à partir de Android 1.6) avec la valeur changeHeure. Je dois donc implémenter la fonction :
Cette fonction se déclenchera donc au clic sur la checkbox ou l’heure. Elle s’occupera d’activer l’alarme ou de la désactiver. Si l’alarme passe en mode activée alors on affichera un TimePickerDialog afin de choisir l’heure.
Puis on replanifiera l’alarme.
Cette fonction se déclenchera donc au clic sur la checkbox ou l’heure. Elle s’occupera d’activer l’alarme ou de la désactiver. Si l’alarme passe en mode activée alors on affichera un TimePickerDialog afin de choisir l’heure.
Puis on replanifiera l’alarme.
01.
public
void
changeHeure(View target){
02.
CheckBox ck_alarm = (CheckBox)findViewById(R.id.heure);
03.
//Si on active l'alarm alors on veut choisir l'heure.
04.
if
(ck_alarm.isChecked()){
05.
TimePickerDialog dialog =
new
TimePickerDialog(
this
,
this
, alarm.getHeure().hour, alarm.getHeure().minute,
true
);
06.
dialog.show();
07.
}
08.
//On replanifie l'alarme.
09.
planifierAlarm();
10.
}
Le deuxième argument du constructeur du TimePickerDialog correspond au callback, le listener OnTimeSetListener qui se déclenche à la validation de la nouvelle heure.
Notre activity implémente donc cette interface et nous avons donc la fonction OnTimeSet qui va changer l’heure de notre objet alarm et replanifier l’alarme.
Notre activity implémente donc cette interface et nous avons donc la fonction OnTimeSet qui va changer l’heure de notre objet alarm et replanifier l’alarme.
01.
@Override
02.
public
void
onTimeSet(TimePicker view,
int
hourOfDay,
int
minute) {
03.
Time t =
new
Time();
04.
t.hour = hourOfDay;
05.
t.minute = minute;
06.
alarm.setHeure(t);
07.
affichage();
08.
planifierAlarm();
09.
}
Pour finir avec notre activity, nous avons la fameuse fonction planifierAlarm. Cette fonction va simplement supprimer (si elle existe) puis ajouter notre alarme dans le service AlarmManager.
Plusieurs étapes :
Plusieurs étapes :
1. On récupère une instance du service AlarmManager
2. On crée un Intent qui va être appelé au déclenchement de l’alarme.
3. On crée le PendingIntent qui identifie notre Alarm avec un ALARM_ID (champ static de notre Activity)
4. On annule l’alarme si elle existe dans l’AlarmManager
5. Ajout de l’alarme
2. On crée un Intent qui va être appelé au déclenchement de l’alarme.
3. On crée le PendingIntent qui identifie notre Alarm avec un ALARM_ID (champ static de notre Activity)
4. On annule l’alarme si elle existe dans l’AlarmManager
5. Ajout de l’alarme
01.
private
void
planifierAlarm() {
02.
//Récupération de l'instance du service AlarmManager.
03.
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
04.
05.
//On instancie l'Intent qui va être appelé au moment du reveil.
06.
Intent intent =
new
Intent(
this
, AlarmReceiver.
class
);
07.
08.
//On créer le pending Intent qui identifie l'Intent de reveil avec un ID et un/des flag(s)
09.
PendingIntent pendingintent = PendingIntent.getBroadcast(
this
, ALARM_ID, intent,
0
);
10.
11.
//On annule l'alarm pour replanifier si besoin
12.
am.cancel(pendingintent);
13.
14.
if
(alarm.isActive()){
15.
//on va déclencher un calcul pour connaitre le temps qui nous sépare du prochain reveil.
16.
Calendar reveil = Calendar.getInstance();
17.
reveil.set(Calendar.HOUR_OF_DAY, alarm.getHeure().hour);
18.
reveil.set(Calendar.MINUTE, alarm.getHeure().minute);
19.
if
(reveil.compareTo(Calendar.getInstance()) == -
1
)
20.
reveil.add(Calendar.DAY_OF_YEAR,
1
);
21.
Calendar cal = Calendar.getInstance();
22.
reveil.set(Calendar.SECOND,
0
);
23.
cal.set(Calendar.SECOND,
0
);
24.
long
diff = reveil.getTimeInMillis() - cal.getTimeInMillis();
25.
26.
//On ajoute le reveil au service de l'AlarmManager
27.
am.set(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis() + diff, pendingintent);
28.
Toast.makeText(
this
,
"Alarme programmé le "
+ reveil.get(Calendar.DAY_OF_MONTH) +
" à "
+ reveil.get(Calendar.HOUR_OF_DAY) +
":"
+ reveil.get(Calendar.MINUTE), Toast.LENGTH_SHORT).show();
29.
}
30.
}
Il nous reste donc maintenant à écrire la classe AlarmReceiver qui va être déclenché au moment du réveil. Cette classe doit dériver de BroadcastReceiver
01.
import
android.content.BroadcastReceiver;
02.
import
android.content.Context;
03.
import
android.content.Intent;
04.
import
android.widget.Toast;
05.
06.
public
class
AlarmReceiver
extends
BroadcastReceiver{
07.
08.
@Override
09.
public
void
onReceive(Context context, Intent intent) {
10.
try
{
11.
Toast.makeText(context,
"C'est l'heure !!!"
,Toast.LENGTH_LONG).show();
12.
//On peut mettre ce que l'on veut. Vibreur, lecture d'un mp3 ou autre.
13.
}
14.
catch
(Exception r) {
15.
Toast.makeText(context,
"Erreur."
,Toast.LENGTH_SHORT).show();
16.
r.printStackTrace();
17.
}
18.
}
19.
}
On peut également créer une autre classe AlarmBootReceiver qui va être déclenché au démarrage du téléphone afin de recharger notre réveil.
Cette classe contient également les méthodes charger et planifierAlarm.
Cette classe contient également les méthodes charger et planifierAlarm.
01.
public
class
AlarmBootReceiver
extends
BroadcastReceiver{
02.
Alarm alarm;
03.
Context context;
04.
@Override
05.
public
void
onReceive(Context context, Intent intent) {
06.
this
.context = context;
07.
charger();
08.
planifierAlarm();
09.
}
10.
11.
...
12.
}
Dernière étape, le manifest :
01.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
02.
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
03.
package
=
"com.bunjix.tuto.Reveil"
04.
android:versionCode
=
"1"
05.
android:versionName
=
"1.0"
>
06.
<
application
android:icon
=
"@drawable/icon"
android:label
=
"@string/app_name"
>
07.
<
activity
android:name
=
".Reveil"
08.
android:label
=
"@string/app_name"
android:theme
=
"@android:style/Theme.Light"
>
09.
<
intent-filter
>
10.
<
action
android:name
=
"android.intent.action.MAIN"
/>
11.
<
category
android:name
=
"android.intent.category.LAUNCHER"
/>
12.
</
intent-filter
>
13.
</
activity
>
14.
<
receiver
android:name
=
"com.bunjix.tuto.Reveil.AlarmReceiver"
android:process
=
":remote"
/>
15.
<
receiver
android:name
=
"com.bunjix.tuto.Reveil.AlarmBootReceiver"
>
16.
<
intent-filter
>
17.
<
action
android:name
=
"android.intent.action.BOOT_COMPLETED"
/>
18.
</
intent-filter
>
19.
</
receiver
>
20.
</
application
>
21.
<
uses-sdk
android:minSdkVersion
=
"4"
/>
22.
23.
<
uses-permission
android:name
=
"android.permission.RECEIVE_BOOT_COMPLETED"
></
uses-permission
>
24.
</
manifest
>
0 commentaires:
Enregistrer un commentaire