Projet Android (LI260) Cours 3 - Laboratoire d`Informatique de Paris 6
Transcription
Projet Android (LI260) Cours 3 - Laboratoire d`Informatique de Paris 6
Quelques rappels Services et communication simple Projet Android (LI260) Cours 3 Nicolas Baskiotis Université Pierre et Marie Curie (UPMC) Laboratoire d’Informatique de Paris 6 (LIP6) S2 - 2013/2014 Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Plan Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Rappel : démarrer une activité Problème • chaque activité dans un processus séparé ⇒ communication entre activités impossible directement (appel de méthodes, passage de paramètres, lecture de variables . . . ) • solution facile : Intent ! (l’action voulue, les données, . . . ) Deux modes : • Deux types d’activités : sans “filtrage” de retour : • new Intent(Context,Class<?>) • avec retour : startActivityForResult(Intent, • implicite : new Intent(String action, [Uri uri]) int reqcode) startActivity(Intent) explicite : Gestion du retour : • dans l’activité appelée : (new Intent()).putExtra(String key, XXX val) • dans l’activité d’origine : v o i d onResult ( i n t reqcode , i n t rescode , I n t e n t i n t e n t ){ i f ( ( reqcode== REQ) && ( rescode = ACTION OK ) ) { i n t e n t . g e t S t r i n g E x t r a ( key ) ; }} Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Exemple p u b l i c c l a s s M a i n A c t i v i t y extends A c t i v i t y { ... o n C l i c k B u t t o n 1 ( View v ) { I n t e n t i n t e n t =new I n t e n t ( M a i n A c t i v i t y . t h i s , S e c o n d A c t i v i t y . c l a s s ) ; startActivityForResult ( intent , 1); } o n C l i c k B u t t o n 2 ( View v ) { I n t e n t i n t e n t =new I n t e n t ( ACTION VIEW ) ; startActivityForResult ( intent , 2); } p r o t e c t e d v o i d o n A c t i v i t y R e s u l t ( i n t requestCode , i n t resultCode , I n t e n t data ){ super . o n A c t i v i t y R e s u l t ( requestCode , resultCode , data ) i f ( requestCode ==1){ t e x t V i e w . s e t T e x t ( data . g e t S t r i n g E x t r a ( ”MESSAGE” ) ) ; i f ( requestCode ==2){ t e x t V i e w . s e t T e x t ( ACTION VIEW ) ; } } p u b l i c c l a s s S e c o n d A c t i v i t y extends A c t i v i t y { ... p u b l i c v o i d o n C l i c k ( View arg0 ) { S t r i n g message= e d i t T e x t . g e t T e x t ( ) . t o S t r i n g ( ) ; I n t e n t i n t e n t =new I n t e n t ( ) ; i n t e n t . p u t E x t r a ( ”MESSAGE” , message ) ; s e t R e s u l t ( ACTION OK , i n t e n t ) ; finish (); } } Quelques rappels Services et communication simple Plan Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Service Définition • tourne en tâche de fond • n’a pas d’interface graphique • prioritaire sur les activités • cycle de vie simplifié • lié ou non à des activités Exemples • media player • écriture/lecture de fichiers, de ressources • communication réseau • localisation Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Un exemple simple p u b l i c c l a s s TestMyService1 extends A c t i v i t y implements O n C l i c k L i s t e n e r { TextView txtMsg ; ComponentName s e r v i c e ; I n t e n t intentMyService1 ; @Override p u b l i c v o i d onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; setContentView (R . l a y o u t . main ) ; txtMsg = ( TextView ) f i n d V i e w B y I d (R . i d . txtMsg ) ; i n t e n t M y S e r v i c e 1 = new I n t e n t ( t h i s , MyService1 . c l a s s ) ; service = s t a r t S e r v i c e ( intentMyService1 ) ; txtMsg . s e t T e x t ( ” MyService1 s t a r t e d\n ( see LogCat ) ” ) ; } p u b l i c v o i d o n C l i c k ( View v ) { try { stopService ( intentMyService1 ) ; txtMsg . s e t T e x t ( ” A f t e r s t o p p i n g S e r v i c e : \n ” + s e r v i c e . getClassName ( ) ) ; } c a t c h ( E x c e p t i o n e ) {Toast . makeText ( t h i s , e . getMessage ( ) , 1 ) . show ( ) ; } } } p u b l i c c l a s s MyService1 extends S e r v i c e { @Override p u b l i c v o i d onCreate ( ) {super . onCreate ( ) ; } @Override p u b l i c v o i d o n S t a r t ( I n t e n t i n t e n t , i n t s t a r t I d ) {Log . e ( ”<<MyService1−o n S t a r t>>” , ” I am a l i v e −1! ” ) ; } @Override p u b l i c v o i d onDestroy ( ) {Log . e ( ”<<MyService1−onDestroy>>” , ” I am dead−1” ) ; } } et dans le manifest : <service android:name=‘‘MyService1’’ /> Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Communiquer avec un service Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Broadcast : plus simple la vie Une seule méthode : void onReceive(Context context, Intent brdMsg) • quand un message est reçu, cette méthode est appelée • tout le reste du temps, le broadcast est inactif ! • gestion des destinataires par filtres et catégories Envoyer un broadcast • sendBroadcast : aucune garantie sur l’ordre de réception, ni le quand ! • sendOrderedBroadcast : reception en cascade ordonnée par priorité (définie dans le filtre) Cycle de vie • statique : définie dans le manifest, toujours à l’écoute • dynamique : instanciation dans le code, registerReceiver(recv,filter) et unregisterReceiver(recv). Quelques rappels Services et communication simple Exemple Une application à 3 services : tiré du cours de V. Matos, Cleveland University, http://grail.cba.csuohio.edu/˜matos/ • MyService4 : lecture de musique • MyService5Async : calcu récursif de Fibonacci • MyService6 : localisation GPS p u b l i c c l a s s T e s t S e r v i c e 4 extends A c t i v i t y { TextView txtMsg ; Intent intentCallService4 ; Intent intentCallService5 ; Intent intentCallService6 ; BroadcastReceiver r e c e i v e r ; @Override p u b l i c v o i d onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; setContentView (R . l a y o u t . main ) ; txtMsg = ( TextView ) f i n d V i e w B y I d (R . i d . txtMsg ) ; i n t e n t C a l l S e r v i c e 4 = new I n t e n t ( t h i s , MyService4 . c l a s s ) ; i n t e n t C a l l S e r v i c e 5 = new I n t e n t ( t h i s , MyService5Async . c l a s s ) ; i n t e n t C a l l S e r v i c e 6 = new I n t e n t ( t h i s , MyService6 . c l a s s ) ; I n t e n t F i l t e r f i l t e r 5 = new I n t e n t F i l t e r ( ” matos . a c t i o n . GOSERVICE5” ) ; I n t e n t F i l t e r f i l t e r 6 = new I n t e n t F i l t e r ( ” matos . a c t i o n . GPSFIX ” ) ; r e c e i v e r = new MyEmbeddedBroadcastReceiver ( ) ; registerReceiver ( receiver , f i l t e r 5 ) ; registerReceiver ( receiver , f i l t e r 6 ) ; } Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Exemple @Override p u b l i c v o i d o n C l i c k ( View v ) { i f ( v . g e t I d ( ) == R . i d . b t n S t a r t 4 ) Log . e ( ” MAIN ” , ” o n C l i c k : s t a r t i n g s e r v i c e 4 ” } e l s e i f ( v . g e t I d ( ) == R . i d . btnStop4 ) { Log . e ( ” MAIN ” , ” o n C l i c k : s t o p p i n g s e r v i c e 4 ” } e l s e i f ( v . g e t I d ( ) == R . i d . b t n S t a r t 5 ) { Log . e ( ” MAIN ” , ” o n C l i c k : s t a r t i n g s e r v i c e 5 ” } e l s e i f ( v . g e t I d ( ) == R . i d . btnStop5 ) { Log . e ( ” MAIN ” , ” o n C l i c k : s t o p p i n g s e r v i c e 5 ” } e l s e i f ( v . g e t I d ( ) == R . i d . b t n S t a r t 6 ) { Log . e ( ” MAIN ” , ” o n C l i c k : s t a r t i n g s e r v i c e 6 ” } e l s e i f ( v . g e t I d ( ) == R . i d . btnStop6 ) { Log . e ( ” MAIN ” , ” o n C l i c k : s t o p p i n g s e r v i c e 6 ” } } ) ; startService ( intentCallService4 ) ; ) ; stopService ( intentCallService4 ) ; ) ; startService ( intentCallService5 ) ; ) ; stopService ( intentCallService5 ) ; ) ; startService ( intentCallService6 ) ; ) ; stopService ( intentCallService6 ) ; p u b l i c c l a s s MyEmbeddedBroadcastReceiver extends BroadcastReceiver { @Override p u b l i c v o i d onReceive ( Context c o n t e x t , I n t e n t i n t e n t ) { Log . e ( ” MAIN>>>” , ” ACTION : ” + i n t e n t . g e t A c t i o n ( ) ) ; i f ( i n t e n t . g e t A c t i o n ( ) . equals ( ” matos . a c t i o n . GOSERVICE5” ) ) { S t r i n g s e r v i c e 5 D a t a = i n t e n t . g e t S t r i n g E x t r a ( ” MyService5DataItem ” ) ; Log . e ( ” MAIN>>>” , ” Data r e c e i v e d from S e r v i c e 5 : ” + s e r v i c e 5 D a t a ) ; txtMsg . append ( ”\nService5Data : > ” + s e r v i c e 5 D a t a ) ; } e l s e i f ( i n t e n t . g e t A c t i o n ( ) . equals ( ” matos . a c t i o n . GPSFIX ” ) ) { double l a t i t u d e = i n t e n t . g e t D o u b l e E x t r a ( ” l a t i t u d e ” , −1); double l o n g i t u d e = i n t e n t . g e t D o u b l e E x t r a ( ” l o n g i t u d e ” , −1); String provider = intent . getStringExtra ( ” provider ” ) ; S t r i n g s e r v i c e 6 D a t a = p r o v i d e r + ” l a t : ” + Double . t o S t r i n g ( l a t i t u d e )+ ” l o n : ” +Double . t o S t r i n g ( l o n g i t u d e ) ; Log . e ( ” MAIN>>>” , ” Data r e c e i v e d from S e r v i c e 6 : ” + s e r v i c e 6 D a t a ) ; txtMsg . append ( ”\nService6Data : > ” + s e r v i c e 6 D a t a ) ; } } } } Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Service4 : Player p u b l i c c l a s s MyService4 extends S e r v i c e { p u b l i c s t a t i c boolean b o o l I s S e r v i c e C r e a t e d = f a l s e ; MediaPlayer p l a y e r ; @Override p u b l i c I B i n d e r onBind ( I n t e n t i n t e n t ) { return null ; } @Override p u b l i c v o i d onCreate ( ) { Toast . makeText ( t h i s , ” MyService4 Created ” , Toast . LENGTH LONG ) . show ( ) ; Log e ( ” MyService4 ” , ” onCreate ” ) ; boolIsServiceCreated = true ; p l a y e r = MediaPlayer . c r e a t e ( g e t A p p l i c a t i o n C o n t e x t ( ) , R . raw . good bad ugly ) ; } p u b l i c v o i d onDestroy ( ) { Toast . makeText ( t h i s , ” MyService4 Stopped ” , Toast . LENGTH LONG ) . show ( ) ; Log . e ( ” MyService4 ” , ” onDestroy ” ) ; player . stop ( ) ; player . release ( ) ; player = n u l l ; } @Override public void onStart ( I n t e n t intent , i n t s t a r t i d ) { i f ( player . isPlaying ( ) ) Toast . makeText ( t h i s , ” MyService4 A l r e a d y S t a r t e d ” + s t a r t i d , Toast . LENGTH LONG ) . show ( ) ; e l s e Toast . makeText ( t h i s , ” MyService4 S t a r t e d ” + s t a r t i d , Toast . LENGTH LONG ) . show ( ) ; Log . e ( ” MyService4 ” , ” o n S t a r t ” ) ; player . s t a r t ( ) ; } } Quelques rappels Services et communication simple Plan Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Plus compliquée la vie... : les Threads Beaucoup de problèmes • peut être dans le même processus ou non • code complexe • interblocage • communication par file de messages : classe Handler p u b l i c c l a s s M a i n A c t i v i t y extends A c t i v i t y { @Override p u b l i c v o i d onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; setContentView (R . l a y o u t . main ) ; new Thread ( new Runnable ( ) { @Override p u b l i c v o i d run ( ) { try { Thread . s l e e p ( 2 0 0 0 ) ; Log . i ( ” Thread ” , ” coucou ” ) ; } c a t c h ( I n t e r r u p t e d E x c e p t i o n e ) {e . p r i n t S t a c k T r a c e ( ) ; } } } ). start (); } Quelques rappels Services et communication simple En détail Heureusement, il y a : • IntentService • ASyncTask Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Threads, IntentService, ASyncTask IntentService Avantages/Inconvénients : • simple à utiliser : une méthode onHandleIntent() • ne peut manipuler l’interface • une seule instance : plusieurs exécutions en séquence uniquement • ne peut être interrompu p u b l i c c l a s s MyService extends I n t e n t S e r v i c e { @Override protected void onHandleIntent ( I n t e n t i n t e n t ) { / / f a i r e quelque chose publishResults ( ) ; } p r i v a t e v o i d p u b l i s h R e s u l t s (){ I n t e n t i n t e n t = new I n t e n t (RESULTATS ) . p u t E x t r a (RESULT, r e s u l t ) ; sendBroadcast ( i n t e n t ) ; } } p u b l i c c l a s s M a i n A c t i v i t y extends A c t i v i t y { p r i v a t e BroadcastReceiver r e c e i v e r = new BroadcastReceiver ( ){ p u b l i c v o i d onReceive . . . } ; p u b l i c v o i d o n C l i c k ( View v){ I n t e n t i n t e n t = new I n t e n t ( t h i s , MyService . c l a s s ) ; startService ( intent ) ; } Quelques rappels Services et communication simple Threads, IntentService, ASyncTask ASyncTask : communication simplifiée Avantages/inconvénients • permet d’intéragir avec l’interface • une seule exécution à la fois ! p r i v a t e c l a s s VerySlowTask extends AsyncTask<S t r i n g , Long , Void> { / / Begin − can use UI t h r e a d here p r o t e c t e d v o i d onPreExecute ( ) {} / / t h i s i s t h e SLOW background t h r e a d t a k i n g care o f heavy t a s k s / / cannot d i r e c t l y change UI p r o t e c t e d Void doInBackground ( f i n a l S t r i n g . . . args ) { ... p u b l i s h P r o g r e s s ( ( Long ) someLongValue ) ; } / / p e r i o d i c updates − i t i s OK t o change UI @Override p r o t e c t e d v o i d onProgressUpdate ( Long . . . v a l u e ) { } / / End − can use UI t h r e a d here p r o t e c t e d v o i d onPostExecute ( f i n a l Void unused ) { } } Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Exemple p u b l i c c l a s s M a i n A c t i v i t y extends A c t i v i t y { p u b l i c v o i d o n C l i c k ( f i n a l View v ) { new VerySlowTask ( ) . execute ( ” dummy1 ” , ” dummy2 ” ) ; } p r i v a t e c l a s s VerySlowTask extends AsyncTask<S t r i n g , Long , Void> { p r i v a t e f i n a l P r o g r e s s D i a l o g d i a l o g = new P r o g r e s s D i a l o g ( M a i n A c t i v i t y . t h i s ) ; S t r i n g waitMsg = ” Wait\nSome SLOW j o b i s being done . . . ” ; p r o t e c t e d v o i d onPreExecute ( ) { s t a r t i n g M i l l i s = System . c u r r e n t T i m e M i l l i s ( ) ; txtMsg . s e t T e x t ( ” S t a r t Time : ” + s t a r t i n g M i l l i s ) ; t h i s . d i a l o g . setMessage ( waitMsg ) ; t h i s . d i a l o g . show ( ) ; } p r o t e c t e d Void doInBackground ( f i n a l S t r i n g . . . args ) { Log . e ( ” doInBackground>>” , ” T o t a l args : ” + args . l e n g t h ) ; Log . e ( ” doInBackground>>” , ” args [ 0 ] = ” + args [ 0 ] ) ; try { f o r ( Long i = 0L ; i < 5L ; i ++) { Thread . s l e e p ( 1 0 0 0 0 ) ; / / s i m u l a t e t h e slow j o b here p u b l i s h P r o g r e s s ( ( Long ) i ) ; }} c a t c h ( I n t e r r u p t e d E x c e p t i o n e ) {Log . e ( ” slow−j o b i n t e r r u p t e d ” , e . getMessage ( ) ) ; } return null ; } @Override p r o t e c t e d v o i d onProgressUpdate ( Long . . . v a l u e ) { super . onProgressUpdate ( v a l u e ) ; d i a l o g . setMessage ( waitMsg + v a l u e [ 0 ] ) ; txtMsg . append ( ”\nworking . . . ” + v a l u e [ 0 ] ) ; } / / can use UI t h r e a d here p r o t e c t e d v o i d onPostExecute ( f i n a l Void unused ) { i f ( t h i s . d i a l o g . isShowing ( ) ) { t h i s . dialog . dismiss ( ) ; } txtMsg . append ( ”\nEnd Time : ” + ( System . c u r r e n t T i m e M i l l i s ( ) − s t a r t i n g M i l l i s ) / 1 0 0 0 ) ; txtMsg . append ( ”\ndone ! ” ) ; } Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Service6 : GPS p u b l i c c l a s s MyService6 extends S e r v i c e { S t r i n g GPS FILTER = ” matos . a c t i o n . GPSFIX ” ; Thread s e r v i c e T h r e a d ; LocationManager lm ; GPSListener m y L o c a t i o n L i s t e n e r ; @Override p u b l i c I B i n d e r onBind ( I n t e n t arg0 ) {r e t u r n n u l l ;} @Override p u b l i c v o i d onCreate ( ) {super . onCreate ( ) ; } @Override public void onStart ( I n t e n t intent , i n t s t a r t I d ) { Log . e ( ”<<MyGpsService−o n S t a r t>>” , ” I am a l i v e−GPS! ” ) ; s e r v i c e T h r e a d = new Thread ( new Runnable ( ){ p u b l i c v o i d run ( ) { getGPSFix Version1 ( ) ; / / uses NETWORK p r o v i d e r getGPSFix Version2 ( ) ; / / uses GPS c h i p p r o v i d e r } }); serviceThread . s t a r t ( ) ; } p u b l i c v o i d getGPSFix Version1 ( ) { LocationManager l o c a t i o n M a n a g e r = ( LocationManager ) getSystemService ( Context . LOCATION SERVICE ) ; C r i t e r i a c r i t e r i a = new C r i t e r i a ( ) ; S t r i n g p r o v i d e r = locationManager . getBestProvider ( c r i t e r i a , f a l s e ) ; L o c a t i o n l o c a t i o n = l o c a t i o n M a n a g e r . getLastKnownLocation ( p r o v i d e r ) ; i f ( l o c a t i o n ! = n u l l ){ double l a t i t u d e = l o c a t i o n . g e t L a t i t u d e ( ) ; double l o n g i t u d e = l o c a t i o n . g e t L o n g i t u d e ( ) ; I n t e n t myFilteredResponse = new I n t e n t ( GPS FILTER ) ; myFilteredResponse . p u t E x t r a ( ” l a t i t u d e ” , l a t i t u d e ) ; myFilteredResponse . p u t E x t r a ( ” l o n g i t u d e ” , l o n g i t u d e ) ; myFilteredResponse . p u t E x t r a ( ” p r o v i d e r ” , p r o v i d e r ) ; Log . e ( ”>>GPS Service<<” , p r o v i d e r + ” =>L a t : ” + l a t i t u d e + ” l o n : ” + l o n g i t u d e ) ; sendBroadcast ( myFilteredResponse ) ; } } Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Service6 : GPS p u b l i c v o i d getGPSFix Version2 ( ) { try { Looper . prepare ( ) ; lm = ( LocationManager ) getSystemService ( Context . LOCATION SERVICE ) ; m y L o c a t i o n L i s t e n e r = new GPSListener ( ) ; l o n g minTime = 2000; / / 2 seconds f l o a t minDistance = 5 ; / / 5 meter lm . r e q u e s t L o c a t i o n U p d a t e s ( LocationManager . GPS PROVIDER, minTime , minDistance , m y L o c a t i o n L i s t e n e r ) ; Looper l o o p ( ) ; } c a t c h ( E x c e p t i o n e ) {e . p r i n t S t a c k T r a c e ( ) ; } } @Override p u b l i c v o i d onDestroy ( ) { super . onDestroy ( ) ; Log . e ( ”<<MyGpsService onDestroy>>” , ” I am dead GPS” ) ; t r y { lm . removeUpdates ( m y L o c a t i o n L i s t e n e r ) ; isRunning = f a l s e ; } c a t c h ( E x c e p t i o n e ) {Toast . makeText ( g e t A p p l i c a t i o n C o n t e x t ( ) , e . getMessage ( ) , 1 ) . show ( ) ; } } p r i v a t e c l a s s GPSListener implements L o c a t i o n L i s t e n e r { p u b l i c v o i d onLocationChanged ( L o c a t i o n l o c a t i o n ) { double l a t i t u d e = l o c a t i o n . g e t L a t i t u d e ( ) ; double l o n g i t u d e = l o c a t i o n . g e t L o n g i t u d e ( ) ; I n t e n t myFilteredResponse = new I n t e n t ( GPS FILTER ) ; myFilteredResponse . p u t E x t r a ( ” l a t i t u d e ” , l a t i t u d e ) ; myFilteredResponse . p u t E x t r a ( ” l o n g i t u d e ” , l o n g i t u d e ) ; myFilteredResponse . p u t E x t r a ( ” p r o v i d e r ” , l o c a t i o n . g e t P r o v i d e r ( ) ) ; Log . e ( ”>>GPS Service<<” , ” L a t : ” + l a t i t u d e + ” l o n : ” + l o n g i t u d e ) ; sendBroadcast ( myFilteredResponse ) ; } p u b l i c v o i d o n P r o v i d e r D i s a b l e d ( S t r i n g p r o v i d e r ) {} p u b l i c v o i d onProviderEnabled ( S t r i n g p r o v i d e r ) {} p u b l i c v o i d onStatusChanged ( S t r i n g p r o v i d e r , i n t s t a t u s , Bundle e x t r a s ) {} }; / / GPSListener c l a s s } Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Service5 : Fibonacci p u b l i c c l a s s MyService5Async extends S e r v i c e { boolean isRunning = t r u e ; p r i v a t e Handler h a n d l e r = new Handler ( ) { @Override p u b l i c v o i d handleMessage ( Message msg ) { super . handleMessage ( msg ) ; Log . e ( ” MyService5Async−Handler ” , ” Handler g o t from MyService5Async : ” + ( S t r i n g ) msg . o b j ) ; } }; @Override p u b l i c I B i n d e r onBind ( I n t e n t arg0 ) { return null ; } @Override p u b l i c v o i d onCreate ( ) { super . onCreate ( ) ; } public void onStart ( I n t e n t intent , i n t s t a r t I d ) { Log . e ( ”<<MyService5Async−o n S t a r t>>” , ” I am a l i v e −5Async ! ” ) ; new ComputeFibonacciRecursivelyTask ( ) . execute ( 2 0 , 5 0 ) ; } p u b l i c I n t e g e r f i b o n a c c i ( I n t e g e r n){ i f ( n==0 || n==1 ) return 1; else r e t u r n f i b o n a c c i ( n−1) + f i b o n a c c i ( n−2);} @Override p u b l i c v o i d onDestroy ( ) { super . onDestroy ( ) ; Log . e ( ”<<MyService5Async−onDestroy>>” , ” I am dead−5−Async ” ) ; isRunning = f a l s e ; } Quelques rappels Services et communication simple Threads, IntentService, ASyncTask Service5 : Fibonacci p u b l i c c l a s s ComputeFibonacciRecursivelyTask extends AsyncTask <I n t e g e r , I n t e g e r , I n t e g e r > { @Override p r o t e c t e d I n t e g e r doInBackground ( I n t e g e r . . . params ) { f o r ( i n t i =params [ 0 ] ; i<params [ 1 ] ; i ++) Integer fibn = fibonacci ( i ) ; publishProgress ( i , f i b n ) ; } return null ; } @Override p r o t e c t e d v o i d onProgressUpdate ( I n t e g e r . . . v a l u e s ) { super . onProgressUpdate ( v a l u e s ) ; I n t e n t i n t e n t F i l t e r 5 = new I n t e n t ( ” matos . a c t i o n . GOSERVICE5” ) ; S t r i n g data = ” dataItem−5−f i b o n a c c i−AsyncTask ” + v a l u e s [ 0 ] + ” : ” + v a l u e s [ 1 ] ; i n t e n t F i l t e r 5 . p u t E x t r a ( ” MyService5DataItem ” , data ) ; sendBroadcast ( i n t e n t F i l t e r 5 ) ; Message msg = h a n d l e r . obtainMessage ( 5 , data ) ; h a n d l e r . sendMessage ( msg ) ; } }} Quelques rappels Services et communication simple Un dernier p u b l i c c l a s s LocalWordService extends S e r v i c e { p r i v a t e f i n a l I B i n d e r mBinder = new MyBinder ( ) ; p r i v a t e A r r a y L i s t<S t r i n g> l i s t = new A r r a y L i s t<S t r i n g >(); @Override p u b l i c i n t onStartCommand ( I n t e n t i n t e n t , i n t f l a g s , i n t s t a r t I d ) { Random random = new Random ( ) ; i f ( random . nextBoolean ( ) ) { l i s t . add ( ” L i n u x ” ) ; } i f ( random . nextBoolean ( ) ) { l i s t . add ( ” Android ” ) ; } i f ( random . nextBoolean ( ) ) { l i s t . add ( ” iPhone ” ) ; } i f ( random . nextBoolean ( ) ) { l i s t . add ( ” Windows7 ” ) ; } i f ( l i s t . s i z e ( ) >= 20) { l i s t . remove ( 0 ) ; } r e t u r n S e r v i c e . START NOT STICKY ; } @Override p u b l i c I B i n d e r onBind ( I n t e n t arg0 ) { r e t u r n mBinder ; } p u b l i c c l a s s MyBinder extends B i n d e r { LocalWordService g e t S e r v i c e ( ) { r e t u r n LocalWordService . t h i s ; } } p u b l i c L i s t<S t r i n g> g e t W o r d L i s t ( ) { Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Un dernier p u b l i c c l a s s MyScheduleReceiver extends BroadcastReceiver { / / r e s t a r t s e r v i c e every 30 seconds p r i v a t e s t a t i c f i n a l l o n g REPEAT TIME = 1000 ∗ 3 0 ; @Override p u b l i c v o i d onReceive ( Context c o n t e x t , I n t e n t i n t e n t ) { AlarmManager s e r v i c e = ( AlarmManager ) c o n t e x t . getSystemService ( Context . ALARM SERVICE ) ; I n t e n t i = new I n t e n t ( c o n t e x t , M y S t a r t S e r v i c e R e c e i v e r . c l a s s ) ; P e n d i n g I n t e n t pending = P e n d i n g I n t e n t . g e t B r o a d c a s t ( c o n t e x t , 0 , i , P e n d i n g I n t e n t . FLAG CANCEL CURRENT ) ; Calendar c a l = Calendar . g e t I n s t a n c e ( ) ; / / s t a r t 30 seconds a f t e r boot completed c a l . add ( Calendar .SECOND, 3 0 ) ; / / f e t c h every 30 seconds / / I n e x a c t R e p e a t i n g a l l o w s Android t o o p t i m i z e t h e energy consumption s e r v i c e . s e t I n e x a c t R e p e a t i n g ( AlarmManager .RTC WAKEUP, c a l . g e t T i m e I n M i l l i s ( ) , REPEAT TIME , pending ) ; / / s e r v i c e . s e t R e p e a t i n g ( AlarmManager .RTC WAKEUP, c a l . g e t T i m e I n M i l l i s ( ) , / / REPEAT TIME , pending ) ; } } p u b l i c c l a s s M y S t a r t S e r v i c e R e c e i v e r extends BroadcastReceiver { @Override p u b l i c v o i d onReceive ( Context c o n t e x t , I n t e n t i n t e n t ) { I n t e n t s e r v i c e = new I n t e n t ( c o n t e x t , LocalWordService . c l a s s ) ; context . startService ( service ) ; } } Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Un dernier p u b l i c c l a s s M a i n A c t i v i t y extends L i s t A c t i v i t y { p r i v a t e LocalWordService s ; @Override p u b l i c v o i d onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; setContentView (R . l a y o u t . main ) ; w o r d L i s t = new A r r a y L i s t<S t r i n g >(); a d a p t e r = new ArrayAdapter<S t r i n g >(t h i s , android .R. l a y o u t . s i m p l e l i s t i t e m 1 , android .R. i d . text1 , wordList ) ; s e t L i s t A d a p t e r ( adapter ) ; } @Override p r o t e c t e d v o i d onResume ( ) { super . onResume ( ) ; I n t e n t i n t e n t = new I n t e n t ( t h i s , LocalWordService . c l a s s ) ; b i n d S e r v i c e ( i n t e n t , mConnection , Context . BIND AUTO CREATE ) ; } @Override p r o t e c t e d v o i d onPause ( ) { super . onPause ( ) ; u n b i n d S e r v i c e ( mConnection ) ; } Threads, IntentService, ASyncTask Quelques rappels Services et communication simple Un dernier p r i v a t e S e r v i c e C o n n e c t i o n mConnection = new S e r v i c e C o n n e c t i o n ( ) { p u b l i c v o i d onServiceConnected ( ComponentName className , IBinder binder ) { LocalWordService . MyBinder b = ( LocalWordService . MyBinder ) b i n d e r ; s = b . getService ( ) ; Toast . makeText ( M a i n A c t i v i t y . t h i s , ” Connected ” , Toast . LENGTH SHORT) . show ( ) ; } p u b l i c v o i d onServiceDisconnected ( ComponentName className ) { s = null ; } }; p r i v a t e ArrayAdapter<S t r i n g> a d a p t e r ; p r i v a t e L i s t<S t r i n g> w o r d L i s t ; p u b l i c v o i d o n C l i c k ( View view ) { i f ( s != n u l l ) { Toast . makeText ( t h i s , ” Number o f elements ” + s . g e t W o r d L i s t ( ) . s i z e ( ) , Toast . LENGTH SHORT ) . show ( ) ; wordList . clear ( ) ; wordList . addAll ( s . getWordList ( ) ) ; a d a p t e r . notifyDataSetChanged ( ) ; } } } Threads, IntentService, ASyncTask