28
Projet Android À la création d’un projet Android (IDE AndroidStudio – package ue2i013.appdroid – thème empty) tout un ensemble de répertoires et de fichiers sont engendrés. On en distingue 3 : 1. un fichier AndroidManifest.xml (dans le répertoire manifests) qui donne au système Android les caractéristiques de votre application ; dont, en particulier, la liste de ses activités. 2. un répertoire java où sont placés les codes JAVA de votre application. 3. un répertoire res contenant d’autres répertoires, dont layout. Dans ces répertoires sont placés des fichiers, au format XML, de description des ressources des interfaces graphiques de l’application. XML et JAVA

Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Projet Android

À la création d’un projet Android (IDE AndroidStudio – packageue2i013.appdroid – thème empty) tout un ensemble derépertoires et de fichiers sont engendrés. On en distingue 3 :1. un fichier AndroidManifest.xml (dans le répertoire

manifests) qui donne au système Android les caractéristiquesde votre application ; dont, en particulier, la liste de sesactivités.

2. un répertoire java où sont placés les codes JAVA de votreapplication.

3. un répertoire res contenant d’autres répertoires, dont layout.Dans ces répertoires sont placés des fichiers, au format XML,de description des ressources des interfaces graphiques del’application.

XML et JAVA

Page 2: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android"package="ue2i013.appdroid"><applicationandroid:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" />

</intent-filter></activity>

</application></manifest>

Page 3: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

MainActivity.javaClasse JAVA engendrée par défaut à la création d’un projet

package ue2i013.appdroid;

import android.app.Activity;import android.os.Bundle;

public class MainActivity extends Activity {

@Overrideprotected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);

}

}

On ne définit ni n’utilise de constructeur d’activité

Nota Bene : oublier AppCompatActivity pour Activity

Page 4: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

res/layout/activity_main.xmlFichier XML engendré à la création du projet<?xml version="1.0" encoding="utf-8"?><RelativeLayout

xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="16dp"android:paddingLeft="16dp"android:paddingRight="16dp"android:paddingTop="16dp"tools:context="ue2i0013.appdroid.MainActivity">

<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!" />

</RelativeLayout>

Page 5: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Visualisation sur un terminal

Page 6: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Soigner la présentationI center les éléments graphiquesI modifier la tailleI modifier le contenu du message

Editer res/layout/activity_main.xml, balise TextView

<RelativeLayout[...]android:gravity="center"tools:context="ue2i0013.appdroid.MainActivity">

<TextViewandroid:id="@+id/title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="30dp"android:text="Hello Droid!" />

</RelativeLayout>

NOTA BENE : nommage du composant (android:id)

Page 7: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Visualisation

Page 8: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Ajouter un composant

Un bouton EXIT placé en colonne sous le titre pour quitterl’application.

1. ajouter le composant graphique à l’interface : modifieractivity_main.xml.

2. définir l’action associée à l’activation du bouton : modifierMainActivity.

Page 9: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

activity_main.xml

<Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/title"android:background="#ff0000"android:textSize="30dp"android:text="EXIT"android:onClick="onClickExit"/>

I RelativeLayout : placement relatiflayout_below="@id/title"

I couleur de fond rouge : background="#ff0000" (RGB)I action : onClick=onClickExit (c.f. classe MainActivity)

Page 10: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Visualisation

Page 11: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

MainActivity

JAVA - XMLDans la classe MainActivity : définir la méthode onClickExit

public class MainActivity extends Activity {

@Overrideprotected void onCreate(Bundle savedInstanceState) {

[..]}

public void onClickExit(View v) {finish();

}}

Paramètre View v : origine de l’invocation.

Page 12: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Une application : 2 activités

Ajouter une deuxième activité de jeu à l’application.L’activité de jeu est lancée par un bouton depuis l’activitéprincipale1. déclarer l’activité comme ressource de l’application : modifier

AndroidManifest.xml2. ajouter un bouton PLAY à l’activité principale :

2.1 modifier activity_main.xml : nouveau Button2.2 modifier MainActivity : nouvelle méthode onClickPlay

3. créer l’interface graphique de l’activité de jeu : nouveau fichieractivity_play.xml

4. créer la classe PlayActivity

Page 13: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

AndroidManifest

<manifest [..]>

<application[..] ><activity android:name=".MainActivity">

[..]</activity><activity android:name=".PlayActivity" />

</application>

</manifest>

Page 14: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Ajouter le bouton PLAYDans activity_main.xml

<Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/playButton"android:layout_below="@id/title"android:textSize="30dp"android:text="PLAY"android:onClick="onClickPlay"/>

Nota : modifier le layout_below du bouton EXIT (valeur :@id/playButton)

Dans MainActivity pour démarrer l’activité de jeu

public void onClickPlay(View v) {Intent playIntent = new Intent(this, PlayActivity.class);startActivity(playIntent);

}

Page 15: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Activité de jeuInterface graphique : créer res/layout/activity_play.xml<LinearLayout [..] >

<Button[..]android:onClick="onClickQuit"/>

</LinearLayout>

Nota : une autre classe de layout

L’activité : créer PlayActivity.javapublic class PlayActivity extends Activity {

@Overrideprotected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.activity_play);

}public void onClickQuit(View v) {

finish();}

}

Page 16: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Une aire de jeu

Surface de dessin réactiveJAVA+XML1. définir une nouvelle classe JAVA : GameBoard

I qui hérite de SurfaceView pour le dessin et l’interactivité ;I et qui implémente l’interface SurfaceHolder.Callback pour

le contrôle de l’affichage.2. intégrer la surface de jeu à l’interface graphique de l’activité

I une nouvelle balise XML dans activity_play

Un (premier) jeu idiot : afficher un point (petit cercle) au touché dela surface

Page 17: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

GameBoard : JAVASchémapublic class GameBoard extends SurfaceView

implements SurfaceHolder.Callback {public GameBoard(Context c) { [..] }public GameBoard(Context c, AttributeSet as) { [..] }public void reDraw() { [..] }@Overridepublic void onDraw(Canvas c) { [..] }@Overridepublic void surfaceCreated(SurfaceHolder holder) { [..] }@Overridepublic void surfaceChanged

(SurfaceHolder holder, int format, int width, int height){ [..] }

@Overridepublic void surfaceDestroyed(SurfaceHolder holder) { [..] }@Overridepublic boolean onTouchEvent(MotionEvent event) { [..] }

}

Page 18: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

GameBoard : XML

Ajouter à activity_play.xml

<LinearLayout [..] >

<ue2i013.appdroid.GameBoardandroid:layout_width="match_parent"android:layout_height="256dp"android:id="@+id/boardSurface"/>

<Button [..] />

</LinearLayout>

I nouvelle balise : package+classeI ATTENTION à la taille fixe : il faudra faire mieux...

Page 19: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

GameBoard : JAVALes constructeurs

public GameBoard(Context context) {super(context);getHolder().addCallback(this);

}public GameBoard(Context context, AttributeSet attrs) {

super(context, attrs);getHolder().addCallback(this);

}

getHolder donne le contrôleur de la surfaceaddCallback(this) lui signifie qu’il peut adresser des messages àla surface elle-même aux moments clés de sa vie : création,changement, destruction

Pourquoi 2 constructeurs ? Mystère ...

Page 20: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

GameBoard : JAVA(Re)dessiner

Concurrence, section critique

void reDraw() {Canvas c = getHolder().lockCanvas();if (c != null) {

this.onDraw(c);getHolder().unlockCanvasAndPost(c);

}}

Le dessin proprement dit : un simple fond gris (pour l’instant)

@Overridepublic void onDraw(Canvas c) {

c.drawColor(Color.LTGRAY);}

Page 21: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

GameBoard : JAVAles «call back»

Synchronisation : se dessiner au bon moment

@Overridepublic void surfaceCreated(SurfaceHolder sh) {

// rien}@Overridepublic void

surfaceChanged(SurfaceHolder sh, int f, int w, int h) {reDraw();

}@Overridepublic void surfaceDestroyed(SurfaceHolder sh) {

// rien}

SurfaceHolder.Callback : surfaceChanged n’est invoquée quelorsque la surface de dessin (canvas) est effective.Nota : on connaît alors ses dimensions (w et h)

Page 22: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Un jeu et son interface

Un jeu idiot : afficher un point à chaque endroit touchéUne réalisation plus délicate :

I mémoriser l’ensemble des points touchésI garder cette information persistanteI partager cette information entre différentes composantes ou

méthodesUne solution : un modèle de jeu logé au niveau de l’application quipeut être partagée par l’ensemble de composants de l’application(activités et composants graphiques)

Page 23: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Le modèleLe bête modèle du jeu idiot.public class Model {

ArrayList<Position> xys;Model() {

xys = new ArrayList<Position>();}void add(int x, int y) {

xys.add(new Position(x,y));}ListIterator<Position> getAll() {

return xys.listIterator();}

}avecpublic class Position {

int x, y;Position(int x, int y) { this.x = x; this.y = y; }Integer getX() { return x; }Integer getY() { return y; }

}

Page 24: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Partage et persistance du modèleLe modèle est détenu par l’application⇒ personnaliser la classe Application d’Android :public class TheApplication extends Application {

Model m;@Overridepublic void onCreate() {

super.onCreate();m = new Model();

}Model getModel() {

return m;}

}Déclarer (nommer) l’application au système : AndroidManifest<manifest [..] >

<application android:name="TheApplication" [..] >[..]

</application></manifest>

Page 25: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

PartagerAccéder à l’application depuis une activité :public class MainActivity extends Activity {

TheApplication app;@Overrideprotected void onCreate(Bundle savedInstanceState) {

[..]app = (TheApplication)(this.getApplication());

}

Depuis un composant graphique de l’activitépublic class GameBoard extends SurfaceView

implements SurfaceHolder.Callback {GameApplication app;public GameBoard(Context context, AttributeSet attrs) {

[..]app = (TheApplication) (context.getApplicationContext());

}

Page 26: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Dessiner l’état du jeu

Affiner onDraw dans GameBoard

@Overridepublic void onDraw(Canvas c) {

Model m = app.getModel();Paint p = new Paint();ListIterator<Position> it = m.getAll();c.drawColor(Color.LTGRAY);while(it.hasNext()) {

Position xy = it.next();p.setColor(Color.DKGRAY);c.drawCircle(xy.getX(), xy.getY(),13,p); // ATTENTION: constante

}}

Notez l’utilisation de l’itérateur

Page 27: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Réagir au toucher1. notifier au modèle2. notifier au dessin

Dans GameBoard (re)définir onTouchEvent@Overridepublic boolean onTouchEvent(MotionEvent event) {

int x = (int) event.getX();int y = (int) event.getY();int action = event.getAction();switch (action) {

case MotionEvent. ACTION_DOWN: {app.getModel().add(x,y);reDraw();return true;

}default:

return false;}

}

Autres événements gérables : ACTION_MOVE, ACTION_UP, etc.

Page 28: Projet Android - irif.freleph/Enseignement/2016-17/2I013-Android/android1.pdfProjet Android Àlacréationd’unprojet Android (IDEAndroidStudio–package ue2i013.appdroid –thèmeempty)toutunensemblede

Jouer encoreAjouter à l’interface de jeu la possibilité de réinitialiser l’état du jeu.Réinitialiser l’état du jeu (Model)

void reset() { xys.clear() }

Un bouton reset dans l’interface (activity_play.xml)

<Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="RESET"android:onClick="onClickReset"/>

Réagir à la demande de réinitialisation (PlayActivity.java)

public void onClickReset(View v) {app.getMoel().reset();((GameBoard)findViewById(R.id.boardSurface)).reDraw();

}

Notez findViewById