android 本地服务 远程服务器,Android:远程服务Service(含AIDL & IPC讲解)

34326751b2c6

前言

Service作为Android四大组件之一,应用非常广泛

本文将介绍Service其中一种常见用法:远程Service

如果你对Service还未了解,建议先阅读我写的另外一篇文章:

Android四大组件:Service史上最全面解析

目录

34326751b2c6

目录

1. 远程服务与本地服务的区别

远程服务与本地服务最大的区别是:远程Service与调用者不在同一个进程里(即远程Service是运行在另外一个进程);而本地服务则是与调用者运行在同一个进程里

二者区别的详细区别如下图:

34326751b2c6

按运行地点分类

2. 使用场景

多个应用程序共享同一个后台服务(远程服务)

即一个远程Service与多个应用程序的组件(四大组件)进行跨进程通信

34326751b2c6

使用场景

3. 具体使用

为了让远程Service与多个应用程序的组件(四大组件)进行跨进程通信(IPC),需要使用AIDL

IPC:Inter-Process Communication,即跨进程通信

AIDL:Android Interface Definition Language,即Android接口定义语言;用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。

在多进程通信中,存在两个进程角色(以最简单的为例):服务器端和客户端

以下是两个进程角色的具体使用步骤:

服务器端(Service)

步骤1:新建定义AIDL文件,并声明该服务需要向客户端提供的接口

步骤2:在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法(onCreat、onBind()、blabla)

步骤3:在AndroidMainfest.xml中注册服务 & 声明为远程服务

客户端(Client)

步骤1:拷贝服务端的AIDL文件到目录下

步骤2:使用Stub.asInterface接口获取服务器的Binder,根据需要调用服务提供的接口方法

步骤3:通过Intent指定服务端的服务名称和所在包,绑定远程Service

接下来,我将用一个具体实例来介绍远程Service的使用

4. 具体实例

实例描述:客户端远程调用服务器端的远程Service

具体使用:

4.1 服务器端(Service)

新建一个服务器端的工程:Service - server

步骤1. 新建一个AIDL文件

34326751b2c6

新建AIDL文件

步骤2. 在新建AIDL文件里定义Service需要与Activity进行通信的内容(方法),并进行编译(Make Project)

// 在新建的AIDL_Service1.aidl里声明需要与Activity进行通信的方法

package scut.carson_ho.demo_service;

interface AIDL_Service1 {

void AIDL_Service();

}

//AIDL中支持以下的数据类型

//1. 基本数据类型

//2. String 和CharSequence

//3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型;

//4. AIDL自动生成的接口(需要导入-import)

//5. 实现android.os.Parcelable 接口的类(需要导入-import)

34326751b2c6

编译

步骤3:在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法(onCreat、onBind()、blabla)

MyService.java

public class MyService extends Service {

// 实例化AIDL的Stub类(Binder的子类)

AIDL_Service1.Stub mBinder = new AIDL_Service1.Stub() {

//重写接口里定义的方法

@Override

public void AIDL_Service() throws RemoteException {

System.out.println("客户端通过AIDL与远程后台成功通信");

}

};

//重写与Service生命周期的相关方法

@Override

public void onCreate() {

super.onCreate();

System.out.println("执行了onCreat()");

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

System.out.println("执行了onStartCommand()");

return super.onStartCommand(intent, flags, startId);

}

@Override

public void onDestroy() {

super.onDestroy();

System.out.println("执行了onDestory()");

}

@Nullable

@Override

public IBinder onBind(Intent intent) {

System.out.println("执行了onBind()");

//在onBind()返回继承自Binder的Stub类型的Binder,非常重要

return mBinder;

}

@Override

public boolean onUnbind(Intent intent) {

System.out.println("执行了onUnbind()");

return super.onUnbind(intent);

}

}

步骤4:在AndroidMainfest.xml中注册服务 & 声明为远程服务

android:name=".MyService"

android:process=":remote" //将本地服务设置成远程服务

android:exported="true" //设置可被其他进程调用

>

//该Service可以响应带有scut.carson_ho.service_server.AIDL_Service1这个action的Intent。

//此处Intent的action必须写成“服务器端包名.aidl文件名”

至此,服务器端(远程Service)已经完成了。

4.2 客户端(Client)

新建一个客户端的工程:Service - Client

步骤1:将服务端的AIDL文件所在的包复制到客户端目录下(Project/app/src/main),并进行编译

注:记得要原封不动地复制!!什么都不要改!

34326751b2c6

复制后的目录

步骤2:在主布局文件定义“绑定服务”的按钮

MainActivity.xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context="scut.carson_ho.service_client.MainActivity">

android:layout_centerInParent="true"

android:id="@+id/bind_service"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="绑定服务"

/>

步骤3:在MainActivity.java里

使用Stub.asInterface接口获取服务器的Binder;

通过Intent指定服务端的服务名称和所在包,进行Service绑定;

根据需要调用服务提供的接口方法。

MainActivity.java

public class MainActivity extends AppCompatActivity {

private Button bindService;

//定义aidl接口变量

private AIDL_Service1 mAIDL_Service;

//创建ServiceConnection的匿名类

private ServiceConnection connection = new ServiceConnection() {

//重写onServiceConnected()方法和onServiceDisconnected()方法

//在Activity与Service建立关联和解除关联的时候调用

@Override

public void onServiceDisconnected(ComponentName name) {

}

//在Activity与Service建立关联时调用

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

//使用AIDLService1.Stub.asInterface()方法获取服务器端返回的IBinder对象

//将IBinder对象传换成了mAIDL_Service接口对象

mAIDL_Service = AIDL_Service1.Stub.asInterface(service);

try {

//通过该对象调用在MyAIDLService.aidl文件中定义的接口方法,从而实现跨进程通信

mAIDL_Service.AIDL_Service();

} catch (RemoteException e) {

e.printStackTrace();

}

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

bindService = (Button) findViewById(R.id.bind_service);

//设置绑定服务的按钮

bindService.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//通过Intent指定服务端的服务名称和所在包,与远程Service进行绑定

//参数与服务器端的action要一致,即"服务器包名.aidl接口文件名"

Intent intent = new Intent("scut.carson_ho.service_server.AIDL_Service1");

//Android5.0后无法只通过隐式Intent绑定远程Service

//需要通过setPackage()方法指定包名

intent.setPackage("scut.carson_ho.service_server");

//绑定服务,传入intent和ServiceConnection对象

bindService(intent, connection, Context.BIND_AUTO_CREATE);

}

});

}

}

4.3 测试结果

34326751b2c6

点击绑定服务按钮

从上面测试结果可以看出:

打印的语句分别运行在不同进程(看语句前面的包名);

客户端调用了服务端Service的方法

即客户端和服务端进行了跨进程通信

4.4 Demo地址

5. 总结

本文对Android组件Service中的远程Service进行了全面介绍

如果你还想了解关于Service的其他知识,请浏览以下文章:

接下来会介绍继续介绍Android开发中的相关知识,感兴趣的同学可以继续关注本人运营的Wechat Public Account:

请点赞!因为你们的赞同/鼓励是我写作的最大动力!

不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。

34326751b2c6

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值