Activite Intent BroadcastReceiver Fragments

Demander un devis
Je souhaite télécharger le programme ou imprimer le programme
  • Imprimer

tutoriel_vers_formation_Android

Activité

Une activité est l'un des 4 composants android.
Un composant android (activité, service, broadcastReceiver et ContentProvider), représente un point d'entrée pour exécuter du code sur notre téléphone. Il n'est pas possible de commencer l'exécution d'un code sur android sans passer par ces 4 points d'entrées. Pour avoir un rapprochement, c'est l'équivalent du main() sur un pc.
L'activité est le seul composant qui permet d'afficher une interface graphique. Il n'est pas possible d'afficher une interface si l'on n'exécute aucune activité.
Pour exécuter son activité, android utilise un resolver, c'est a dire un traitement instanciant automatiquement l'activité avec certains paramètres à « résoudre » (plus de précision lors de la partie intent).
Puisque c'est android qui se charge d'instancier notre activité, il appellera automatiquement des méthodes clés en fonction de l'état de l'activité pour gérer les ressources internes (ouverture de connexion, création de threads, abonnement à des broadcast, lancement du gps...).

 

auto-formation-android-activite

Nous devons donc connaître quand ces fameuses méthodes seront lancées et quelles sont leurs utilités.

onCreate est appelé au début de la création de l’activité et n’est appelé qu’une seule fois. Il est équivalent du constructeur et sert donc à initialiser des variables, affecter des listener..

onStart sert à lancer les animations, ou généralement tout ce qui est liée à l’affichage graphique, car elle est également appelé lors d’un retour de focus sur l’activité (dans ce cas onRestart est appelé avant).

onResume est appelé de suite après onStart et sert généralement à lancer ou relancer des process tel que le rafraichissement des informations sur l’écran..

onPause est appelé toujours avant un on stop ou lorsque l’application à besoin de mémoire

onStop est appelé lorsque une activité (par ex l’activité téléphone) s’affiche par dessus ou lorsque nous cliquons sur la maison. Nous fermons donc toutes les ressources graphites utilisées

onDestroy sera appelé lorsque l’on quitte l’activité avec le bouton flèche arrière.

 

Il arrive également que la machine soit en manque de mémoire et que l’activité soit détruite pour pouvoir récupérer la mémoire manquante. Si l’utilisateur re-intéragie, une nouvelle instance est appelée et onCreate est à nouveau appelé.

 

En rentrant dans les détails du fonctionnement, nous savons que c’est le garbage qui détruit toute les mémoires non utilisés, et que bien sur, si nous n’arrêtons pas les thread et autres processus dans le onDestroy, ceux ci ont des chances de continuer à tourner. Donc concrètement onDestroy ne signifie pas la destruction physique de l’objet mais tout simplement que la mémoire n’est plus gérée par android. Donc les fameuses méthodes du cycle de vie sont une sorte de gestion applicative de la création/destruction de l’objet. 

 

En réalité pour chaque application lancé, une instance de la machine virtelle est lancée et un processus est alloué pour cette application

Attention, une activité n’est pas l’application. Une activité est l’un des points d’entrée de cette application. On ne termine pas l’application lorsque l’activité est fermée, donc le processus utilisé pour cette activité continu de tourner.

 

Exemple d’utilisation

public class HelloActivity extends Activity {
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
         setContentView(R.layout.<em>main</em>);
 
   }

 

La fonction setContentView est obligatoire pour associer à l’activité une vue.

Pour lancer une activité, il faut le déclarer dans le manifest à l’intérieur de la balise Application. Nous pouvons remarquer que le point signifie que nous sommes dans le package de base du projet.

 

<activity android:name=<em>".Edit"</em> >
</activity>

 

Intent

Un intent représente une intention d’un composant à envoyer à envoyer une requete au systeme android. Des exemples d’intentions sont : le démarrage d’une activité, l’envoi d’un broadcast, le démarrage d’un service. Donc nous savons donc que le système est utilisé comme intermédiaire pour la gestion des composants android.

 

Concernant l’activité, nous pouvons utiliser ces intents pour demander à android de démarrer une autre activité et en même temps lui passer des informations

 

Utilisation

Intent t = new Intent(this,Edit.class);
t.putExtra("musicUpdate", 10);
startActivity(t);

 

Nous remarquons que startActivity() ne peux être lancé que par un composant android (plus précisément grâce à son objet Context).

L’intent à également la possibilité de stocker n’importe quelle primitive et objet serializable à l’intérieur de son tableau associatif grâce à la fonction putExtra.

Il est préférable d’utiliser les intents et ses extras pour transmettre des informations (avec un broadcast par exemple), et non pas utiliser des variables statiques

Sur la nouvelle activité créé, nous récupérons ces informations dans sa fonction onCreate().

 

public class Edit extends Activity {
      /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.edit);
 
       //verification si passage d'une musique en argument
       if(this.getIntent().getExtras()!=null){
             this.m=(Music)this.getIntent().getExtras().getInt("musicUpdate");
 
       }
   }
}

 

 

On a vu qu’il était possible de passer des infos du lanceur au lancé, mais il est également possible au lanceur de récupérer les informations donnée par l’activité qui à été lancé.

Pour cela il suffit d’utiliser startActivityForResult(intent i,int requestCode) a la place de startActivity.

Dans l’activité lancé, il faut appeler la fonction setResult(int res, Intent t) avant de quitter.

Au niveau de l’activité 1, il faut redéfinir une fonction onActivityResult(int requestCode, int resultCode, Intent data)  ou requestCode est le chiffre passé dans startActivityForResult et responseCode, le chiffre passé dans setResult et data l’intent passé dans setResult

 

 

Exemple complet

Activité 1 démarre l’activité 2

Intent t = new Intent(this,Edit.class);
t.putExtra("musicUpdate", 10);
startActivityForResult(t,110);

 

L’activité 2 envoi les informations et quitte.

int m = 30;
      Intent t = new Intent();
      t.putExtra("maMusic",m);
      setResult(50, t);
     Edit.this.finish();

 

L’activité1 reçoit les infos.

@Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       super.onActivityResult(requestCode, resultCode, data);
     //retour edit
     if (resultCode==50){
 
     int m= data.getExtras().getInt("maMusic");
 
      }
   }

 

Schéma

auto-formation-android-intent

 

Les intents utilisés précédemment sont appelés intent implicite, c’est à dire que leur exécutions dépendent uniquement de leur déclaration dans le fichier manifest et de leur présence physique dans notre application (par exemple ici Edit est une classe dans notre application).

Il est aussi possible d’appeler un composant de manière « implicite » en spécifiant une action dans l’intent (qui est en réalité une chaine).

 

Ce principe peut être assimilé à une ouverture d’un fichier sur pc. Si le pc connaît l’extension du document, il va nous proposer avec « ouvrir avec » une liste d’applications adaptés.

 

Pour utiliser ce principe, nous devons renseigner dans le manifest des filtres sur l’activité. Ces filtres vont simplement permettre à l’activité de se porter «candidat » pour le résolveur d’intent lorsqu’il recevra l’intent implicite.

 

Utilisation

Intent t = new Intent("toto");
      t.putExtra("musicUpdate", 10);
      startActivity(t);

 

Dans cet exemple notre action ici est « toto ». Comment faire pour que notre activité Edit soit lancé après startActivity? Grace à un filtre que l’on rajoute dans sa déclaration dans le fichier manifest.

 

Exemple de déclaration d’une activité dans le fichier AndroidManifest.xml

<activity android:name=<em>".Edit"</em> android:label=<em>"@string/app_name"</em>>
     <intent-filter>
         <action android:name=<em>"toto"</em> />
         <category android:name=<em>"android.intent.category.DEFAULT"</em> />
     </intent-filter>
</activity>

 

Intent filter va être un filtre qui sera lu par l’intent resolveur du système et mettra cet activité candidat pour startActivity . S’il y a des applications possédant une activité déclaré avec la même action sur votre téléphone, il y aura un choix a faire au lancement de l’activité (un exemple concret sont les lien youtube sur le navigateur : on peut continuer avec le navigateur sur le site de youtube ou simplement ouvrir l’appli youtube).

La catégorie est une information supplémentaire indiquée dans l’intent pour pouvoir rajouter de la précision sur l’activité à lancer.

android.intent.category.DEFAULT est obligatoire si nous lançons un intent implicite a partir de startActivity.

Il existe bien sur d’autre categories et il est possible de créer nos propres catégories. Par exemple l’action “android.intent.action.MAIN” et la catégorie “android.intent.category.LAUNCHER” sert à l’application bureau à pouvoir choisir l’activité à lancer si on clique sur son icône.

Les intents implicites sont traité de la même façon que les intents explicites, c’est à dire qu’il est également possible d’utiliser les extra et appeler la fonction onActivityResult.

 

Le but quand même des intents implicite est d’exécuter des activités (ou des composants) présent sur le téléphones, il y a donc des intents «officiel » que l’on peut utiliser dans nos application.

 

Action

Uri

Descripton

Intent.ACTION_VIEW

geo:latitude,longitude

ouvre google maps en cherchant les lat/long

Intent.ACTION_VIEW

geo:0,0?q=street+address

ouvre google maps en cherchant l'adresse

Intent.ACTION_CALL

tel:phone_number

ouvre l'appli tel pour faire un appel

Intent.ACTION_DIAL

tel:phone_number

ouvre l'appli tel directement avec le no composé

Intent.ACTION_VIEW

http://web_address

ouvre un browser

Intent.ACTION_WEB_SEARCH

un texte

ouvre un browser avec une recherche google

 

 

 

 

 

 

 

 

 

 

 

 

 

Donc pour appeler une methode

<strong>final</strong> String requete = <a href="http://www.google.fr/search?q=test">http://www.google.fr/search?q=test</a>;
Intent intent = <strong>new</strong> Intent(Intent.<em>ACTION_VIEW</em>, Uri.parse(requete));
startActivity(intent);

 

 

BroadcastReceiver

Un broadcast receiver est un composant permettant de communiquer avec des composants déjà lancés entre elles. Un broadcastReceiver sert à executer une fonction lors d’une réception d’un broadcast.

Un Broadcast est un signal qui est envoyé à toute les application sur chaque changement d’état de celui ci. Ca peut être un signal de batterie faible, de gps activé, de wifi disponible. Malheureusement, il n’existe pas de liste regroupant tout les broadcast officiels et tout est dispatché à l’intérieur de la javadoc(par exemple les broadcasts wifi sont dans le package wifi). Seul les principaux se trouvent dans la classe Intent.

Un Broascast est lancé avec un intent mais contrairement à startActivity, un broadcast peut activer plusieurs broadcastReceiver. Le principe reste le même que l’intent implicite c’est à dire qu’il faut déclarer un filtre sur le broascast receiver pour le déclarer comme candidat.

 

public class MyIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
            ...
}
}

2 façons d’associer des broadcasts:

 

Dans le manifest à l’intérieur de la balise Application avec intentFilter.

<receiver android:name=<em>".MyBroadReceiver"></em>
<intent-filter>
<action android:name=<em>"com.formation.broad"></action></em>
</intent-filter>
</receiver>

 

Directement dans le code

MyBroadReceiver myVarBrodcastReceiver= new MyBroadReceiver() ;
registerReceiver(myVarBrodcastReceiver, new IntentFilter("<em>com.formation.broad</em> "))

 

Dans le 1er cas, la fonction onReceive sera automatiquement appellé sans instance.

Dans le 2eme cas, il faut appeler l’instance, soit dans l’activité, soit dans un service. Il est donc possible de définir un broadcastReceiver en classe interne pour avoir accès aux attributs et méthode de l’activité.

 

Pour envoyer un broadcast, il nous suffit tout simplement de définir un message dans un intent et d’envoyer cet intent avec la fonction :

sendBroadcast(new Intent("com.formation.broad"));

 

Exemple de broadcast receiver qui s’exécute lors du démarrage du telephone.

<receiver android:name=<em>"service.OnBootReceiver"</em> >
   <intent-filter >
       <action android:name=<em>"android.intent.action.BOOT_COMPLETED"</em> />
   </intent-filter>
</receiver>

public class OnBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
            ...
}
}

 

 

Fragments

 

Les fragments permettent de gérer plusieurs « sous »  activités dans une même fenêtre. Nous avons vu que les activités correspondaient à une classe et qu’elles étaient associées à une interface. Ici, c’est potentiellement l’interface qui sera associé à plusieurs classes !!

 

Exemple : nous créons 2 fichiers xml layout, puis 2 classe héritant de Fragment pour les associer

<?xml version=<em>"1.0"</em> encoding=<em>"utf-8"</em>?>
<LinearLayout
xmlns:android=<em>"<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>"</em>
android:orientation=<em>"vertical"</em>
android:layout_width=<em>"fill_parent"</em>
android:layout_height=<em>"fill_parent"</em>
android:background=<em>"#00FF00"</em>>
<TextView
android:layout_width=<em>"fill_parent"</em>
android:layout_height=<em>"wrap_content"</em>
android:text=<em>"This is fragment #1"</em> />
</LinearLayout>

public class Frag1 extends Fragment {   
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.<em>frag1</em>, container, false);
      }
}

<?xml version=<em>"1.0"</em> encoding=<em>"utf-8"</em>?>
<LinearLayout
xmlns:android=<em>"<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>"</em>
android:orientation=<em>"vertical"</em>
android:layout_width=<em>"fill_parent"</em>
android:layout_height=<em>"fill_parent"</em>
android:background=<em>"#FFFE00”</em>> 
<TextView
android:layout_width=<em>"fill_parent"</em>
android:layout_height=<em>"wrap_content"</em>
android:text=<em>"This is fragment #2"</em> />
</LinearLayout>

public class Frag2 extends Fragment {   
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.<em>frag2</em>, container, false);
}
}

 

Pour l’activité principale nous créons un layout incluant les 2 fragments.

Pour chaque fragment nous indiquons sa classe associé par l’attribut « android:name ».

 

<?xml version=<em>”1.0”</em> encoding=<em>”utf-8”?</em>>
<LinearLayout xmlns:android=<em>”<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>”</em>
android:orientation=<em>”horizontal”</em>
android:layout_width=<em>”match_parent”</em>
android:layout_height=<em>”match_parent”</em>>
<fragment
android:name=<em>”net.learn2develop.Fragments.Fragment1”</em>
android:id=<em>”@+id/fragment1”</em>
android:layout_weight=<em>”1”</em>
android:layout_width=<em>”0px”</em>
android:layout_height=<em>”match_parent”</em> />
<fragment
android:name=<em>”net.learn2develop.</em> Fragments.Fragment2”
android:id=<em>”@+id/fragment2”</em>
android:layout_weight=<em>”1”</em>
android:layout_width=<em>”0px”</em>
android:layout_height=<em>”match_parent”</em> />
</LinearLayout>

 

 

Supposons que ce layout s’appelle main.xml. Il est possible de spécifier des variations d’extension de ce fichier xml pour déterminer son affichage sur certain type de device (téléphone/tablette) suivant la densité et la taille son orientation..

Voici donc le détail pour la taille des écrans.

auto-formation-android-fragments

Screen characteristic

Qualifier

Description

Size

small

Resources for small size screens.

normal

Resources for normal size screens. (This is the baseline size.)

large

Resources for large size screens.

xlarge

Resources for extra large size screens.

Density

ldpi

Resources for low-density (ldpi) screens (~120dpi).

mdpi

Resources for medium-density (mdpi) screens (~160dpi). (This is the baseline density.)

hdpi

Resources for high-density (hdpi) screens (~240dpi).

xhdpi

Resources for extra high-density (xhdpi) screens (~320dpi).

nodpi

Resources for all densities. These are density-independent resources. The system does not scale resources tagged with this qualifier, regardless of the current screen's density.

tvdpi

Resources for screens somewhere between mdpi and hdpi; approximately 213dpi. This is not considered a "primary" density group. It is mostly intended for televisions and most apps shouldn't need it—providing mdpi and hdpi resources is sufficient for most apps and the system will scale them as appropriate. If you find it necessary to provide tvdpi resources, you should size them at a factor of 1.33*mdpi. For example, a 100px x 100px image for mdpi screens should be 133px x 133px for tvdpi.

Orientation

land

Resources for screens in the landscape orientation (wide aspect ratio).

port

Resources for screens in the portrait orientation (tall aspect ratio).

Aspect ratio

long

Resources for screens that have a significantly taller or wider aspect ratio (when in portrait or landscape orientation, respectively) than the baseline screen configuration.

notlong

Resources for use screens that have an aspect ratio that is similar to the baseline screen configuration.

 

Voici donc un exemple d’agencement des layouts dans notre projet

 

res/layout/my_layout.xml             // layout par defaut
res/layout-small/my_layout.xml       // layout pour petite taille d’ecran
res/layout-large/my_layout.xml       // layout pour ecran < 7 pouces
res/layout-xlarge/my_layout.xml      // layout pour ecran > 7 pouces
res/layout-xlarge-land/my_layout.xml // layout pour ecran > 7 pouces en paysage

Notre activité principale reste une activité classique avec son cycle de vie classique (onCreate/onDestroy), et reste le même quelque soit la densité de l’écran.

public class TestFragmentActivity extends Activity {
      /** Called when the activity is first created. */
      @
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
      }
}

 

 

 

 

.

.
X
 
 
 
 
 

You havecharacters left.