AIDL跨进程通信和Service调用
16lz
2021-01-24
AIDL的作用
1.aidl 是Android interface definition Language 的英文缩写,意思Android 接口定义语言。
2.使用aidl 可以帮助我们发布以及调用远程服务,实现跨进程通信。
在Android中, 每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,Java中是不支持跨进程内存共享的。因此要传递对象, 需要把对象解析成操作系统能够理解的数据格式, 以达到跨界对象访问目的。
3.将服务的aidl 放到对应的src 目录,工程的gen 目录会生成相应的接口类。
在JavaEE中,采用RMI通过序列化传递对象。在Android中, 则采用AIDL方式实现。 AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。AIDL的IPC 机制和EJB所采用的CORBA很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应 的对象。
由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员 来说是透明的。
AIDL中的数据类型
- 除了short以外的7种基本数据类型
- String和CharSequence
- List和Map,在使用这2种集合时,必须声明为in、out或inout
- Parcelable类型
在AIDL中使用自定义数据类型
- 在自定义数据类型Music中实现Parcelable接口
- 创建自定义数据类型的aidl文件,例如Music.aidl,内容例如:
package xx.xx.xx.xx;
parcelable Music;
以上代码中,package语句保持与Music.java完全相同 - 在使用了该类型的AIDL接口文件中,使用import语句显式的导包,即使是同包的也必须导包
- 将Music.java、Music.aidl及使用了Music类型的AIDL接口文件全部复制并粘贴到客户端
1.[S]创建WorkService类,继承自android.app.Service,并注册,且注册时,为节点配置子级,使得该Service是可以被隐式激活的
<service android:name="cn.tedu.aidl_server.WorkService" > <intent-filter> <action android:name="tedu.intent.action.WORK_SERVICE"/> <category android:name="android.intent.category.DEFAULT"/> intent-filter> service>
- [S]使用AIDL语法创建IMusicPlayer接口,并在接口中定义那些由Service去实现功能,却由Activity调用的方法,例如:
– void playMusic()
– void pauseMusic()
– boolean isPlaying()
//服务端IMusicPlayer.aidlpackage cn.tedu.aidl_server;import cn.tedu.aidl_server.Music;interface IMusicPlayer { void play(); void pause(); boolean isPlaying(); Music getMusic();}
3.[S][WorkService] 定义内部类InnerBinder,继IMusicPlayer .Stub,并重写抽象方法
4.[S][WorkService] 在onBind()方法中,创建InnerBinder的对象,并作为该方法的返回值
package cn.tedu.aidl_server;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class WorkService extends Service { @Override public IBinder onBind(Intent intent) { InnerBinder binder = new InnerBinder(); return binder; } private class InnerBinder extends IMusicPlayer.Stub { @Override public void play() throws RemoteException { Log.i("tedu", "[Server] WorkService$InnerBinder.play()"); } @Override public void pause() throws RemoteException { Log.i("tedu", "[Server] WorkService$InnerBinder.pause()"); } @Override public boolean isPlaying() throws RemoteException { boolean result = true; Log.i("tedu", "[Server] WorkService$InnerBinder.isPlaying() -> " + result); return result; } @Override public Music getMusic() throws RemoteException { Music music = new Music(); music.artist = "张学友"; music.title = "雪狼湖"; music.duration = 9527; Log.i("tedu", "[Server] WorkService$InnerBinder.getMusic() -> " + music); return music; } }}
- [C][MainActivity] 定义内部类InnerServiceConnection,实现androi.content.ServiceConnection,并添加实现2个抽象方法
- [C][MainActivity] 当需要绑定Service时,调用bindService()方法,第1个参数是Intent对象,用于隐式指定被激活的Service组件,第2个参数是InnerServiceConnection的对象,且该对象必须声明为全局变量,便于后续解绑,第3个参数是Context.BIND_AUTO_CREATE常量
- [C][MainActivity] 声明全局变量IMusicPlayer player,在InnerServiceConnection类的onServiceConnected()方法中,调用IMusicPlayer.Stub.asInterface()方法,将第2个参数IBinder service作为asInterface()方法的参数,返回值赋值给player
package cn.tedu.aidl_client;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.view.View;import android.widget.Toast;import cn.tedu.aidl_server.IMusicPlayer;import cn.tedu.aidl_server.Music;public class MainActivity extends Activity implements View.OnClickListener { private View btnBindService; private View btnCallPlay; private View btnCallPause; private View btnCallIsPlaying; private View btnCallGetMusic; private ServiceConnection conn; private IMusicPlayer player; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnBindService = findViewById(R.id.btn_bind_service); btnCallPlay = findViewById(R.id.btn_call_play); btnCallPause = findViewById(R.id.btn_call_pause); btnCallIsPlaying = findViewById(R.id.btn_call_is_playing); btnCallGetMusic = findViewById(R.id.btn_call_get_music); btnBindService.setOnClickListener(this); btnCallPlay.setOnClickListener(this); btnCallPause.setOnClickListener(this); btnCallIsPlaying.setOnClickListener(this); btnCallGetMusic.setOnClickListener(this); } @Override protected void onDestroy() { unbindService(conn); super.onDestroy(); } private class InnerServiceConnection implements ServiceConnection { @Override public void onServiceConnected( ComponentName name, IBinder service) { player = IMusicPlayer.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_bind_service: Intent service = new Intent(); service.setAction("tedu.intent.action.WORK_SERVICE"); conn = new InnerServiceConnection(); int flags = BIND_AUTO_CREATE; bindService(service, conn, flags); break; case R.id.btn_call_play: if (player == null) { Toast.makeText(this, "请先绑定Service!!!", Toast.LENGTH_SHORT).show(); } else { try { player.play(); Toast.makeText(this, "调用成功!", Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } break; case R.id.btn_call_pause: if (player == null) { Toast.makeText(this, "请先绑定Service!!!", Toast.LENGTH_SHORT).show(); } else { try { player.pause(); Toast.makeText(this, "调用成功!", Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } break; case R.id.btn_call_is_playing: if (player == null) { Toast.makeText(this, "请先绑定Service!!!", Toast.LENGTH_SHORT).show(); } else { try { boolean result = player.isPlaying(); Toast.makeText(this, "调用成功! -> " + result, Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } break; case R.id.btn_call_get_music: if (player == null) { Toast.makeText(this, "请先绑定Service!!!", Toast.LENGTH_SHORT).show(); } else { try { Music music = player.getMusic(); Toast.makeText(this, "调用成功! -> " + music, Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } break; } }}
源码下载地址:http://download.csdn.net/download/luzhiweistudy/9693197
lypeer 原码分析:http://www.jianshu.com/p/0cca211df63c
更多相关文章
- 剖析 Android(安卓)架构组件之 ViewModel
- Android(安卓)ContentProvider 使用
- Android(安卓)TV框架TIF
- 属性动画
- android中setNegativeButton和setNeutralButton的区别是什么?
- Android(安卓)Material Design之Snackbar
- Android(安卓)ANR介绍与避免
- Android核心分析 ----- Android电话系统之RIL-Java
- Android(安卓)Touch事件分发机制