50
Naive application development - Learning Android from failure 2010/03/17 shakalaca

Naive application development

Embed Size (px)

DESCRIPTION

Learning android from failure - PlurQ development experience sharing

Citation preview

Page 1: Naive application development

Naive application development- Learning Android from failure

2010/03/17 shakalaca

Page 2: Naive application development

About shakalaca (shaka)

• Engineer @ Qisda– Android UI development & system integration

• Where to find me ?– @plurk, @facebook, @twitter

• Contact– @gmail.com

• Published Android App– PlurQ / Beauty Clock Widget

Page 3: Naive application development

Outline

• A short introduction• Go ahead and DIY ?• Taking picture should be easy ?• Lots of memory out there ?• Networking is simple as doc told you so ?• Upload and your app should be published ?• My 2 cents• Q & A

Page 4: Naive application development

A short introduction

Page 5: Naive application development

About PlurQ

“Missing the timeline view of Plurk? Enjoying surfing between Plurk mesages? PlurQ provides almost the same look-n-feel as Plurk on your web browser.

Feature:-Similar look-n-feel as Plurk on web browser, including the timeline view” - http://www.cyrket.com/p/android/mobi.qiss.plurq/

Page 6: Naive application development

Story of PlurQ

• API first developed @ 2009/Mar– As a practice of getting started with Android

• River view first developed @ 2009/Sep– Inspired by HTC sense™ UI– Creating custom view– PlurkClient as a Demo– Spare time project

Page 7: Naive application development

PlurkClient (former PlurQ)

Page 8: Naive application development

Birth of PlurQ

• Published @ 2009/12/15– via Qiss• A Group of people interested in Android Market

– “Shrek” as mascot• Cute version of Android Robot

– Not spare time project anymore• Statistics (2010/03/15)– 4710 download, 2833 active installs (60%)

Page 9: Naive application development

Screenshot

Page 10: Naive application development

Screenshot

Page 12: Naive application development

Go ahead and DIY ?

Page 13: Naive application development

DIY is good, but..

• Don’t reinvent wheel– Official API– Unofficial API– Do a search on http://code.google.com/ or

http://github.com/ first• Bad for PlurQ– Not noticing this open source project :

http://code.google.com/p/jplurkapi/

Page 14: Naive application development

Analyzing first..

• No official API– Unofficial Plurk API : http://plurkapi.com (down)

• Problems– Not all methods are listed– Input/Output are not match to current state– Plurk said there will be official API .. soon ?

Page 15: Naive application development

Go go go ! Fire in the hole !

• Shim code– Wrapper for underlying API– Easy to change difference implementation

• 2 days after official API released

• Digg plurk.com– Firefox + Live HTTP header add-on (

https://addons.mozilla.org/en-US/firefox/addon/3829)

– Get methods from .js– Faster than reading document .

Page 16: Naive application development

Dealing with strange output

• Format of “date” in return JSON object is wrong– ("Mon, 12 Jan 1976 00:01:00 GMT")

• Solution– Copy from android and hack– Not used after official API released

Page 17: Naive application development

Taking picture should be easy ?

Page 18: Naive application development

Get picture from camera

• Use intentIntent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(intent, Common.PLURKPOST_REQ_IMAGE);

• Get result (thumbnail)protected void onActivityResult(int req, int result, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (result == RESULT_CANCELED) return; switch (req) { case Common.PLURKPOST_REQ_IMAGE: { mBitmapOfSmallerUploadImage = (Bitmap) data.getExtras().getParcelable("data"); doUploadImage(); } break; }}

Page 19: Naive application development

Only thumbnail ?

• For HTC devicesprotected void onActivityResult(int req, int result, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (result == RESULT_CANCELED) return; switch (req) { case Common.PLURKPOST_REQ_IMAGE: { mUriImage = data.getData(); mBitmapImage = (Bitmap) data.getExtras().getParcelable("data"); doUploadImage(); } break; }}

• But for other devices ?

Page 20: Naive application development

Get larger picture

• Set temp URI at firstIntent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);File tmpFile = File.createTempFile("plurq-camera", ".jpg");mUriOfPicFromCamera = Uri.fromFile(tmpFile);intent.putExtra(MediaStore.EXTRA_OUTPUT, mUriOfPicFromCamera);startActivityForResult(intent, Common.PLURKPOST_REQ_IMAGE);

Page 21: Naive application development

Get larger picture (cont.)

• Get resultprotected void onActivityResult(int req, int result, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (result == RESULT_CANCELED) { if (mUriOfPicFromCamera != null) { File tmpFile = new File(mUriOfPicFromCamera.getPath()); tmpFile.delete(); mUriOfPicFromCamera = null; } return; } switch (req) { case Common.PLURKPOST_REQ_IMAGE: { if (data != null) { mUriImage = data.getData(); mBitmapImage = (Bitmap) data.getExtras().getParcelable("data"); } doUploadImage(); } break; } }

Page 22: Naive application development

Side Story

• Activity closed after launching camera– Sometimes FC after taking picture

• Analysis– Due to memory issue

• Solution– Do no assumptions– Do login check when activity starts

Page 23: Naive application development

Lots of memory out there ?

Page 24: Naive application development

Memory is big enough, right ?

• "640K ought to be enough for anybody"• Specs of phones– G1 : 192MB– HTC Magic : 288MB (or 192MB)– HTC Hero : 288MB– Nexus One : 512MB

Page 25: Naive application development

Truth is ..• http://developer.android.com/intl/zh-TW/referen

ce/android/app/ActivityManager.html– getMemoryClass()

• Return the approximate per-application memory class of the current device. This gives you an idea of how hard a memory limit you should impose on your application to let the overall system work best. The returned value is in megabytes; the baseline Android memory class is 16 (which happens to be the Java heap limit of those devices); some device with more memory may return 24 or even higher numbers.

• On G1 or most device : 16MB• Droid & Nexus One : 24MB

Page 26: Naive application development

BitmapCache

• Scale down if image is too bigBitmapFactory.Options options = new BitmapFactory.Options();options.inSampleSize = 2;bitmap = BitmapFactory.decodeStream(in,null,options);

• Remember to clear– Catch OutOfMemoryError is not enough– HashMap + SoftReference

• For PlurQ : policy is changing all the time– What to cache ? (avatar -> thumbnail -> all ?!– When to clear ? (600K -> LRU -> each page)

Page 27: Naive application development

Problem with SKIA

• What happened in this code ?in = new BufferedInputStream(url.openStream(), 4096);bitmap = BitmapFactory.decodeStream(in);

– decoder->decode returned false error

Page 28: Naive application development

Solution

• Use BitmapFactory.decodeByteArray insteadBitmap bitmap = null;InputStream in = null;BufferedOutputStream out = null;try { in = new BufferedInputStream(url.openStream(), 4096); final ByteArrayOutputStream ds = new ByteArrayOutputStream(); out = new BufferedOutputStream(ds, 4096); copy(in, out); out.flush(); final byte[] data = ds.toByteArray(); bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);} catch (...) { }private void copy(InputStream in, OutputStream out) throws IOException { byte[] b = new byte[4096]; int read; while ((read = in.read(b)) != -1) { out.write(b, 0, read); }}

Page 29: Naive application development

Memory optimization tools

• ddms process heap monitor• Memory Analyzer for Eclipse– Finding memory leaks

Page 30: Naive application development

Networking is simple as doc told you so ?

Page 31: Naive application development

Problems

• Users complain– Can’t login (a few users)– Can’t see picture (some users)– Sometimes it takes a long time loading something

• Analyze– Proxy– Timeout– Secure connection

Page 32: Naive application development

Dealing with proxy• Java.net.Proxy

private void configureHttpProxy() { this.httpProxyHost = android.net.Proxy.getDefaultHost(); this.httpProxyPort = android.net.Proxy.getDefaultPort(); if (this.httpProxyHost != null && this.httpProxyPort != null) { SocketAddress proxyAddress = new InetSocketAddress( this.httpProxyHost, this.httpProxyPort); this.httpProxy = new Proxy(Proxy.Type.HTTP, proxyAddress); } else { this.httpProxy = Proxy.NO_PROXY; }}urlc = url.openConnection(this.httpProxy);

• Tips– Useful in simulator– Some operators use proxy (?)

Page 33: Naive application development

Set timeout

• Connection timeout & socket timeout• HttpParams

HttpParams params = new BasicHttpParams();params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 20000);params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000);DefaultHttpClient client = new DefaultHttpClient(params);

• Tips– Adjust timeout value with care– Weak connection with TWM + Galaxy• Auto timeout adjustment

Page 34: Naive application development

Secure connection

• SchemeRegistrySchemeRegistry schemeRegistry = new SchemeRegistry();schemeRegistry.register(new Scheme("http",

PlainSocketFactory.getSocketFactory(), 80));schemeRegistry.register(new Scheme("https",

SSLSocketFactory.getSocketFactory(), 443));DefaultHttpClient client = new DefaultHttpClient(new

ThreadSafeClientConnManager(params, schemeRegistry), params);

• Tips– Option to toggle• Not supported by all phones or operators• Exception happened in Galaxy

Page 35: Naive application development

Pretending a browser

• Change the way fetching images in BitmapCacheurlc = url.openConnection();urlc.setRequestProperty("User-Agent", "Mozilla/5.0");urlc.setReadTimeout(DEFAULT_READ_TIMEOUT);urlc.setConnectTimeout(DEFAULT_CONN_TIMEOUT);in = new BufferedInputStream(urlc.getInputStream(),

4096);

Page 36: Naive application development

Upload and your app should be published ?

Page 37: Naive application development

Problems

• Can’t be found in Android Market– Tattoo– A688

• Analysis– SDK– Layout (screen)– Layout (screen)– Permission

Page 38: Naive application development

SDK issues• Always use the latest Android SDK release– 1.6+

• Use emulator provided by vendors– SE :

http://developer.sonyericsson.com/wportal/devworld/home?cc=gb&lc=en

– Motorola : http://developer.motorola.com/• Put in your AndroidManifest.xml– <uses-sdk

android:minSdkVersion="3”/>– Not sure: android:targetSdkVersion="4“

Page 39: Naive application development

Layout (screen) issues

• res/layout, res/layout-*dpi– At least ldpi

• AndroidManifest.xml<supports-screens

android:largeScreens="true“android:normalScreens="true“android:smallScreens="true“android:anyDensity="true" />

• Yeah ! Can be found on Tattoo & A688, but..

Page 40: Naive application development

Ugly layout

• Because of android:anyDensity="true" – Android won’t auto adjust UI elements– UI hell if you’re coding in the wrong way

• Tips– Prefer wrap_content, fill_parent and the dip unit to px in

XML layout files (sp for text)– Avoid AbsoluteLayout– Do not use hard coded pixel values in your code– Use density and/or resolution specific resources– http://developer.android.com/intl/zh-TW/guide/practices/

screens_support.html#dips-pels

Page 41: Naive application development

Add permission only when needed

• Story– PlurQ is not found on Tattoo market -> Problem solved– PlurQ uses camera, should add

“android.permission.CAMERA” to AndroidManifest.xml– PlurQ is not found on Tattoo market, again.– Only AndroidManifest.xml differs– After hours of testing, remove this stupid change and

Booom !

• Tips– Add permission only when exception occurs.

Page 42: Naive application development

My 2 cents

Page 43: Naive application development

Experience sharing..

• Field try is important– Buy one !– Borrow one !– Go local store and try it !– Win one !• ADC or ADL ?

• Record exception log– You don’t know WTF is going on with users’ phone– Log should be easily turn on/off and get

Page 44: Naive application development

Experience sharing.. (cont.)

• Don’t be sad when you only have an old G1– If your program can run flawlessly on G1,

robustness++ for your application!• Don’t be frustrated by your defective Nexus

One– If your program can survive under the horrible

networking environment on NO, robustness++ for your application!

Page 45: Naive application development

Performance tuning

• Tools– Log.*– traceview

• Tips– Some UI components can be created later– Use AsyncTask if you want to something in

background and return result to UI

Page 46: Naive application development

Q & A

Page 47: Naive application development

Any reQuests or Advises ?

Page 48: Naive application development

On-going features

• Social Activity– View profile / View plurks / Add friend,fan..

• Share via …• Widget• Notification

Page 49: Naive application development

Wish list

• Friend Browser / Editor– Send private plurk / clique

• Theme• Short url• Video upload• Search plurker• Music listening• GPS support

Page 50: Naive application development

Reference

• Plurk API– http://code.google.com/p/jplurk/– http://code.google.com/p/anplurkapi/– http://code.google.com/p/jplurkapi/

• Mobile development– LG :

http://developer.lgmobile.com/lge.mdn.mai.RetrieveMainPage.dev

– Samsung : http://innovator.samsungmobile.com/– Acer : http://mobile.acer.com/en/developers/