使用AIDL来进行跨进程通信

绑定服务调用服务里方法的过程

整个Activty绑定Service并调用其中方法的过程可以体现为下面的一张图,其中的核心是通过借助中间人IBinder来达到调用Service中方法的目的。。

接下来在明确一下调用过程的代码步骤:①首先服务里有一个方法需要被调用②定义一个中间人对象(继承Bidner类的内部类MyBinder)③在onBind方法中把我们自己定义的中间人返回MyBinder④在Activity里面调用bindService()方法,获取我们的中间人对象⑤间接利用中间人对象调用服务里面的方法。音乐盒小案例

既然我们已经清楚了,在Activity如何调用Service中的方法,那么就练习一下吧。

在我们日常中,都使用过音乐APP,它们都可以在后台中继续播放音乐,那么我们也模仿一下,当然其中的播放、暂停、继续播放功能都用Log来代替。

另外,在之前的代码中,在ServiceConnection的onServiceConnected()方法中,每次都是把参数service,向下转型为Service内部的MyBinder对象,这样灵活性又不高、耦合性又强,所以采用接口的方式进行解耦。

整体而言还是非常简单的,我们来看下代码。

为了更方便的调用服务里的方法,我们抽取了一个接口:

{();();();}

在Service的内部,有着play、pause、replay等三个内部方法,创建一个私有的内部类,继承Binder并实现IService,然后在onBind()方法中,返回此对象。

{@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}() {System.out.println(“播放音乐”);}() {System.out.println(“暂停播放”);}() {System.out.println(“继续播放音乐”);}{() {// 调用服务内部的方法play();}() {pause();}() {replay();}}}

在MainActivity中也是比较简单,我们直接在onCreate()开启服务并绑定服务,并通过按钮调用的相应IServiec接口中的方法。

{private ServiceConnection conn;private IService iService;(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent service = new Intent(this, MusicService.class);// 启动服务startService(service);// 绑定服务conn = new MyServiceConnection();bindService(service, conn, Context.BIND_AUTO_CREATE);}(View v) {iService.callPlay();}(View v) {iService.callPause();}(View v) {iService.callReplay();}{(ComponentName name, IBinder service) {iService = (IService) service;}(ComponentName name) {}}}

测试结果如下:

看到这里你可能就有疑问了,与之前没有什么太大的区别呀,唯一的区别就是使用了IService接口解除了Activity和Service通信的耦合。

不错,这就是关键点。这里要说明一个概念,远程服务和本地服务的区别。

在Android中,远程服务就是运行在其他应用(进程)里面的服务 ,而本地服务就是运行在自己应用(进程)里面的服务。它们都是运行在同一个手机里。

这就涉及到了IPC进程间通信了,Google已经为我们提供了解决进程间通信的方法,叫做AIDL,而其中就是使用类似IService的接口来达到目的的。更为详细的在下面讲述。

利用服务注册特殊广播接收者

是时候把服务和广播结合起来了,这样功能才会更强大。而就广播而言,这里用到了动态注册广播的方法,说白了就是通过代码注册一个广播。

我们可以使用registerReceiver()方法动态注册一个广播;另一个方面,,什么才叫做特殊的广播接受者呢?一般来说,像电池电量低,屏幕锁屏等使用频率非常高的称为特殊广播接受者,它们只能够使用代码的方式进行注册。

那为什么这些广播需要在服务中进行动态注册呢? 试想一下,我们在普通应用中直接注册一个屏幕锁屏的广播接收者,当这个应用开启时肯定可以接收到屏幕锁屏的广播事件的。但是,当应用程序退出后,应用变成空进程,也就接收不到广播了。而在服务中动态注册屏幕锁屏事件,只要我们的Service不死,那么便一直可以接收到广播。

接下来就做一个在服务中动态注册锁屏广播事件的小案例。

还是先从界面开始,两个按钮,并在MainActivity中实现了对应的点击方法。

对应的代码也很简单:

(View v) {Intent service = new Intent(this, ScreenService.class);startService(service);}(View v) {Intent service = new Intent(this, ScreenService.class);stopService(service);}

接下来写一个接收广播的类,既然我们打算在服务中动态进行注册,那么便不需要再清单文件中声明了。

{(Context context, Intent intent) {String action = intent.getAction();if (“android.intent.action.SCREEN_OFF”.equals(action)) {System.out.println(“接收到锁屏广播”);}else if (“android.intent.action.SCREEN_ON”.equals(action)) {System.out.println(“接收到解锁广播”);}}}

接下来创建一个服务,并在服务中动态注册广播接收者。

{private BroadcastReceiver receiver;@Overridepublic IBinder onBind(Intent intent) {return null;}() {super.onCreate();// 接收广播的对象receiver = new ScreenReceiver();// 意图过滤器,添加关心的动作IntentFilter filter = new IntentFilter();filter.addAction(“android.intent.action.SCREEN_OFF”);filter.addAction(“android.intent.action.SCREEN_ON”);// 注册广播registerReceiver(receiver, filter);System.out.println(“注册了屏幕锁屏的广播接收者”);}() {super.onDestroy();// 解除注册unregisterReceiver(receiver);System.out.println(“反注册了屏幕锁屏的广播接收者”);}}

至此,整个小案例的操作就完毕了。看一下测试图:

使用AIDL来进行跨进程通信

在上面我们已经说过远程服务和本地服务的区别,那么如何才能让Activity与一个远程Service建立关联呢?这就要使用AIDL来进行跨进程通信了(IPC – Inter Process Communication 进程间通信)。

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

说话可能太苍白,还是用一个示例来演示吧。我们平常都玩过手机斗地主,当我们买欢乐豆是,可能会用到支付宝的服务。

那么我们就用买欢乐豆使用支付宝支付,来作为我们的小案例吧。

既然是远程服务,也就是不同进程间通信,我们需要创建两个Android工程,一个工程名叫支付宝,另一个叫斗地主。支付宝是服务端,我们先从服务端开始。

这里的风景美不胜收,真让人流连忘返。

使用AIDL来进行跨进程通信

相关文章:

你感兴趣的文章:

标签云: