##綁定服務的步驟
1. 定義服務
public class ServcieDemo extends Service {}
2. 註冊服務
<service android:name="com.itheima.bind.ServcieDemo"></service>
3. 編寫服務的方法
/**
* 錄取通知書
* 服務中的內部方法
*/
public void methodInService(String name , int money){
if(money <= 100000){
Toast.makeText(this, name+",你的錢不夠.", 0).show();
}else{
Toast.makeText(this,name+"先生,您的中國人民大學本科錄取通知書已經辦妥了..", 0).show();
}
}
4. 定義一個內部類
/**
* 內部招生老師,內部代理對象
*/
class MyBinder extends Binder{
/**
* 內部人員中固有的方法,它的作用就讓別人來訪問它,然後它自己去訪問服務中的方法。
* 通過迂迴的手段達到從外部類調用服務中的方法效果。
* @param name
* @param money
*/
public void callMethodInService(String name , int money){
methodInService(name , money);
}
}
5. 服務綁定後返回內部代理對象
/**
* 如果服務成功綁定上了,那麼就返回一個通訊頻道,
* 返回一個內部人員,內部代理對象
*/
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
//返回內部代理對象
return new MyBinder();
}
6. 在activity綁定服務
//綁定服務
public void bind(View v) {
Intent service = new Intent(this , ServcieDemo.class);
/**
* 第一個參數:intent對象
* 第二個參數:servcieConnection 用於監聽服務當前的狀態
* 第三個參數:BIND_AUTO_CREATE 服務自動創建,然後綁定。
*/
bindService(service, new MyConn(), BIND_AUTO_CREATE);
}
7. 在onServcieConnected方法中獲取到內部代理對象
/**
* 監聽服務的狀態,服務是啓動還是停止都會收到信息。
*/
class MyConn implements ServiceConnection{
/**
* 如果服務能夠成功綁定上,那麼這個方法將會調用,啓動的參數service就是服務返回的內部對象 MyBinder
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//獲取到服務內部返回的代理對象 ,用binder承接起來
binder = (MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {}
}
8. 在其他地方調用內部對象中的方法
//調用服務的方法
public void call(View v) {
//通過內部代理對象,調用內部 類中的方法,實際上是調用了服務中的方法
binder.callMethodInService("張三丰", 1000000);
}
##綁定服務的生命週期
* 完整的生命週期
> onCreate【創建】---onBind【綁定】 --onUnBind【解除綁定】--onDesotry【銷燬】
* 多次綁定服務
> 不會調用任何服務中生命週期方法
* 多次解綁
> 將會拋出服務沒有註冊的異常,因爲服務的綁定和解綁是根據conn對象來解析的。
* 多次綁定,一次解綁
> 將會拋出服務沒有註冊的異常
> 建議:服務綁定一次,解綁一次。
##兩種啓動服務的區別
* startService
> 生命週期: onCreate---onStartCommand---onDestory
> 與服務的通訊: 無法與服務進行直接通訊
> 與開啓者的關係: 服務一旦開啓與開啓者(activity)將沒有什麼聯繫了,就算開啓者銷燬了,服務依然存活。
> 在設置界面中有顯示
* binderSerivce
> 生命週期: onCreate--onBind--onUnBind--onDestory
> 與服務通訊: 通過內部代理對象間接調用服務的方法
> 與開啓者的關係: 一旦開啓者銷燬了,那麼服務也將隨之銷燬。
> 在設置界面無顯示
##能不能讓服務長期運行在後臺,並且還能與服務進行通訊
* startService : 讓服務長期運行在後臺,但是無法與服務進行通訊
* bindServcie : 可以與服務進行通訊,但是無法長期運行在後臺
##混合開啓服務
1. startService 啓動服務
2. bindService 綁定服務
3. 調用服務的方法
4. unBindService 解除綁定服務
5. stopService 停止服務
##練習-使用混合開啓服務去優化音樂播放器
1. 使用綁定服務的方式去播放音樂
2. 讓音樂在後臺運行,並且還能操作next -- pre [混合開啓服務]
##本地服務和遠程服務
* 本地服務 --local service
> 服務運行在當前的應用程序裏面
* 遠程服務 --remote service
> 服務運行在其他的應用程序裏面
##重要的概念
* 進程
> 所謂的進程就是指系統給每一個應用程序分配的一塊獨立的內存工作空間
* IPC
> inter process communication 進程間通訊
* AIDL
> andrid interface definition language 安卓接口定義語言
##使用AIDL訪問遠程服務的步驟
1. 定義服務類
public class ServiceDemo extends Service {}
2. 註冊服務
<service android:name="com.itheima.remote.ServiceDemo">
<intent-filter >
<action android:name="com.itheima.remote.SERVICE"/>
</intent-filter>
</service>
4. 修改IService接口的後綴名
5. 去掉IService中的public定義
6. 修改MyBinder的繼承關係
/**
* 改變繼承的關係,原來是繼承了Biner 實現了IService接口
* 但是顯示爲了滿足遠程調用,所以應該讓其繼承IService.stub
*/
private class MyBinder extends IService.Stub{
@Override
public void callMethodInService() {
methodInService();
}
}
7. 拷貝aidl文件到其他應用中同名包下
8. 綁定服務
public void bind(View v) {
//綁定06中的服務
Intent service = new Intent();
service.setAction("com.itheima.remote.SERVICE");
conn = new MyConn();
bindService(service, conn, BIND_AUTO_CREATE);
}
9. 轉化對象,調用服務的方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//轉化binder對象的時候,使用IServcie。stub的內部方法來轉化
binder = IService.Stub.asInterface(service);
//binder = (IService)service; //不允許這麼強制類型轉化
}
###重點
1. 綁定服務
2. 綁定服務和啓動服務的區別
3. 遠程服務--aidl
4. 系統服務
> XXXManager manger = (XXXManager) getSystemService(系統服務的名字)