View
3.527
Download
0
Category
Tags:
Preview:
DESCRIPTION
Learning android from failure - PlurQ development experience sharing
Citation preview
Naive application development- Learning Android from failure
2010/03/17 shakalaca
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
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
A short introduction
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/
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
PlurkClient (former PlurQ)
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%)
Screenshot
Screenshot
Go ahead and DIY ?
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/
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 ?
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 .
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
Taking picture should be easy ?
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; }}
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 ?
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);
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; } }
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
Lots of memory out there ?
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
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
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)
Problem with SKIA
• What happened in this code ?in = new BufferedInputStream(url.openStream(), 4096);bitmap = BitmapFactory.decodeStream(in);
– decoder->decode returned false error
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); }}
Memory optimization tools
• ddms process heap monitor• Memory Analyzer for Eclipse– Finding memory leaks
Networking is simple as doc told you so ?
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
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 (?)
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
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
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);
Upload and your app should be published ?
Problems
• Can’t be found in Android Market– Tattoo– A688
• Analysis– SDK– Layout (screen)– Layout (screen)– Permission
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“
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..
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
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.
My 2 cents
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
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!
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
Q & A
Any reQuests or Advises ?
On-going features
• Social Activity– View profile / View plurks / Add friend,fan..
• Share via …• Widget• Notification
Wish list
• Friend Browser / Editor– Send private plurk / clique
• Theme• Short url• Video upload• Search plurker• Music listening• GPS support
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/
Recommended