Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Introduction (part I): Java and Android basics Alexey Golubev, Dmitry Lukashev What is the plan? Android UI Android in Action JVM, GC, Threads, SDK, NDK, Activity, Code style, etc. Layouts, ListView, Menu, Dialog, Widgets, Tips & tricks, etc. Screen rotation, Memory analyze, AIDL, SAX, Debug, Wakelock, etc. Part I Part II Part III Java +Android (basics) Part I: Introduction What is this about? • Introduction to Java world • JVM, Dalvik VM, JIT • GC, multithreading, collections, etc. • Android Basics • Architecture • Building blocks, SDK, NDK, etc. • NDK demo Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style Where to start • • • • http://developer.android.com/ http://source.android.com/ http://android.git.kernel.org/ http://android-developers.blogspot.com/ Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style JVM Class loader subsystem class files Thread VM Сlass The pc register (program counter) JVM Stack Native methods stacks Heap Method Area Runtime Constant Pool Execution engine Native method interface native method libraries Dalvik VM • Was written by Dan Bornstein • Transform class files into DEX • It is VM… – – – – – integrated with Linux uses shared memory, mmap for OS without swap space while powered by a battery zygote • The Dalvik VM is register-based: fewer instructions, code units, instructions • Verification & optimization at installation time Give me your huddled bytecodes yearning to run free. And I lift the light beside the coder’s door DEX file – shared constant pool .jar file .class file heterogeneous constant pool other data .class file heterogeneous constant pool other data .dex file string_ids constant pool “Hello World” “Lcom/data/Data” type_ids constant pool int String[ ] proto_ids constant pool String fn() void fn(int) field_ids constant pool String.offset Integer.MAX_VALUE method_ids constant pool PrintStream.println(…) Collection.size() .class file heterogeneous constant pool other data other data DEX file – memory saving • • • minimal repetition per-type pools (implicit typing) implicit labeling common system libraries (U) 21445320 — 100% (uncompressed jar file) (J) 10662048 — 50% (compressed jar file) (D) 10311972 — 48% (uncompressed dex file) web browser app (U) 470312 — 100% (J) 232065 — 49% (D) 209248 — 44% • Google claims that Dalvik bytecode is more efficient than Sun’s stack bytecode JIT (since Android 2.2) • • • • Translates byte code to optimized native code at run time Part of the open source Trace JIT vs Method JIT Trace JIT – – – – – Minimizing memory usage critical for mobile devices (100K) Important to deliver performance boost quickly Trace request is built during interpretation Compiled traces chained together in translation cache Per process translation cache • Leave open the possibility of supplementing with methodbased JIT Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style Garbage collection • GC is under control of the JVM • An object is eligible for garbage collection when no live thread can access it • System.gc(); Runtime.getRuntime().gc() • static – variables with the longest life time public class Island { Island i; public static void main(String[] args) { Island i2 = new Island(); Island i3 = new Island(); Island i4 = new Island(); i2.n = i3; i3.n = i4; i4.n = i2; i2 = null; i3 = null; i4 = null; Island x = new Island(); x = null; } } The heap i2 i2.n i3 i4 i3.n i4.n “Islands of Isolation” x Mark and Sweep example • • Parallel mark bits in Obtain locks and suspend threads Dalvik VM (separate from other heap memory) Mark phase – Process of identifying all objects reachable from the root set. – All “live” objects are marked by setting a mark bit in the mark bit vector. • Sweep phase – Sweep phase identifies all the objects that have been allocated, but no longer referenced. Compaction (optional) – Once garbage has been removed, we consider compacting the resulting set of objects to remove spaces between them. Release locks and resume threads • • Generational GC • Most recently created objects – most likely to become unreachable quickly Young Generation Old Generation • Minor Collection – takes place only in the young generation, normally done through direct copying – very efficient • Major Collection – takes place in the new and old generation and uses the normal mark/sweep (+compact) algorithm Strings • Strings are immutable in Java String s1 = "abc"; // 1 object, 1 reference String s2 = "abc"; // s1 == s2 String s3 = new String("abc"); // 2 objects, 1 reference String s4 = new String("abc"); // s3 != s4 String x = “Hi"; The heap “Hi” x // optimization by interning strings s3 = s3.intern(); s4 = s4.intern(); • Use StringBuffer, StringBuilder • Set initial capacity of StringBuilder x = x.concat(" GTUG!"); The heap “Hi” x “Hi GTUG” Quiz class Foo { int[] mArray = { 1, 2, 3, 4, 5 }; } [ ref0, ref1, ref2] public class Test { public static void main(String[] args) { Foo[] fa = new Foo[3]; Foo() [] fa[0] = new Foo(); Foo f = new Foo(); fa[1] = f; f = null; fa[1] = null; // how many objects were created at this point? // how many are eligible for gc()? } } Foo() [] Performance • Do not allocate memory as much as you can • GC is slow (~x00 ms on Android device) • Decrease number of objects – GC will work faster (i.e. StringBuffer vs String) • Use primitive types for arrays (int vs Integer) • Use special methods: String.indexOf(), substring(), etc. • Use exact class types instead of interfaces (i.e. HashMap instead of Map) on devices without JIT • Use static where possible ArrayList<MyClass> mList = new ArrayList<MyClass>(); • Avoid internal getters/setters ... for (MyClass next : mList) { • Use enhanced for-loop syntax ... } Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style References • Strong reference: Object obj = new Object(); • SoftReference – soft references will be cleared before the JVM reports an out-of-memory condition (memory-sensitive cache) • WeakReference – gc frees weakly reachable object when it founds it, avoid memory leaks (e.g. http://en.wikipedia.org/wiki/Flyweight_pattern) • PhantomReference – is useful only to track the impending collection of the referring object. Must be used only with the ReferenceQueue class. Most often used for scheduling premortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism SoftReference: simple cache private final HashMap<String, SoftReference<T>> mCache; public put(String key, T value) { mCache.put(key, new SoftReference<T>(value)); } public T get(String key, ValueBuilder builder) { T value = null; SoftReference<T> reference = mCache.get(key); if (reference != null) { value = reference.get(); } // Not in cache or gc'd if (value == null) { value = builder.build(key); mCache.put(key, new SoftReference<T>(value)); } return value; } git://android.git.kernel.org/platform/packages/apps/Mms.git/src/com/android/mms/model/ImageModel.java package com.android.mms.model; public class ImageModel extends RegionMediaModel { private static final String TAG = "Mms/image"; private static final int THUMBNAIL_BOUNDS_LIMIT = 480; private SoftReference<Bitmap> mBitmapCache = new SoftReference<Bitmap>(null); ... private Bitmap internalGetBitmap(Uri uri) { Bitmap bm = mBitmapCache.get(); if (bm == null) { try { bm = createThumbnailBitmap(THUMBNAIL_BOUNDS_LIMIT, uri); if (bm != null) { mBitmapCache = new SoftReference<Bitmap>(bm); } } catch (OutOfMemoryError ex) { // fall through and return a null bitmap. // The callers can handle a null // result and show R.drawable.ic_missing_thumbnail_picture } } return bm; } } SoftReference git://android.git.kernel.org/platform/frameworks/base.git/core/java/android/app/Dialog.java package android.app; public class Dialog implements DialogInterface, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener { ... private static final class ListenersHandler extends Handler { private WeakReference<DialogInterface> mDialog; public ListenersHandler(Dialog dialog) { mDialog = new WeakReference<DialogInterface>(dialog); } @Override public void handleMessage(Message msg) { switch (msg.what) { case DISMISS: ((OnDismissListener) msg.obj).onDismiss(mDialog.get()); break; case CANCEL: ((OnCancelListener) msg.obj).onCancel(mDialog.get()); break; case SHOW: ((OnShowListener) msg.obj).onShow(mDialog.get()); break; } } } } WeakReference finalize() • The finalize() method is guaranteed to run once and only once before GC deletes an object • GC makes no guarantees, finalize() may never run • You can uneligibilize an object for GC within finalize() • Do not use it for resource closing Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style Exceptions try { // do stuff } catch (SomeException e) { // do exception handling } finally { // clean up } try { // do stuff } finally { // clean up } AssertionError StackOverflowError OutOfMemoryError NullPointerException IndexOfBoundException IOException SQLiteException Object Throwable Error Exception RuntimeException try/catch/finally (1) class Test { private String data = "test"; private int test() { try { System.out.println(data.length()); return 0; } catch (NullPointerException e) { System.out.println("exception"); return 1; } finally { System.out.println("finally"); return 2; } } public static void main(String[] args) { Test t = new Test(); System.out.println("result = " + t.test()); } } 4 finally result = 2 try/catch/finally (2) class Test { private String data; private int test() { try { System.out.println(data.length()); return 0; } catch (NullPointerException e) { System.out.println("exception"); return 1; } finally { System.out.println("finally"); return 2; } } public static void main(String[] args) { Test t = new Test(); System.out.println("result = " + t.test()); } } exception finally result = 2 DefaultExceptionHandler public class DefaultExceptionHandler implements UncaughtExceptionHandler { private UncaughtExceptionHandler mDefaultExceptionHandler; public DefaultExceptionHandler(UncaughtExceptionHandler pDefaultExceptionHandler) { mDefaultExceptionHandler = pDefaultExceptionHandler; } public void uncaughtException(Thread t, Throwable e) { mDefaultExceptionHandler.uncaughtException(t, e); t.getThreadGroup().destroy(); } } Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler(Thread.getDefaultUncaughtExceptionHandler())); Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style Threads • When it comes to threads, very little is guaranteed • Create thread: extend java.lang.Thread or implement Runnable interface • A thread is done being a thread when its target run() method completes • Once a thread has been started, it can never be started again • The order in which runnable threads are chosen is not guaranteed • sleep(long ms), yield(), join(), setPriority(int priority), wait(), notify(), notifyAll() Thread states Waiting/ blocking wait, sleep, join, lock yield New Runnable Running start() not alive Dead run() completes alive not alive Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style Synchronization • Every Object in java has build-in lock • Only methods or blocks can be synchronized public static synchronized int getCount() { return count; } public static int getCount() { synchronized(MyClass.class) { // Class c = Class.forName(“MyClass”); return count; } } • notify(), join(), sleep(), yield() keep locks, wait() gives up lock • synchronized keyword is not automatically inherited when subclasses override superclass method Volatile public class Task extends Thread { private volatile boolean mIsStop; class VolatileExample { int x = 0; volatile boolean v = false; public void run() { while (!mIsStop) { // do some stuff... } } public void writer() { x = 42; v = true; } public void reader() { if (v == true) { // uses x - guaranteed to see 42. } } public void stopMe() { mIsStop = true; } } } volatile: • Every thread accessing the field will read its current value before continuing, instead of (potentially) using a cached value • Statements accessing the variable will be executed in the order they are written (Java 5 or later) Singleton pattern example (1) public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return INSTANCE; } } thread-safe public class Singleton { private static Singleton sInstance; private Singleton() {} public static Singleton getInstance() { if (sInstance == null) { sInstance = new Singleton(); } return sInstance; } } lazy init non-thread-safe Singleton pattern example (2) public class Singleton { private static Singleton sInstance; private Singleton() {} public synchronized static Singleton getInstance() { if (sInstance == null) { sInstance = new Singleton(); } return sInstance; } } lazy init thread-safe low performance Singleton pattern example (3) public class Singleton { private static Singleton sInstance; private Singleton() {} public static Singleton getInstance() { if (sInstance == null) { synchronized (Singleton.class) { if (sInstance == null) { // “Double-Checked Locking” idiom sInstance = new Singleton(); } } } return sInstance; } } Singleton pattern example (4) public class Singleton { private volatile static Singleton sInstance; private Singleton() {} public static Singleton getInstance() { if (sInstance == null) { synchronized (Singleton.class) { if (sInstance == null) { sInstance = new Singleton(); } } } return sInstance; } } lazy init & thread-safe (Java 5 or later) Singleton pattern example (5) public class Singleton { private Singleton() {} private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } lazy init & thread-safe (for all Java version) Quiz public class Foo { private private private private static final int DELTA = 6; static Foo sInstance = new Foo(); static int sBase = 7; int mX; private Foo() { mX = sBase + DELTA; } public static void main(String[] args) { System.out.println(Foo.sInstance.mX); } } What is the print? 6 Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style Collections Collection Set List HashSet SortedSet LinkedHashSet NavigableSet 1.6 ArrayList Queue Vector TreeSet WeakHashMap ConcurrentHashMap CopyOnWriteArraySet etc… LinkedList PriorityQueue Map SortedMap HashTable HashMap NavigableMap 1.6 LinkedHashMap TreeMap Hash table • Choosing a good hash function • Collision resolution: separate chaining, open addressing • Load factor Key Hashcode Algorithm Hashcode Alex A(1)+L(12)+E(5)+X(24) 42 Bob B(2)+O(15)+B(2) 19 Dirk D(4)+I(9)+R(18)+K(11) 42 Fred F(6)+R(18)+E(5)+D(4) 33 19 Bob 19 Bob 33 Fred 33 Fred 42 Alex 42 43 Alex Dirk Dirk • Find the right bucket (using hashCode()) • Search the bucket for the right element (using equals()) Contracts The equals() contract • Reflexive – x.equals(x)=true • Symmetric – x.equals(y)=true -> y.equals(x)=true • Transitive – x.equals(y)=true, y.equals(z)=true -> x.equals(z)=true • Consistent – multiple invocations • x.equals(null)=false The hashCode() contract • Consistent during the app execution • If x.equals(y) -> hash must be the same @Override public int hashCode() { return 1; } Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style int Wrapper Classes and Boxing (1) • The wrapper classes correlate to primitive types • Wrappers have two main functions: – To wrap primitives so that they can be handled like objects – To provide utility methods for primitives (conversions) • Wrapper constructors can take String (except Character) • As of Java 5, boxing allows to convert primitives to wrappers or vice versa automatically. Integer x = 100; x++; int x2 = x.intValue(); x2++; x = new Integer(x2); Wrapper Classes and Boxing (2) Integer i1 = 1000; Integer i2 = 1000; if (i1 != i2) System.out.println("i1!=i2"); i1!=i2 if (i1 == i2) System.out.println("i1==i2"); Integer i1 = 100; Integer i2 = 100; if (i1 != i2) System.out.println("i1!=i2"); if (i1 == i2) System.out.println("i1==i2"); JVM saves memory for: • Boolean • Byte • Character from \u0000 to \u007f • Short and Integer from -128 to 127 I1==i2 Java overview • • • • • • • • • Sun VM, Dalvik VM, JIT Garbage collection References Exceptions Threads Synchronization Collections Wrapper classes Java and Android code style Java Code Style: why? • 80% of the lifetime cost of a piece of software goes to maintenance • Hardly any software is maintained for its whole life by the original author • Code conventions improve the readability of the software, allowing engineers to understand new code more quickly and thoroughly • Makes it easier to conduct code reviews http://developers.sun.com/sunstudio/products/archive/whitepapers/java-style.pdf Comments, TODOs, etc. • Comments • TODO, FIXME, XXX – Use TODO comments for code that is temporary, a shortterm solution, or good-enough but not perfect. • Copyrights Android Code Style (1) • Import ordering – Android imports – Imports from third parties (com, junit, net, org) – java and javax • Indentation – We use 4 space indents for blocks. We never use tabs. When in doubt, be consistent with code around you – We use 8 space indents for line wraps, including function calls and assignments • Field Names – – – – Non-public, non-static field names start with m. Static field names start with s. Other fields start with a lower case letter. Public static final fields (constants) are ALL_CAPS_WITH_UNDERSCORES. Android Code Style (2) • Braces – Braces do not go on their own line; they go on the same line as the code before them if (condition) { body; // ok } if (condition) body; // ok - 1 line if (condition) body; // bad • Line length – Each line of text in your code should be at most 100 characters long. • Annotations, Logging http://source.android.com/submit-patches/code-style-guide BAD Code Style sample (1) for(int i=0;i<amount;++i) db.execSQL(sqls[i]); public static final int sMaxSQLsInTransaction= 1000; if (delayed == true) { ... } else { ... } Good: XmlHttpRequest getCustomerId class Html long id Bad: XMLHTTPRequest getCustomerID class HTML long ID BAD Code Style sample (2) public static final boolean PushValues(String pattern, ArrayList<Integer> patternIds,/*OUT */ArrayList<String> values) { int idsAmount= (null != patternIds ? patternIds.size() : 0); if(0<idsAmount){ final int patternLen=(null!=pattern ? pattern.length():0); if(0<patternLen){ for(int i=0; i<idsAmount; ++i){ if(!pushValues(pattern,patternLen,patternIds.get(i),values)){ return (false); } } return (true); } } return (false); } BAD Code Style sample (2) public static final ArrayList<String> getValues(final String pattern, final ArrayList<Integer> patternIds) { ArrayList<Integer> result = new ArrayList<Integer>(); if (pattern != null && pattern.length() > 0 && patternIds != null) { for (int patternId : patternIds) { ArrayList<Integer> values = getValuesForPatternId(pattern, patternId); if (values == null) { return null; } result.addAll(values); } } return result; } Let’s Have a Break! 10 min Android basics • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better Android • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better Android History • Jul 2005 – Google acquired Android Inc. (co-founded by Andy Rubin) • Nov 2007 – Google Android presentation and “early look” release Sep 2008 1.0 Éclair Mar 2009 May 2009 Sep 2009 Oct 2009 Dec 2009 1.1 1.5 1.6 2.0 2.0.1 Cupcake Donut Froyo Jan 2010 May 2010 2.1 2.2 Gingerbread Android Architecture Overview Applications Home Contacts Phone Browser … View System Resource Manager NDK / JNI Application Framework Activity Manager Package Manager Window Manager Content Providers Telephony Manager Notification Manager Libraries Location Manager Android Runtime Surface Manager Media Framework SQLite Core Libraries OpenGL | ES FreeType WebKit Dalvik VM SGL SSL libc Linux Kernel Display Driver Camera Driver Flash Memory Driver Binder (IPC) Driver Keypad Driver WiFi Driver Audio Drivers Power Management Android • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better Android Application Building Blocks • Activity – Presents UI – Each Activity is independent screen – Activity: setContentView(View) • Service – Used for background operations • BroadcastReceiver – Receive and process broadcast system or user events • ContentProvider – Share application data with others – Data can be stored in FS, DB or even in memory – Communicate via ContentResolver • Intent – Used to activate Activities, Services & BroadcastReceivers http://developer.android.com/guide/topics/fundamentals.html Android Application • Controls global Application state • Extend Application class (android.app.Application) – – – – onCreate() onLowMemory() onTerminate() getApplicationContext() – to use it in classes, where is no Context • Point custom Application class in AndroidManifest.xml Android Context Application Context Activity Context • • • • • • • Same as for Application, but specific to current Activity • startActivityForResult(Intent) / finish() • bindService(Intent) • UI: setContentView(View), findViewById() • User events handling (Keys, Touches, Trackball) Non UI Context startActivity(Intent) start /stopService(Intent) sendBroadcast(Intent) register / unregisterReciever() Application FS, Preferences, Resources • getSystemService Android • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better AndroidManifest.xml (1) <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.my.example" android:versionName="1.0 beta" android:versionCode="2"> <application android:name=".MyApplication" android:label="..." android:icon="..."> <activity android:name=".MyActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service ... /> <receiver ... /> <provider ... /> </application> </manifest> AndroidManifest.xml (2) <activity android:name=".MyActivity" android:launchMode="singleTask" android:theme="@style/Theme.MyDialog" /> <service android:name=".MyService" android:process="new"/> <receiver android:name=".MyReceiver" > <intent-filter> <action android:name= "android.intent.action.PACKAGE_REMOVED" /> <category android:name= "android.intent.category.DEFAULT" /> <data android:scheme= "package" /> </intent-filter> </receiver> <provider android:name=".MyProvider" android:authorities="com.my.provider" /> AndroidManifest.xml (3) <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="..." package="com.my.example" android:versionName="1.0 beta" android:versionCode="2"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="4"/> <supports-screens android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" android:resizeable="true" android:anyDensity="true" /> <application ...> ... </application> </manifest> AndroidManifest.xml (4) <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="..." package="com.my.example" android:versionName="1.0 beta" android:versionCode="2"> <uses-configuration android:reqHardKeyboard="true" android:reqTouchScreen="true" /> <uses-feature android:name="android.software.live_wallpaper" /> <uses-feature android:name="android.hardware.telephony" /> <uses-feature android:name="android.hardware.telephony.cdma" /> ... </manifest> Android • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better Android System Services Object getApplicationContext().getSystemService(String serviceName) serviceName value (contsants in Context) Service Class name Description WINDOW_SERVICE WindowManager Controls on-screen windows and their parameters LAYOUT_INFLATER_SERVICE LayoutInflater Inflates layout resources POWER_SERVICE PowerManager Controls power management NOTIFICATION_SERVICE NotificationManager Status bar notifications CONNECTIVITY_SERVICE ConnectivityManager Handling network connections WIFI_SERVICE WifiManager Handling Wi-Fi network status TELEPHONY_SERVICE TelephonyManager Handling phone calls states LOCATION_SERVICE LocationManager Controls location (GPS) updates SENSOR_SERVICE SensorManager Controls sensor … … … Android • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better Android Platform Versions • May 2009 – platform ver. 1.5 • May 2010 – platform ver. 2.2 • Six platform releases in a year (platform ver.1.1 is hard to find on real phones) • Platforms are back-compatible • It is good point to be compatible with dominated platforms (1.5, 1.6, 2.0.1 and 2.1) • To use advantages of the latest platform versions, Java Reflection mechanism should be used Android Platform Fragmentation in the World December 2009 June 2010 Android Platform Fragmentation in Russia Android 2.0.1 ; 0,6% Android 2.2 ; 0,5% Android 2.0 ; 0,1% Android 1.6 ; 21,7% Android 1.5 ; 43,6% Android 2.1; 33,6% • Data gathered by Flurry service in real application • About 0.5% of 2.1 in Russia are custom ROMs Java Reflection • Originally used to inspect classes, interfaces, fields and methods at runtime, without knowing the names of them at compile time. It can be used for observing and/or modifying program execution at runtime • Classes: Class, Method, Field, Constructor, etc. // Without reflection Foo foo = new Foo(); foo.hello(); // With reflection Class cls = Class.forName("Foo"); Object foo = cls.newInstance(); Method method = cls.getMethod("hello", null); method.invoke(foo, null); Java Reflection and Android public class ClassHolder { private static NewClass foo; public static void tryNewClass() { foo = new NewClass(); } } try { ClassHolder.tryNewClass(); // NewClass available } catch (VerifyError e) {} try { Method methodName = ClassName.class.getMethod(...); methodName.invoke(Object obj, Object... args); } catch (NoSuchMethodException e) {} try { Field fieldName = ClassName.class.getField(...); fieldName.getType(Object obj); } catch (NoSuchFieldException e) {} Java Reflection and Android (Example) private static Field densityDpiField; private static Field densityDpiLowResValue; private static boolean sIsLowRes = false; private static boolean sIsNormalRes = true; static { try { densityDpiField = DisplayMetrics.class.getField("densityDpi"); densityDpiLowResValue = DisplayMetrics.class.getField("DENSITY_LOW"); } catch (NoSuchFieldException nfe) { // Old device - no density Field } } Java Reflection and Android (Example) (Cont.) static { if (densityDpiField != null) { DisplayMetrics dMetrics = sContext.getResources().getDisplayMetrics(); int densityDpi = 0; try { densityDpi = densityDpiField.getInt(dMetrics); sIsLowRes = (densityDpi == densityDpiLowResValue.getInt(dMetrics)); sIsNormalRes =(densityDpi==densityDpiMediumResValue.getInt(dMetrics)); } catch (Exception e) { sIsLowRes = false; sIsNormalRes = true; } } } Java Reflection and Android (Example) (Cont.) public static int scaleToDensity(int dp_size) { if (dp_size == 0 || sIsNormalRes) { return dp_size; } return (int)(dp_size * sContext.getResources().getDisplayMetrics().density + 0.5f); } Android • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better Saving State of Android Application • Shared Preferences are stored in the application private data space and can be shared only inside this Application, but between launches and versions • Instance of SharedPreferences class should be obtained: Activity.getPreferences() PreferenceManager.getDefaultSharedPreferences(Context ctx) Context.getSharedPreferences(String name, int mode) • To read: mPreferences.getType(String key, T defValue); • To write: SharedPreferences.Editor editor = mPreferences.edit(); editor.putType(String key, T value); editor.commit(); • SharedPreferences.OnSharedPreferenceChangeListener Backup Application Data (android.app.backup – 2.2) • • • • Perform backup arbitrary data to remote “cloud” storage Easily perform backup of SharedPreferences and files Restore the data saved to remote storage Controlled by Android Backup Manager – Extend class BackupAgent and override onBackup() & onRestore() OR – Extend BackupAgentHelper to backup/restore SharedPreferences and files from internal storage – Add your agent to AndroidManifest.xml <application android:backupAgent=".MyBackupAgent" > • BackupManager.dataChanged()/requestRestore() • New bmgr tool for testing http://developer.android.com/guide/developing/tools/bmgr.html • Full guide with examples: http://developer.android.com/guide/topics/data/backup.html Android • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better Android NDK (Native Development Kit) • Provides ability and tools to embed components that make use of native code in Android applications • Supports only restricted set of native libraries: – – – – – – libc (C library) headers libm (math library) headers JNI interface headers libz (Zlib compression) headers liblog (Android logging) header OpenGL ES 1.1 (since 1.6) and OpenGL ES 2.0 (3D graphics libraries, since 2.0) headers – libjnigraphics (Pixel buffer access) header (since 2.2) – A Minimal set of headers for C++ support • For Windows Cygwin 1.7 (or higher) is needed Android NDK Demo Android • • • • • • • • Architecture Overview Building Blocks Manifest System Services Platform versions Saving Application State NDK Make your code better Designing for Performance • • • • Use final for constants Avoid enums Avoid float Use local variables for access to object fields inside loops (or more than once) • Don’t use private scope with Inner Classes Action Time Add a local variable 1 Add a member variable 4 Call String.length() 5 Call empty static native method 5 Call empty static method 12 Call empty virtual method 12.5 Call empty interface method 15 Call Iterator:next() on a HashMap 165 Call put() on a HashMap 600 Inflate 1 View from XML 22,000 Inflate 1 LinearLayout containing 1 TextView 25,000 Inflate 1 LinearLayout containing 6 TextView objects 135,000 Launch an empty activity 3000,000 Designing for Responsiveness • Application Not Responding (ANR) dialog: – No response to an input event (e.g. key press, screen touch) within 5 seconds – A BroadcastReceiver hasn't finished executing within 10 seconds • Quick Activity life-cycle methods (onCreate, onResume) and all other methods working on UI thread • Use new Thread for long-time operations (i.e. network/database operations, expensive computations, bitmap resizing, etc.) • Use ProgressBar or ProgressDialog to show “Loading…” or use splash screen when starting application • To avoid long-time operations in BroadcastReceiver – start Service (not Activity!) Designing for Seamlessness • React correctly on system events (i.e. phone call) • onSaveInstanceState/onResumeInstanceState • onPause/onResume • TelephonyManager, etc. • Share data using ContentProvider • Use NotificationManager and Notifications from background processes (Service, BroadcastReceiver) • Don’t overload a single Activity screen – use several Activities for correct dealing with history and Android “backstack” model • Use Threads for long-time operations to avoid ANR • Remember about multiple screen resolutions and multiple Android platform versions • Assume the Network is slow (change speed in Eclipse DDMS for Emulator) • Don’t assume Touchscreen or Keyboard • Remember about battery life Partners Contacts Dmitry Lukashev http://ru.linkedin.com/in/dmitrylukashev [email protected] Alexey Golubev http://ru.linkedin.com/in/golubevalexey [email protected] Blog - http://android.amberfog.com/ Future reading • • • • • • • http://developer.android.com/guide/index.html http://developer.android.com/resources/index.html Soft, weak, phantom references: http://www.ibm.com/developerworks/library/jrefs/ http://www.ibm.com/developerworks/java/library/j-jtp11225/index.html http://www.ibm.com/developerworks/java/library/j-jtp01246.html JVM specification: http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html The Java Memory Model: http://www.cs.umd.edu/~pugh/java/memoryModel/ Dalvik VM: http://sites.google.com/site/io/dalvik-vm-internals Reflection: http://java.sun.com/docs/books/tutorial/reflect/TOC.html http://tutorials.jenkov.com/java-reflection/index.html Thank You! Questions?