I. Prérequis▲
Le tutoriel implique que vous ayez déjà des connaissances de base dans le développement Android. Veuillez consulter le tutoriel de développement Android pour en apprendre les bases.
II. Vue d'ensemble▲
II-A. Live Wallpapers▲
Les Live Wallpapers sont des fonds d'écran animés, interactifs, pour l'écran d'accueil d'Android. Un fond d'écran est similaire à d'autres applications Android et peut utiliser la plupart des mêmes fonctionnalités.
II-B. Comment créer un fond d'écran animé▲
Pour créer un fond d'écran animé, vous devez créer un fichier XML qui décrit votre fond d'écran. Ce fichier doit contenir une description de l'application et peut contenir un aperçu et un lien vers une activité de préférence Activité, qui permet de personnaliser le fond d'écran animé.
Vous pouvez également créer un service qui doit étendre la classe WallpaperService. Celle-ci est la classe de base pour tous les fonds d'écran animés du système. Vous devez implémenter la méthode onCreateEngine() et retourner un objet de type android.service.wallpaper.WallpaperService.Engine. Ces objets gèrent le cycle de vie des événements, animations et dessins du papier peint. La classe Engine définit les méthodes du cycle de vie, comme onCreate(), onSurfaceCreated(), onVisibilityChanged(), onOffsetsChanged(), onTouchEvent() et onCommand().
Le service nécessite l'autorisation android.permission.BIND_WALLPAPER et doit être enregistré par un filtre d'intention pour l'action android.service.wallpaper.WallpaperService.
Vous devriez également indiquer dans le fichier AndroidManifest.xml de l'application que votre application utilise la fonctionnalité android.software.live_wallpaper. Cela permettra d'éviter que votre fond d'écran puisse être installé sur des appareils qui ne prennent pas en charge les fonds d'écran animés.
II-C. Intention pour modifier le papier peint▲
Vous pouvez utiliser une Intention pour modifier le fond d'écran.
// Bouton pour changer le papier paint
public
void
onClick
(
View view) {
Intent intent =
new
Intent
(
WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra
(
WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
new
ComponentName
(
this
, MyWallpaperService.class
));
startActivity
(
intent);
}
III. Exemple fond d'écran Android▲
Créez un nouveau projet appelé de.vogella.android.wallpaper. Ne créez pas une activité.
Créez le dossier /res/xml et le fichier mywallpaper.xml.
<?xml version="1.0" encoding="UTF-8"?>
<wallpaper
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
thumbnail
=
"@drawable/icon"
android
:
description
=
"@string/wallpaper_description"
android
:
settingsActivity
=
"de.vogella.android.wallpaper.MyPreferencesActivity"
/>
Ce fichier contient une description et un aperçu de votre fond d'écran. Vous pouvez y insérer un lien vers une activité qui permet de configurer le fond d'écran. Ce fichier de ressources sera lié à partir de AndroidManifest.xml. Vous pouvez également y inclure le « android:thumbnail attribute », qui pointerait vers un drawable avec une image plus petite du papier peint courant.
Modifiez votre AndroidManifest.xml comme suit pour définir votre service MyWallpaperService. Définissez également l'uses-feature.
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
package
=
"de.vogella.android.wallpaper"
android
:
versionCode
=
"1"
android
:
versionName
=
"1.0"
>
<application
android
:
icon
=
"@drawable/icon"
android
:
label
=
"@string/app_name"
>
<service
android
:
name
=
"MyWallpaperService"
android
:
enabled
=
"true"
android
:
label
=
"Wallpaper Example "
android
:
permission
=
"android.permission.BIND_WALLPAPER"
>
<intent-filter>
<action
android
:
name
=
"android.service.wallpaper.WallpaperService"
>
</action>
</intent-filter>
<meta-data
android
:
name
=
"android.service.wallpaper"
android
:
resource
=
"@xml/mywallpaper"
>
</meta-data>
</service>
<activity
android
:
name
=
".MyPreferencesActivity"
android
:
exported
=
"true"
android
:
label
=
"@string/app_name"
android
:
theme
=
"@android:style/Theme.Light.WallpaperSettings"
>
</activity>
<activity
android
:
name
=
".SetWallpaperActivity"
android
:
label
=
"@string/app_name"
android
:
theme
=
"@android:style/Theme.Light.WallpaperSettings"
>
<intent-filter>
<action
android
:
name
=
"android.intent.action.MAIN"
/>
<category
android
:
name
=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
<uses-sdk
android
:
minSdkVersion
=
"10"
/>
<uses-feature
android
:
name
=
"android.software.live_wallpaper"
android
:
required
=
"true"
>
</uses-feature>
</manifest>
Nous créons la classe MyPoint pour enregistrer les éléments que nous avons dessinés.
package
de.vogella.android.wallpaper;
public
class
MyPoint {
String text;
private
int
x;
private
int
y;
public
MyPoint
(
String text, int
x, int
y) {
this
.text =
text;
this
.x =
x;
this
.y =
y;
}
}
Créez une nouvelle activité et le fichier de préférences prefs.xml dans le dossier res/xml.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
>
<CheckBoxPreference
android
:
key
=
"touch"
android
:
title
=
"Enable Touch"
></CheckBoxPreference>
<EditTextPreference
android
:
key
=
"numberOfCircles"
android
:
title
=
"Number of Circles"
></EditTextPreference>
</PreferenceScreen>
Créez une nouvelle activité appelée MyPreferencesActivity et la classe suivante :
package
de.vogella.android.wallpaper;
import
android.os.Bundle;
import
android.preference.Preference;
import
android.preference.Preference.OnPreferenceChangeListener;
import
android.preference.PreferenceActivity;
import
android.widget.Toast;
public
class
MyPreferencesActivity extends
PreferenceActivity {
@Override
protected
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
addPreferencesFromResource
(
R.xml.prefs);
// ajoutez un validateur à la préférence "numberOfCircles", afin
// qu'elle accepte des nombres
Preference circlePreference =
getPreferenceScreen
(
).findPreference
(
"numberOfCircles"
);
// ajoutez le validateur
circlePreference.setOnPreferenceChangeListener
(
numberCheckListener);
}
/**
* Vérifier si une préférence est une valeur numérique valide
*/
Preference.OnPreferenceChangeListener numberCheckListener =
new
OnPreferenceChangeListener
(
) {
@Override
public
boolean
onPreferenceChange
(
Preference preference, Object newValue) {
// vérifier si la chaîne représente la valeur d'un entier
if
(
newValue !=
null
&&
newValue.toString
(
).length
(
) >
0
&&
newValue.toString
(
).matches
(
"
\\
d*"
)) {
return
true
;
}
// Si ce n'est pas le cas, créer un message pour l'utilisateur
Toast.makeText
(
MyPreferencesActivity.this
, "Invalid Input"
,
Toast.LENGTH_SHORT).show
(
);
return
false
;
}
}
;
}
Écrivez ce code pour le service de fond d'écran :
package
de.vogella.android.wallpaper;
import
java.util.ArrayList;
import
java.util.List;
import
android.content.SharedPreferences;
import
android.graphics.Canvas;
import
android.graphics.Color;
import
android.graphics.Paint;
import
android.os.Handler;
import
android.preference.PreferenceManager;
import
android.service.wallpaper.WallpaperService;
import
android.view.MotionEvent;
import
android.view.SurfaceHolder;
public
class
MyWallpaperService extends
WallpaperService {
@Override
public
Engine onCreateEngine
(
) {
return
new
MyWallpaperEngine
(
);
}
private
class
MyWallpaperEngine extends
Engine {
private
final
Handler handler =
new
Handler
(
);
private
final
Runnable drawRunner =
new
Runnable
(
) {
@Override
public
void
run
(
) {
draw
(
);
}
}
;
private
List<
MyPoint>
circles;
private
Paint paint =
new
Paint
(
);
private
int
width;
int
height;
private
boolean
visible =
true
;
private
int
maxNumber;
private
boolean
touchEnabled;
public
MyWallpaperEngine
(
) {
SharedPreferences prefs =
PreferenceManager
.getDefaultSharedPreferences
(
MyWallpaperService.this
);
maxNumber =
Integer
.valueOf
(
prefs.getString
(
"numberOfCircles"
, "4"
));
touchEnabled =
prefs.getBoolean
(
"touch"
, false
);
circles =
new
ArrayList<
MyPoint>(
);
paint.setAntiAlias
(
true
);
paint.setColor
(
Color.WHITE);
paint.setStyle
(
Paint.Style.STROKE);
paint.setStrokeJoin
(
Paint.Join.ROUND);
paint.setStrokeWidth
(
10
f);
handler.post
(
drawRunner);
}
@Override
public
void
onVisibilityChanged
(
boolean
visible) {
this
.visible =
visible;
if
(
visible) {
handler.post
(
drawRunner);
}
else
{
handler.removeCallbacks
(
drawRunner);
}
}
}
@Override
public
void
onSurfaceDestroyed
(
SurfaceHolder holder) {
super
.onSurfaceDestroyed
(
holder);
this
.visible =
false
;
handler.removeCallbacks
(
drawRunner);
}
@Override
public
void
onSurfaceChanged
(
SurfaceHolder holder, int
format,
int
width, int
height) {
this
.width =
width;
this
.height =
height;
super
.onSurfaceChanged
(
holder, format, width, height);
}
@Override
public
void
onTouchEvent
(
MotionEvent event) {
if
(
touchEnabled) {
float
x =
event.getX
(
);
float
y =
event.getY
(
);
SurfaceHolder holder =
getSurfaceHolder
(
);
Canvas canvas =
null
;
try
{
canvas =
holder.lockCanvas
(
);
if
(
canvas !=
null
) {
canvas.drawColor
(
Color.BLACK);
circles.clear
(
);
circles.add
(
new
MyPoint
(
String.valueOf
(
circles.size
(
) +
1
), x, y));
drawCircles
(
canvas, circles);
}
}
finally
{
if
(
canvas !=
null
)
holder.unlockCanvasAndPost
(
canvas);
}
super
.onTouchEvent
(
event);
}
}
private
void
draw
(
) {
SurfaceHolder holder =
getSurfaceHolder
(
);
Canvas canvas =
null
;
try
{
canvas =
holder.lockCanvas
(
);
if
(
canvas !=
null
) {
if
(
circles.size
(
) >=
maxNumber) {
circles.clear
(
);
}
int
x =
(
int
) (
width *
Math.random
(
));
int
y =
(
int
) (
height *
Math.random
(
));
circles.add
(
new
MyPoint
(
String.valueOf
(
circles.size
(
) +
1
),
x, y));
drawCircles
(
canvas, circles);
}
}
finally
{
if
(
canvas !=
null
)
holder.unlockCanvasAndPost
(
canvas);
}
handler.removeCallbacks
(
drawRunner);
if
(
visible) {
handler.postDelayed
(
drawRunner, 5000
);
}
}
// La vue de surface nécessite que tous les éléments soient entièrement dessinés
private
void
drawCircles
(
Canvas canvas, List<
MyPoint>
circles) {
canvas.drawColor
(
Color.BLACK);
for
(
MyPoint point : circles) {
canvas.drawCircle
(
point.x, point.y, 20.0
f, paint);
}
}
}
Créez l'activité suivante qui devrait utiliser une mise en page incluant un bouton. Celui-ci doit utiliser la propriété onClick pour pointer vers la méthode onClick.
package
de.vogella.android.wallpaper;
import
android.app.Activity;
import
android.app.WallpaperManager;
import
android.content.ComponentName;
import
android.content.Intent;
import
android.os.Bundle;
import
android.view.View;
public
class
SetWallpaperActivity extends
Activity {
@Override
protected
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.main);
}
public
void
onClick
(
View view) {
Intent intent =
new
Intent
(
WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra
(
WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
new
ComponentName
(
this
, MyWallpaperService.class
));
startActivity
(
intent);
}
}
Si vous démarrez votre application, elle devrait permettre de définir le papier peint. Il devrait ressembler à la capture d'écran ci-dessous. Si vous avez activé Touch dans les préférences, vous pouvez cliquer sur l'écran pour supprimer les cercles existants, vous pouvez également définir dans les paramètres le nombre de cercles qui doivent être affichés.
IV. Liens▲
V. Remerciements Developpez▲
Vous pouvez retrouver l'article original à l'adresse Android Live Wallpaper - Tutorial. Nous remercions Lars Vogel qui nous a aimablement autorisés à traduire et héberger ses articles.
Nous remercions aussi Mishulyna pour sa traduction, ainsi que ced pour sa relecture orthographique.