Ce diaporama a bien été signalé.
Le téléchargement de votre SlideShare est en cours. ×

ProTips DroidCon Paris 2013

ProTips DroidCon Paris 2013

La conférence « ProTips » de Mathias Seguy (Android2EE).
Cette conférence a eu lieu lors du BarCamp de la DroidCon Paris, Lundi 17 Juin 2013.
Si vous êtes un JUG ou un AUG et que cette conférence vous interesse, n'hésitez pas à me contacter.

Si vous souhaitez apprendre la technologie Android, contacter moi: mathias.seguy@android2ee.com, je suis formateur Android et les formations Android que je dispense sont exceptionnelles.

Speaker:Mathias est le fondateur de la société Android2ee spécialisée dans la technologie Android.
Il est :
• formateur Android,
• expert logiciel Android,
• speaker Android sur de grandes conférences Java : AndroidCon, Devoxx France, Eclipse Day Toulouse, JCertif Africa, Toulouse JUG, CocoAhead,…
• Rédacteur Android sur Developpez.com ;
• Programmateur Android : MyLight, MyTorch, MySensors, JCertifMobile disponibles sur GooglePlay ;
• Docteur en Mathématiques Fondamentales et Ingénieur de l’ENSEEIHT ;
• Expert technique de l’agence nationale de la recherche française ;
Il présentera au cours de cette conférence sa vision sur la mise en place d’une architecture d’une application Android pertinente et partagera les meilleurs pro-tips (astuces de pro) de sa connaissance. A ne pas manquez.

Mathias Séguy
mathias.seguy@android2ee.com
Fondateur Android2EE
Formation – Expertise – Consulting Android.
Ebooks pour apprendre la programmation sous Android.

La conférence « ProTips » de Mathias Seguy (Android2EE).
Cette conférence a eu lieu lors du BarCamp de la DroidCon Paris, Lundi 17 Juin 2013.
Si vous êtes un JUG ou un AUG et que cette conférence vous interesse, n'hésitez pas à me contacter.

Si vous souhaitez apprendre la technologie Android, contacter moi: mathias.seguy@android2ee.com, je suis formateur Android et les formations Android que je dispense sont exceptionnelles.

Speaker:Mathias est le fondateur de la société Android2ee spécialisée dans la technologie Android.
Il est :
• formateur Android,
• expert logiciel Android,
• speaker Android sur de grandes conférences Java : AndroidCon, Devoxx France, Eclipse Day Toulouse, JCertif Africa, Toulouse JUG, CocoAhead,…
• Rédacteur Android sur Developpez.com ;
• Programmateur Android : MyLight, MyTorch, MySensors, JCertifMobile disponibles sur GooglePlay ;
• Docteur en Mathématiques Fondamentales et Ingénieur de l’ENSEEIHT ;
• Expert technique de l’agence nationale de la recherche française ;
Il présentera au cours de cette conférence sa vision sur la mise en place d’une architecture d’une application Android pertinente et partagera les meilleurs pro-tips (astuces de pro) de sa connaissance. A ne pas manquez.

Mathias Séguy
mathias.seguy@android2ee.com
Fondateur Android2EE
Formation – Expertise – Consulting Android.
Ebooks pour apprendre la programmation sous Android.

Plus De Contenu Connexe

ProTips DroidCon Paris 2013

  1. 1. vous présente : Spécialiste Android 1
  2. 2. Android2EE est référencé en tant qu’organisme de formation, vous pouvez faire prendre en charge tout ou partie du montant de cette formation par votre OPCA. Cette formation Initiation avancée à Android est éligible au titre du DIF et CIF. Lieu : Paris, Toulouse, Lyon Durée : 3 jours Prix : 1680 € Lieu : Paris, Toulouse, Lyon Durée : 5 jours Prix : 2980 € Lieu : Paris, Toulouse, Lyon Durée : 3 jours Prix : 1780 €
  3. 3. Android2ee.com Formations: http://www.android2ee.com/fr/formations-android/inter-entreprises http://www.android2ee.com/fr/formations-android/formation-complete Open Ressources http://www.android2ee.com/fr/videos/devoxx-android-a-quick-course-1 http://www.android2ee.com/fr/livre-en-consultation/introduction-openbook http://www.android2ee.com/tutoriaux/appwidget.html mathias.seguy@android2ee.com https://github.com/MathiasSeguy-Android2EE http://fr.linkedin.com/pub/mathias-seguy/37/a71/a59 https://plus.google.com/115788770291974884100/about https://plus.google.com/b/109641731378552898326/109641731378552898326/about http://fr.slideshare.net/Android2EE https://play.google.com/store/apps/developer?id=ANDROID2EE http://fr.twitter.com/#%21/android2ee @deprectaed use linkedIn http://mathias-seguy.developpez.com/homepage/index.php http://blog.developpez.com/android2ee-mathias-seguy/ To GDG Vous souhaitez que je vienne faire une conférence dans votre Android User Group. Contactez moi, je suis preneur.
  4. 4. 4
  5. 5. 5 From Google I/O And Devoxx Ce chapitre est un extrait des « meilleurs » proTips donnés par les équipes Google lors des GoogleI/O, notamment : •Android ProTips, Reto Meier, Google I/O 2011 •Making Good Apps Great , Reto Meier, Google I/O 2012 •Google I_O 2013 - Android Protips_ Making Apps Work Like Magic , Reto Meier, Google I/O 2013 •Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010 Merci à eux pour ces présentations.
  6. 6. 6 Statics as Temporaries Utiliser des variables statiques pour vos variables temporaires public boolean pointInArea(int x, int y, Area area) { Point testPoint = new Point(x, y); return area.intersect(testPoint); } static final Point tmpPoint = new Point(); public boolean pointInArea(int x, int y, Area area) { tmpPoint.x = x; tmpPoint.y = y; return area.intersect(tmpPoint.yPoint); } Autoboxing creates Objects Utiliser les types primitifs, l’AutoBoxing créé des objets! Est équivalent à float x = 5; Float y = x; doSomething(x); void doSomething(Float z) {} float x = 5; Float y = new Float(x); doSomething(new Float(x)); void doSomething(Float z) {} Recycle those Bitmaps Les ressources sont limitées, recyclez vos Bitmaps le plus tôt possible (n’attendez pas la méthode finalize()) Vous pensez que cela aide: Mais en fait vous souhaitez: // done using this one, clear reference myBitmap = null; // done using this one, recycle it myBitmap.recycle(); From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010
  7. 7. 7 Use ViewStub La ViewStub permet le lazy loading de layouts. <ViewStub android:id="@+id/stub_import" android:inflatedId="@+id/panel_import" android:layout="@layout/progress_overlay" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" /> findViewById(R.id.stub_import).setVisibility(View.VISIBLE); // or View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();id/stub_import id/panel_import From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010
  8. 8. 8 Use merge et include <!-- The merge tag must be the root tag --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Content --> </merge> <!– The include tag is the one to use--> <LinearLayout …> <include layout="@layout/subLayout" /> <LinearLayout> .. </LinearLayout> </LinearLayout> Without merge With merge From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010
  9. 9. 9 Compounds Drawables Utiliser les balises android:drawable*** pour mettre des images à droite, à gauche … de vos composants héritant de TextView (TextView, Button, EditText,…) <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello" android:drawableLeft="@drawable/icon" /> Balises android:drawableBottom android:drawableEnd android:drawablePadding android:drawableRight android:drawableStart android:drawableTop From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010
  10. 10. 10 ListView and ArrayAdpater : Use ViewHolder and convertView public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.list_item_icon_text, parent, false); holder = new ViewHolder(); holder.text = (TextView) convertView.findViewById(R.id.text); holder.icon = (ImageView) convertView.findViewById(R.id.icon); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.text.setText(DATA[position]); holder.icon.setImageBitmap((position & 1) ==? mIcon1 : mIcon2); return convertView; } static class ViewHolder { TextView text; ImageView icon; } From Android Graphics, Animations and Tips & Tricks, Romain Guy & Chet Haase, Devoxx 2010
  11. 11. 11 UUID : Unique User ID L’ UUID Pattern permet détecter l'utilisateur plutôt que les installations. Si vous avez besoin d’identifier de manière unique l'utilisateur qui possède l’application, ce pattern est à utiliser. private static String uniqueID = null; private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID"; public synchronized static String id(Context context) { if (uniqueID == null) { SharedPreferences sharedPrefs = context.getSharedPreferences(PREF_UNIQUE_ID, Context.MODE_PRIVATE ); uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null); if (uniqueID == null) { uniqueID = UUID.randomUUID().toString(); Editor editor = sharedPrefs.edit(); editor.putString(PREF_UNIQUE_ID, uniqueID); editor.commit(); } } return uniqueID; } Android ProTips, Reto Meier, Google I/O 2011
  12. 12. 12 Know your Network and Battery context <receiver android:name="DeviceStateReceiever" > <action android:name="android.intent.action.ACTION_DOCK_EVENT" /> <action android:name="android.intent.action.ACTION_BATTERY_LOW" /> <action android:name="android.intent.action.ACTION_POWER_CONNECTED" /> <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <action android:name="android.net.wifi.STATE_CHANGE" /> </receiver> Android ProTips, Reto Meier, Google I/O 2011 ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); boolean isConnected = activeNetwork.isConnectedOrConnecting(); boolean isMobile = activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE;
  13. 13. 13 KeyBoard and EditText : Customize KeyBoard and set Action Quand vous définissez un champ de type EditText vous devez définir : • Son type de clavier 7 • L’action IME • (et le Hint) <EditText android:id="@+id/editEmailInput" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/compose_email_hint" android:imeOptions="actionSend|flagNoEnterAction" android:inputType="textShortMessage| textAutoCorrect| textCapSentences" /> Android ProTips, Reto Meier, Google I/O 2011 EditText.OnEditorActionListener myActionListener = new EditText.OnEditorActionListener() { @Override public boolean onEditorAction(EditText v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { // do here your stuff f return true; } return false; } };
  14. 14. 14 Always be asynchronous Rendez tout asynchrone en utilisant les Handler, Asynctask, IntentService (le système des Intents quoi), AsyncQueryHandler (le GetContentResolver en un sens), Loader (abstractClass) and CursorLoader (HoneyComb only). public class TutoActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor> { SimpleCursorAdapter mAdapter; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // … // Create an empty adapter we will use to display the loaded data. mAdapter = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_2, null, new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS }, new int[] { android.R.id.text1, android.R.id.text2 }, 0); listView.setAdapter(mAdapter); // Prepare the loader. Either re-connect with an existing one, // or start a new one. getLoaderManager().initLoader(0, null, this); } // Callbacks public Loader<Cursor> onCreateLoader(int id, Bundle args) { Uri baseUri = MyContentProvider.CONTENT_URI; return new CursorLoader(this, baseUri, null, null, null, null); } public void onLoadFinished(Loader<Cursor> loader, Cursor data) { mAdapter.swapCursor(data); } public void onLoaderReset(Loader<Cursor> loader) { mAdapter.swapCursor(null); } } Android ProTips, Reto Meier, Google I/O 2011
  15. 15. 15 Use the big cookies strategy when possible Préférez transférer un gros paquet de données au travers d’internet quand c’est possible plutôt que plein de petits paquets. Making Good Apps Great, Reto Meier, Google I/O 2012 int prefetchCacheSize = DEFAULT_PREFETCH_CACHE; switch (activeNetwork.getType()) { case ConnectivityManager.TYPE_WIFI: prefetchCacheSize = MAX_PREFETCH_CACHE; break; case ConnectivityManager.TYPE_MOBILE): { switch (telephonyManager.getNetworkType()) { case TelephonyManager.NETWORK_TYPE_LTE: case TelephonyManager.NETWORK_TYPE_HSPAP: prefetchCacheSize *= 4; break; case TelephonyManager.NETWORK_TYPE_EDGE: case TelephonyManager.NETWORK_TYPE_GPRS: prefetchCacheSize /= 2; break; default: break; } break; } default: break; }
  16. 16. Use AndroidBeam Parce que c'est tout simple d'échanger des données entre deux devices. Send Receive 16 Android Protips_ Making Apps Work Like Magic, Reto Meier, Google I/O 2013 public void onResume() { super.onResume(); NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); nfcAdapter.setNdefPushMessageCallback(new CreateNdefMessageCallback() { public NdefMessage createNdefMessage(NfcEvent event) { NdefMessage message = createMessage(); return message; } }, this); // ...} private void createMessage() { String mimeType = "application/com.myapp.nfcbeam"; byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII")); String payLoad = ""; // TODO Contextualized payload.; NdefMessage nfcMessage = new NdefMessage(new NdefRecord[] { new NdefRecord(ndefRecord.TNF_MIME_MEDIA, mimeByes, new byte[], payload.getBytes()), NdefRecord.createApplicationRecord("com.myapp.nfcbeam") }); } private void extractPayload(Intent beamIntent) { Parcelable[] messages = beamIntent.getParcelableArrayExtra( NfcAdapter.EXTRA_NDEF_MESSAGES); NdefAdapter message = (NdefMessage)message[0]; NdefRecord record = message.getRecords()[0]; String payload = new String(record.getPayload()); navigateTo(payload); } <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="application/com.myapp.nfcbeam"/> </intent-filter>
  17. 17. Location Utiliser le ServiceGooglePlay, il connait vos utilisateurs mieux que vous. 17 Android Protips_ Making Apps Work Like Magic, Reto Meier, Google I/O 2013 private void connectLBS() { int gpsExists = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (gpsExists == ConnectionResult.SUCCESS) { mLocationClient = new LocationClient(this, this, this); mlocationClient.connect(); } } @Override public void onConnected(Bundle connectionHint) { requestUpdates(mlocationClient); } private void requestUpdates(LocationClient mlocationClient) { LocationRequest request = LocationRequest.create(); request.setInterval(minTime); request.setPriority(lowPowerMoreImportantThanAccuracy ? LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY : LocationRequest.PRIORITY_HIGH_ACCURACY); mlocationClient.requestLocationUpdates(request, new LocationListener() { @Override public void onLocationChanged(Location location) { updateLocation(location); } }); }
  18. 18. Activity Recognition Adapter vos applications au contexte utilisateur (devant la télé, en voiture, en vélo, à pied...). 18 Android Protips_ Making Apps Work Like Magic, Reto Meier, Google I/O 2013 Intent intent = new Intent(this, ActivityRecognitionIntentService.class); intent.setAction(MyActivity.ACTION_STRING); PendingIntent pi = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURR ENT); mActivityRecognitionClient.requestActivityUpdates(interval, pi); @Override protected void onHandleIntent(Intent intent) { if (intent.getAction() == MyActivity.ACTION_STRING) { if (ActivityRecognitionResult.hasResult(intent)) { ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent); DetectedActivity detectedActivity = result.getMostProbableActivity(); int activityType = detectedActivity.getType(); if (activityType == DetectedActivity.STILL) setUpdateSpeed(PAUSED); else if (activityType == DetectedActivity.IN_VEHICLE) setUpdateSpeed(FASTER); else setUpdateSpeed(REGULAR); } } }
  19. 19. TextToSpeech : TTS De parlez à vos utilisateurs, parfois c'est super. Initialize Use 19 Android Protips_ Making Apps Work Like Magic, Reto Meier, Google I/O 2013 private void initTextToSpeech() { Intent intent = new Intent(Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(intent, TTS_DATA_CHECK); } protected void onActivityResult(int request, int result, Intent data) { if (request == TTS_DATA_CHECK && result == Engine.CHECK_VOICE_DATA_PASS) { tts = new TextToSpeech(this, new OnInitListener() { public void onInit(int status) { if (status == TextToSpeech.SUCCESS) ttsIsInit = true; } }); } else startActivity(new Intent(Engine.ACTION_INSTALL_TTS_DATA); } private void say(String text) { if (tts != null && ttisIsInit) tts.speak(text, TextToSpeech.QUEUE_ADD, null); }
  20. 20. Speech Recognition D'écouter vos utilisateurs, parfois c'est encore plus super. Record Consume 20 Android Protips_ Making Apps Work Like Magic, Reto Meier, Google I/O 2013 private void requestVoiceInput() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.String.voice_input_prompt); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.ENGLISH); startActivityForResult(intent, VOICE_RECOGNITION); } @Override protected void onActivityResult(int request, int result, Intent data) { if (request == VOICE_RECOGNITION && result == RESULT_OK) { ArrayList<String> results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); String mostLikelyResult = results[0]; useSpeechInput(mostLikelyResult); } }
  21. 21. 21
  22. 22. 22 From Google I/O 2012 Ce chapitre est un extrait de la conférence des Google I/O 2012 : •Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 Qui est exceptionnel sur la lutte contre la fragmentation, un très grand moment, merci à eux.
  23. 23. 23 Be Lazy Utiliser une classe abstraite qui sera instanciée par une factory et renverra l’implémentation correspondant à le version du système. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 public abstract class VersionedLoremIpsum { public abstract String doLorem(); public abstract int doIpsum(); } public class EclairLoremIpsum extends VersionedLoremIpsum { public String doLorem() { // do lorem, Eclair-style } public abstract int doIpsum() { // deliver ipsum, a là Eclair } } public class FroyoLoremIpsum extends EclairLoremIpsum { public String doLorem() { String l = super.doLorem(); // additional processing return l; } public abstract int doIpsum() { ... Activity VersionedLoremIpsum li; li=VLIFactory.get() VLIFactory public static VersionedLoremIpsum get( int sdk = Build.VERSION.SDK_INT; if (sdk <= Build.VERSION_CODES.ECLAIR) { li = new EclairLoremIpsum(); } else if (sdk <= Build.VERSION_CODES.FROYO) { li = new FroyoLoremIpsum(); } else { li = new GingerbreadLoremIpsum(); } )
  24. 24. 24 Resources are your best friend, use them. Utilisez des booléens pour savoir quelle est la version du système. Ils s’utilisent dans le code et dans le Manifest.xml. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 Manifest <receiver android:name="MyPreICSAppWidget" android:enabled="@bool/preICS"> ... </receiver> <receiver android:name="MyPostICSAppWidget" android:enabled="@bool/postICS"> ... </receiver> SomeWhere in java Resources res = getResources(); boolean postICS = res.getBoolean(R.bool.postICS); if (postICS) { // do something cool and cutting-edge } else { // do something old-school but elegant! } Resvalues-v14bools.xml <?xml version="1.0" encoding="utf-8"?> <resources> <bool name="postICS">true</bool> <bool name="preICS">false</bool> </resources> Resvaluesbools.xml <?xml version="1.0" encoding="utf-8"?> <resources> <bool name="postICS">false</bool> <bool name="preICS">true</bool> </resources>
  25. 25. 25 Construisez vos Layouts dynamiquement en fonction de la version système. Utilisez merge et include pour construire des IHM qui s’adaptent à la version de manière transparente. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 Reslayoutmain.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout ... <!-- non multi-versioned stuff here --> <include layout="@layout/desserts" /> <!-- more non multi-versioned stuff here --> </LinearLayout> Reslayoutdesserts.xml <?xml ... ?> <merge xmlns:android="..."> <CheckBox ... /> <CheckBox ... /> <CheckBox ... /> ... </merge> Reslayout-v11desserts.xml <?xml ... ?> <merge xmlns:android="..."> <Switch ... /> <Switch ... /> <Switch ... /> ... </merge>
  26. 26. 26 Hériter du thème de la version. Restez cohérent avec le thème du SDK de l’appareil cible, conservez une application cohérente avec l’appareil. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 MyTheme resvaluestheme.xml <style name=" MyBaseTheme" parent="@android:style/Theme" /> <style name="MyTheme" parent="MyBaseTheme"> <style name="MyButtonStyle" parent="@android:style/Widget.Button"> resvalues-v11theme.xml <style name=" MyBaseTheme" parent="@android:style/Theme.Holo" /> <style name="MyButtonStyle" parent="@android:style/Widget.Holo.Button"> MyBaseTheme Theme Theme.Holo
  27. 27. 27 Utiliser les Fragments et l’ActionBar sur toutes vos versions. Ayez une application identique quelque soit la version du système et utilisez le même fichier de layout. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 public class SpeakerDetailFragmentHC extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.speaker_detail, container, false); return view; } public class SpeakerDetailFragment extends android.support.v4.app.Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.speaker_detail, container, false); return view; } public class BaseActivityHC extends Activity{...} public class BaseActivityLegacy extends android.support.v4.app.FragmentActivity {...}android.support.v4.app.ActionBarActivity
  28. 28. private void pushInboxNotifications() { Notification notification = new Notification.Builder(this) .setContentTitle("10 New emails for me") .setContentText("subject") .setSmallIcon(android.R.drawable.ic_menu_agenda) .setStyle(Notification.InboxStyle) .addLine("Line 1, i can add more if i want") .addAction(R.drawable.icon,R.string.notification_message,new PendingIntent(....)) .setSound(aSound) .build(); NotificationManager notificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notification); } 28 Utiliser les notifications PreJB, PostJB. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012 if version >= JellyBean use Notification.Builder else use NotificationCompat.Builder
  29. 29. 29 L’ordre des boutons a changé depuis ICS. Avant ICS le bouton OK est à gauche, le bouton non ou cancel à droite. Après ICS le bouton OK est à droite, le bouton non ou cancel à gauche. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
  30. 30. <uses-sdk android:maxSdkVersion="16" android:minSdkVersion="8" android:targetSdkVersion="17" /> 30 Min et target SDK importe. Multiversioning Android, Bruno Oliveira & Adam Powell , Google I/O 2012
  31. 31. 31
  32. 32. 32 MinSDK=11 ?o? Utiliser le parrallel pattern. Deux types d'animation incompatibles : Avant (TweenAnimation) Après (ObjectAnimator, ViewProperty) HoneyComb. CodeDependent Chet Haase http://graphics-geek.blogspot.fr/. Be short. Le temps d'animation par défaut est de 300 ms. Cela dépend de l'objet à animer (une vue, une activité ce n'est pas un bouton). Be Amazing... but once. Les animations longues, belles et délirantes deviennent ennuyeuses au bout de 3. Remplacer les par des animations efficaces au bout de 3. Si en développement votre animation ne vous pourrit pas la vie alors elle ne pourrira pas celle de vos utilisateurs. Thanks Chet. Depuis HoneyComb, les animations sont améliorées, simplifiées et super flexibles. Dev.Bytes nous poste des tutos de 3 minutes pour nous les apprendre. Merci à Chet Haase pour tout ça.
  33. 33. <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:animateLayoutChanges="true" android:id="@+id/container"/> 33 MinSDK=16. Ajoutez cette balise à vos Layouts. Dès qu'un changement est détecté, il sera automatiquement animé pour le plaisir de vos utilisateurs. Dev.Bytes Chet Haase LayoutTransChanging https://www.youtube.com/watch?v=55wLsaWpQ4g. // Note that this assumes a LayoutTransition is set on the container, which is the // case here because the container has the attribute "animateLayoutChanges" set to true // in the layout file. You can also call setLayoutTransition(new LayoutTransition()) in // code to set a LayoutTransition on any container. LayoutTransition transition = container.getLayoutTransition(); // New capability as of Jellybean; monitor the container for *all* layout changes // (not just add/remove/visibility changes) and animate these changes as well. transition.enableTransitionType(LayoutTransition.CHANGING);
  34. 34. // Create bitmap to be re-used, based on the size of one of the bitmaps mBitmapOptions = new BitmapFactory.Options(); //Set for asking only the width and height of the bitmap, not the bitmap itself mBitmapOptions.inJustDecodeBounds = true; //With that option, bitMap is not load, but its size is set in mBitmapOptions.outWidth and mBitmapOptions.outHeight BitmapFactory.decodeResource(getResources(), R.drawable.a, mBitmapOptions); //Then create bitmap object (still not displaying any drawable) mCurrentBitmap = Bitmap.createBitmap(mBitmapOptions.outWidth, mBitmapOptions.outHeight, Bitmap.Config.ARGB_8888); //Then change the inJustDecode for asking the bitmap itself mBitmapOptions.inJustDecodeBounds = false; //Then define where the loaded bitmap will be drop in the mBitmapOptions.inSampleSize = 1; //and finally load it (as mBitmapOptions.inBitmap = mCurrentBitmap, the loaded bitmap will be in mCurrentBitmap) BitmapFactory.decodeResource(getResources(), R.drawable.a, mBitmapOptions); imageview.setImageBitmap(mCurrentBitmap); 34 MinSDK=15. Créer un objet BitMap et réutilisé le pour charger les images suivantes. Dev.Bytes Chet Haase Bitmap Allocation https://www.youtube.com/watch?v=rsQet4nBVi8 mCurrentIndex = (mCurrentIndex + 1) % imageIDs.length; BitmapFactory.Options bitmapOptions = null; if (reuseBitmapAllocation) { } long startTime = System.currentTimeMillis(); mCurrentBitmap = BitmapFactory.decodeResource(getResources(), imageIDs[mCurrentIndex], bitmapOptions); imageview.setImageBitmap(mCurrentBitmap); Premier chargement Chargements Suivants mBitmapOptions.inBitmap = mCurrentBitmap; // Re-use the bitmap by using BitmapOptions.inBitmap bitmapOptions = mBitmapOptions; bitmapOptions.inBitmap = mCurrentBitmap; Allocation Mémoire et Garbage optimisés Rapidité de chargement accrue
  35. 35. Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.jellybean_statue); originalImageView.setImageBitmap(bitmap); for (int i = 2; i < 10; ++i) { addScaledImageView(bitmap, i, container); } 35 MinSDK=15. Créer un objet BitMap et réutilisé le pour charger les images suivantes. Dev.Bytes Chet Haase LayoutTransChanging private Bitmap addScaledImageView(Bitmap original, int sampleSize, LinearLayout container) { // inSampleSize tells the loader how much to scale the final image, which it does at // load time by simply reading less pixels for every pixel value in the final bitmap. // Note that it only scales by powers of two, so a value of two results in a bitmap // 1/2 the size of the original and a value of four results in a bitmap 1/4 the original // size. Intermediate values are rounded down, so a value of three results in a bitmap 1/2 // the original size. BitmapFactory.Options bitmapOptions = new BitmapFactory.Options(); Bitmap scaledBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.jellybean_statue, bitmapOptions); return scaledBitmap; } Chargement normal bitmapOptions.inSampleSize = sampleSize; Chargement réduit
  36. 36. static class MyView extends View { Bitmap mBitmap; Paint paint = new Paint(); int mShapeX, mShapeY; int mShapeW, mShapeH; public MyView(Context context, AttributeSet attrs, int defStyle) {...; setupShape();} public MyView(Context context, AttributeSet attrs) {...; setupShape();} public MyView(Context context) {{...; setupShape();} private void setupShape() {Initialisation des objets graphiques...} @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { //Initialisation des tailles des composants et des positions mShapeX = (w - mBitmap.getWidth()) / 2; } 36 MinSDK=14. Animer vos vues. Vous pouvez en redéfinir une ou bien le mettre en place directement dans votre activité. Dev.Bytes Chet Haase Bouncer https://www.youtube.com/watch?v=vCTcmPIKgpM Initialisation de votre custom View
  37. 37. Dev.Bytes Chet Haase Bouncer https://www.youtube.com/watch?v=vCTcmPIKgpM 37 MinSDK=14. Mise en place de l'animation. 1. Définir et lancer l'animation. void startAnimation() { // This variation uses an ObjectAnimator. The ObjectAnimator automatically animate the target object for us, so we no longer need to listen for frame updates and do that work ourselves. ObjectAnimator anim = getObjectAnimator(); anim.setRepeatCount(ValueAnimator.INFINITE); anim.setRepeatMode(ValueAnimator.REVERSE); anim.setInterpolator(new AccelerateInterpolator()); anim.start();} ObjectAnimator getObjectAnimator() { } public void setShapeY(int shapeY) { //Set the new value mShapeY = shapeY; //Calculate the dirty area and ask to redraw it int minY = mShapeY;int maxY = mShapeY + mShapeH;minY = Math.min(mShapeY, minY); maxY = Math.max(mShapeY + mShapeH, maxY); //ask to redraw the rectangle area invalidate(mShapeX, minY, mShapeX + mShapeW, maxY); } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(mBitmap, mShapeX, mShapeY, paint);} return ObjectAnimator.ofInt(this, "shapeY", 0, (getHeight() - mShapeH)); 2. Construire l'ObjectAnimator 3. Mettre a jour les données graphiques Calculer la zone a redessiner Demander le redraw 4. Dessiner l'objet
  38. 38. // Create the AnimationDrawable in which we will store all frames of the animation final AnimationDrawable animationDrawable = new AnimationDrawable(); for (int i = 0; i < 10; ++i) { animationDrawable.addFrame(createDrawableForFrameNumber(i), 300); } // Run until we say stop animationDrawable.setOneShot(false); imageview.setImageDrawable(animationDrawable); animationDrawable.start(); 38 MinSDK=14. Animer vos vues. Vous pouvez en redéfinir une ou bien le mettre en place directement dans votre activité. Dev.Bytes Chet Haase KeyframeAnimation https://www.youtube.com/watch?v=V3ksidLf7vA AnimationDrawable private BitmapDrawable createDrawableForFrameNumber(int frameNumber) { Bitmap bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawColor(Color.GRAY); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setTextSize(80); paint.setColor(Color.BLACK); canvas.drawText("Frame " + frameNumber, 40, 220, paint); return new BitmapDrawable(getResources(), bitmap); } Building a Bitmap from scratch
  39. 39. 39 From Google I/O 2013 By Chet Haase and Romain Guy Google I/o 2013 Romain Guy - Chet Haase "A Moving Experience" http://graphics-geek.blogspot.fr/2013/06/devbytes-animating-listview-deletion.html mListView.setEnabled(false); v.animate().setDuration(duration).alpha(endAlpha).translationX(endX). withEndAction(new Runnable() { @Override public void run() { // Restore animated values v.setAlpha(1); v.setTranslationX(0); }}); 0.Lancement de l'animation dans View.OnTouchListener# MotionEvent.ACTION_UP animateRemoval(mListView, v);
  40. 40. Google I/o 2013 Romain Guy - Chet Haase "A Moving Experience" http://graphics-geek.blogspot.fr/2013/06/devbytes-animating-listview-deletion.html 40 From Google I/O 2013 By Chet Haase and Romain Guy private void animateRemoval(final ListView listview, View viewToRemove) { observer.removeOnPreDrawListener(this); for (int i = 0; i < listview.getChildCount(); ++i) { child.setTranslationY(delta); if (firstAnimation) { child.animate().withEndAction(new Runnable() { public void run() { mBackgroundContainer.hideBackground(); mSwiping = false; mListView.setEnabled(true); } }); mItemIdTopMap.clear(); return true;}}); final ViewTreeObserver observer = listview.getViewTreeObserver(); observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { child.animate().setDuration(MOVE_DURATION).translationY(0); 1.Récupération du ViewTreeObserver 2.Ajout du Listener PreDraw 3.Mise en place de l'animation dans le preDraw
  41. 41. 41 And of course thanks to
  42. 42. Merci pour votre attention. android2ee.com. #android2ee mathias.seguy@android2ee.com 42 MyTorchMyLightMySensor My Google Public Profile

×