Having problems with Android application compatibility? You're not alone.
From the very beginning of the Android platform, developers always had to cope with a very difficult target: developing on a moving platform, a very fast moving one.
Release after release, features and goodies piled up, but, to a minor extent, so did API differentiation. This talk will step through how platform releases can risk jeopardizing professional development of Android applications, analyzing how to keep consistent UI patterns and implementation, and ending with the biggest release since 1.0: Honeycomb.
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Android 1.5 to 3.0: a compatibility journey
1. Android 1.5 to 3.0
a compatibility journey
Emanuele Di Saverio
Senior Technologist
frog
Monday, May 23, 2011
2. Who?
• Emanuele Di Saverio
– Senior Technologist for Android Platform @
– Open Source Committer
Monday, May 23, 2011
3. Objectives
• Code Compatibility
• Screen Compatibility
• User Interface Patterns
• a Real Life Example
Monday, May 23, 2011
4. DISCLAIMER!
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla the following is result of my professional experience and will be
technical and advanced topics, I will give for granted a good level of familiarity with the
platform bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla
Monday, May 23, 2011
5. 1.5 - Cupcake
• Virtual Keyboard: IME
• AppWidget
• 2 New Widget
Monday, May 23, 2011
6. 1.6 - Donut
• Screen Fragmentation
• Resources Framework
• Search Integration for
App
Monday, May 23, 2011
7. 2.0 - Eclair
• Support for HTML5
• Bluetooth Support
• Sync Services
Monday, May 23, 2011
8. 2.1 - Eclair (again)
• Live Wallpapers
• Enrich WebKit
• lots of bug fixes
Monday, May 23, 2011
9. 2.2 - Froyo
• App on SD
• Cloud 2 Device
Messaging
• Device Manager
• Data backup
Monday, May 23, 2011
10. 2.3 - Gingerbread
• Near Field
Communication
• Gyroscope,
Barometer, various
Sensors
• StrictMode
• SIP
Monday, May 23, 2011
11. 2.3.4 - Gingerbread
(again)
• more NFC Api
• more BT Api
• lots of Bug fixes
• fix for ClientLogin
• Accessory DevKit
Monday, May 23, 2011
13. • Every release brings new classes, new
methods, changes and deprecations
• We Want New Features
• We Want to target ALL devices
• We Don’t Want to constantly rewrite!
Monday, May 23, 2011
16. Android does no
magic here
We compile against
only one JAR:
choose our feature
set!
On device we will
have di erent
classes
Monday, May 23, 2011
17. Code Fragmentation
• 3 Techniques
• Canary
• Switch by Code/Resource
• Reflection
Monday, May 23, 2011
18. Canary
• Canaries are use in cave digging as a
“probes” for venomous gases
• If they don’t come back, you can’t use
that cave
• We want a Code Canary!
Monday, May 23, 2011
19. • We can’t replace or modify Java
Classloader in a Dalvik VM :(
• classes are verified as soon as
somebody new them
• ..so classloaders load classes lazily!
Monday, May 23, 2011
20. If this code is executed on a VM where
ScaleGestureDetector class is not
available, we can “gracefully degrade”
class Canary {
android.view.ScaleGestureDetector delegatto;
static void tryNewClass() {
android.view.ScaleGestureDetector foo = new
android.view.ScaleGestureDetector(null, null);
}
/* use the delegatto */
}
Monday, May 23, 2011
22. Switch by Code
• use info from android.os.Build
• can be used on the fly
• or via Factory pattern if performance is
needed (i.e. operations on UI Thread)
Monday, May 23, 2011
23. ad-hoc
public class RomaSkiFragmentActivity extends
FragmentActivity {
private final boolean isHoneycomb =
android.os.Build.VERSION.SDK_INT > 10;
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
if (!isHoneycomb) {
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
}
/* cut */
Monday, May 23, 2011
24. factory
public static synchronized LocalDevice getInstance() {
if (instance == null) {
int vInt = LocalDevice.getVersionNumber();
log.i(LocalDevice.class, "Parsed version number is " + vInt);
if (vInt < SDK_NUM_2_0) {
instance = new it.gerdavax.easybluetooth.LocalDevice1Impl();
} else {
instance = new it.gerdavax.easybluetooth.LocalDevice2Impl();
}
}
log.i(LocalDevice.class, "Returning: " + instance);
return instance;
}
private static int getVersionNumber() {
return Integer.parseInt(Build.VERSION.SDK.trim());
}
Monday, May 23, 2011
25. Switch by Resource
• leverage the Resource framework
• the -v su x is for versions
• es. -v4 resource will be selected for Api
level 4 (Donut)
Monday, May 23, 2011
26. Reflection
• Java allows us to:
• instantiate classes starting from their
name in a String
• invoke methods, even private
• inspect fields, even private
• Some problems with final and static
though
• With big power comes big...risks
Monday, May 23, 2011
27. If you miss
something...
private static int R_id_message_handle = -1;
static {
try {
Class clazz = Class.forName("com.android.internal.R$id");
R_id_message_handle = clazz.getField("message").getInt(clazz);
} catch (Throwable e) {
// who cares
e.printStackTrace();
}
}
public static void setRightAlignToMessageField(Dialog d) {
if (R_id_message_handle != -1) {
TextView tv = (TextView) d.findViewById(R_id_message_handle);
if (tv != null) {
tv.setGravity(Gravity.RIGHT);
Monday, May 23, 2011
28. android-bluetooth library
void bindAndListen() {
try {
Method bindMethod = bluetoothSocketClass.getMethod
(METHOD_BIND, new Class[] { String.class });
bindMethod.invoke(bluetoothSocketObject, new Object[]
{ "devicename-tobeignored" });
Method listenMethod = bluetoothSocketClass.getMethod
(METHOD_LISTEN, new Class[] { int.class });
listenMethod.invoke(bluetoothSocketObject, new Object[]
{ this.port });
Method getPortMethod = bluetoothSocketClass.getMethod
(METHOD_GET_PORT, new Class[] {});
Integer getPortMethodReturnValue = (Integer)
getPortMethod.invoke(bluetoothSocketObject,
new Object[] {});
this.port = getPortMethodReturnValue.intValue();
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
Monday, May 23, 2011
29. disclaimer on Reflection
• It’s dangerous: depends on names, avoids
compiler checks, makes your code ugly
without remedy
• It allows to access @hide functionalities,
and break the public API
• Google hates it: for good reasons
• ...and makes you feel quite a hacker :)
Monday, May 23, 2011
30. Screen Fragmentation
• Google tackled aggressively the
fragmentation problem since 1.6
• The approach is based on “buckets”:
this is an -eventually correct- approach
Monday, May 23, 2011
31. small medium large xlarge
ldpi
mdpi
hdpi
xhdpi
Monday, May 23, 2011
32. small medium large xlarge
cheapo,
ldpi highly
portable
midrange,
mdpi
old school
iPhone one
hdpi like (or handed tablet
wannabe) tablet
xhdpi
Monday, May 23, 2011
33. • It’s not a universal solution!
• What happens if I have a extra-large
screen with low density???
Monday, May 23, 2011
35. • But it works for real-life devices
• Pragmatic Balance between
performances and image definition
• That’s why “eventually correct”
Monday, May 23, 2011
36. The Real Reason
• behind screen compat framework is...
• keeping the physical size the same (dpi =
dot per inch)
• has to do with human size factor
...with the size of the thumb actually :)
Monday, May 23, 2011
37. Real Estate
• so I just have to provide image for ldpi
mdpi and hdpi and I am set, right?
• NOPE
• you real estate will change!
Monday, May 23, 2011
38. • 800x480 (240 dpi)= 5/3
but DIPs are scaled
• 480x320 (160 dpi) = 3/2
homogeneously!
• 320x240 (120 dpi) = 4/3
Monday, May 23, 2011
39. Solutions
• Modal Controls:
SlidingDrawer, FlipViews, Alerts,
Notifications
• or simply cut the ancillary content!
Monday, May 23, 2011
42. ...but don’t do Least Common
Denominator :(
Monday, May 23, 2011
43. Design Patterns
• Google doesn’t enforce constraints on
Application UI Design
• No Censorship, No Certification, No
Approval!
• ....but strongly suggests them
Monday, May 23, 2011
45. Twitter App
GoogleIO 2010
Monday, May 23, 2011
46. Twitter App
Home Action Bar
GoogleIO 2010
Dashboard
Live Wallpaper Quick
Actions
Monday, May 23, 2011
47. Resources
• Home, QuickActions, ActionBar:
Cyril Motter’s GreenDroid
https://github.com/cyrilmottier/GreenDroid
• Dashboard:
Roman Nurik’s Layout
https://gist.github.com/882650
• Live Wallpapers:
SDK Samples: CubeLiveWallpaper
http://developer.android.com/resources/articles/live-wallpapers.html
Monday, May 23, 2011
48. Designing Android UIs
for Phones and Tablets
• Pattern consolidated and implemented in
platform
• Direct support for ActionBar and Home
• Extension to tablets
• IO Schedule App is again reference
implementation - Fragment Compat!!!
Monday, May 23, 2011
51. Home
Action Bar
Dashboard
Monday, May 23, 2011
52. So...
• Use the patterns - they are designed for
delivering YOUR content
• Use the libraries - they provide
consistent and compatible
implementations
• Concentrate on the “painting” instead
of the “frame”
Monday, May 23, 2011
53. A real life example:
RomaSki
• Application for keeping under control
webcams from Ski Resorts in the Rome area
(I needed it)
• Compatibility Fragment Library
• Versioned Scale
Monday, May 23, 2011
58. Action Bar (was: “Title”)
• title Bar under HoneyComb is so powerful! Also has
tabs! is ACTION Bar
• ...forget it! Fragments Compability Library doesn’t
allow
• You have to inherit by compat FragmentActivity, not
the HoneyComb one, same classes but di erent
pkg!
Monday, May 23, 2011
61. Versioned Scale
• Android uses GestureDetectors for decoupling
• ScaleGestureDetector is in 2.2 and up
• 2.0 already had multitouch though: class
copypasted from source
• 1.6 single finger gesture: custom
ScaleGestureDetector
Monday, May 23, 2011
62. private OnScaleGestureListener mListener;
private ScaleGestureDetector internalDelegate;
private Canary nativeDelegate;
public ScaleGestureDetector(Context ctx, OnScaleGestureListener listener)
{
mListener = listener;
int buildInt = android.os.Build.VERSION.SDK_INT;
if (buildInt == android.os.Build.VERSION_CODES.DONUT) {
internalDelegate = new ScaleGestureDetector16(ctx, this);
} else if (buildInt == android.os.Build.VERSION_CODES.ECLAIR) {
internalDelegate = new ScaleGestureDetector21(ctx, this);
} else if (buildInt >= android.os.Build.VERSION_CODES.FROYO) {
try {
Canary.tryNewClass(ctx);
initalizeNative(ctx);
} catch (Throwable th) {
th.printStackTrace();
internalDelegate = new ScaleGestureDetector16(ctx, this);
}
} else {
throw new RuntimeException("Version not supported! " + buildInt);
}}
Monday, May 23, 2011
64. Design API for change
• The public interfaces of the Versioned
ScaleGestureDetector are same as SDK one
• In the future will be easy to switch back to SDK!
since
• IceCream Sandwich is expected for Q4 2011, with new
(unspecified) compatibility features!
Monday, May 23, 2011
66. Resources
• GoogleIO Schedule App src:
http://code.google.com/p/iosched/
• RomaSki src: https://github.com/hazam/RomaSki
https://github.com/hazam/hAndy
• Dan Morrill: Android Open Source & Compatibility Tech Lead
twitter: @morrildl
• HC Design Patterns: https://docs.google.com/present/view?
id=ah8kttmgmwgb_21d9rnw7d6
Monday, May 23, 2011
67. What was left out
• AndroidManifest filters: <supports_screen> will suprise
you,
• 2.3 adds <compatible-screens>
• Fragments Compatibility Library :/
• Accessory DevKit support for 2.3.4 library :/
• Google TV! (10ft experience, but mostly D-Pad)
Monday, May 23, 2011