Android:远程服务Service(含AIDL & IPC讲解)
来源:互联网 发布:iphone电池不耐用 知乎 编辑:程序博客网 时间:2024/06/05 19:45
版权声明:本文为博主原创文章,未经博主允许不得转载,更多文章请继续关注Carson_Ho的博客!
目录(?)[+]
- 前言
- 目录
- 远程服务与本地服务的区别
- 使用场景
- 具体使用
- 具体实例
- 1 服务器端Service
- 2 客户端Client
- 3 测试结果
- 4 Demo地址
- 总结
- 请点赞因为你们的赞同鼓励是我写作的最大动力
- 欢迎关注Carson_Ho的简书
前言
- Service作为Android四大组件之一,应用非常广泛
- 本文将介绍Service其中一种常见用法:远程Service
如果你对Service还未了解,建议先阅读我写的另外一篇文章:
Android四大组件:Service史上最全面解析
目录
1. 远程服务与本地服务的区别
- 远程服务与本地服务最大的区别是:远程Service与调用者不在同一个进程里(即远程Service是运行在另外一个进程);而本地服务则是与调用者运行在同一个进程里
- 二者区别的详细区别如下图:
2. 使用场景
多个应用程序共享同一个后台服务(远程服务)
即一个远程Service与多个应用程序的组件(四大组件)进行跨进程通信
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
先下Demo再看,效果会更好:Github_RemoteService_Server
步骤1. 新建一个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)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
步骤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); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
步骤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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
至此,服务器端(远程Service)已经完成了。
4.2 客户端(Client)
新建一个客户端的工程:Service - Client
先下Demo再看,效果会更好:Github_RemoteService_Client
步骤1:将服务端的AIDL文件所在的包复制到客户端目录下(Project/app/src/main),并进行编译
注:记得要原封不动地复制!!什么都不要改!
步骤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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
步骤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); } }); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
4.3 测试结果
从上面测试结果可以看出:
- 打印的语句分别运行在不同进程(看语句前面的包名);
- 客户端调用了服务端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开发:最全面、最易懂的Android屏幕适配解决方案
Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)
Android开发:顶部Tab导航栏实现(TabLayout+ViewPager+Fragment)
Android开发:底部Tab菜单栏实现(FragmentTabHost+ViewPager)
Android开发:JSON简介及最全面解析方法!
Android开发:XML简介及DOM、SAX、PULL解析对比
欢迎关注Carson_Ho的简书!
不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。
- Android:远程服务Service(含AIDL & IPC讲解)
- Android:远程服务Service(含AIDL & IPC讲解)
- Android服务Service详解(作用,生命周期,AIDL)系列文章--远程服务AIDL&IPC
- Android中的服务(service)--AIDL远程服务
- Service (aidl远程服务)
- android绑定Service(含IPC)
- Android开发之AIDL实现远程服务进程通信(IPC)
- Android AIDL 远程service
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Vim插件之investigate.vim
- [置顶] 你不知道的 Android WebView 使用漏洞
- 322. Coin Change(unsolved)
- C#----串口数据接收发送
- jeesite开发平台初学-业务表配置及基本认识
- Android:远程服务Service(含AIDL & IPC讲解)
- RecyclerView 使用中的几个问题
- 简单的猜数字小游戏
- Spark图计算GraphX介绍及实例
- 每日一题 No.15 兔子繁殖问题(斐波那契数列)
- 安装无GPU的caffe教程
- Vim插件之open-browser
- 局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍
- Android:SQLiteOpenHelper类(SQLlite数据库操作)详细解析