A propos 
Yoann Gotthilf, CTO d’une startup et freelance Web/Mobile 
•développeur Android depuis 6 ans 
•développeur Web depuis 13 ans 
•consultant sécurité pendant 6 ans 
•développeur FullstackJS depuis 1 ans 
yoann.gotthilf atgmail.com •@ygotthilf
Références 
Site officiel http://developer.android.com 
Blog officiel http://android-developers.blogspot.fr 
Blog Romain Guy http://www.curious-creature.org/category/android 
Blog Cyril Mottier(Fr + En) http://cyrilmottier.com
Qu'est ce qu'Android? 
Une plateforme unifiée pour terminaux mobiles 
(système d'exploitation + frameworks) 
Ce n'est pas une distribution Linux.
Qui développe Android? 
Android est open source: il existe donc de nombreux forks (CyanogenMod, Amazon, ...)
Qui soutient Android? 
L'Open Handset Alliance: un consortium d'industriels créé par Google en 2007.
L'histoire sans grand H 
1991, norme GSM (communication «voix») 
1992, IBM Simon (1er «smartphone») 
2005, startup Android racheté par Google 
2007, lancement iPhone + forfait data «illimité» 
Sept. 2008, officialisation et publication SDK 
Oct. 2008, lancement du 1ersmartphone Android
Le marché
Architecture Android 1/4
Architecture Android 2/4
Architecture Android 3/4
Architecture Android 4/4
Ou développer dans cette architecture? 
Uniquement sur la couche framework applicatif! 
Les développeurs tiers n'ont pas accès aux couches systèmes sous-jacentes.
IDE
Tester son application 
3 méthodes : 
•Emulateur livré avec le SDK (pas terrible) 
•Emulateur Genymotion (pas mal) 
•Son smartphone (top) 
La communication s’effectue grâce au ADB
Les versions 
•Courante :KitKat 4.4 (API 19) 
•Prochaine : L (API 20)
Répartition des versions
Gérer la fragmentation 
Utiliser la librairie de support 
http://developer.android.com/tools/support-library/index.html
Que contient une application? 
•Manifeste Android 
•Ressources 
•Classes Java (Dalvik ou ART) 
•Librairies & JNI 
Le livrable est un APK (Android Package)
AndroidManifest.xml 
Permet au système de «connaître» l'application: 
•nom, logo et version 
•compatibilité (écran, version d'Android,…) 
•permissions 
•composants (activité, service, BR, CP)
Ressources Qu'est-ce? 
image 
fichier multimédia (musique, vidéo) 
layout (vue) 
style (couleur, marge, police, ...) 
animation 
internationalisation
Ressources L’organisation 
Chaque type à son propre répertoire 
Nom des fichiers : [a-z0-9_]+.<extention>
Ressources Gérer la configuration 1/2 
Commentgérer les ressources en fonction de la configuration de chaque terminal Android? 
C’ést-à-dire de la langue, taille d'écran, ratio d'écran, résolution, version d'Android, ...
Ressources Gérer la configuration 2/2 
1.Le développeurclasse par répertoire les différentes configurations souhaitées 
2.A l'exécution, Androidchoisit les bonnes ressources
Ressources Les valeurs 1/2 
•chaîne de caractères (chaîne simple, tableau, pluriel) 
•couleur 
•style 
•booléen 
•id 
•entier 
•tableau typé
Ressources Les valeurs 2/2 
<?xml version="1.0" encoding="utf-8"?> 
<resources> 
<stringname="app_name">My first app</string> 
<stringname="hello">Hello world</string> 
<colorname="primary_color">#ff33b5e5</color> 
<colorname="secondary_color">#df0000</color> 
<string-arrayname="week_end_days"> 
<item>Sunday</item> 
<item>Saturday</item> 
</string-array> 
<dimenname="default_margin">2dp</dimen> 
<boolname="test_mode">false</bool> 
</resources> 
Fichier res/values/all.xml
Ressources Exemple de layout 
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:orientation="vertical"> 
<TextView 
android:text="@string/hello_world" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:textColor="@color/primary_color"/> 
<ImageView 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:src="@drawable/ic_launcher"/> 
</LinearLayout> 
Fichier res/layout/main.xml
Ressources Accès depuis un XML 
@<type>/<nom variable> 
Exemples : 
•@string/hello_world 
•@drawable/icon 
•@color/primary_color
Ressources Accès depuis le code 
imageView.setImageResource(R.drawable.icon); 
textView.setText(R.string.hello_world); 
aapt 
packagefr.imac.test; 
publicfinalclassR { 
publicstaticfinalclassattr { 
} 
publicstaticfinalclassdrawable { 
publicstaticfinalinticon=0x7f020000; 
} 
publicstaticfinalclassid { 
publicstaticfinalinthello_text=0x7f060000; 
} 
publicstaticfinalclasslayout { 
publicstaticfinalintinfo=0x7f030000; 
publicstaticfinalintmain=0x7f030001; 
} 
publicstaticfinalclassraw { 
publicstaticfinalintintra=0x7f040000; 
} 
publicstaticfinalclassstring { 
publicstaticfinalintapp_name=0x7f050000; 
publicstaticfinalinthello_world=0x7f050001; 
} 
}
Ressources prédéfinies 
Le SDK Android propose des ressources prédéfinies 
A manipuler comme les ressources du projet mais préfixé par Android. 
android.R.string.ok 
@android:string/ok 
La liste dans <Répertoire Android Studio>sdkplatformsandroid-<version>datares
Les composants UI
Déclarer une vue 
Démo
Exécution d'application 
Le système gère seul le cycle de vie des composantsapplicatifs. 
Le système vous donne temporairement la main dans des méthodes de callback pour exécuter vos traitements.
Activité Qu’est ce ? 
Une Activityréprésente un écrandans une application 
Son rôle est d’afficher et de contrôler une seule vue
import android.os.Bundle; 
import android.support.v7.app.ActionBarActivity; 
import android.view.Menu; 
public class MyActivity extends ActionBarActivity { 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
} 
@Override 
protected void onDestroy() { 
super.onDestroy(); 
// The activity is about to be destroyed. 
} 
@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
// Inflate the menu; 
return true; 
} 
} 
Activité Cycle de vie
public class MyActivity extends ActionBarActivity { 
@Override 
protectedvoidonCreate(Bundle savedInstanceState){ 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_my); 
} 
} 
Activité Afficher une vue
<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:orientation="vertical"> 
<TextView 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:textAppearance="?android:attr/textAppearanceMedium" 
android:text="@string/connection" 
android:layout_gravity="center_horizontal" /> 
<EditText 
android:inputType="textEmailAddress" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:hint="@string/email" 
android:id="@+id/email" /> 
<EditText 
android:inputType="textPassword" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:hint="@string/password" 
android:id="@+id/password" /> 
<Button 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:text="@android:string/ok" 
android:id="@+id/submit"/> 
</LinearLayout> 
public class MyActivity extends ActionBarActivity { 
private EditText mEmailText ; 
private EditText mPasswordText ; 
private Button mSubmitButton ; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_my); 
mEmailText = (EditText) findViewById(R.id.email); 
mPasswordText = (EditText) findViewById(R.id.password); 
mSubmitButton = (Button) findViewById(R.id.submit); 
} 
[...] 
} 
Activité Récupérer les composants graphiques
@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_my); 
mEmailText = (EditText) findViewById(R.id.email); 
mPasswordText = (EditText) findViewById(R.id.password); 
mSubmitButton = (Button) findViewById(R.id.submit); 
mSubmitButton.setOnClickListener(new View.OnClickListener() { 
@Override 
public void onClick(View view) { 
String email = mEmailText.getText().toString(); 
System.out.println(email); 
} 
}); 
} 
Activité Intéraction
Activité Exemple 
Démo
Fragment Problème 
Layout list 
Layout message 
Activity list 
Activity message 
Layout inbox 
Activity inbox 
Affiche 
Contrôle 
Contrôle 
Affiche 
Affiche 
Contrôle 
Phone 
Tablet
Fragment Solution 
Layout list 
Layout message 
Activity main 
Activity detail 
Phone 
Tablet 
Contrôle 
Contrôle 
Affiche 
Affiche 
Fragment list 
Fragment message 
Lance 
Lance 
Layout main
Fragment En détail 
packagefr.imac.uberconverter; 
importandroid.app.Fragment; 
importandroid.os.Bundle; 
importandroid.view.LayoutInflater; 
importandroid.view.View; 
importandroid.view.ViewGroup; 
importandroid.widget.EditText; 
publicclassExampleFragment extendsFragment { 
@Override 
publicView onCreateView(LayoutInflater inflater, ViewGroup container, 
Bundle savedInstanceState) { 
// Inflate the layout for this fragment 
returninflater.inflate(R.layout.fragment_main, container, false); 
} 
@Override 
publicvoidonActivityCreated(Bundle savedInstanceState) { 
super.onActivityCreated(savedInstanceState); 
View parent=getView(); 
EditText celsius = (EditText) parent.findViewById(R.id.celsius); 
} 
}
Fragment Chargement et manipulation 
<?xmlversion="1.0"encoding="utf-8"?> 
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="horizontal" 
android:layout_width="match_parent" 
android:layout_height="match_parent"> 
<fragmentandroid:name="com.example.news.ArticleListFragment" 
android:id="@+id/list" 
android:layout_weight="1" 
android:layout_width="0dp" 
android:layout_height="match_parent"/> 
<fragmentandroid:name="com.example.news.ArticleReaderFragment" 
android:id="@+id/viewer" 
android:layout_weight="2" 
android:layout_width="0dp" 
android:layout_height="match_parent"/> 
</LinearLayout> 
<?xmlversion="1.0"encoding="utf-8"?> 
<fragmentxmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/list" 
android:name="com.example.news.ArticleListFragment" 
android:layout_width="match_parent" 
android:layout_height="match_parent"/> 
res/layout-large/activity1.xml 
res/layout/activity1.xml 
FragmentManager fragmentManager = getFragmentManager(); 
FragmentTransaction fragmentTransaction = fragmentManager 
.beginTransaction(); 
ArticleReaderFragmentfragment = newArticleReaderFragment(); 
fragmentTransaction.add(R.id.viewer, fragment); 
fragmentTransaction.commit(); 
Dans une activité
Fragment exemple 
Démo
L'ActionBar 
Depuis 3.0 
Eléments : 
Actions items 
Navigation 
Tabs 
Drop-down Navigation 
Navigation drawer 
Recherche 
Vue personnalisable
AdapterView présentation 
Vue dont l’affichage des enfants est géré par un adaptateur 
•Implémentations : ListView, GridView, Spinner, Gallery, … 
•Optimisé pour l’affichage de beaucoup de vues : 
•Construction à la volé d’une vue 
•Réutilisation des vues inutilisés
AdapterView fonctionnement 
AdapterView 
Adapter 
ListView 
GridView 
ListAdapter 
CursorAdapter 
BaseAdapter 
Données 
Layout 
Utilise 
Construit 
Récupère 
Hérite 
Hérite
AdapterView exemple ListView 
publicclassList1 extendsListActivity { 
@Override 
publicvoidonCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.list_1); 
ListAdapter adapter=newArrayAdapter<String>(this, 
android.R.layout.simple_list_item_1, mStrings); 
setListAdapter(adapter); 
} 
privateString[] mStrings= { 
"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi" 
}; 
<TextViewxmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@android:id/text1" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:textAppearance="?android:attr/textAppearanceListItemSmall" 
android:gravity="center_vertical" 
android:paddingStart="?android:attr/listPreferredItemPaddingStart" 
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" 
android:minHeight="?android:attr/listPreferredItemHeightSmall" 
/> 
<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:orientation="vertical"> 
<TextView 
style="?android:attr/textAppearanceLarge" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:text="@string/cheeses"/> 
<ListView 
android:id="@android:id/list" 
android:layout_width="match_parent" 
android:layout_height="match_parent"/> 
</LinearLayout> 
res/layout/simple_list_item1.xml dans le sdk 
res/layout/list_1.xml 
List1.java
Settings/Preferences 
public class SettingsFragment extends PreferenceFragment { 
@Override 
public void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
// Load the preferences from an XML resource 
addPreferencesFromResource(R.xml.preferences); 
} 
... 
} 
<PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategoryandroid:title="@string/pref_sms_storage_title" android:key="pref_key_storage_settings"> <CheckBoxPreferenceandroid:key="pref_key_auto_delete" android:summary="@string/pref_summary_auto_delete" android:title="@string/pref_title_auto_delete" android:defaultValue="false"... /> <Preferenceandroid:key="pref_key_sms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_sms_delete"... /> <Preferenceandroid:key="pref_key_mms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_mms_delete"... /> </PreferenceCategory> ... </PreferenceScreen>
Autres vues spécifiques 
•Boîte de dialogue 
•Toast 
•Notification
Composants principaux 
•Activity: gestion du cycle de vie d'une vue 
•Service: traitement en tâche de fond 
•BroadcastReceiver: traitement événementiel 
•ContentProvider: partage de données inter- application 
•Intent: canal de communication entre composants et applications
Sandbox 
Chaque application à : 
•son UID et GUID 
•son processus et sa VM 
•son répertoire protégé 
Une permission dans le manifeste : 
•doit être validé par l'utilisateurà l'installation 
•attribut un GUID à l'application 
Service IPC: via le Binder (Intent, AIDL)
Service 
Lancer des opérations en arrière plan sans interface graphique et indépendamment de l’utilisation de l’application
Intent présentation 
Message pour lancer une action d’un composant
Intent envoie 
Intent intent = newIntent(); 
intent.setAction(Intent.ACTION_VIEW); 
intent.setData(Uri.parse("http://www.youtube.com/watch?v=iwsqFR5bh6Q")); 
context.startActivity(intent); 
Intent takePictureIntent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE); 
context.startActivityForResult(takePictureIntent, 1); 
Intent i=newIntent(Intent.ACTION_SEND); 
i.putExtra(Intent.EXTRA_EMAIL, newString[{"imac2011@googlegroups.com"}); 
i.putExtra(Intent.EXTRA_TEXT, "Ca avance le projet ?"); 
Intent i2=Intent.createChooser(i, "Choisir..."); 
context.startActivity(i2); 
context.startActivity(new Intent(context, SettingsActivity.class)); 
context.startService(new Intent(context, CurrencyService.class)); 
Implicite 
Explicite
Intent réception 
<receiverandroid:name=".CurrencyReceiver"> 
<intent-filter> 
<actionandroid:name="android.intent.action.TIMEZONE_CHANGED"/> 
<actionandroid:name="android.intent.action.ACTION_BOOT_COMPLETED"/> 
</intent-filter> 
</receiver> 
<activityandroid:name=".YouTubeActivityActivity"> 
<intent-filter> 
<actionandroid:name="android.intent.action.VIEW"/> 
<data 
android:host="www.youtube.com" 
android:scheme="http"/> 
</intent-filter> 
</activity> 
Intent filter dans le manifeste
BroadcastReceiver 
<receiver 
android:name=".MySMSReceiver"> 
<intent-filterandroid:priority="100"> 
<actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/> 
</intent-filter> 
</receiver> 
publicclassMySMSReceiver extendsBroadcastReceiver { 
privatefinalString ACTION_RECEIVE_SMS= "android.provider.Telephony.SMS_RECEIVED"; 
@Override 
publicvoidonReceive(Context context, Intent intent) { 
if(intent.getAction().equals(ACTION_RECEIVE_SMS)) { 
Bundle bundle = intent.getExtras(); 
if(bundle != null) { 
Object[] pdus = (Object[]) bundle.get("pdus"); 
finalSmsMessage[] messages = newSmsMessage[pdus.length]; 
for(inti = 0; i < pdus.length; i++) { 
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); 
} 
if(messages.length> -1) { 
finalString messageBody = messages[0].getMessageBody(); 
finalString phoneNumber = messages[0] 
.getDisplayOriginatingAddress(); 
Toast.makeText(context, "Expediteur : "+ phoneNumber, 
Toast.LENGTH_LONG).show(); 
Toast.makeText(context, "Message : "+ messageBody, 
Toast.LENGTH_LONG).show(); 
} 
} 
} 
} 
}
Persistance des données 
5 méthodes: 
•Le stockage externe(données publiques) 
•Le stockage interne 
•Les préférences 
•La base de donnéesprivée SQLite 
•La connexion réseau
Testing 
•Test unitaire (JUnit) 
•Test d’interface utilisateur 
•Mock 
•…

Introduction à Android

  • 2.
    A propos YoannGotthilf, CTO d’une startup et freelance Web/Mobile •développeur Android depuis 6 ans •développeur Web depuis 13 ans •consultant sécurité pendant 6 ans •développeur FullstackJS depuis 1 ans yoann.gotthilf atgmail.com •@ygotthilf
  • 3.
    Références Site officielhttp://developer.android.com Blog officiel http://android-developers.blogspot.fr Blog Romain Guy http://www.curious-creature.org/category/android Blog Cyril Mottier(Fr + En) http://cyrilmottier.com
  • 4.
    Qu'est ce qu'Android? Une plateforme unifiée pour terminaux mobiles (système d'exploitation + frameworks) Ce n'est pas une distribution Linux.
  • 5.
    Qui développe Android? Android est open source: il existe donc de nombreux forks (CyanogenMod, Amazon, ...)
  • 6.
    Qui soutient Android? L'Open Handset Alliance: un consortium d'industriels créé par Google en 2007.
  • 7.
    L'histoire sans grandH 1991, norme GSM (communication «voix») 1992, IBM Simon (1er «smartphone») 2005, startup Android racheté par Google 2007, lancement iPhone + forfait data «illimité» Sept. 2008, officialisation et publication SDK Oct. 2008, lancement du 1ersmartphone Android
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
    Ou développer danscette architecture? Uniquement sur la couche framework applicatif! Les développeurs tiers n'ont pas accès aux couches systèmes sous-jacentes.
  • 14.
  • 15.
    Tester son application 3 méthodes : •Emulateur livré avec le SDK (pas terrible) •Emulateur Genymotion (pas mal) •Son smartphone (top) La communication s’effectue grâce au ADB
  • 16.
    Les versions •Courante:KitKat 4.4 (API 19) •Prochaine : L (API 20)
  • 17.
  • 18.
    Gérer la fragmentation Utiliser la librairie de support http://developer.android.com/tools/support-library/index.html
  • 19.
    Que contient uneapplication? •Manifeste Android •Ressources •Classes Java (Dalvik ou ART) •Librairies & JNI Le livrable est un APK (Android Package)
  • 20.
    AndroidManifest.xml Permet ausystème de «connaître» l'application: •nom, logo et version •compatibilité (écran, version d'Android,…) •permissions •composants (activité, service, BR, CP)
  • 21.
    Ressources Qu'est-ce? image fichier multimédia (musique, vidéo) layout (vue) style (couleur, marge, police, ...) animation internationalisation
  • 22.
    Ressources L’organisation Chaquetype à son propre répertoire Nom des fichiers : [a-z0-9_]+.<extention>
  • 23.
    Ressources Gérer laconfiguration 1/2 Commentgérer les ressources en fonction de la configuration de chaque terminal Android? C’ést-à-dire de la langue, taille d'écran, ratio d'écran, résolution, version d'Android, ...
  • 24.
    Ressources Gérer laconfiguration 2/2 1.Le développeurclasse par répertoire les différentes configurations souhaitées 2.A l'exécution, Androidchoisit les bonnes ressources
  • 25.
    Ressources Les valeurs1/2 •chaîne de caractères (chaîne simple, tableau, pluriel) •couleur •style •booléen •id •entier •tableau typé
  • 26.
    Ressources Les valeurs2/2 <?xml version="1.0" encoding="utf-8"?> <resources> <stringname="app_name">My first app</string> <stringname="hello">Hello world</string> <colorname="primary_color">#ff33b5e5</color> <colorname="secondary_color">#df0000</color> <string-arrayname="week_end_days"> <item>Sunday</item> <item>Saturday</item> </string-array> <dimenname="default_margin">2dp</dimen> <boolname="test_mode">false</bool> </resources> Fichier res/values/all.xml
  • 27.
    Ressources Exemple delayout <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:text="@string/hello_world" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/primary_color"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher"/> </LinearLayout> Fichier res/layout/main.xml
  • 28.
    Ressources Accès depuisun XML @<type>/<nom variable> Exemples : •@string/hello_world •@drawable/icon •@color/primary_color
  • 29.
    Ressources Accès depuisle code imageView.setImageResource(R.drawable.icon); textView.setText(R.string.hello_world); aapt packagefr.imac.test; publicfinalclassR { publicstaticfinalclassattr { } publicstaticfinalclassdrawable { publicstaticfinalinticon=0x7f020000; } publicstaticfinalclassid { publicstaticfinalinthello_text=0x7f060000; } publicstaticfinalclasslayout { publicstaticfinalintinfo=0x7f030000; publicstaticfinalintmain=0x7f030001; } publicstaticfinalclassraw { publicstaticfinalintintra=0x7f040000; } publicstaticfinalclassstring { publicstaticfinalintapp_name=0x7f050000; publicstaticfinalinthello_world=0x7f050001; } }
  • 30.
    Ressources prédéfinies LeSDK Android propose des ressources prédéfinies A manipuler comme les ressources du projet mais préfixé par Android. android.R.string.ok @android:string/ok La liste dans <Répertoire Android Studio>sdkplatformsandroid-<version>datares
  • 31.
  • 32.
  • 33.
    Exécution d'application Lesystème gère seul le cycle de vie des composantsapplicatifs. Le système vous donne temporairement la main dans des méthodes de callback pour exécuter vos traitements.
  • 34.
    Activité Qu’est ce? Une Activityréprésente un écrandans une application Son rôle est d’afficher et de contrôler une seule vue
  • 35.
    import android.os.Bundle; importandroid.support.v7.app.ActionBarActivity; import android.view.Menu; public class MyActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override protected void onDestroy() { super.onDestroy(); // The activity is about to be destroyed. } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; return true; } } Activité Cycle de vie
  • 36.
    public class MyActivityextends ActionBarActivity { @Override protectedvoidonCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); } } Activité Afficher une vue
  • 37.
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/connection" android:layout_gravity="center_horizontal" /> <EditText android:inputType="textEmailAddress" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/email" android:id="@+id/email" /> <EditText android:inputType="textPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/password" android:id="@+id/password" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@android:string/ok" android:id="@+id/submit"/> </LinearLayout> public class MyActivity extends ActionBarActivity { private EditText mEmailText ; private EditText mPasswordText ; private Button mSubmitButton ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); mEmailText = (EditText) findViewById(R.id.email); mPasswordText = (EditText) findViewById(R.id.password); mSubmitButton = (Button) findViewById(R.id.submit); } [...] } Activité Récupérer les composants graphiques
  • 38.
    @Override protected voidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); mEmailText = (EditText) findViewById(R.id.email); mPasswordText = (EditText) findViewById(R.id.password); mSubmitButton = (Button) findViewById(R.id.submit); mSubmitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String email = mEmailText.getText().toString(); System.out.println(email); } }); } Activité Intéraction
  • 39.
  • 40.
    Fragment Problème Layoutlist Layout message Activity list Activity message Layout inbox Activity inbox Affiche Contrôle Contrôle Affiche Affiche Contrôle Phone Tablet
  • 41.
    Fragment Solution Layoutlist Layout message Activity main Activity detail Phone Tablet Contrôle Contrôle Affiche Affiche Fragment list Fragment message Lance Lance Layout main
  • 42.
    Fragment En détail packagefr.imac.uberconverter; importandroid.app.Fragment; importandroid.os.Bundle; importandroid.view.LayoutInflater; importandroid.view.View; importandroid.view.ViewGroup; importandroid.widget.EditText; publicclassExampleFragment extendsFragment { @Override publicView onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment returninflater.inflate(R.layout.fragment_main, container, false); } @Override publicvoidonActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); View parent=getView(); EditText celsius = (EditText) parent.findViewById(R.id.celsius); } }
  • 43.
    Fragment Chargement etmanipulation <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragmentandroid:name="com.example.news.ArticleListFragment" android:id="@+id/list" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <fragmentandroid:name="com.example.news.ArticleReaderFragment" android:id="@+id/viewer" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent"/> </LinearLayout> <?xmlversion="1.0"encoding="utf-8"?> <fragmentxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list" android:name="com.example.news.ArticleListFragment" android:layout_width="match_parent" android:layout_height="match_parent"/> res/layout-large/activity1.xml res/layout/activity1.xml FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager .beginTransaction(); ArticleReaderFragmentfragment = newArticleReaderFragment(); fragmentTransaction.add(R.id.viewer, fragment); fragmentTransaction.commit(); Dans une activité
  • 44.
  • 45.
    L'ActionBar Depuis 3.0 Eléments : Actions items Navigation Tabs Drop-down Navigation Navigation drawer Recherche Vue personnalisable
  • 46.
    AdapterView présentation Vuedont l’affichage des enfants est géré par un adaptateur •Implémentations : ListView, GridView, Spinner, Gallery, … •Optimisé pour l’affichage de beaucoup de vues : •Construction à la volé d’une vue •Réutilisation des vues inutilisés
  • 47.
    AdapterView fonctionnement AdapterView Adapter ListView GridView ListAdapter CursorAdapter BaseAdapter Données Layout Utilise Construit Récupère Hérite Hérite
  • 48.
    AdapterView exemple ListView publicclassList1 extendsListActivity { @Override publicvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.list_1); ListAdapter adapter=newArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStrings); setListAdapter(adapter); } privateString[] mStrings= { "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi" }; <TextViewxmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:gravity="center_vertical" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:minHeight="?android:attr/listPreferredItemHeightSmall" /> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView style="?android:attr/textAppearanceLarge" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheeses"/> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> res/layout/simple_list_item1.xml dans le sdk res/layout/list_1.xml List1.java
  • 49.
    Settings/Preferences public classSettingsFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Load the preferences from an XML resource addPreferencesFromResource(R.xml.preferences); } ... } <PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategoryandroid:title="@string/pref_sms_storage_title" android:key="pref_key_storage_settings"> <CheckBoxPreferenceandroid:key="pref_key_auto_delete" android:summary="@string/pref_summary_auto_delete" android:title="@string/pref_title_auto_delete" android:defaultValue="false"... /> <Preferenceandroid:key="pref_key_sms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_sms_delete"... /> <Preferenceandroid:key="pref_key_mms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_mms_delete"... /> </PreferenceCategory> ... </PreferenceScreen>
  • 50.
    Autres vues spécifiques •Boîte de dialogue •Toast •Notification
  • 51.
    Composants principaux •Activity:gestion du cycle de vie d'une vue •Service: traitement en tâche de fond •BroadcastReceiver: traitement événementiel •ContentProvider: partage de données inter- application •Intent: canal de communication entre composants et applications
  • 52.
    Sandbox Chaque applicationà : •son UID et GUID •son processus et sa VM •son répertoire protégé Une permission dans le manifeste : •doit être validé par l'utilisateurà l'installation •attribut un GUID à l'application Service IPC: via le Binder (Intent, AIDL)
  • 53.
    Service Lancer desopérations en arrière plan sans interface graphique et indépendamment de l’utilisation de l’application
  • 54.
    Intent présentation Messagepour lancer une action d’un composant
  • 55.
    Intent envoie Intentintent = newIntent(); intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.youtube.com/watch?v=iwsqFR5bh6Q")); context.startActivity(intent); Intent takePictureIntent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE); context.startActivityForResult(takePictureIntent, 1); Intent i=newIntent(Intent.ACTION_SEND); i.putExtra(Intent.EXTRA_EMAIL, newString[{"imac2011@googlegroups.com"}); i.putExtra(Intent.EXTRA_TEXT, "Ca avance le projet ?"); Intent i2=Intent.createChooser(i, "Choisir..."); context.startActivity(i2); context.startActivity(new Intent(context, SettingsActivity.class)); context.startService(new Intent(context, CurrencyService.class)); Implicite Explicite
  • 56.
    Intent réception <receiverandroid:name=".CurrencyReceiver"> <intent-filter> <actionandroid:name="android.intent.action.TIMEZONE_CHANGED"/> <actionandroid:name="android.intent.action.ACTION_BOOT_COMPLETED"/> </intent-filter> </receiver> <activityandroid:name=".YouTubeActivityActivity"> <intent-filter> <actionandroid:name="android.intent.action.VIEW"/> <data android:host="www.youtube.com" android:scheme="http"/> </intent-filter> </activity> Intent filter dans le manifeste
  • 57.
    BroadcastReceiver <receiver android:name=".MySMSReceiver"> <intent-filterandroid:priority="100"> <actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> publicclassMySMSReceiver extendsBroadcastReceiver { privatefinalString ACTION_RECEIVE_SMS= "android.provider.Telephony.SMS_RECEIVED"; @Override publicvoidonReceive(Context context, Intent intent) { if(intent.getAction().equals(ACTION_RECEIVE_SMS)) { Bundle bundle = intent.getExtras(); if(bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); finalSmsMessage[] messages = newSmsMessage[pdus.length]; for(inti = 0; i < pdus.length; i++) { messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); } if(messages.length> -1) { finalString messageBody = messages[0].getMessageBody(); finalString phoneNumber = messages[0] .getDisplayOriginatingAddress(); Toast.makeText(context, "Expediteur : "+ phoneNumber, Toast.LENGTH_LONG).show(); Toast.makeText(context, "Message : "+ messageBody, Toast.LENGTH_LONG).show(); } } } } }
  • 58.
    Persistance des données 5 méthodes: •Le stockage externe(données publiques) •Le stockage interne •Les préférences •La base de donnéesprivée SQLite •La connexion réseau
  • 59.
    Testing •Test unitaire(JUnit) •Test d’interface utilisateur •Mock •…