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中的数据类型

  1. 除了short以外的7种基本数据类型
  2. String和CharSequence
  3. List和Map,在使用这2种集合时,必须声明为in、out或inout
  4. Parcelable类型

在AIDL中使用自定义数据类型

  1. 在自定义数据类型Music中实现Parcelable接口
  2. 创建自定义数据类型的aidl文件,例如Music.aidl,内容例如:
    package xx.xx.xx.xx;
    parcelable Music;
    以上代码中,package语句保持与Music.java完全相同
  3. 在使用了该类型的AIDL接口文件中,使用import语句显式的导包,即使是同包的也必须导包
  4. 将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>
  1. [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;        }    }}
  1. [C][MainActivity] 定义内部类InnerServiceConnection,实现androi.content.ServiceConnection,并添加实现2个抽象方法
  2. [C][MainActivity] 当需要绑定Service时,调用bindService()方法,第1个参数是Intent对象,用于隐式指定被激活的Service组件,第2个参数是InnerServiceConnection的对象,且该对象必须声明为全局变量,便于后续解绑,第3个参数是Context.BIND_AUTO_CREATE常量
  3. [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

更多相关文章

  1. 剖析 Android(安卓)架构组件之 ViewModel
  2. Android(安卓)ContentProvider 使用
  3. Android(安卓)TV框架TIF
  4. 属性动画
  5. android中setNegativeButton和setNeutralButton的区别是什么?
  6. Android(安卓)Material Design之Snackbar
  7. Android(安卓)ANR介绍与避免
  8. Android核心分析 ----- Android电话系统之RIL-Java
  9. Android(安卓)Touch事件分发机制

随机推荐

  1. 0802-演绎php遍历数组与js遍历数组的区别
  2. 简单的选显卡和懒加载
  3. php第一天---变量
  4. 0803作业
  5. 原生轮播图
  6. 学习笔记:php.ini的开发配置
  7. 【前端 · 面试 】HTTP 总结(三)—— HTTP
  8. PHP循环实例与js循环实例
  9. 实例演绎php遍历数组与js遍历数组的区别
  10. 8月2日作业