2013年8月31日 星期六

第八課: 執行幕後的工作 ---- Service

Service 是 Android 應用程式提供的一個執行背景程式而不需與使用者互動的元件. 當使用者跳轉到不同的 Android 應用程式時, Service 依然會繼續執行它的任務. 因此, 可以將它看作在背後默默為我們執行程式工作的人.

Service 的用法:

1. Started
Stated 指的是藉由 startService() 開始一個背景程式 Service, 但是此 Service 與丟任務進來的元件(Activity)沒有相依, 如果在執行背景程式的過程中, 丟任務的原件先 Destroy() 掉了, 依然不會影響到 Service 的執行. 譬如: 上傳照片, 下載檔案...等等就滿適合的.

2. Bound
Bound 指的是藉由 bindService() 開始一個背景程式 Service, 讓丟任務進來的元件(Activity)與背景程式 Service 產生相依, 如果在背景程式執行的過程中, 丟任務的原件先 Destroy() 了, 那麼 Service 也會跟著 Destroy(). 當背景程式需要與前端元件溝通時, 我們會使用 Bound.

兩種用法的生命週期 LifeCycle 會不一樣, 直接看圖比較容易瞭解:



Service 的創造:

1. Service :
在主程序執行背景程式, 會使得Activity 的主程序變慢. 如果要執行長時間的背景程式, 必須在 Service 內寫 Thread* 來處理.

* Thread 可以想成是我們的工人, 當我們的程式工作量很大時, 可以同時分派給不同的 Thread.
* 負責執行 Activity 的工人叫做 MainThread.

2. IntentService :
IntentService 會在一個 worker thread 裡依序執行傳進來的 intent 任務, 完成任務後就會自行停止. 在比較長時間的執行中, 會使用 IntentService.

用 IntentService 的好處是不需要額外寫 Thread, 所以程式碼很簡潔, 壞處是只有它只有一個 Thread 工人, 如果有好幾個工作就必須排隊.

用 Service 比較複雜些, 但彈性比較大, 我們在範例裡會使用 Service.

Service 的註冊

我們的 Service 必須在 AndroidManifest.xml 裡註冊,
這樣才能被 Application 給找到 (跟 Activity 一樣!)

 <service android:exported="false" android:name=".TimerService">  
       <intent-filter>  
         <action android:name="com.example.learnservice.action.PLAY" />  
         <action android:name="com.example.learnservice.action.STOP" />  
       </intent-filter>  
 </service>  

Service 的範例 : 用 Service 做一個計時器 (程式碼連結)


作法上是這樣的,
1. 由 MainActivity 透過 intent 來啓動 Service
2. Service 藉由不同的 intent 訊息來判斷要開始倒數或停止
3. 開始倒數時產生一個 Thread 來執行倒數的工作, 同時傳送訊息給 Handler, 讓 Handler* 更新 MainActivity 畫面上的倒數數字.

*Handler 用來處理 Thread 發送的訊息; 在某些情況下, 我們可能有好幾個 Thread 同時工作, 因此 Thread 內去改變畫面顯示是不被 Android 允許的, 必須使用 Handler 來處理元件顯示.

影片教學:
Service 的使用上要比較小心, 如果 Service 跑了 5 秒以上, 而畫面還沒有反應, 就會出現"程式沒有回應"的Dialog, 因此我們要寫一個 Thread. 也必須寫一個 MainThread 的 Handler. 透過影片可以比較容易瞭解這些元件的用法.


* 影片裡漏了在 AndroidManifest.xml 註冊 Service, 所以特地把註冊的程式碼貼在上方


2013年8月21日 星期三

第七課: ListView 以及 Customize ListView

ListView 是將資料以垂直列表的方式呈現,
它大概是所有UI 元件中最常用的一種,

然而,
我們在第三課 Android UI 元件未介紹到 ListView 這個元件,
並不是遺忘了, 而是希望能更進一步講解如何客制化這個元件(Customize ListView),
學會Customize的技巧後, 也能應用在其它元件上.

要Customize ListView 要做兩件事:
1. 撰寫 list_item.xml
每一格List的呈現方式, 以Layout的方式實作出來.

2. 撰寫 ListAdapter 
利用 ListAdapter 將資料串接起來.*

----------------------------------------------------------------------------

教學影片:
在教學影片中會講解如何Customize ListView, 包刮 list_item.xml 以及 ListAdapter 的實作.



今日範例: 原始檔




















*我們在 Gallery 以及 GridView 的元件教學影片中有講解如何寫一個Adapter, 這邊就不多做講解.

2013年8月20日 星期二

第六課: Android 的 Debug

在程式開發的過程中一定會遇到不明白發生在何處的錯誤,
這時就要利用debug來找出錯誤的地方, 並且修正此錯誤.

Android 的 debug 有兩種方式:

ㄧ. 設置斷點:
程式運行在 debug 模式時,  會停止在斷點的設置處, 點擊下一步之後會運行到下一行的程式碼, 如此一來便可知道錯誤是出現在哪一行.




二. 設置Log訊息:
設置Log訊息有v,d,i,w,e五種*, 程式的使用方法如下:








這五種分別會以不同的顏色在Logcat呈現,







------------------------------------------------------------------------------
在這次的影片教學裡, 我們簡單講解如何利用這兩個方式來 debug,



今日範例: 原始檔




2013年8月19日 星期一

第五課: Activity 的訊息傳遞 --- Intent

之前, 我們介紹過如何做一個 Activity, 包括Layout的部分, 以及各UI元件的使用,
現在更進一步: 如果有兩個Activity, 那這兩個Activity之間要如何轉換呢?
Activity 之間的轉換必須用到 Intent* 這個元件.

我們將 Intent 觸發 Activity 的方式分為 Explicit 跟 Implicit 這兩種:
 Explicit intent 是明確指名要開啟哪個 Activity,  例如:
  Intent intent = new Intent(this, ActivityB.class);  
 intent.putExtra("Value", "This value for ActivityABC");  
 startActivity(intent);  

Implicit intent 是說明要做哪個動作, 但未說明要用哪個Activity開啟, 例如:
開啓網頁:
 Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.google.com"));  
 startActivity(intent);  
打電話:
 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:047777777”));  
 startActivity(intent);  
使用地圖:
 String uri = "geo:"+ latitude + "," + longitude + "?q=my+street+address";  
 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(uri)));  

詳細解說請見影音檔:


今日範例: 原始檔



* Intent 是 Activity, Service, BroadcastReceiver 這三大Android 功能的觸發器(Service 跟 BroadcastReceiver 在稍後的課程裡會提到),

2013年8月16日 星期五

第四課: Activity 的生命週期 LifeCycle

我們將Activity切成以下幾個單元來說:

1. Activity 是什麼
Activity 是 Android 程式的表現層, 它管理資料在螢幕的呈現方式.
通常一個Android應用程式(App) 會有好幾個activity, 不同的activity 之間可以透過按鈕以及back鍵轉換.

2. Activity 的 LifeCycle
Actvitiy 從產生到結束會經過幾個不同的states, 我們通常稱之為 LifeCycle (生命週期).
瞭解Activity 是處於哪一個 states, 就能夠知道Activity之後會實作哪一個方法.

知道這個的重要性在於我們能夠及時地釋放或取得的資源, 例如: GPS, Camera, Service, BroadCastReceiver...等
也能夠在適當的時機儲存資訊, ex. 訊息草稿, 遊戲分數等級...等等

3. LifeCycle的圖解
在 Android Developer 新的文件中, 使用金字塔式的圖形來解釋 Android 的LifeCycle.



a. 程式經由onCreate()進入Created state, 在onCreate()應該要宣告並取得你會用到的UI元件, 以及UI元件的互動方法. ex. Click

b. 接著, 程式會經由onStart()進入 Started state, 在onStart()應該要取得使用者的個人使用資料, 並且取得部分需要的資源, ex. GPS.

c. 等程式進入onResumed state, 就是進入了螢幕的顯示狀態, 所以在onResume()的方法中必須取得必要的顯示資源, ex. Camera

d.
*如果程式跳離了畫面但上一個activity還看得到(也就是部分看得到), 那activity就會進入Paused state
*如果整個跳離了(完全看不到), 則activity會進入 Stopped state.

舉個例子而言:
我們的Activity執行到一半, 但有一則Line的訊息進來, 它顯示的是Dialog, 所以我們的Activity會在此時進入Paused state, 如果按取消則程式回到Resumed state.
如果按顯示, 則程式會到Stopped state, 當看完訊息, 按back鍵回到程式時, 就會經過Started state 回到 Resumed state.

所以假設我們的資料會在Line顯示的時候流失, 就應該在onPause() 或者 onStop() 先記錄下來.

那麼大家也可以想想當一通電話打進來的時候, 我們的Activity會經過哪些states?




今日範例(來源): 程式碼



第三課: Android UI 介紹 (5-5) CheckBox, RadioButton

CheckBox 跟 RadioButton 都是Android 幫我們準備好的選擇按鈕,
但是這兩個在使用上有點不同,

CheckBox:
CheckBox 必須看作是可以多選的獨立使用元件,
如果想給使用者兩個選擇, 就必須插入兩個CheckBox元件,

RadioButton:
RadioButton 則是在數個選擇中只能選擇一個的單選元件,
使用上必須用 RadioGroup 將RadioButton包起來,

--------------------------------------------------------------------------------------

影片教學:
在教學影片裡我們示範了如何搭配應用xml的onClick參數以及Activity內的方法,
相信實作上, 應該會很有趣!



今日範例: 程式碼

2013年8月13日 星期二

第三課: Android UI 介紹 (5-4) GridView

GridView 是一個View的容器元件, 它可以將資料作整齊的格子化排列,
當然還是必須透過Adapter當做GridView跟資料的橋梁,

我們在這集裡面比較特別的是將Adapter獨立成另一個Class檔案,
這樣以後在檔案的整理上會方便許多, 例如:
假設未來 APP Project裡有很多不同的Adapter, 就能將它們都收入在同一個package裡,
這樣要修改時更能一目瞭然.

另外, 我們這一集刻意取材自Android Developer,
目的是希望大家在自學時也能多利用這個網站.

-------------------------------------------------------------------------------

影片教學:
今天做一個Android Developer 上的一個關於 GridView的App.



今日範例: 程式碼




2013年8月12日 星期一

第三課: Android UI 介紹 (5-3) Spinner, Dialog

這篇要介紹的是 Spinner 跟 Dialog,

Spinner:
Spinner 和 Gallery 一樣要透過 adapter 做橋梁才能使用,
Android有提供我們基本的ArrayAdapter 以及 android.R.layout.simple_spinner_item,
比自己寫個Adapter (參考Gallery)要簡便得多.

Dialog:
Dialog 通常用於當你希望使用者做某個決定(例如:刪除資料)或輸入某些資料的時候,
最常看到的例子是,
App開發者會將 Dialog 用在使用者按 back 鍵返回桌面時,
彈出框框詢問使用者是否決定離開,
雖然這不是Google推薦的使用方式, 但是積非成是(誤!)*,
我們也把這個例子放入教學影片裡.

Dialog 的使用方式上要先給定參數與方法,
這部分跟其它元件比較不一樣,
建議大家多做幾次, 就會熟悉了.

-------------------------------------------------------------------------------

影片教學:
今天教做一個文字顏色選擇的Spinner, 以及退出程式的Dialog.



今日範例: 程式碼




2013年8月10日 星期六

第三課: Android UI 介紹 (5-2) ImageView, Gallery

ImageView 跟 Gallery 在用法上與一般元件很像,
較困難的是 Gallery 必須另外寫一個 Adapter 才能夠使用.

Adapter 是"連接資料與元件的橋梁",

因此, 對Gallery而言,
GalleryAdapter 的功用就是連接資料圖片, 以及顯示資料圖片在Gallery 這個元件上.

在許多元件中都會用到Adapter,
因此記住Adapter的觀念是相當重要的.

我們寫的Adapter 一般延伸自 BaseAdapter (Android 幫我們準備好的一個class),
重點是必須實作Adapter的建構子, 以及 GetView的方法,

網站上有原始碼連結.
如果影片有不懂之處, 直接看原始碼加以理解會快得多噢!



今日範例: 程式碼





















課程總攬

我們把教學課程在這邊做整理,
同時也提供原始碼的下載點.

如果大家對於code有不懂的地方,
不妨先下載源碼測試,
相信會對學習有所幫助.

Android入門學習

在入門課程的部分, 我們講解一些在開發上需要知道的觀念,以及很可能會用到的元件或工具,
這樣大家在開發自己 App 的過程中如果遇到任何問題, 也就有了基本的解決能力.
這些課程再安排上有些順序性, 如果能夠逐一學習是我認為比較好的方式.

第一課 安裝開發環境以及SayHello (文章連結, 原始碼)
第二課 版面配置 LearnLayout (文章連結, 原始碼)
第三課 UI元件 :
              Part 1: Button, TextView, EditText (文章連結, 原始碼)
              Part 2: ImageView, Gallery (文章連結, 原始碼)
              Part 3: Spinner, Dialog (文章連結, 原始碼)
              Part 4: GridView (文章連結, 原始碼)
              Part 5: CheckBox, RadioButton (文章連結, 原始碼)
第四課 Activity的生命週期  (文章連結, 原始碼)
第五課 不同 Activity 間的轉換 --- Intent  (文章連結, 原始碼)
第六課 Android 的 Debug  (文章連結, 原始碼)
第七課 ListView & Customize ListView  (文章連結, 原始碼)
第八課 在幕後工作 --- Service  (文章連結, 原始碼)
第九課 廣播的接收器 --- BroadCastReceiver (文章連結, 原始碼)
第十課 App的資料分享 --- ContentProvider (文章連結, 原始碼)

基礎單元

在基礎單元的部分, 我們講解各自獨立的元件或技巧, 這些不同的單元彼此沒有什麼相關性, 可以直接選擇有興趣的來學習. 

單元一 Android 的影音播放 --- MediaPlayer (文章連結原始碼)
單元二 Android 的資料存取 --- SQLite 的使用 :
             方法一: 直接使用 SQLite (文章連結原始碼)
             方法二: 使用 SQLite + ContentProvider + Loader  (文章連結原始碼)
單元三 Fragment 的多元應用
             模組化的 UI 畫面 --- Fragment (文章連結)
             Fragment 的 Tab 應用 --- TabFragment (文章連結)
             拖拉式的畫面轉換 --- ViewPager (文章連結)
單元四 隱藏式的選單 --- DrawerNavigation (文章連結)

進階單元

Android 的元件不斷推陳出新, 加上其他 Google 的應用也會支援 Android 系統, 不大可能有學全的一天; 反之, 我們應該就自己 App 所需要的元件加以學習. 所以進階單元的內容將更為發散, 大家也應該自行作更深入地學習.

單元一  優化 APP --- Making Apps Beautiful (文章連結原始碼)
單元二  Android 的 pixel 與 dp (文章連結)
單元三  訊息傳遞與過濾器 intents and Intent filters (文章連結)




第三課: Android UI介紹(5-1) Button,TextView, EditText

Android 的UI元件方便我們在開發上可以節省許多寶貴的時間,
我們挑選幾種比較常用的來說.

通常在使用元件上, 有三個步驟.
1. 在畫面中插入原件, 並給予元件ID
2. 在Java檔中宣告, 並找到畫面元件的ID
3. 引用元件已經預先寫好的方法.

以Button為例:


這邊有影片:

第二課: Android的Layout

Android 的 Layout 大略可以分為四個:

1. LinearLayout: 元件的直線排列(可以設定直排或橫排)
2. RelativeLayout: 元件的相關位置排列
3. FrameLayout: 用來佔據元件的顯示位置 (元件會佔據畫面的顯示位置, 較晚插入的元件會覆蓋較早插入的元件)
4. TableLayout: 像表格化的Layout

LinearLayout 跟 RelativeLayout 是比較常用的兩個.

試問, 如果要產生以下畫面應該要如何做呢?


首先, 在Eclipse 的專案中找到 res/layout/畫面名稱.xml, 然後插入方塊:


 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
   xmlns:tools="http://schemas.android.com/tools"  
   android:layout_width="match_parent"  
   android:layout_height="match_parent"  
   android:paddingBottom="@dimen/activity_vertical_margin"  
   android:paddingLeft="@dimen/activity_horizontal_margin"  
   android:paddingRight="@dimen/activity_horizontal_margin"  
   android:paddingTop="@dimen/activity_vertical_margin"  
   tools:context=".MainActivity"  
   android:orientation="vertical" >  
   <TextView  
     android:layout_width="wrap_content"  
     android:layout_height="wrap_content"  
     android:text="LinearLayout" />  
   <LinearLayout  
     android:layout_width="fill_parent"  
     android:layout_height="wrap_content"  
     android:orientation="vertical"  
      >  
      <TextView  
     android:layout_width="fill_parent"  
     android:layout_height="100dp"  
     android:text="方塊A"  
     android:background="#2C9DE8"  
      />  
      <TextView  
     android:layout_width="100dp"  
     android:layout_height="70dp"  
     android:text="方塊B"  
     android:background="#2CE8C6"  
      />  
   </LinearLayout>  
   <TextView  
     android:layout_width="wrap_content"  
     android:layout_height="wrap_content"  
     android:text="RelativeLayout" />  
   <RelativeLayout  
     android:layout_width="fill_parent"  
     android:layout_height="wrap_content"  
     android:orientation="vertical"  
      >  
      <TextView android:id="@+id/rec_c"  
     android:layout_width="100dp"  
     android:layout_height="100dp"  
     android:text="方塊C"  
     android:background="#2C9DE8"  
      />  
      <TextView android:id="@+id/rec_d"  
     android:layout_width="70dp"  
     android:layout_height="70dp"  
     android:text="方塊D"  
     android:background="#2CE8C6"  
     android:layout_toRightOf="@id/rec_c"  
      />  
   </RelativeLayout>  
 </LinearLayout>  


這樣其實就Layout好了,
在LinearLayout的部分它是直線排下來的,
在RelativeLayout的部分我們給元件設了id, 再依id指派 android:layout_toRightOf 這個參數,
Layout只要多接觸就會懂囉!

這邊有影片:

第一課:安裝Eclipse開發環境以及SayHello

現在要安裝Eclipse的開發環境已經相當簡單了,
Google 已經把 ADT (Android Develope Tool, Android 開發工具) 綁入了Google提供下載的 SDK裡, 所以只要下載就行了.

1. 打開瀏覽器, 搜索 "Android SDK"
2. 下載 "Android SDK"
3. 打開 Eclipse, 並新增專案
4. 嘗試更改專案的TextView文字
5. 運行於手機上

如果不清楚以上步驟的話, 可以看看這影片噢!
(建議大家在看影片時, 選擇720p, 會清楚的多~)



關於這個網誌~

我是Jason, 一個Android的手機工程師,

2010 年開始學習Android手機程式以及Java語言,
到現在約有兩年半的時間,
過程中遇到不少挫折與恐懼,
然而, 這項技能最終帶給了我不少的成長,
在收入上, 在思考上都有很大的進步,

在美國, 一個普通的 App 開發者薪水是 US$92,000 一年, 約等於 270 萬台幣,
在台灣, 最好的手機 App 獨立開發商, 也有500萬台幣以上的年收入,

因而,
我相信寫程式(&設計)是最適合台灣的工作形態:
一個沒有國界, 沒有汙染的工作,
只要花時間用心學習, 人人都可以上手.

在這網誌內會寫下 Android 的教學內容,
並以簡短的Youtube教學影片為輔助,
希望這樣可以降低大家的學習門檻與意願.
進而體會到寫程式的樂趣.

Jason 2013.8.11