安卓基礎8:服務
服務:
(在背景運作)
程序:
是安卓應用的載體,4大元件均在程序中運作,更準确的說是在主線程中運作。當系統記憶體不足時,會移除一些舊程序給新的程序。
主線程:
隻要不建立線程,都屬于主線程上運作;主線程不能夠執行耗時操作,需要額外開辟線程運作
程序層級:
ForeGround process:前台程序;
相當于activity執行了onresume方法,使用者正在操作該程序界面
Visible process:可視程序;
沒有前台元件,但是影響使用者使用的界面
Eg:透明應用
透明應用在被部署之後會走onpause方法;
Service process:服務程序;
通過startService開啟了一個服務;
Eg:音樂播放器,再後退之後在背景播放音樂
Background process:背景程序
相當于activity執行了onstop方法;(點home鍵);使用者不可見其界面
Empty process:空程序
背景沒有任何元件運作;相當于退出應用,僅僅是留了線程在上面(目的:為了下次再載入時速度能快一些)
服務:
Activity 和 service都繼承ContextWrapper;兩個要複寫的方法都相似,隻是與界面相關的方法,service都沒有;
服務通過startService()開啟服務,在界面退出之後,服務會在後太長時間運作,最終通過調用stopServce()關閉服務;
服務調用方法順序:
服務第一次開啟時:
調用:onCreate()方法
服務第二次開啟時:
調用:onStartCommand()方法;
當服務關閉時:
調用onDestroy();
電話竊聽器案例:
(通過廣播開啟服務)
布局填充器:
實作步驟:
1、 定義一個服務
2、 在服務的oncreate方法中建立TelephonManager的執行個體,可以通過這個類可以監聽電話的狀态;
3、 定義一個類,myPhoneStateListener用來監聽電話的狀态,并通過MediaRecoder類實作錄音的功能;
4、 廣播中開啟服務
5、 在清單檔案加上響應的檔案
代碼
描述:
1、 通過廣播來監聽接聽電話事件
2、 通過一個服務長期運作,監聽電話狀态
3、 當處于響鈴狀态,準備錄音
4、 當處于接聽狀态,開始錄音
代碼:
事件處理:
通過廣播啟動監聽:
電話服務:
配置清單:
使用服務注冊特殊的廣播接收者
(通過服務開啟廣播)
描述:
在開機之後去啟動服務注冊開屏、鎖屏廣播事件;并接收該廣播事件
代碼:
事件處理
開啟服務
服務中建立開屏、關屏廣播事件
監測廣播事件
配置清單:
通過bind方式開啟服務的生命周期
Bind開啟服務特點:
1、 第一次點選按鈕,通過bindservice開啟服務,服務隻會走oncreate和onbind方法;
2、 關閉app之後,第二次點選按鈕,服務不執行;因為,服務已經被殺死了;
3、 “不求同時生,隻求同時死”:bind開啟的服務,随着主界面消亡而消亡
4、 服務隻能解綁一次,再解綁會報異常;同時,綁定誰,解綁的時候就是誰
5、 通過bindservice開始的服務,在程序設定頁面找不到,可以了解為隐形的服務
6、 當服務的onbind傳回為空時onServiceConnected()方法不執行
直接new出服務對象時,不再是服務,而是普通的對象,不再有上下文對象
步驟:
1、 定義一個服務,并配置清單檔案
2、 Activity想調用服務中的方法
3、 在服務的内部定義一個中間人對象即Ibinder的實作類(在這個實作類中可以間接調用到服務的方法)
4、 在onbind方法中将自己定義的中間人對象傳回
5、 當Activity想要調用服務時,先通過onServiceConnected可以擷取中間人對象
6、 通過中間人對象我們就可以調用我們想要的方法
通過bind啟動服務後執行順序
在服務第一次先執行時:onCreate
當服務被綁定調用時:onBind
當服務被銷毀時調用:onDestroy
當服務再次被啟動時:onStartCommand
代碼
事物處理
主界面通過bind啟動服務
任務執行過程:
配置清單:
通過BinderService對象擷取服務内容
在之前通過startService啟動服務,執行的是服務中指定的程式;我們期望擷取服務中的方法,手動調用服務中的一些方法,是以用Binderservice;
執行過程:
1、 建立一個檢測服務的對象,實作serviceConnextion
2、 利用bindService去連接配接服務
3、 在服務中建立繼承binder的中間對象,裡面放上我想要調用的方法;
4、 通過任務的onBind方法将中間對象送出給serviceConnextion的onServiceConnected方法,然後再去調相應的想用的方法
代碼:
描述:
想辦事不能直接找上司,我們通過中間人去求上司辦事
事務處理:
服務層:
配置清單:
抽取中間對象Binder中的方法為接口
接口可以隐藏代碼内部的細節,暴露程式員想要暴露的方法;
步驟:
1、 定義一個接口,暴露程式員想要暴露的方法;
2、 我們定義的這個中間人對象實作我們的接口的方法
3、 用過bindservice方法擷取我們中間人對象
4、 通過中間人對象調用服務裡面的方法
代碼
事務處理層:
服務層:
接口
配置清單:
百度音樂盒:
需求:我們既想讓服務子在背景長期運作,又想調用服務中的方法
通過startService方法不能調用方法;通過bindservice方法不能長期運作,是以我們需要通過混合方法區實作;
startService
bindService
unbindService
stopService
開啟的先後順序:
1、 必須先startService方法,能夠在背景長期運作
2、 調用bindservice方法,能夠邦正調用服務中的方法
3、 調用unbindService方法,解綁服務
4、 Stopservice現在大多數app都不調用這個方法
代碼:
描述:
建立一個播放器,通過點選裡面的播放、暫停按鈕去調用服務中的方法
事務處理層:
服務層:
接口層:
配置清單:
AIDL(android interface Definition Languge)
基本概念
本地服務:運作在自己應用裡面的服務
遠端服務:運作在其他應用裡面的服務
本地服務與遠端服務間通信稱為程序間通信;
AIDL解決的問題:程序間的通信
AIDL實作步驟:
1、 在一個應用裡面定義一個服務,服務裡面有一個方法,這個方法稱為遠端服務的方法
2、 在這個服務裡面定義中間人對象,定義接口iservice.java把想暴露的方法定義在接口中
3、 把iservice.java檔案改為aidl檔案,注意:aidl不支援public
4、 系統會自動給我們生成一個iservice.java檔案
public static abstractclass Stub extends android.os.Binderimplementscom.itheima.remoteservice.Iservice
5、 把我們定義的中間人對象直接繼承Stub
6、 我想在另一個應用裡面去調用這個服務裡面的方法要保證使用同一個aidl檔案
7、 若要保證aidl檔案相同,谷歌要求包名相同
8、 在本地服務中,還是通過bindservice方法去擷取中間人對象
9、 注意擷取我們定義的中間人對象的方式不一樣,通過stub的一個靜态方法區擷取我們定義的中間人對象Stub.ainterface(Ibinder obj);
遠端端代碼:
服務:
接口:
配置清單:
本地代碼:
事務處理:
通過AIDL,在本地會生成一個對應的stub
AIDL應用場景:
支付寶:
事務處理層:
接口層:
清單配置
歡樂鬥地主:
事務處理層: