##绑定服务的步骤


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(系统服务的名字)