Android(远程服务Service(含AIDL & IPC讲解))

仰天大笑出门去,我辈岂是蓬蒿人。这篇文章主要讲述Android:远程服务Service(含AIDL & IPC讲解)相关的知识,希望能为你提供帮助。
前言

  • Service作为android四大组件之一, 应用非常广泛
  • 本文将介绍Service其中一种常见用法: 远程Service
如果你对Service还未了解, 建议先阅读我写的另外一篇文章:
Android四大组件: Service史上最全面解析
目录
Android(远程服务Service(含AIDL & IPC讲解))

文章图片

1. 远程服务与本地服务的区别
  • 远程服务与本地服务最大的区别是: 远程Service与调用者不在同一个进程里( 即远程Service是运行在另外一个进程) ; 而本地服务则是与调用者运行在同一个进程里
  • 二者区别的详细区别如下图:
Android(远程服务Service(含AIDL & IPC讲解))

文章图片

2. 使用场景 多个应用程序共享同一个后台服务( 远程服务)
即一个远程Service与多个应用程序的组件( 四大组件) 进行跨进程通信
Android(远程服务Service(含AIDL & IPC讲解))

文章图片

3. 具体使用
  • 为了让远程Service与多个应用程序的组件( 四大组件) 进行跨进程通信( IPC) , 需要使用AIDL
  1. IPC: Inter-Process Communication, 即跨进程通信
  2. 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
先下Demo再看, 效果会更好: Github_RemoteService_Server
步骤1. 新建一个AIDL文件
Android(远程服务Service(含AIDL & IPC讲解))

文章图片

步骤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)

Android(远程服务Service(含AIDL & IPC讲解))

文章图片

步骤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中注册服务 & 声明为远程服务
< service android:name= " .MyService" android:process= " :remote" //将本地服务设置成远程服务 android:exported= " true" //设置可被其他进程调用 > //该Service可以响应带有scut.carson_ho.service_server.AIDL_Service1这个action的Intent。 //此处Intent的action必须写成“服务器端包名.aidl文件名” < intent-filter> < action android:name= " scut.carson_ho.service_server.AIDL_Service1" /> < /intent-filter> < /service>

【Android(远程服务Service(含AIDL & IPC讲解))】至此, 服务器端( 远程Service) 已经完成了。
4.2 客户端( Client) 新建一个客户端的工程: Service - Client
先下Demo再看, 效果会更好: Github_RemoteService_Client
步骤1: 将服务端的AIDL文件所在的包复制到客户端目录下( Project/app/src/main) , 并进行编译
注: 记得要原封不动地复制! ! 什么都不要改!
Android(远程服务Service(含AIDL &amp; IPC讲解))

文章图片

步骤2: 在主布局文件定义“绑定服务”的按钮
MainActivity.xml
< ?xml version= " 1.0" encoding= " utf-8" ?> < RelativeLayout 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: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" > < Button android:layout_centerInParent= " true" android:id= " @ + id/bind_service" android:layout_width= " match_parent" android:layout_height= " wrap_content" android:text= " 绑定服务" /> < /RelativeLayout>

步骤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 测试结果
Android(远程服务Service(含AIDL &amp; IPC讲解))

文章图片

从上面测试结果可以看出:
  • 打印的语句分别运行在不同进程( 看语句前面的包名) ;
  • 客户端调用了服务端Service的方法
即客户端和服务端进行了跨进程通信
4.4 Demo地址
  • 客户端: Github_RemoteService_Client
  • 服务端: Github_RemoteService_Server
5. 总结
  • 本文对Android组件Service中的远程Service进行了全面介绍
  • 如果你还想了解关于Service的其他知识, 请浏览以下文章:
Android四大组件: Service史上最全面解析
Android: Service生命周期最全面解析
Android: ( 本地、可通信的、前台、远程) Service使用全面介绍
Android: 远程服务Service( 含AIDL & IPC讲解)
Android多线程全面解析: IntentService用法& 源码
  • 接下来会介绍继续介绍Android开发中的相关知识, 感兴趣的同学可以继续关注carson_ho的微信公众号
    Android(远程服务Service(含AIDL &amp; IPC讲解))

    文章图片

    Android(远程服务Service(含AIDL &amp; IPC讲解))

    文章图片
请帮顶 / 评论点赞! 因为你们的赞同/鼓励是我写作的最大动力!

    推荐阅读