android service作法

http://ozzysun.blogspot.com/2010/11/android-service_02.html

這一個單元是有關服務Service
這個Android裡面的元件Component
這個Android裡面有四大元件
第一個當然是管畫面的Activity
Service則是沒有畫面的一些工作
可以使用Service來設計
那比如說來上傳和下載檔案
或是儲存成績取得網路連線這些工作
都可以使用背景不需要畫面的一些服務
服務類別它是一個繼承Service的類別
它他有三大類第一類是一般常見的服務寫法
那我們只需要在package上按右鍵
然後new一個Java類別
這個類別我取名叫HelloService簡單的測試
那它繼承Super class這邊就
可以輸入Service類別
Service類別選擇android.app.Service
好實作做完了之後呢它需要覆寫方法
那覆寫第一個是叫onBind
onBind方法
這個方法是屬於綁定型Service需要的方法
那接著呢我們要談到服務的產生還有執行跟結束
請各位按Ctrl O
覆寫方法
點擊onCreate
onCreate當服務被產生的時候自動會被執行的方法
那服務執行的時候它是執行onStartCommand
那另外一個結束的時候是onDestroy方法
所以請各位選擇這三個方法覆寫它
當它覆寫完了之後我們還是一樣加入Logcat
Logd Tab
然後建立一些測試的一個指令
把這個TAG常數建立出來
再把這個Logcat指令複製到這些覆寫過的方法中
然後再改變它的訊息
變成onDestroy onStartCommand
那在這個onStartCommand的時候
其實它有一個回傳值它比較特殊
這個回傳值你可以選擇說
這個服務未來如果在執行的過程當中
如果在系統的背景被我們Android系統因為
資源缺乏而把這個服務殺掉的時候
那你要怎麼辦
所以我們直接打START大寫
有幾個常數可以選擇第一個是NOT STICKY
就是說當它被殺了時候就不要再啟動它了
另外一個是相反
如果它被殺了請馬上重啟這一個服務
可是重啟的時候
它他傳進來這個Intent會是null喔
那如果你要叫它再重新把Intent給送進來
重新產生Intent再送進來的時候
你就要選擇REDELIVER INTENT
那我們選擇比較常見的START STICKY
就代表說未來它在背景如果被系統殺掉了
請把它復活重新執行它
那一個Service繼承Service類別
那我們也要在AndroidManifest裡面
請點擊AndroidManifest檔案
在application裡頭的元件中
那加入Service
那它也貼心的掃描到我們類別中
有繼承Service的類別就是我的HelloService
我們打一個斜線完成它
那完成它的之後要怎麼啟動它了
直接找一個Activity
那我們就在LoginActivity這邊做練習
onCreate中我寫一個簡單的註解
要打一個有服務產生出來要先有Intent
Intent
這個Intent我就叫service helloService的Intent
好那等於new Intent
一樣的方法明確的告訴它
我要請HelloService出來
出來執行
好那這個地方我們最後要啟動它的時候
要呼叫startService這個方法
那把Intent剛剛產生的Intent放進去
那它就會啟動喔
好我們執行測試看看
那這個部份要把Logcat開出來
來觀察
好第一個是請各位記得這邊要選擇目前
顯示目前的應用程式就好了
那或者是等一下也可以打一些關鍵字後來篩選它
太多資料
所以我們打入hello
hello
那這個篩選的之後你可以發現
onCreate會被先執行
然後再執行onStartCommand
那當我今天把這個Activity給結束掉
按下返回的按鍵
發現一件事了嗎
那個onDestroy並沒有自動被呼叫
所以onDestroy沒有被呼叫
這樣子的話它還會
在系統的裡面存活著這一個service
所以假如我要手動的話
那我可以放在像今天的案例我可以去覆寫
覆寫
第一件事情先把我們原本的這個Intent
變成屬性Ctrl Alt F
然後再覆寫onStop方法好了
onStop
那onStop方法裡面我們在
呼叫這個停止這個服務stopService
然後把剛才的這個Hello的Intent名稱放進去
好這樣子的話那我們就可以試試看
在返回結束這個Activity的時候
我的背景Service會不會跟著離開跟著結束
好那我們觀察到onCreate onStartCommand執行
那我們按下返回
返回的時候呢
因為它的onStop被呼叫
所以它就被殺掉了
被殺掉結束
所以用這樣子才可以把一個Service給停止掉
一個Service在執行的時候
很多人會因為它是背景的一支程式
而以為它是在另外一個執行緒其實不是
Service裡面的onStartCommand程式碼
其實它是在
它是在它是在UI執行緒裡面
我們做一個測試看看
Thread類別可以讓這個程式在這裡
停止sleep這個方法
Thread.sleep這個方法
可以讓你在目前的這個地方停止
所以我們先把它停5秒鐘
那是毫秒數所以寫5000毫秒代表5秒
那我們按下Alt Enter
因為它會抛出Exception
所以我們就用Surround with try/catch把它包起來
那完成了之後呢我們來觀察一下它會有什麼問題
各位會發現一執行的時候會空白五秒鐘
因為當我們執行到這裡的時候
它使用的是UI執行緒
所以它會停止5秒鐘之後再顯示出來
這裡在我們onCreate裡面
要執行完成後它才會進行畫面的配置
所以我們在這裡
我們直接使用這個Service的時候
它就因為在這個執行這邊它使用的是UI執行緒
才會讓我們的畫面卡住五秒鐘
所以請記得一件事情
Service如果你要寫耗時工作的話或是連線網路
一定要另外用AsyncTask這類的機制去設計
因為它是在UI執行緒當中執行
因為這樣子
Service在早期的時候讓人家很詬病很麻煩
所以再之後呢Android出現了一個叫IntentService
請各位在extends這個Service這裡打入Intent
先選到IntentService
Intent
那這個IntentService所以我們按下Tab鍵
就可以替換掉這個Service
好IntentService有幾個規定
要覆寫的方法名稱不一樣它叫做onHandleIntent
那我們先覆寫出來
好到最上面其實它還是錯誤的
因為你還沒有滿足它第二個規定
它第二個規定是要有一個空的建構子
所以我們按下Alt Enter之後呢
建立一個有一個字串參數的建構子
可是它需要是空的建構子
所以我們這邊先把它刪掉
刪掉之後這個name怎麼辦呢
它只是一個服務的名稱
所以我們可以打入這個類別的名稱來替換
替換它
那這樣子這個服務就已經
這個IntentService就完成了
請記得還有一個要小心的地方
就是原本如果我們覆寫onStartCommand
我們要把它刪除取消掉
不然你又覆寫的onStartCommand
它就會執行onStartCommand的工作
而不會執行剛才我們說的
最下方的這一個叫onHandIeIntent
那我們做一點Log來驗證
它會執行onHandleIntent
那在執行一次
前面的這個產生的方式都不用改
在執行一次
那我們觀察一下Lagcat
好onCreate被執行了
onHandleIntent被執行了
那onHandleIntent執行完了之後
它自動就打就結束了這一個Service
所以其實它用起來的話
比起之前的Service還要更好
那這一個部分就是它的特色
它還有一個特色
它這一塊程式執行的地方
onHandleIntent所執行的地方
它都是用另外一個執行緒而不是用UI執行緒
我們可以測試看看
把剛才的Thread.sleep換到這裡來
五秒鐘的程式碼換到這裡來
好那我們再執行一次
各位可以看到畫面馬上就會出現
因為它並沒有停止5秒鐘
那接下來等了5秒鐘之後onDestroy就自動被呼叫
所以就代表這一個地方是可以執行耗時工作這很方便
IntentService還有一個特色
它如果有很多次的呼叫
它會循序的排隊讓前面那一個執行完才會執行下一個
它也滿特別的
我們可以做一些測試來觀察
這個時候我想要把這個Intent
等一下傳進來的Intent裡面我想要放東西
所以在LoginActivity我執行它的時候
我們可以這樣做
helloService在這個Intent
那我們可以在putExtra
put一個名稱NAME名稱
然後再來我們裡面放
T1假設是這樣的話
那到時候我就可以去取得這個NAME
所以我們接下來
去切換到helloService
接著呢這一個裡面我們就可以先把它的
Intent先取出來
我們就可以呼叫它的Intent再get它的字串值
字串Extra
然後名稱給它NAME然後接著下來我們再測試一下
測試的時候我要產生
兩三個Intent來做測試比如說這樣
我們可以試試看喔
接著我在putExtra這一次我put的是T2
然後再啟動它一次
第三次我put的是T3然後再啟動它一次
來我們來觀察一下
每一次執行它需要耗時5秒鐘
各位看T1執行
T2輪流執行
因為T1執行完了才輪到T2這一次的呼叫
所以各位可以觀查
如果有多次的呼叫我這個Service
去執行的話它會排隊
排隊
而且不會再繼續去產生另外一個物件
各位看它又節省資源不會產生多個物件
那它又可以在另外一個執行緒執行這些工作
而且它還可以排隊順序去執行完所有的工作
這個特色讓近年來的程式設計
很喜歡去使用繼承IntentService這個方法
IntentService並不是沒有缺點的
當我們今天叫一個背景程式去執行的時候
執行完了假如我的Activity需要得到通知跟回報
這個時候它就比較難做到
比如說我叫一個人去幫忙
幫忙完的時候如果它要
就是送個訊息來告知我一下
會很困難那這個部份我可以用什麼來補足
不然我們可以用Broadcast Receiver
Android的四大元件之一
叫做廣播接收器來完成它
要做廣播接收器第一個
我們必須要設計一個Action字串
那個字串名稱叫Action
我們做一個public static
final的字串
psfs那按Tab鍵
那它會幫我產生一個那這個名稱
我取名叫ACTION_HELLO_DONE完成
那這個完成的字串我自己要訂
所以我可以自己隨便訂hello或done
這樣子的訂定就好
訂定完成了之後
那我們未來送出一個Broadcast一個廣播
我們未來用這一個字串來做一個依據
然後送出這個廣播
那怎麼送我舉個例好了
當Thread完成的時候
結束這個onHandleInt的時候
我們可以呼叫sendBroadcast
這一個方法在裡面需要一個Intent
那Intent裡面的除了intent以外
所以我先在前面設計一個Intent
這個是告訴人家說我已經做完
所以做一個Intent名字不好
所以我說寫done然後用一個Intent
那這個Intent你暫時也不需要做任何的設計
那我只需要set它身上的Action
setAction字串
所以先把它字串設定成
剛才我們設定那個字串ACTION
ACTION
這一個叫DONE
好HELLO DONE
那設定完的時候我就把它送出去
系統裡面就是代表說我發出一個廣播
怎麼去接收它呢
在LoginActivity我需要知道何時
這個某一個服務已經完成了嗎
所以我接下來就要在我的onStart
onStart跟onStop裡面
onStart
我在我的onStart覆寫一下onStart方法
那onStart方法裡面我就註冊說我要去
傾聽這一個
我要傾聽一個特殊的Broadcast
好那我們使用registerReceiver
Receiver
那這一個Receiver你可以做很多種的設計
你也可以設計一個獨立的一個屬性
比如說在這個類別的第一層裡面
你可自己設一個BroadcastReceiver
BroadcastReceiver
然後我這個Receiver是要receive
好等於new BroadcastReceiver
它是一個需要在實作方法的類別我們按Enter
最後在這個整指令的後面補一個分號
當我們收到的時候
那它就印出來Logcat Logd
然後印出它所送到的資料
那你也可以直接印出來
它的intent裡面的getAction
Action
所以這樣子我們來觀察到底會不會
那Receive我就接一個Hello以後比較好查錯
多一個Hello
好那接著呢
我們可以在onStart的時候
就是畫面產生出來的時候我就去傾聽它
第一個是怎麼去傾聽這個Receiver呢
那你就把這個Receiver放進去就好了
Receiver放進去就好
那它裡面會有需要一個IntentFilter
我們要怎麼產生呢
現在前面產生一個IntentFilter
這個是我的Filter
Filter過濾器
所以我就new一個IntentFilter
IntentFilter括號裡面它就可以定義它的ACTION值
那我們使用的當然是HelloService裡面的
那個ACTION字串
所以未來如果是有一個Intent身上有
這個字串它才會把它抓進來
所以這部份我再把這個filter放進去
那這個叫做接收的機制
這個叫做廣播的機制
所以它的整個機制叫做廣播接收器
BroadcastReceiver
所以這裡叫Receiver的設計
你一定要一個filter
IntentFilter設計訂定說你要傾聽那一個
你要注意那一個
那當然最後如果離開畫面之後就不要傾聽了嗎
所以你可以呼叫unregisterReceiver
然後把這個Receiver給放進去這樣就完成
那這一個stopService不用了
好所以這個機制就是先設計一個
BroadcastReceiver的物件
然後在onStart onResume的地方把它註冊
呼叫註冊我們來試試看
在每一次HelloService結束的時候它會送出廣播
那我們在觀察我的Activity可不可以抓到它
我們看一下Log
因為這個Log也有它的Hello這個字
我們也可以抓的到
好等五秒鐘結束的時候看看有沒有收到
有了
在LoginActivity裡面的onReceiver收到了
第二次第二個也收到了
等一下第三個最後也會收到
那這就是去接收到說
IntentService的結束的資訊或者是中途
它有要溝通什麼事情的時候可以去取得
那這是合併Service
IntentService
跟BroadcastReceiver的一個單元練習
給各位做參考

留言

這個網誌中的熱門文章

android app之間使用socket做溝通

html css & bootstrap心得