android survival guide - two years of software development
DESCRIPTION
During the session, I'll explore lot of useful tricks I use during my everyday life as Android developer. Testing, background tasks, smartphone and tablet optimization, avoid memory leaks, UI view management, good external libraries to take into account, mobile design patterns and some best practices I found.TRANSCRIPT
![Page 1: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/1.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 1
Who I am
Born in the past millenium and still an happy software developer
Mobile addictedAndroid enthusiastic
Free software fanProud rider
… and Tiramisu' lover
rainbowbreeze
![Page 2: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/2.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 2
Overview
Online learnig resources
Paintless rotation with threads
Easy IoC/DI framework
Testing, from unit to automation
Honeycomb and backward compatibility
Libraries and frameworks
Q&A session
![Page 3: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/3.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 3
Chocolate Interaction model
Don't be scare: interact, collaborate, share your fun!
![Page 4: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/4.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 4
Useful online material – Patterns
Designing and Implementing Android UIshttp://www.google.com/events/io/2011/sessions/designing-and-implementing-android-uis-
for-phones-and-tablets.html http://code.google.com/p/iosched/
Advanced Topics for Expert Android App Devshttp://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-
android-app-developers.html
Developing Android REST client applicationshttp://www.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html
![Page 5: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/5.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 5
Useful online material - ListView
The world of ListViewhttp://www.google.com/events/io/2010/sessions/world-of-listview-android.html
Lazy-loading of remote thumbnailshttp://android-developers.blogspot.com/2010/07/multithreading-for-performance.html
Drag and Drop capable ListView https://github.com/commonsguy/cwac-touchlist
![Page 6: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/6.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 6
Background thread, progress bar and rotation
Your application have to be smooth, don't use UI thread for long operation (> 200ms)
Yuo cannot update UI Thread from external threads
Use Activity.runOnUiThread(Runnable), View.post(Runnable), View.postDelayed(Runnable,
long), Handler to bypass the problem
![Page 7: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/7.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 7
Background thread, progress bar and rotation
public void onClick(View v) { //background thread new Thread(new Runnable() { public void run() { final Bitmap b = loadImageFromNetwork(); //update ui thread mImageView.post(new Runnable() { public void run() { mImageView.setImageBitmap(b); } }); } }).start();}
![Page 8: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/8.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 8
Background thread, progress bar and rotation
The simplest way
AsyncTaskCan access to UI Thread from separate thread
http://android-developers.blogspot.com/2009/05/painless-threading.html
![Page 9: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/9.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 9
Background thread, progress bar and rotation
protected void onCreate(Bundle savedInstanceState) { ... mLblResult = (TextView) findViewById(R.id.lblResult); LongTask longTask = new LongTask(); longTask.execute(); …}
private class LongTask extends AsyncTask<Void, Void, String> ... protected void onPostExecute(String result) { mLblResult.setText(result); }
![Page 10: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/10.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 10
Background thread, progress bar and rotation
But if the screen is rotated while the backgroud thread is still in execution?
UI not updated, dialogs disappear, NullPointerException, memory leaks...
OMG!
![Page 11: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/11.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 11
Background thread, progress bar and rotation
The clean way
- Define an Handler inside the Activity that process thread tasks (update/result)
- Create background thread passing the handler- Call the handler from the thread when a progress must be
published or the thread finish- Update activity reference inside thread using OnPause()
and OnResume()- Pay attention to OnStart and other Activity lifecycle events
http://code.google.com/p/rainbowlibs/source/browse/android/trunk/rainbowlibs/src/it/rainbowbreeze/libs/logic/RainbowBaseBackgroundThread.java
http://code.google.com/p/rainbowlibs/source/browse/android/trunk/rainbowlibs/src/it/rainbowbreeze/libs/ui/RainbowSplashScreenActivity.java
![Page 12: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/12.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 12
Background thread, progress bar and rotation
public class WebcamActivity extends Activity() {
private Handler mActivityHandler = new Handler() {
public void handleMessage(Message msg) { Log.debug("Message from external thread" + msg.what); switch (msg.what) { case RotationThread.OPERATION_STARTS: //create progress dialog + other UI operations break; case RotationThread.OPERATION_COMPLETED:
//remove the dialog + additional logic break; case RotationThread.OPERATION_ERROR: //remove the dialog + additional error logic
![Page 13: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/13.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 13
Background thread, progress bar and rotation
public class WebcamActivity extends Activity() {
private RotatingThread mRotatingThread;
private void showWebcam() { //show a progress dialog showDialog(DIALOG_PREPARE_FOR_FULLSCREEN);
mRotatingThread = new RotatingThread( mActivityHandler,
webcamToShowId); mRotatingThread.start(); }
![Page 14: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/14.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 14
Background thread, progress bar and rotation
public class RotatingThread() extends Thread { private WeakReference<Handler> mCallerHandler;
public RotatingThread(Handler handler, int webcamId) { registerCallerHandler(handler); … }
public void registerCallerHandler(Handler newHandler { mCallerHandler = new WeakReference<Handler>(newHandler); }
public void unregisterCallerHandler() { mCallerHandler = null; }
![Page 15: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/15.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 15
Background thread, progress bar and rotation
public class RotatingThread() extends Thread { ...
public void run() { callHandlerAndRetry(OPERATION_STARTS);
//your long operation here
callHandlerAndRetry(OPERATION_COMPLETED); }
![Page 16: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/16.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 16
Background thread, progress bar and rotation
protected void callHandlerAndRetry(int messageCode) { for (int retries = 0; retries < TOTAL_RETRIES; retries++) {
if (null != mCallerHandler && null != mCallerHandler.get()) { Message message = mCallerHandler.get().obtainMessage(messageCode); message.arg1 = arg1; mCallerHandler.get().sendMessage(message); break; }
try { //what some times, maybe next time activity is ready Thread.sleep(INTERVAL_BETWEEN_RETRIES); } catch (InterruptedException ignoreExcepition) {} }}
![Page 17: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/17.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 17
Background thread, progress bar and rotation
public class WebcamActivity extends Activity() {
@Override protected void onPause() { mRotatingThread.unregisterCallerHandler(); super.onPause(); }
@Override protected void onResume() { mRotatingThread.registerCallerHandler(mActivityHandler); super.onResume(); }
![Page 18: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/18.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 18
Background thread, progress bar and rotation
public class WebcamActivity extends Activity() {
@Override public Object onRetainNonConfigurationInstance() { return mRotatingThread; }
@Override protected void onStart() { super.onStart(); mRotatingThread = (RotatinThread)getLastNonConfigurationInstance(); //nothing saved, first run of the activity if (null == mRotatingThread) showWebcam(); }
![Page 19: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/19.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 19
Background thread, progress bar and rotation
The short (but no totally complete) way
Use a Fragment and setRetainInstance(true)http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/
app/FragmentRetainInstance.html
![Page 20: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/20.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 20
Lazy loading singleton
Singleton PatternEnsure that only one instance of a class is created and provide a
global point of access to the object.
Create your own singleton or extend android.app.Application and modify its onCreate()
method.Base class for those who need to maintain global application state. You can provide your own implementation by specifying its name in
your AndroidManifest.xml’s <application> tag, which will cause that class to be instantiated for you when the process for your
application/package is created.
![Page 21: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/21.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 21
Lazy loading singleton
public class App extends Application { public static int myGlobalStaticValue; public int myGlobalValue;
@Override public void onCreate() { super.onCreate(); myGlobalStaticValue = 10; myGlobalValue = 20; }
<application android:name="it.rainbowbreeze.singleton.App">
int value = App.myGlobalStaticValue;int value = ((App)context.getApplication()).myGlobalValue;
![Page 22: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/22.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 22
Lazy loading singleton
DrawbacksSingleton is a pattern or an anti-pattern?
http://stackoverflow.com/questions/3826905/singletons-vs-application-context-in-android
OS may kill your application process, including the Application subclass instance. As a result the state is lost. When you later return to the application, then the OS will restore its activity
stack and Application subclass instance, but its fields will be null.
If you really need singleton, at least use lazy-loading singleton and avoid static fields to store
application lifecycle data
![Page 23: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/23.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 23
Lazy loading singleton
public class MySingleton() { private MySingleton mInstance;
public synchronized MySingleton getInstance(Context c) { if (null == mInstance) { mInstance = new MySingleton(context); } return mInstance; }
private MySingleton(Context appContext) { //initializes the object //reload SharedPreferences data }
![Page 24: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/24.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 24
Inversion of Control / Dependency Injection
Dependency Injection PatternThe object does not need to know in advance about how the
other part of the system works. Instead, the programmer provides (injects) the relevant system component in advance
along with a contract that it will behave in a certain way.http://en.wikipedia.org/wiki/Dependency_injection
Reduce the coupling among software components: better code testability, useful in libraries, clean
code.
![Page 25: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/25.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 25
Inversion of Control / Dependency Injectionpublic class ItemDao implements ItemDao {
public ItemDao(Context appContext) { //performs initialization }}
public DataManager implements IDataManager { INetManager mNetManager; IItemDao mItemDao;
public DataManager(INetManager netMngr, IItemDao itemDao) { mNetManager = netMngr; mItemDao = itemDao; }
![Page 26: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/26.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 26
Inversion of Control / Dependency Injection
DrawbacksComplex and less readable code
Chain of dependenciesMore code to write
SolutionsIoc/DI frameworks manage all the boring things!
![Page 27: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/27.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 27
Inversion of Control / Dependency Injection
public class AppEnv() { public static AppEnv i(Context appContext) { … mInstance = new AppEnv(appContext); return mInstance; }
private AppEnv(Context appContext) { mItemDao = new ItemDao(appContext); mDataManager = new DataManager(mNetMngr, mItemDao); }
ItemsDao mItemDao; public ItemsDao getItemDao(){ return mItemDao; }
![Page 28: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/28.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 28
Inversion of Control / Dependency Injection
DrawbacksCannot inject mock for testiong purposes
SolutionsSeparate the object factory from the singleton
![Page 29: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/29.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 29
Inversion of Control / Dependency Injection
public class ObjFactory {
public ItemDao createDao(Context appContext) { return new ItemDao(appContext); }
public DataManager createDataManager( INetManager netMngr, ItemDao itemDao) { return new DataManager(netManager, itemDao); }
}
![Page 30: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/30.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 30
Inversion of Control / Dependency Injection
public class AppEnv() { private static ObjFactory mObjFactory = new ObjFactory();
public static AppEnv i(Context c) { … mInstance = new AppEnv(c, mObjFactory); return mInstance; }
public static AppEnv i(Context c, ObjFactory customFactory) { … mInstance = new AppEnv(c, customFactory); return mInstance; }
![Page 31: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/31.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 31
Inversion of Control / Dependency Injection
public class AppEnv() { …
private AppEnv(Context appContext, ObjFactory objFactory) { mDao = objFactory.createDao(appContext); //... other initialization mDataManager = objFactory.createDataManager( mNetMngr, mDao); }
private ItemsDao mDao; public ItemsDao getItemDao(){ return mDao; }
![Page 32: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/32.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 32
Inversion of Control / Dependency Injection
--- inside your activity / component ---AppEnv appEnv = AppEnv.i(getContext());ItemDao dao = appEnv.getItemDao();
--- inside your test class ---MockObjFactory mockFactory = new MockObjFactory() { @Overrides public ItemDao createDao(Context appContext) { return new MockItemDao(appContext); }};AppEnv appEnv = AppEnv.i(getContext(), mockFactory);ItemDao dao = appEnv.getItemDao();
![Page 33: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/33.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 33
Inversion of Control / Dependency Injection
RoboGuiceLike Google Guice, but for Android
http://code.google.com/p/roboguice/http://stackoverflow.com/questions/5067681/guice-performance-on-android
Other solutionshttp://stackoverflow.com/questions/1029696/the-hunt-for-the-j2me-friendly-ioc-container-is-on
![Page 34: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/34.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 34
Testing - basic
Software testing = reduce risks of software implementation
Lot of support Android sidehttp://developer.android.com/guide/topics/testing/testing_android.html
![Page 35: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/35.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 35
Testing - first steps
Create new “Android Test Project”Create a class that extends TestCase
Code first test
Red, Green, Refactor!
http://developer.android.com/resources/tutorials/testing/helloandroid_test.html
![Page 36: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/36.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 36
Testing - first steps
public class MyFirstTest extends TextCase() { Private MyStringConverter mConverter;
public void setUp() { mConverter = new MyStringConverter(); }
public testUpperCaseConversion() { String result = mConverter.toUppercase(“ota2011”); assertEquals(“Wrong value”, “OTA2011”, result); }}
![Page 37: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/37.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 37
Testing with special Android Mock
AndroidTestCaseaccess to a context
http://developer.android.com/reference/android/test/AndroidTestCase.html
ApplicationTestCasetest app lifecycle, inject mock context
http://developer.android.com/reference/android/test/ApplicationTestCase.html
Activity Testing APItest activity lifecycle, inject mocks, send key or touch events, etc
http://developer.android.com/resources/tutorials/testing/activity_test.html
http://developer.android.com/guide/topics/testing/activity_testing.html
![Page 38: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/38.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 38
Testing with special Android Mock
public class SpinnerActivityTest extends ActivityInstrumentationTestCase2<SpinnerActivity> {
protected void setUp() throws Exception { … mActivity = getActivity(); mSpinner = (Spinner) mActivity.findViewById(R.id.Spinner01); … } public void testSpinnerUI() { this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); mPos = mSpinner.getSelectedItemPosition(); mSelection = (String)mSpinner.getItemAtPosition(mPos); assertEquals(resultText, mSelection);
![Page 39: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/39.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 39
Testing with special Android Mock
ProviderTestCase2test contentProvicer with isolated context
http://developer.android.com/guide/topics/testing/contentprovider_testing.html
ServiceTestCasetest the service lifecycle, not the logic (detached)http://developer.android.com/guide/topics/testing/service_testing.html
ViewAsserts, MoreAssertsextended assertsextended asserts
![Page 40: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/40.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 40
Test automation with monkey
adb shell monkey -p your.package.name -v 500sends sequences of random events
http://developer.android.com/guide/developing/tools/monkey.html
monkeyrunner A Python program that runs an application, sends keystrokes to it,
takes screenshots of its user interface, and stores themhttp://developer.android.com/guide/developing/tools/monkeyrunner_concepts.html
![Page 41: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/41.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 41
Testing with external tools
RobotiumAutomatic black-box test cases for Android applications, with
gesture and actionshttp://code.google.com/p/robotium/
RobolectricFast and easy TDD, runs tests in normal JavaVM with mock
Android classes, no need to deploy on devicehttp://pivotal.github.com/robolectric/
![Page 42: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/42.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 42
Honeycomb and Backward Compatibility
Nowadays Android has two separate branches, but Ice Cream Sandwich will merge them
Avoid different versions of same app and prefer one adaptive Use alternative resources
AndroidManifest.xml filters for sdk, screen, hwPut some dirty if in code
http://code.google.com/p/iosched/
![Page 43: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/43.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 43
Honeycomb and Backward Compatibility
Resources
res/layout/main_activity.xml # For phonesres/layout-xlarge/main_activity.xml # Large screenres/layout-sw600dp/main_activity.xml # For 7” tabletsres/layout-sw720dp/main_activity.xml # For 10” tablets… and much more!
http://android-developers.blogspot.com/2011/07/new-tools-for-managing-screen-sizes.html
![Page 44: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/44.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 44
Honeycomb and Backward Compatibility
<!-- Tablet-only application --><manifest ... > <supports-screens android:smallScreens="false" android:normalScreens="false" android:largeScreens="false" android:xlargeScreens="true" android:requiresSmallestWidthDp="600" /> <application ... > ... </application></manifest>
http://android-developers.blogspot.com/2011/09/preparing-for-handsets.html http://android-developers.blogspot.com/2011/07/new-mode-for-apps-on-large-
screens.html
![Page 45: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/45.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 45
Testing with special Android Mock
Dirty if
private static boolean fragmentsSupported = false;
private static void checkFragmentsSupported()throws NoClassDefFoundError { fragmentsSupported = android.app.Fragment.class != null;}
static { try { checkFragmentsSupported(); } catch (NoClassDefFoundError e) { fragmentsSupported = false; }
![Page 46: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/46.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 46
Testing with special Android Mock@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
Intent intent = null; if (!fragmentsSupported) intent = new Intent(this, MainNonFragmentActivity.class); else intent = new Intent(this, MainFragmentActivity.class);
startActivity(intent); finish(); }}
http://blog.radioactiveyak.com/2011/02/strategies-for-honeycomb-and-backwards.html
![Page 47: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/47.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 47
Honeycomb and Backward Compatibility
Android Compatibility PackageBackport some 3.x APIs to 1.6 and 2.x
http://developer.android.com/sdk/compatibility-library.html
Support for Fragment, Loader, ViewPager
Native code on 3.x, library code on 2.x
![Page 48: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/48.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 48
Honeycomb and Backward Compatibility
Fragment
http://android-developers.blogspot.com/2011/03/fragments-for-all.html
![Page 49: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/49.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 49
Honeycomb and Backward Compatibility
setRetainInstance(true)activity is rotated but fragment is not destroyed and
recreated, lifecycle events are called.Finally!
Bug: http://code.google.com/p/android/issues/detail?id=17423Bug: http://stackoverflow.com/questions/6250580/fragment-already-added-
illegalstateexception
![Page 50: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/50.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 50
Honeycomb Backward Compatibility
ActionBarSherlockLibrary that uses native code for 3.x or its own code for 2.x
http://actionbarsherlock.com/
GreenDroidBrand new actionbar implementation
http://android.cyrilmottier.com/?p=274
![Page 51: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/51.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 51
Useful libraries and resources
Android UI patterns blogshttp://www.androiduipatterns.com http://www.androidpatterns.com
Android-ui-utilsAsset Studio, Pencil stencils, icon templates
http://code.google.com/p/android-ui-utils/
Additional Eclipse plugins for Androidsorce code, api level analysishttp://code.google.com/p/adt-addons/
Maven Android pluginhttp://code.google.com/p/maven-android-plugin/
![Page 52: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/52.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 52
Useful libraries and resources
Kernel sourceto learn, to get inspired and to solve bugs!
http://grepcode.com/snapshot/repository.grepcode.com/java/ext/com.google.android/android/2.3.4_r1/
Clean code in AndroidIoC, Binding, Annotation etc
http://blog.springsource.com/2011/08/26/clean-code-with-android
Crash reporthttp://androidblogger.blogspot.com/2010/03/crash-reporter-for-android-slight.html
![Page 53: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/53.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 53
Useful libraries and resources
Use Apache HTTP library instead of Java.NetHttps bugs, bufferization problems, etchttp://code.google.com/p/android/issues/detail?id=3164
http://groups.google.com/group/android-developers/msg/4ddd2e502f195e3a http://stackoverflow.com/questions/2105364/
Be part of communitiesmailing list, StackOveflow, ...
http://developer.android.com/resources/community-groups.html
![Page 54: Android Survival Guide - Two years of software development](https://reader031.vdocuments.us/reader031/viewer/2022020115/554a21b7b4c90520578b4583/html5/thumbnails/54.jpg)
Android Survival GuideAlfredo Morresi (http://www.rainbowbreeze.it) Slide 54
Conclusion
Q & A(example: “Isn't it lunch time yet?”)