TheEdge 2010: Android Advanced Techniques


Published on

TheEdge 2010:

The Android platform has matured rapidly during the last two years.
We're going to bring you up to speed in the latest cutting edge Android development techniques including: New UI Patterns, supporting multiple screen resolutions, REST clients, Push applications and optimizing your applications.

Published in: Technology
  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • Present as a story:Designing smart and cool UIThe work behind to UI – I/OAnd how to make it all work fast
  • What is an activity: each screen is an activityA screen is defined by a layout, a layout could be an XML or Code. Explain why XML is better than code, and some Layout types.Intent is a way of describing of you want the android OS to do.
  • When mentioninggoogle IO mention what is it
  • Your application Home Screen
  • The first screen the user sees
  • Explain in short what’s a LinearLayout
  • Voice search, suggestion, global search
  • (Don’t believe the emulator!)
  • Why rawQuery? Query method has too many parameters, they should use a builder…
  • TheEdge 2010: Android Advanced Techniques

    1. 1. Advanced Android Techniques<br />By: GiladGaron<br />
    2. 2. This presentation is based onTheEdge 2010 Android Application:<br />Download it from the Market<br />Download the source code: all the examples in this presentation<br />Before we begin!<br />TheEdge 2010 Android App<br />
    3. 3. UI Design Patterns<br />I/O Access<br />Optimizations<br />Agenda<br />
    4. 4. UI Design Patterns<br />
    5. 5. Activity<br />Layouts<br />Intent<br />A little reminder about:<br />UI Design Patterns<br />
    6. 6. Dashboard<br />Action Bar<br />Search Bar<br />Quick Actions<br />Flingable List Item<br />“Applications are ahead of the framework”<br />UI Design Patterns<br />
    7. 7. Dashboard<br />You know what they say about First Impressions...<br />UI Design Patterns<br />Dashboard<br />
    8. 8. Introduce your application<br />Reveal its functionality<br />Update the user<br />Just a layout, nothing fancy<br />Dashboard<br />UI Design Patterns<br />
    9. 9. Dashboard Components<br />UI Design Patterns<br />Action Bar<br />Updates Panel<br />Functionality Panel<br />
    10. 10. Implementation<br />UI Design Patterns<br /><?xmlversion="1.0"encoding="utf-8"?><br /><LinearLayoutxmlns:android=""<br />android:orientation="vertical"<br />android:layout_width="fill_parent"<br />android:layout_height="fill_parent"<br />android:background="@color/background"><br /> <LinearLayoutxmlns:android=""<br />android:orientation="horizontal"<br />android:layout_width="fill_parent"<br />android:layout_height="45dip"<br />android:background="@color/action_bar_background"><br /> <!-- Action Bar Code --><br /> </LinearLayout><br /> <br /> <LinearLayoutxmlns:android=""<br />android:orientation="horizontal"<br />android:layout_width="fill_parent"<br />android:layout_height="wrap_content"<br />android:layout_weight="1"><br /> <!-- Functionality Panel --><br /> </LinearLayout><br /> <br /> <LinearLayoutxmlns:android=""<br />android:id="@+id/now_playing"<br />android:layout_width="fill_parent"<br />android:layout_height="90dip"<br />android:orientation="horizontal"><br /> <!-- Update Panel --><br /> </LinearLayout><br /></LinearLayout><br />
    11. 11. Action Bar<br />UI Design Patterns<br />Action Bar<br />
    12. 12. Improved Title Bar<br />Persistent across the application<br />Includes common actions<br />Navigation Control<br />Action Bar<br />UI Design Patterns<br />
    13. 13. Implementation<br />UI Design Patterns<br /><LinearLayoutxmlns:android=""<br />android:orientation="horizontal"<br />android:layout_width="fill_parent"<br />android:layout_height="45dip"<br />android:background="@color/action_bar_background"><br /> <ImageButtonstyle="@style/action_bar_button"<br />android:src="@drawable/home_btn_default"<br />android:onClick="onHomeClick"/><br /> <br /> <ImageViewstyle="@style/action_bar_separator"/><br /> <TextViewstyle="@style/action_bar_text"<br />android:text="Sessions"/><br /> <br /> <ImageViewstyle="@style/action_bar_separator"/><br /> <ImageButtonandroid:id="@+id/search_button"<br />style="@style/action_bar_button"<br />android:src="@drawable/search_button"<br />android:onClick="onSearchClick"/><br /></LinearLayout><br />
    14. 14. Search Bar<br />UI Design Patterns<br />Search Bar<br />
    15. 15. Implement search in your app<br />Persistent across the application<br />Can be used with the Action Bar<br />Multiple search modes<br />A clearer way to filter results<br />Search Bar<br />UI Design Patterns<br />
    16. 16. Declare your application as searchable<br />Declare an activity that handles the search<br />Handle the search itself<br />Implementation<br />UI Design Patterns<br />
    17. 17. Declare in /res/xml/searchable.xml<br />Searchable Configuration<br />UI Design Patterns<br /><?xmlversion="1.0"encoding="utf-8"?><br /><searchablexmlns:android=""<br />android:label="@string/app_name"<br />android:hint="Hint" ><br /></searchable><br />
    18. 18. Searchable Activity<br />Declare as Searchable in the AndroidManifest.xml:<br />UI Design Patterns<br /><manifestxmlns:android=""<br />package="com.alphacsp.theedge"<br />android:versionCode="4"<br />android:versionName="1.03"<br />android:installLocation="preferExternal"><br /> <br /> <applicationandroid:label="TheEdge 2010"android:icon="@drawable/ic_launcher"><br /> <br /> <activityandroid:name=".ui.activities.SearchActivity"android:label="Search"android:theme="@style/Theme.TheEdge"><br /> <intent-filter><br /> <actionandroid:name="android.intent.action.SEARCH"/><br /> </intent-filter><br /> <meta-dataandroid:name=""android:resource="@xml/searchable"/><br /> </activity><br /> <activityandroid:name=".ui.activities.AboutActivity"android:label="About“ android:theme="@style/Theme.TheEdge"/><br /> <br /> <meta-dataandroid:name=""android:value=".ui.activities.SearchActivity"/> <br /></manifest><br />
    19. 19. Searchable Activity<br />Handle the Query:<br />UI Design Patterns<br />publicclassSearchActivityextendsTabActivity {<br />@Override<br />publicvoidonCreate(BundlesavedInstanceState) {<br />super.onCreate(savedInstanceState);<br />setContentView(R.layout.search_activity);<br /> <br />Intentintent = getIntent();<br />String query = intent.getStringExtra(SearchManager.QUERY);<br /> <br />finalTabHost host = getTabHost();<br /> <br />IntentspeakersIntent = new Intent(SearchActivity.this, SpeakersActivity.class);<br />speakersIntent.putExtra(SearchManager.QUERY, query);<br />host.addTab(host.newTabSpec("Speakers").setIndicator(buildIndicator("Speakers")).setContent(speakersIntent));<br /> <br />IntentsessionsIntent = new Intent(SearchActivity.this, SessionsActivity.class);<br />sessionsIntent.putExtra(SearchManager.QUERY, query);<br />host.addTab(host.newTabSpec("Sessions").setIndicator(buildIndicator("Sessions")).setContent(sessionsIntent));<br /> }<br />
    20. 20. Quick Actions<br />Quick context menu<br />UI Design Patterns<br />
    21. 21. Contextual actions driven popup menu<br />Natural flow to the screen context<br />Simple and effective<br />Wow effect<br />Quick Actions<br />UI Design Patterns<br />
    22. 22. Not in the SDK<br />Custom Views<br />Implementation taken from: Lorenz’s Blog<br />Implementation<br />UI Design Patterns<br />
    23. 23. Flingable List Item<br />Flingable context menu<br />UI Design Patterns<br />
    24. 24. Contextual actions driven flinged menu<br />Natural flow to the screen context<br />Wow effect<br />Flingable List Item<br />UI Design Patterns<br />
    25. 25. Major players:<br />ViewFlipper Layout<br />GestureDetector<br />ListAdaptor<br />ListActivity<br />Implementation<br />UI Design Patterns<br />
    26. 26. Vertical scrollable view that allows multiple rows views (List Item)<br />Uses ListAdapter to populate each List Item<br />Recycles Views (So don’t cache them!)<br />Supports different view types<br />A few words about ListView<br />UI Design Patterns<br />
    27. 27. ListView should not hold N Views.<br />Use ConvertView in getView method:<br />ListView Recycler<br />UI Design Patterns<br />@Override<br />publicViewgetView(int position, ViewconvertView, ViewGroup parent) {<br />if (convertView == null) {<br />convertView = inflater.inflate(R.layout.speakers_list, parent, false);<br /> }<br /> //Get your components from the view<br />finalTextViewspeakerName = (TextView) convertView.findViewById(;<br /> <br /> //Get your item<br />Speakerspeaker = getItem(position);<br />returnconvertView;<br /> }<br />
    28. 28. ListView Recycler in action<br />UI Design Patterns<br />
    29. 29. ViewFlipper<br />UI Design Patterns<br />Allows transition between layouts<br />Supports animations<br /><ViewFlipperxmlns:android=""<br />android:id="@+id/flipper"<br />android:layout_width="fill_parent"<br />android:layout_height="fill_parent"><br /> <includeandroid:id="@+id/first"layout="@layout/sessions_list"/><br /> <includeandroid:id="@+id/second"layout="@layout/sessions_list_flinged"/><br /></ViewFlipper><br />
    30. 30. GestureDetector<br />UI Design Patterns<br />Detects various gestures and events using the supplied MotionEvents<br />GestureDetectorgestureDetector= newGestureDetector(newGestureDetector.SimpleOnGestureListener() {<br />@Override<br />publicbooleanonFling(MotionEvent e1, MotionEvent e2, floatvelocityX, floatvelocityY) {<br /> }<br /> <br />@Override<br />publicbooleanonDown(MotionEvent e) {<br /> }<br /> <br />@Override<br />publicbooleanonSingleTapUp(MotionEvent e) {<br /> }<br /> });<br />
    31. 31. Implementation<br />UI Design Patterns<br />Read the Source Code…<br />
    32. 32. I/O Access<br />
    33. 33. File System<br />Database<br />Network<br />Types of I/O:<br />I/O Access<br />
    34. 34. Reading is fast<br />Writing is slow <br />Disk space affects performance<br />Make sure you support External Storage (Both in installation and in caches/data)<br />Flash I/O<br />I/O Access<br />
    35. 35. Virtual Table that allows Full Text Search<br />Produces results significantly faster than LIKE<br />Comprehensive syntax<br />SQLite FTS<br />I/O Access<br />
    36. 36. Creating FTS table<br />Similar to creating a regular table:<br />I/O Access<br />publicclassDatabaseHelperextendsSQLiteOpenHelper { <br />privatestaticfinalStringDATABASE_NAME = "TheEdge";<br />publicstaticfinalStringSPEAKERS_TABLE = "speakers";<br /> <br />@Language("SQLite")<br />privatestaticfinalStringCREATE_SPEAKERS_TABLE = "CREATE VIRTUAL TABLE " + SPEAKERS_TABLE + " USING fts3 (speaker_name TEXT , bio TEXT, company TEXT, image_uri TEXT)";<br /> <br />publicDatabaseHelper(Contextcontext, String name, SQLiteDatabase.CursorFactory factory, int version) {<br />super(context, name, factory, version);<br /> }<br /> <br />@Override<br />publicvoidonCreate(SQLiteDatabasesqLiteDatabase) {<br />Log.i(this.getClass().getSimpleName(), "Creating DB");<br />sqLiteDatabase.execSQL(CREATE_SPEAKERS_TABLE);<br /> }<br /> <br />
    37. 37. Using:<br />Use the MATCH keyword:<br />I/O Access<br />publicList<Session> searchSessions(String query) {<br />finalList<Session> sessionList = newArrayList<Session>();<br />finalSQLiteDatabasereadableDatabase = getReadableDatabase();<br />finalCursorcursor = readableDatabase.rawQuery("select * from " + SESSIONS_TABLE + " where " + SESSIONS_TABLE + " match '" + query + "'", null);<br />if (cursor.moveToFirst()) {<br />do {<br />finalSessionsession = newSession();<br />session.setTopic(cursor.getString(cursor.getColumnIndex("topic")));<br />session.setPresenter(cursor.getString(cursor.getColumnIndex("presenter")));<br />session.setSessionAbstract(cursor.getString(cursor.getColumnIndex("abstract")));<br />sessionList.add(session);<br /> } while (cursor.moveToNext());<br /> }<br />if (!cursor.isClosed()) {<br />cursor.close();<br /> }<br />returnsessionList;<br />}<br /> <br />
    38. 38. Use a Service<br />Use Apache HTTPClient not URLConnection<br />Don’t do it on the UI thread<br />Parsing can be costly, design your data structure carefully<br />Network<br />I/O Access<br />
    39. 39. When using network, remember the following:<br />Availability:Always check connectivity with ConnectivityManager.<br />Performance:Don’t run on the UI Thread, use AsyncTask or Service.<br />Bandwidth:Use as little as you can.<br />Battery drain:Only use the network when you have to.<br />I/O Access<br />
    40. 40. I/O Access<br />Activity with separate thread for Network<br />
    41. 41. Optimization<br />
    42. 42. Allows you to execute a task without having to manage thread pools.<br />Defined by three generic types: Parameters, Progress and Result.<br />Has a lifecycle:<br />onPreExecute – Called before running the task.<br />doInBackground – Actual work<br />onProgressUpdate – Callback to update the UI on task progress<br />onPostExecute – Called after task has ended, receives the response object<br />Very smart and easy.<br />AsyncTask<br />Optimization<br />
    43. 43. In order to implment lazy loading, we’ll need to do the following:<br />Load the ListView an you would normally do.<br />Create a task to fetch the data, use AsyncTask or a Service.<br />Change the data on the UI thread.<br />Use notifyDataSetChanged() to let ListView to update itself.<br />Lazy Loading your ListView<br />Optimization<br />
    44. 44. Example<br />Optimization<br />publicclassSpeakersActivityextendsListActivityimplementsServiceListener {<br /> <br />privatevoidfetchImages() {<br />for (Speakerspeaker : speakers) {<br />SpeakerImageFetcherspeakerImageFetcher = newSpeakerImageFetcher();<br />speakerImageFetcher.execute(speaker);<br /> }<br /> } <br /> <br />privateclassSpeakerImageFetcherextendsAsyncTask<Speaker, Void, Void> {<br /> <br />@Override<br />protectedVoiddoInBackground(Speaker... speakers) {<br />finalSpeakerspeaker = speakers[0];<br />finalBitmapbitmap = dataAccessor.fetchImage(speaker.getImageUrl());<br />speaker.setSpeakerImage(bitmap);<br />returnnull;<br /> }<br /> <br />@Override<br />protectedvoidonPostExecute(VoidaVoid) {<br />speakersAdapter.notifyDataSetChanged();<br /> }<br /> }<br />}<br />
    45. 45. Runs in the background<br />Is not killed when the application ends<br />Running a service is easy<br />Getting callbacks is a bit awkward<br />Declare it in your AndroidManifest.xml<br />Services<br />Optimization<br />
    46. 46. Services oriented application:<br />Optimization<br />SQLite<br />HttpClient<br />Data Accessor<br />Service<br />Service Helper<br />Activity<br />
    47. 47. Service Example:<br />Optimization<br />publicclassNetworkServiceextendsIntentService {<br /> <br />@Override<br />protectedvoidonHandleIntent(Intent intent) {<br />finalDataAccessordataAccessor = DataAccessor.getSingleton(this);<br /> <br />finalResultReceiver receiver = intent.getParcelableExtra(STATUS_LISTENER);<br />finalintrequestAction = intent.getIntExtra(REFRESH_ACTION, -1);<br />boolean result = false;<br /> <br />if (requestAction == REFRESH_SPEAKERS) {<br /> result = dataAccessor.syncAllSpeakers();<br /> } elseif (requestAction == REFRESH_SESSIONS) {<br /> result = dataAccessor.syncAllSessions();<br /> } elseif (requestAction == REFRESH_SCHEDULE) {<br /> result = dataAccessor.syncAllEvents();<br /> } elseif (requestAction == REFRESH_ALL) {<br />dataAccessor.syncAllSpeakers();<br />dataAccessor.syncAllSessions();<br />dataAccessor.syncAllEvents();<br /> }<br />if (result) {<br />receiver.send(STATUS_REFRESHED, Bundle.EMPTY);<br /> }<br />receiver.send(STATUS_NOT_REFRESHED, Bundle.EMPTY);<br /> }<br />}<br /> <br />
    48. 48. ResultReceiver:<br />Implements Parcelable, so can be passed in the Intent object<br />Good for “Here and now” results per intent<br />Getting a Callback from a Service:<br />Optimization<br />
    49. 49. ResultReceiver Example<br />Accepts the Activity as the Listener using a custom interface<br />Optimization<br />publicclassNetworkServiceHelperextendsResultReceiver {<br />  privatefinalServiceListenerlistener;<br />  publicNetworkServiceHelper(ServiceListener listener) {<br />super(new Handler()); this.listener = listener;<br /> }<br />  @Override<br />protectedvoidonReceiveResult(intresultCode, BundleresultData) {<br />if (listener != null) {<br />listener.onReceiveResult(resultCode, resultData);<br /> }<br /> }<br />}<br />
    50. 50. Optimization<br />Using the service:<br />publicclassScheduleActivityextendsActivityimplementsServiceListener {<br />  privateNetworkServiceHelpernetworkServiceHelper;<br />  @Override<br />publicvoidonCreate(BundlesavedInstanceState) {<br />super.onCreate(savedInstanceState);<br />setContentView(R.layout.schedule_activity);<br />dataAccessor = DataAccessor.getSingleton(this);<br />initCalendar();<br />networkServiceHelper = newNetworkServiceHelper(this);<br />finalIntentserviceIntent = new Intent(Intent.ACTION_SYNC, null, this, NetworkService.class);<br />serviceIntent.putExtra(NetworkService.STATUS_LISTENER, networkServiceHelper);<br />serviceIntent.putExtra(NetworkService.REFRESH_ACTION, NetworkService.REFRESH_SCHEDULE);<br />startService(serviceIntent);<br /> }<br />@Override<br />publicvoidonReceiveResult(intresultCode, BundleresultData) { <br />if (resultCode == NetworkService.STATUS_REFRESHED) { <br />calendarLayout.removeAllViews(); <br />initCalendar(); <br /> }<br /> }<br />}<br />
    51. 51. Reference<br />
    52. 52. Reference<br /><br /><br /><br /><br /><br /><br /><br />
    53. 53. Thank You!<br />We appreciate your feedback<br />
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.