SlideShare uma empresa Scribd logo
1 de 42
vous présente :
Spécialiste Android
1
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 €
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
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
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
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
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
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
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
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
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
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
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
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;
}
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>
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);
}
});
}
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);
}
}
}
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);
}
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
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
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
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
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
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
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
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
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
<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
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.
<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);
// 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
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
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
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
// 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
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);
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
And of course thanks to
Merci pour votre attention.
android2ee.com.
#android2ee
mathias.seguy@android2ee.com
42
MyTorchMyLightMySensor My Google
Public Profile

Mais conteúdo relacionado

Mais procurados

Anton Minashkin Dagger 2 light
Anton Minashkin Dagger 2 lightAnton Minashkin Dagger 2 light
Anton Minashkin Dagger 2 lightMichael Pustovit
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Mahmoud Hamed Mahmoud
 
Vaadin 7 CN
Vaadin 7 CNVaadin 7 CN
Vaadin 7 CNjojule
 
Handling action bar in Android
Handling action bar in AndroidHandling action bar in Android
Handling action bar in Androidindiangarg
 
Data binding в массы! (1.2)
Data binding в массы! (1.2)Data binding в массы! (1.2)
Data binding в массы! (1.2)Yurii Kotov
 
CDI do básico ao avançado
CDI do básico ao avançadoCDI do básico ao avançado
CDI do básico ao avançadoAlberto Souza
 
Advancing the UI — Part 1: Look, Motion, and Gestures
Advancing the UI — Part 1: Look, Motion, and GesturesAdvancing the UI — Part 1: Look, Motion, and Gestures
Advancing the UI — Part 1: Look, Motion, and GesturesSamsung Developers
 
Techlunch - Dependency Injection with Vaadin
Techlunch - Dependency Injection with VaadinTechlunch - Dependency Injection with Vaadin
Techlunch - Dependency Injection with VaadinPeter Lehto
 
Dagger 2 vs koin
Dagger 2 vs koinDagger 2 vs koin
Dagger 2 vs koinJintin Lin
 
Android dev toolbox
Android dev toolboxAndroid dev toolbox
Android dev toolboxShem Magnezi
 
What I’ve learned when developing BlockAlertViews
What I’ve learned when developing BlockAlertViewsWhat I’ve learned when developing BlockAlertViews
What I’ve learned when developing BlockAlertViewsGustavo Ambrozio
 
안드로이드 데이터 바인딩
안드로이드 데이터 바인딩안드로이드 데이터 바인딩
안드로이드 데이터 바인딩GDG Korea
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesMichael Galpin
 
Why SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptWhy SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptmartinlippert
 

Mais procurados (20)

Popup view on Mortar
Popup view on MortarPopup view on Mortar
Popup view on Mortar
 
Anton Minashkin Dagger 2 light
Anton Minashkin Dagger 2 lightAnton Minashkin Dagger 2 light
Anton Minashkin Dagger 2 light
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
 
Vaadin 7 CN
Vaadin 7 CNVaadin 7 CN
Vaadin 7 CN
 
Handling action bar in Android
Handling action bar in AndroidHandling action bar in Android
Handling action bar in Android
 
Device fragmentation vs clean code
Device fragmentation vs clean codeDevice fragmentation vs clean code
Device fragmentation vs clean code
 
Introduction toandroid
Introduction toandroidIntroduction toandroid
Introduction toandroid
 
Data binding в массы! (1.2)
Data binding в массы! (1.2)Data binding в массы! (1.2)
Data binding в массы! (1.2)
 
iphonedevcon 2010: Cooking with iAd
iphonedevcon 2010:  Cooking with iAd iphonedevcon 2010:  Cooking with iAd
iphonedevcon 2010: Cooking with iAd
 
CDI do básico ao avançado
CDI do básico ao avançadoCDI do básico ao avançado
CDI do básico ao avançado
 
Advancing the UI — Part 1: Look, Motion, and Gestures
Advancing the UI — Part 1: Look, Motion, and GesturesAdvancing the UI — Part 1: Look, Motion, and Gestures
Advancing the UI — Part 1: Look, Motion, and Gestures
 
Lab1-android
Lab1-androidLab1-android
Lab1-android
 
Techlunch - Dependency Injection with Vaadin
Techlunch - Dependency Injection with VaadinTechlunch - Dependency Injection with Vaadin
Techlunch - Dependency Injection with Vaadin
 
Dagger 2 vs koin
Dagger 2 vs koinDagger 2 vs koin
Dagger 2 vs koin
 
Android dev toolbox
Android dev toolboxAndroid dev toolbox
Android dev toolbox
 
What I’ve learned when developing BlockAlertViews
What I’ve learned when developing BlockAlertViewsWhat I’ve learned when developing BlockAlertViews
What I’ve learned when developing BlockAlertViews
 
안드로이드 데이터 바인딩
안드로이드 데이터 바인딩안드로이드 데이터 바인딩
안드로이드 데이터 바인딩
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and Smartphones
 
Why SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptWhy SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScript
 
Creating Alloy Widgets
Creating Alloy WidgetsCreating Alloy Widgets
Creating Alloy Widgets
 

Destaque

Mise en place de l'ActionBarCompat dans vos projets Android.
Mise en place de l'ActionBarCompat dans vos projets Android.Mise en place de l'ActionBarCompat dans vos projets Android.
Mise en place de l'ActionBarCompat dans vos projets Android.Mathias Seguy
 
Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur...
Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur...Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur...
Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur...Mathias Seguy
 
Android un nouveau futur s'ouvre à nous
Android un nouveau futur s'ouvre à nousAndroid un nouveau futur s'ouvre à nous
Android un nouveau futur s'ouvre à nousMathias Seguy
 
CocoaHeads An Android Overview (fr)
CocoaHeads An Android Overview (fr)CocoaHeads An Android Overview (fr)
CocoaHeads An Android Overview (fr)Mathias Seguy
 
Treatment, Architecture and Threads
Treatment, Architecture and ThreadsTreatment, Architecture and Threads
Treatment, Architecture and ThreadsMathias Seguy
 
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2Mathias Seguy
 
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)Mathias Seguy
 
Voyage en monde Android. Trucs et astuces tout au long de la route.
Voyage en monde Android. Trucs et astuces tout au long de la route.Voyage en monde Android. Trucs et astuces tout au long de la route.
Voyage en monde Android. Trucs et astuces tout au long de la route.Mathias Seguy
 
Android2EE training: Tutorials list of Android projects
Android2EE training: Tutorials list of Android projectsAndroid2EE training: Tutorials list of Android projects
Android2EE training: Tutorials list of Android projectsMathias Seguy
 

Destaque (9)

Mise en place de l'ActionBarCompat dans vos projets Android.
Mise en place de l'ActionBarCompat dans vos projets Android.Mise en place de l'ActionBarCompat dans vos projets Android.
Mise en place de l'ActionBarCompat dans vos projets Android.
 
Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur...
Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur...Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur...
Conférence "Architecture Android" du 19 Mars 2013 par Mathias Seguy fondateur...
 
Android un nouveau futur s'ouvre à nous
Android un nouveau futur s'ouvre à nousAndroid un nouveau futur s'ouvre à nous
Android un nouveau futur s'ouvre à nous
 
CocoaHeads An Android Overview (fr)
CocoaHeads An Android Overview (fr)CocoaHeads An Android Overview (fr)
CocoaHeads An Android Overview (fr)
 
Treatment, Architecture and Threads
Treatment, Architecture and ThreadsTreatment, Architecture and Threads
Treatment, Architecture and Threads
 
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
Architecture et Bonnes pratiques Android #DevoxxFr2016 Part2
 
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
Animate Me, if you don't do it for me do it for chet (DroidCon Paris)
 
Voyage en monde Android. Trucs et astuces tout au long de la route.
Voyage en monde Android. Trucs et astuces tout au long de la route.Voyage en monde Android. Trucs et astuces tout au long de la route.
Voyage en monde Android. Trucs et astuces tout au long de la route.
 
Android2EE training: Tutorials list of Android projects
Android2EE training: Tutorials list of Android projectsAndroid2EE training: Tutorials list of Android projects
Android2EE training: Tutorials list of Android projects
 

Semelhante a ProTips DroidCon Paris 2013

Android UI Development: Tips, Tricks, and Techniques
Android UI Development: Tips, Tricks, and TechniquesAndroid UI Development: Tips, Tricks, and Techniques
Android UI Development: Tips, Tricks, and TechniquesEdgar Gonzalez
 
Android UI Tips, Tricks and Techniques
Android UI Tips, Tricks and TechniquesAndroid UI Tips, Tricks and Techniques
Android UI Tips, Tricks and TechniquesMarakana Inc.
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best PracticesYekmer Simsek
 
Mobile 2.0 Open Ideas WorkShop: Building Social Media Enabled Apps on Android
Mobile 2.0 Open Ideas WorkShop: Building Social Media Enabled Apps on AndroidMobile 2.0 Open Ideas WorkShop: Building Social Media Enabled Apps on Android
Mobile 2.0 Open Ideas WorkShop: Building Social Media Enabled Apps on AndroidAlberto Ruibal
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in AndroidRobert Cooper
 
Android activity, service, and broadcast recievers
Android activity, service, and broadcast recieversAndroid activity, service, and broadcast recievers
Android activity, service, and broadcast recieversUtkarsh Mankad
 
Android Workshop 2013
Android Workshop 2013Android Workshop 2013
Android Workshop 2013Junda Ong
 
ハンズオン資料 電話を作ろう(v1.6用)
ハンズオン資料 電話を作ろう(v1.6用)ハンズオン資料 電話を作ろう(v1.6用)
ハンズオン資料 電話を作ろう(v1.6用)Kenji Sakashita
 
21 android2 updated
21 android2 updated21 android2 updated
21 android2 updatedGhanaGTUG
 
STYLISH FLOOR
STYLISH FLOORSTYLISH FLOOR
STYLISH FLOORABU HASAN
 
Android accessibility for developers and QA
Android accessibility for developers and QAAndroid accessibility for developers and QA
Android accessibility for developers and QATed Drake
 
android level 3
android level 3android level 3
android level 3DevMix
 
Android Workshop
Android WorkshopAndroid Workshop
Android WorkshopJunda Ong
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideVisual Engineering
 
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...mharkus
 
Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Alfredo Morresi
 

Semelhante a ProTips DroidCon Paris 2013 (20)

Android UI Development: Tips, Tricks, and Techniques
Android UI Development: Tips, Tricks, and TechniquesAndroid UI Development: Tips, Tricks, and Techniques
Android UI Development: Tips, Tricks, and Techniques
 
Android UI Tips, Tricks and Techniques
Android UI Tips, Tricks and TechniquesAndroid UI Tips, Tricks and Techniques
Android UI Tips, Tricks and Techniques
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
Mobile 2.0 Open Ideas WorkShop: Building Social Media Enabled Apps on Android
Mobile 2.0 Open Ideas WorkShop: Building Social Media Enabled Apps on AndroidMobile 2.0 Open Ideas WorkShop: Building Social Media Enabled Apps on Android
Mobile 2.0 Open Ideas WorkShop: Building Social Media Enabled Apps on Android
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in Android
 
Day 5
Day 5Day 5
Day 5
 
Android activity, service, and broadcast recievers
Android activity, service, and broadcast recieversAndroid activity, service, and broadcast recievers
Android activity, service, and broadcast recievers
 
Android Workshop 2013
Android Workshop 2013Android Workshop 2013
Android Workshop 2013
 
ハンズオン資料 電話を作ろう(v1.6用)
ハンズオン資料 電話を作ろう(v1.6用)ハンズオン資料 電話を作ろう(v1.6用)
ハンズオン資料 電話を作ろう(v1.6用)
 
Android For All The Things
Android For All The ThingsAndroid For All The Things
Android For All The Things
 
21 android2 updated
21 android2 updated21 android2 updated
21 android2 updated
 
Compose In Practice
Compose In PracticeCompose In Practice
Compose In Practice
 
STYLISH FLOOR
STYLISH FLOORSTYLISH FLOOR
STYLISH FLOOR
 
Android accessibility for developers and QA
Android accessibility for developers and QAAndroid accessibility for developers and QA
Android accessibility for developers and QA
 
android level 3
android level 3android level 3
android level 3
 
Android Workshop
Android WorkshopAndroid Workshop
Android Workshop
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
 
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
 
Mini curso Android
Mini curso AndroidMini curso Android
Mini curso Android
 
Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)
 

Último

Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 

Último (20)

Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 

ProTips DroidCon Paris 2013

  • 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. 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
  • 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 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 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 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 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 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 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 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 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 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 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. 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. 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. 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. 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. 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
  • 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 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 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 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 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 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. 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 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. <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
  • 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. <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. // 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. 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. 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. 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. // 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 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. 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 And of course thanks to
  • 42. Merci pour votre attention. android2ee.com. #android2ee mathias.seguy@android2ee.com 42 MyTorchMyLightMySensor My Google Public Profile