Android, the life of your app
-
Upload
eyal-lezmy -
Category
Technology
-
view
269 -
download
0
description
Transcript of Android, the life of your app
THE LIFE OF YOUR APP
Eyal LEZMY
http://eyal.fr
SLIDES http://bit.ly/lifeofapp
AGENDACODEURS EN SEINE
01
Install it
02
Launch it
03
Look at it
04
Use it
IT ALL STARTS ON THE PLAY STORE
01
Request only what your app requires
1/3 of apps request more permissions than they need
MINIMISE PERMISSIONS
Users should prefer apps
requesting the least
permissions
You don’t need permission
Use ContentProviders
MINIMISE PERMISSIONS
Users should prefer apps
requesting the least
permissions
Permission are not required to launch another activity that has the permission
MINIMISE PERMISSIONS
Need a contact?
MINIMISE PERMISSIONS
Use the force, Luke
MINIMISE PERMISSIONS
MINIMISE PERMISSIONS
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType(Phone.CONTENT_ITEM_TYPE);startActivityForResult(intent, MY_REQUEST_CODE);
void onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { Uri uri = data.getData(); if (uri != null) { Cursor c = getContentResolver().query(uri, new String[] {Contacts.DISPLAY_NAME, Phone.NUMBER}, null, null, null);} }
}}
MINIMISE PERMISSIONS
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType(Phone.CONTENT_ITEM_TYPE);startActivityForResult(intent, MY_REQUEST_CODE);
Start the contact app
void onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { Uri uri = data.getData(); if (uri != null) { Cursor c = getContentResolver().query(uri, new String[] {Contacts.DISPLAY_NAME, Phone.NUMBER}, null, null, null);} }
}}
MINIMISE PERMISSIONS
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType(Phone.CONTENT_ITEM_TYPE);startActivityForResult(intent, MY_REQUEST_CODE);
Start the contact app
Handle the result
void onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { Uri uri = data.getData(); if (uri != null) { Cursor c = getContentResolver().query(uri, new String[] {Contacts.DISPLAY_NAME, Phone.NUMBER}, null, null, null);} }
}}
Need an UUID? TelephonyManager.getDeviceId()
Requires READ_PHONE_STATE permission
MINIMISE PERMISSIONS
Settings.Secure.ANDROID_IDReset at every wipeNot applicable on multi user environment
Need an UUID? TelephonyManager.getDeviceId()
Requires READ_PHONE_STATE permission
MINIMISE PERMISSIONS
Settings.Secure.ANDROID_IDReset at every wipeNot applicable on multi user environment
NO!
Need an UUID? Generate your own UUID and use
Backup API !
MINIMISE PERMISSIONS
String id = UUID.randomUUID().toString();
Need an UUID? Generate your own UUID and use
Backup API !
MINIMISE PERMISSIONS
String id = UUID.randomUUID().toString();
YES!
Android Backup API
· API is available on all Android devices. · Manufacturors can implements their own transport and storage for the API
· Each device as its own backup data
· A new device will take a backup from a device associated with your google account.
· IT'S NOT A SYNC API !
MINIMISE PERMISSIONS
THE FIRST LAUNCH02
Make a good
impression
THE FIRST LAUNCH
Lets start!
THE FIRST LAUNCH
http://cyrilmottier.com
THE FIRST LAUNCH
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.MyTheme" ... >
We define our personal theme including the correct styles and colors
Let’s start...Again!
THE FIRST LAUNCH
My Big
BRAND
LOADING ...
A bunch of data to insert? Use SQL transactions to save
time!
THE FIRST LAUNCH
THE FIRST LAUNCH
db.beginTransaction();
try{for(int i=0; i<selectedIds.length; i++){
values.put(COLUMN_ID,selectedIds[i]);values.put(COLUMN_STARRED,starred);db.insert(TABLE_STARRED,null,values);db.yieldIfContendedSafely();
}
db.setTransactionSuccessful();
} finally {db.endTransaction();
}
Start transaction
THE FIRST LAUNCH
db.beginTransaction();
try{for(int i=0; i<selectedIds.length; i++){
values.put(COLUMN_ID,selectedIds[i]);values.put(COLUMN_STARRED,starred);db.insert(TABLE_STARRED,null,values);db.yieldIfContendedSafely();
}
db.setTransactionSuccessful();
} finally {db.endTransaction();
}
Start transaction
End transaction
THE FIRST LAUNCH
db.beginTransaction();
try{for(int i=0; i<selectedIds.length; i++){
values.put(COLUMN_ID,selectedIds[i]);values.put(COLUMN_STARRED,starred);db.insert(TABLE_STARRED,null,values);db.yieldIfContendedSafely();
}
db.setTransactionSuccessful();
} finally {db.endTransaction();
}
Start transaction
End transaction Optimise multi-threaded insertion
Import directly, ready to use databases
Faster?
THE FIRST LAUNCH
openDatabase(dbPath, null,SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.CREATE_IF_NECESSARY);
· Create your db file using SQlite and fill it
· Name your primary key columns "_id"
· Create the table : "android_metadata"
· And insert a single row containing the local if defined (ex: "en_US"), or open your database using :
THE FIRST LAUNCH
ON THE SERVER
· Grab the zipped database from assets or network
· Unzip it to your getDatabaseDir()
· Open the database
THE FIRST LAUNCH
ON THE MOBILE
Be careful of the SQLite version !
LOOK AND FEEL03
? ? ?
LOOK AND FEEL
HOTMAIL OUTLOOK.COM
LOOK AND FEEL
HOTMAIL OUTLOOK.COM
SAME!
LOOK AND FEEL
FOLLOW THE GUIDELINES!http://d.android.com/design
Redesigned by Taylor Ling
LOOK AND FEEL
By Microsoft
LOOK AND FEEL
LOOK AND FEEL
LOOK AND FEEL
LOOK AND FEEL
FOLLOW THE GUIDELINES!http://d.android.com/design
LOOK AND FEEL
FOLLOW THE GUIDELINES!http://d.android.com/design
PLEASE!
A DAILY USE04
UI Thread =
Events+Draw 16 ms to draw a frame (~60 fps)
SMOOTHEN YOUR UI
Garbage Collector may take 10ms And stop all threads
Flatten the View
Hierarchy· Use RelativeLayout instead of LinearLayout
· Use the <merge/> tag when possible
· Use hierarchyviewer to inspect your layouts
SMOOTHEN YOUR UI
Avoid overdraws · Do not draw your background several times
· Use the “GPU Overdraw” tool from Android 4.2
SMOOTHEN YOUR UI
Use SparseArray
SMOOTHEN YOUR UI
Avoid autoboxing
SMOOTHEN YOUR UI
Hashmap<Integer, Object> hashmap = new HashMap<Integer, Object>();hashmap.put(1789, mRevolution);...hashmap.get(1789);
SparseArray<Object> sparseArray = new SparseArray<Object>();sparseArray.put(1789, mRevolution);...sparseArray.get(1789);
SMOOTHEN YOUR UI
Hashmap<Integer, Object> hashmap = new HashMap<Integer, Object>();hashmap.put(1789, mRevolution);...hashmap.get(1789);
new Integer(1789)
SparseArray<Object> sparseArray = new SparseArray<Object>();sparseArray.put(1789, mRevolution);...sparseArray.get(1789);
SMOOTHEN YOUR UI
Hashmap<Integer, Object> hashmap = new HashMap<Integer, Object>();hashmap.put(1789, mRevolution);...hashmap.get(1789);
new Integer(1789)new Integer(1789)
SparseArray<Object> sparseArray = new SparseArray<Object>();sparseArray.put(1789, mRevolution);...sparseArray.get(1789);
SMOOTHEN YOUR UI
Hashmap<Integer, Object> hashmap = new HashMap<Integer, Object>();hashmap.put(1789, mRevolution);...hashmap.get(1789);
new Integer(1789)new Integer(1789)
Low memory footprint and no more GC!
SparseArray<Object> sparseArray = new SparseArray<Object>();sparseArray.put(1789, mRevolution);...sparseArray.get(1789);
· Reuse it
· Use sampling
SMOOTHEN YOUR UI
Load bitmapcleverly
SMOOTHEN YOUR UI
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inBitmap = myOldBitmap;
Bitmap scaledBitmap = BitmapFactory.decode...(..., bitmapOptions);
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = sampleSize;
SMOOTHEN YOUR UI
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inBitmap = myOldBitmap;
Bitmap scaledBitmap = BitmapFactory.decode...(..., bitmapOptions);
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = sampleSize;
Define the bitmap to reuse (API level 11)
SMOOTHEN YOUR UI
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inBitmap = myOldBitmap;
Bitmap scaledBitmap = BitmapFactory.decode...(..., bitmapOptions);
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = sampleSize;
Use the option for loadingDefine the bitmap to reuse (API level 11)
SMOOTHEN YOUR UI
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inBitmap = myOldBitmap;
Bitmap scaledBitmap = BitmapFactory.decode...(..., bitmapOptions);
Define the subsampling level (API Level 1)
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = sampleSize;
Use the option for loadingDefine the bitmap to reuse (API level 11)
PRESERVE THE BATTERY
Screen: 1st item of consumtion30 to 70% of the battery life
PRESERVE THE BATTERY
Basically you don’t need itOnly a few kind of applications should need to stay the device awake (Reader, Games, …)
Think about the contextRelease wake lock if you have good assumptions that the user is not using your app anymore
WakeLocks
PRESERVE THE BATTERY
GPS· Permission ACCESS_FINE_LOCATION · Drains a lot of power· Works offline
Network location· Permission ACCESS_COARSE_LOCATION· Need to be online· Fast· Precise in urban area
Geolocation
PRESERVE THE BATTERY
Define a strategy· What is the needed precision for my app?· Define the measure interval wisely· Consider the GPS fix time
Use Fused Location ProviderOn Google Play Services
Geolocation
PRESERVE THE BATTERY
Radio drains a lot of powerGroup data to minimize the number of requests
Use caching!
Network
PRESERVE THE BATTERY
PRESERVE THE BATTERY
private void enableHttpResponseCache() { try {
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
File httpCacheDir = new File(getCacheDir(), “http”);
Class.forName(“android.net.http.HttpResponseCache”)
.getMethod(“install”, File.class, long.class)
.invoke(null, httpCacheDir, httpCacheSize);
} catch (Exception httpResponseCacheNotAvailable) {
Log.d(TAG, “HTTP response cache is unavailable.”);
}
}
Enable cache, if available (API level 13)Or use a backport like HttpResponseCache
Enable GZIP on the server30 to 50% less trafic
Use ETAGs
Network
PRESERVE THE BATTERY
PRESERVE THE BATTERY
BE INSPIRED
Gestures Text to Speech Accelerometer
Voice recognition Proximity sensor Bluetooth
NFC Direct Wifi Second Screen
BE INSPIRED
Explore all the device’s possibilities
Thank You for your time !
http://eyal.fr
SLIDEShttp://bit.ly/lifeofapp