绑定本地Service和远程Service并调用其中方法

来源:互联网 发布:java 系统登录界面 编辑:程序博客网 时间:2024/06/02 05:08
远程服务:调用者和服务在不同的工程代码里面。

本地服务:调用者和服务在同一个工程代码里面。


本地服务:服务和启动它的组件在同一个进程
##远程服务:服务和启动它的组件不在同一个进程
* 远程服务只能隐式启动,类似隐式启动Activity,在清单文件中配置Service标签时,必须配置intent-filter子节点,并指定action子节点


#AIDL
* Android interface definition language
* 安卓接口定义语言
* 作用:跨进程通信
* 应用场景:远程服务中的中间人对象,其他应用是拿不到的,那么在通过绑定服务获取中间人对象时,就无法强制转换,使用aidl,就可以在其他应用中拿到中间人类所实现的接口


##支付宝远程服务
1. 定义支付宝的服务,在服务中定义pay方法
2. 定义中间人对象,把pay方法抽取成接口
3. 把抽取出来的接口后缀名改成aidl
4. 中间人对象直接继承Stub对象
5. 注册这个支付宝服务,定义它的intent-Filter


##需要支付的应用
1. 把刚才定义好的aidl文件拷贝过来,注意aidl文件所在的包名必须跟原包名一致
2. 远程绑定支付宝的服务,通过onServiceConnected方法我们可以拿到中间人对象
3. 把中间人对象通过Stub.asInterface方法强转成定义了pay方法的接口
4. 调用中间人的pay方法


服务的分类
###远程服务
* 与启动者在不同应用的服务
###本地服务
* 与启动者在同一应用的服务


#AIDL
* Android interface definition language
* 在Android中用于进程间通讯
###步骤
#####修改 05远程服务
1. 把接口文件的后缀名改成aidl
2. aidl文件中所有东西都是public的,不需要也不能自己定义访问修饰符
3. 中间人对象继承Stub,这个对象已经继承了Binder并实现了PublicBusiness接口
#####修改 06启动远程服务
1. 把05项目的aidl文件复制到06项目,然后aidl所在的包名06和05项目必须一致
2. 把06项目获取到的中间人对象使用Stub.asInterface强转


aidl:android interface definition language  安卓接口定义语言
aidl文件都是公有的,没有访问权限修饰符
IPC: inter process communication 进程间通讯


每一个应用程序都是运行在自己独立的进程里面的。

进程操作系统分配内存空间的一个单位。进程的数据都是独立的。独立的内存空间。


把服务看成一个领导,服务中有一个banZheng方法,如何才能访问?
* 绑定服务时,会触发服务的onBind方法,此方法会返回一个Ibinder的对象给MainActivity,通过这个对象访问服务中的方法
* 绑定服务


Intent intent = new Intent(this, BanZhengService.class);
    bindService(intent, conn, BIND_AUTO_CREATE);
* 绑定服务时要求传入一个ServiceConnection实现类的对象
* 定义这个实现类


class MyServiceconn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
zjr = (PublicBusiness) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
   
    }
* 创建实现类对象


conn = new MyServiceconn();
* 在服务中定义一个类实现Ibinder接口,以在onBind方法中返回


class ZhongJianRen extends Binder implements PublicBusiness{
public void QianXian(){
//访问服务中的banZheng方法
BanZheng();
}
public void daMaJiang(){

}
}
* 把QianXian方法抽取到接口PublicBusiness中定义


绑定本地服务调用方法的步骤:
1.在服务的内部创建一个内部类 提供一个方法,可以间接调用服务的方法
private class MiddlePerson extends Binder implements IMiddlePerson{}
2.实现服务的onbind方法,返回的就是中间人 MiddlePerson
3.在activity 绑定服务。bindService();
4.在服务成功绑定的时候 会执行一个方法 onServiceConnected 传递过来一个 IBinder对象
5.强制类型转化 调用接口里面的方法。

/** * 中间人的接口定义 * */public interface IMiddlePerson {/** * 代办暂住证 * @param money */public void callMethodInService(int money);}
public class MyService extends Service {//2.实现服务成功绑定的代码 ,返回一个中间人。@Overridepublic IBinder onBind(Intent arg0) {System.out.println("服务被成功绑定了。。。。");return new MiddlePerson();}@Overridepublic boolean onUnbind(Intent intent) {System.out.println("onunbind");return super.onUnbind(intent);}@Overridepublic void onCreate() {System.out.println("oncreate");super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {System.out.println("onstartcommand");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {System.out.println("ondestory");super.onDestroy();}/** * 这是服务里面的一个方法 */public void methodInService(){Toast.makeText(this, "哈哈,服务给你办好了暂住证。", 0).show();}//1.第一步服务要暴露方法 必须要有一个中间人private class MiddlePerson extends Binder implements IMiddlePerson{/** * 代办暂住证 * @param money 给钱 50块钱以上才给办。 */public void callMethodInService(int money){if(money>=50){methodInService();}else{Toast.makeText(getApplicationContext(), "多准备点钱。", 0).show();}}/** * 陪领导打麻将 */public void playMajiang(){System.out.println("陪领导打麻将。");}}}
activity_main.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:orientation="vertical"    tools:context=".MainActivity" >    <Button        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:onClick="bind"        android:text="绑定服务" />    <Button        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:onClick="unbind"        android:text="解除绑定服务" />    <Button        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:onClick="call"        android:text="调用服务里面的方法" /></LinearLayout>

public class MainActivity extends Activity {private MyConn conn;private IMiddlePerson mp;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}// 绑定服务public void bind(View view) {// 3.activity采用绑定的方式去开启服务。Intent intent = new Intent(this, MyService.class);conn = new MyConn();bindService(intent, conn, BIND_AUTO_CREATE);}// 解除绑定服务public void unbind(View view) {unbindService(conn);mp = null;}@Overrideprotected void onDestroy() {System.out.println("啊啊啊,我是activity,我挂了");super.onDestroy();}// 调用服务里面的方法。public void call(View view) {// 5.通过中间人调用服务里面的方法。mp.callMethodInService(55);}private class MyConn implements ServiceConnection {// 4. 当服务被连接的时候调用 服务别成功 绑定的时候调用@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {System.out.println("在activity里面成功得到了中间人");mp = (IMiddlePerson) service;}// 当服务失去连接的时候调用(一般进程挂了,服务被异常杀死)@Overridepublic void onServiceDisconnected(ComponentName name) {}}}
绑定远程服务调用方法的步骤:
1.在服务的内部创建一个内部类 提供一个方法,可以间接调用服务的方法
2.把暴露的接口文件的扩展名改为aidl文件 去掉访问修饰符 public
private class MiddlePerson extends IMiddlePerson.Stub{}  IPC的子类
3.实现服务的onbind方法,返回的就是中间人 IMiddlePerson
4.在activity 绑定服务。bindService();
5.在服务成功绑定的时候 会执行一个方法 onServiceConnected 传递过来一个 IBinder对象
6.IMiddlePerson.Stub.asInterface(binder) 调用接口里面的方法。


远程服务的代码:

 

 interface IMiddlePerson {/** * 调用服务里面的方法 */ void callMethodInService();}

public class RemoteService extends Service {@Overridepublic void onCreate() {System.out.println("远程服务被创建了。。。");super.onCreate();}@Overridepublic void onDestroy() {System.out.println("远程服务被销毁了。");super.onDestroy();}@Overridepublic IBinder onBind(Intent intent) {return new MiddlePerson();}private void methodInService(){System.out.println("我是远程服务的方法,我被调用了。。。。");}//1.创建一个中间人  远程服务继承的是ipc的一个实现类private class MiddlePerson extends IMiddlePerson.Stub{@Overridepublic void callMethodInService() {methodInService();}}}


绑定远程服务(调用远程服务)的代码:



 interface IMiddlePerson {/** * 调用服务里面的方法 */ void callMethodInService();}

public class MainActivity extends Activity {private MyConn conn;private IMiddlePerson iMp;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}/** * 绑定远程服务 * @param view */public void bind(View view){Intent intent = new Intent();intent.setAction("com.itheima.remoteservice");conn = new MyConn();bindService(intent, conn, BIND_AUTO_CREATE);}private class MyConn implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {iMp = IMiddlePerson.Stub.asInterface(service);} @Overridepublic void onServiceDisconnected(ComponentName name) {}}public void call(View view){try {iMp.callMethodInService();} catch (RemoteException e) {e.printStackTrace();}}@Overrideprotected void onDestroy() {unbindService(conn);super.onDestroy();}}

参考:

Android Service 的生命周期

混合调用Service(Service既能后台长期运行,又能调用Service中方法)



0 0
原创粉丝点击