远程服务Service & AIDL & IPC

网友投稿 605 2022-05-30

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

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

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

远程服务与本地服务不同点在于,它是运行在独立进程中,常常向多个应用提供服务。

那么其他应用应该如何与远程服务通信呢?在Android中提供了AIDL的机制进行IPC进程间通信。

创建远程服务Service

远程服务Service,要通过以下步骤建立起来:

步骤1:定义AIDL文件,并声明提供服务的接口

// IMyAidlInterface.aidl package com.ti.remoteservice; // Declare any non-default types here with import statements interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); // AIDL中支持以下的数据类型 // 1. 基本数据类型 // 2. String 和CharSequence // 3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型; // 4. AIDL自动生成的接口(需要导入-import) // 5. 实现android.os.Parcelable 接口的类(需要导入-import) void aidlService(); }

1

2

3

4

5

6

7

8

远程服务Service & AIDL & IPC

9

10

11

12

13

14

15

16

17

18

19

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

package com.ti.remoteservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class RemoteService extends Service { // 实例化AIDL的Stub类(Binder的子类) IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public void aidlService() throws RemoteException { Log.d("远程服务##", "客户端通过AIDL与远程后台成功通信"); } }; public RemoteService() { } // 重写接口里定义的方法 @Override public void onCreate() { super.onCreate(); Log.d("远程服务##", "onCeate创建服务"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("远程服务##", "onStartCommand运行服务"); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { Log.d("远程服务##", "onBind绑定服务"); // 在onBind()返回继承自Binder的Stub类型的Binder,非常重要 return mBinder; } @Override public boolean onUnbind(Intent intent) { Log.d("远程服务##", "onUnbind解绑服务"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.d("远程服务##", "onDestroy销毁服务"); super.onDestroy(); } }

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

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

... android:process=":remote"> ...

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

至此,远程服务Service就已经完成了。

远程服务demo已上传至Github,欢迎下载学习。

要使用该远程服务的应用要做的事

步骤1:原封不动地(包名要有服务端的一样)复制远程服务Service端的AIDL文件到本应用对应的目录下。(如果复制的AIDL文件所在的包路径与服务端的不一样,运行程序时就会崩溃)

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

// 定义aidl接口变量 private IMyAidlInterface 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 = IMyAidlInterface.Stub.asInterface(service); try { // 通过该对象调用在MyAIDLService.aidl文件中定义的接口方法,从而实现跨进程通信 mAIDL_Service.aidlService(); } catch (RemoteException e) { e.printStackTrace(); } } };

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

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

// 通过Intent指定服务端的服务名称和所在包,与远程Service进行绑定 // 参数与服务器端的action要一致,即"服务器包名.aidl接口文件名" Intent intent = new Intent("com.ti.remoteservice.IMyAidlInterface"); // Android5.0后无法只通过隐式Intent绑定远程Service // 需要通过setPackage()方法指定包名 intent.setPackage("com.ti.remoteservice"); // 绑定服务,传入intent和ServiceConnection对象 bindService(intent, connection, Context.BIND_AUTO_CREATE);

1

2

3

4

5

6

7

8

客户端demo已上传至Github,欢迎下载学习。

谢谢阅读。

任务调度

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:华三vlan配置和 trunk实验配置
下一篇:2022CANN训练营新手应用开发课学习笔记
相关文章