Download Introduction (part I): Java and Android basics

Document related concepts
no text concepts found
Transcript
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?