Android : Les intentions

25 mai 2013 rdorigny 0 commentaires

Le framework android propose un outil de communication spécifique dédié à la réalisation d'une action, ce sont les intentions. Ce mécanisme permet à Android de gérer au mieux les ressources du système. En gros la philosophie est : on propose une intention, et le système, en fonction de sa capacité, la réalise.

L'intention est la méthode à privilégier pour réaliser une action définie. Voyons comment cela fonctionne précisément.



1)Principe et réalisation

Le framework Java d'Android définit une classe Intent, qui précise les échanges avec le système JAVA ou avec l'activité, voir l'application. Il existe deux types d'intentions:
  • les intentions explicites : on précise le composant qui sera utilisé,
  • les intentions implicites : on laisse le système choisir le composant pour réaliser l'action demandée.


  • Les intentions sont utilisées pour:

  • lancer une activité dans l'application, notamment pour ouvrir une vue spécifique,
  • lancer une autre application ou un service (voir chapitre précédent),
  • transmettre des messages aux applications.
  • 1.1)Lancer une activité dans l'application courante

    L'intention est la meilleure méthode pour ouvrir une vue et donc une activité. Pour cela, on instancie un objet Intent en précisant la classe de l'activité à ouvrir. Attention à ne pas oublier de préciser dans l'application définie dans le fichier manifest la nouvelle activité. Voici un exemple de code pour lancer une activité dans l'application courante.

    Il faut créer la nouvelle activité à ouvrir:
    package fr.doritique.test_intent; import android.os.Bundle; import android.app.Activity; public class NewActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.new_vue); } }

    On définit son layout par new_vue.xml:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" /> </RelativeLayout>

    Ensuite, dans l'activité principale, on créé un bouton qui permettera d'ouvrir l'activité dite fille:
    package fr.doritique.test_intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import android.app.Activity; import android.content.Intent; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.MyBtn); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Affiche_Vue(); } }); } protected void Affiche_Vue() { Toast toast=Toast.makeText(this,"Affichage de la nouvelle vue!",Toast.LENGTH_LONG); toast.show(); Intent intent=new Intent(this,NewActivity.class); startActivity(intent); } }

    Le layout de l'activité principale:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:text="Afficher la vue" android:id="@+id/MyBtn" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button> </RelativeLayout>

    Enfin, il est nécessaire de déclarer l'activité dans le fichier manifest:
    <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="fr.doritique.test_intent" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:allowTaskReparenting="true"> <activity android:name="fr.doritique.test_intent.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity><activity android:name="NewActivity"></activity> </application> </manifest>

    Donc lorsque l'on clique sur le bouton, l'activité fille s'ouvre.

    1.2)Lancer une activité avec résultat

    Souvent on demande à une activité fille de retourner un résultat à l'activité principale. Pour cela, on utilisera la méthode startActivityForResult() qui transmet le résultat lorsque l'activité se termine. Dans l'application fille, la méthode setResult() doit permettre de retourner la valeur. Enfin, dans l'application principale, la méthode onActivityResult() traite la réception de l'information.

    Nous allons prendre pour exemple une application fille qui doit renvoyer à l'application principale une validation ou une annulation.

    D'abord, on retouche légèrement la vue de l'application fille pour obtenir deux boutons de retours, un pour la validation et un autre pour l'annulation:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:text="OK" android:id="@+id/MyBtn1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button> <Button android:id="@+id/MyBtn2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginTop="52dp" android:text="Annulation" /> </RelativeLayout>

    Ensuite, on code l'activité secondaire:
    package fr.doritique.test_intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.app.Activity; public class NewActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.new_vue); Button btn1 = (Button) findViewById(R.id.MyBtn1); Button btn2 = (Button) findViewById(R.id.MyBtn2); btn1.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { handleClick(v); } }); btn2.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { handleClick(v); } }); } public void handleClick(View v){ switch(v.getId()){ case R.id.MyBtn1: setResult(RESULT_OK); finish(); break; case R.id.MyBtn2: setResult(RESULT_CANCELED); finish(); break; } } }

    Enfin l'activité principale avec la fonction de gestion des retours onActivityResult():
    package fr.doritique.test_intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import android.app.Activity; import android.content.Intent; public class MainActivity extends Activity { private static final int NUM_ACTIVITY=1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.MyBtn); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Affiche_Vue(); } }); } protected void Affiche_Vue() { Toast toast=Toast.makeText(this,"Affichage de la nouvelle vue!",Toast.LENGTH_LONG); toast.show(); Intent intent=new Intent(this,NewActivity.class); startActivityForResult(intent, NUM_ACTIVITY); } protected void onActivityResult(int requestCode, int resultCode, Intent data){ switch(requestCode){ case NUM_ACTIVITY: switch (resultCode) { case RESULT_OK: Toast.makeText(this, "Valeur OK", Toast.LENGTH_LONG).show(); break; case RESULT_CANCELED: Toast.makeText(this, "Annulation", Toast.LENGTH_LONG).show(); break; } } } }

    2)Lancement d'une application externe

    Il est possible également de lancer une application externe. On utilise pour cela les intentions implicites. Dans ce cas, c'est le système qui choisit l'application qui sera lancée.

    Voici un exemple pour lancer l'application téléphone sur un numéro défini:
    package fr.doritique.test_intent2; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import android.app.Activity; import android.content.Intent; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.MyBtn); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Lancement(); } }); } protected void Lancement() { Toast toast=Toast.makeText(this,"Lancement du numéro de téléphone",Toast.LENGTH_LONG); toast.show(); Uri uri=Uri.parse("tel:9876543210"); Intent intent=new Intent(Intent.ACTION_DIAL,uri); startActivity(intent); } }

    Les intentions implicites désignent des actions prédéfinies qui sont connus du framework Android. Voici quelques actions :
  • ACTION_VIEW: ouvre le navigateur web sur une url,
  • ACTION_SEND: pour envoyer un SMS,
  • ACTION_SEND_TO: pour envoyer un mail,
  • ACTION_CALL: pour envoyer un mail,
  • ACTION_DELETE: pour supprimer un objet.

  • Attention, certaines application nécessitent la paramétrage de permissions dans le fichier manifest.

    3)Transmettre des données

    Il est possible de transmettre des données en utilisant les fonctions putExtra() et getExtras().

    Donc dans l'activité principale:
    Intent intent=new Intent(this,NewActivity.class); intent.putExtra("variable","ma valeur"); startActivityForResult(intent, NUM_ACTIVITY);

    Et pour récupérer la variable transmise dans l'activité secondaire:
    //Récupération de la variable Bundle extra=this.getIntent().getExtras(); if (extra!=null){ String str=extra.getString("variable"); Toast toast=Toast.makeText(this,str,Toast.LENGTH_LONG); toast.show(); }

    4)Le Broadcast Receiver

    Le système Android permet de transmettre des intentions en broadcast, c'est à dire à toutes les applications qui sont en écoute. Les intentions sont utiles pas seulement pour lancer une activité, mais aussi pour transmettre des informations comme nous l'avons précédemment décrit. Notamment, on l'utilise pour transmettre des informations liées au système Android (réseaux disponibles, ...).

    4.1) Transmettre une information par un broadcast intent

    Pour transmettre, une information en broadcast, on transmet en broadcast une intention par la méthode sendBroadcast(). Cette méthode demande en paramètre le nom de l'intention à diffuser, il suffira donc d'ajouter l'information à transmettre dans l'intention au préalable de la diffusion.

    Voici un exemple où il suffit d'appuyer sur un bouton pour transmettre l'intention et l'information associée.
    package fr.doritique.testbroadcastreceiver; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.app.Activity; import android.content.Intent; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.MyBtn); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { AfficheBR(); } }); } protected void AfficheBR() { Intent intent=new Intent(MyBR.VIEW); intent.putExtra("extra", "le message"); sendBroadcast(intent); } }

    4.2)Récupération de l'information diffusée

    Pour cela, il suffit de créer un Broadcast Receiver qui se chargera de récupérer les réception d'intention diffusée.
    Pour créer notre Broadcast Receiver, il suffit de créer une classe JAVA, de la faire hériter de la classe BroadcastReceiver, et de surcharger la méthode onReceive(Context context,Intent intent) chargée de traiter la réception du message.

    L'exemple ci-dessous propose une solution pour créer un Broadcast Receiver qui affieche les messages receptionnés.
    package fr.doritique.testbroadcastreceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public final class MyBR extends BroadcastReceiver { public static final String VIEW="doritique.intent.action.VIEW"; @Override public void onReceive(Context context, Intent intent) { String str=intent.getExtras().getString("extra"); Affiche(context,str); } protected void Affiche(Context context,String str) { Toast toast=Toast.makeText(context,"Réception du message transmis en broadcast : " +str,Toast.LENGTH_LONG); toast.show(); } }


    Ce qui donnera:

    Attention, il faut déclarer notre récepteur dans le fichier manifest:
    <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="fr.doritique.testbroadcastreceiver" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="fr.doritique.testbroadcastreceiver.MainActivity" 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="MyBR"> <intent-filter> <action android:name="doritique.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> </application> </manifest>

    Cette déclaration du récepteur est dite statique, il est possible de créer ses récepteurs sans passer par une déclaration dans le fichier manifest. Ce mode dynamique est possible en enregistrant le récepteur lors de l’exécution du programme, on utilisera alors les méthodes registerReceiver() et unregisterReceiver().

    Voici un exemple de déclaration dynamique d'un récepteur:
    package fr.doritique.testbroadcastreceiverdynamique; import com.example.testbroadcastreceiverdynamique.R; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; public class MainActivity extends Activity { public MyBR receiver; @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); receiver=new MyBR(); IntentFilter filter=new IntentFilter(MyBR.VIEW); registerReceiver(receiver, filter); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); unregisterReceiver(receiver); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.MyBtn); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { AfficheBR(); } }); } protected void AfficheBR() { Intent intent=new Intent(MyBR.VIEW); intent.putExtra("extra", "le message"); sendBroadcast(intent); } }

    Conclusion

    L'intention est la méthode privilégiée pour ouvrir une vue, pour transmettre une information ou pour ouvrir une application externe en mode implicite. C'est un outil indispensable du dévellopeur d'application Android.




    Pseudonyme (obligatoire) :
    Adresse mail (obligatoire) :
    Site web :

    Pour valider votre commentaire, écrivez le texte affiché sur l'image :



    © 2017 www.doritique.fr par Robert DORIGNY