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.aidl
package 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;
}
}
}
源码下载地址:
lypeer 原码分析:http://www.jianshu.com/p/0cca211df63c