AIDL——Android接口定义语言初步探索
来源:互联网 发布:csgo脚本优化 编辑:程序博客网 时间:2024/06/06 17:47
前言
这几天项目不是特别的忙,想在Android技术方面寻求突破,就在网上搜索AIDL是什么,也看了几篇关于AIDL的博客,现在想把自己对AIDL的理解记录下来。
AIDL(Android Interface Definition Language)即Android接口定义语言,主要作用于跨进程通信;对于在Android里的应用,在应用层,简单点就是一款APP能够使用另一款APP提供的服务(service),通过传递参数,或者调用方法来完成需求。
接下来说一下怎么使用AIDL(AS开发工具):
服务器端
- 数据对象——这个对象包含了我们需要用到的数据信息
在java目录下新建一个InfoBean.java文件,声明两个变量name和age,添加set和get方法,该类要实现Parcelable接口。
public class InfoBean implements Parcelable { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "InfoBean{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.name); dest.writeInt(this.age); } public void readFromParcel(Parcel dest){//该方法自己需要手动添加 name=dest.readString(); age=dest.readInt(); } public InfoBean() { } protected InfoBean(Parcel in) { this.name = in.readString(); this.age = in.readInt(); } public static final Creator<InfoBean> CREATOR = new Creator<InfoBean>() { @Override public InfoBean createFromParcel(Parcel source) { return new InfoBean(source); } @Override public InfoBean[] newArray(int size) { return new InfoBean[size]; } };}
这里推荐使用Android Parcelable code generator 插件自动完成Parcelable 的实现。
插件安装完成后需要重启AS才能生效。使用插件:
把光标停在需要实现Parcelable的类上,按Alt+Insert,选择Parcelable,在弹窗里把所有的全部选中,ok
完成一系列操作后还需要手写readFromParcel方法,因为数据双向通信,readFromParcel方法和writeToParcel方法相似,一个是读数据,一个是写数据,照着写就可以了,顺序要一样。
- 新建AIDL文件
在main目录下新建aidl文件夹,在aidl文件夹中新建一个包,包名与上面数据对象InfoBean.java的包名要一样,在包下新建两个aidl文件,InfoBean.aidl和InfoManager.aidl
InfoBean.aidl引入InfoBean对象为其他aidl文件使用
// Info.aidl//这个文件的作用是引入了一个序列化对象 InfoBean 供其他的AIDL文件使用//注意:InfoBean.aidl与InfoBean.java的包名应当是一样的package com.aidl.server;parcelable InfoBean;
InfoManager.aidl文件声明要实现的几个方法
package com.aidl.server;// Declare any non-default types here with import statementsimport com.aidl.server.InfoBean;//引入定义的aidl文件,使用序列化对象,interface InfoManager { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ //下面定义几个接口要实现的方法 void addInfo(in InfoBean info); InfoBean getInfo(in int i); List<InfoBean> getAllInfo(); void changeInfo(in InfoBean inInfo,out InfoBean outInfo,inout InfoBean inoutInfo);}
定义的方法参数前面的in、out、inout是什么意思
它们表示数据流向,在AIDL语言规则中,java数据基本类型和String 都默认是in并且只能是in,非基本类型数据需要指定数据流向:
in:表示服务端接收从客户端传过来的数据,当在服务端改变参数时,客户端对象变量不变。
out:表示服务端不会接收客户端传过来的数据对象,服务端会新建一个数据对象,回传给客户端,同时改变客户端参数的值。
inout:表示服务端接收客户端传过来的对象,改变属性后,客户端对象的属性同样改变。
Rebuild 工程会在app\build\generated\source\aidl\debug\com\aidl\server目录下自动生成InfoManager.java文件,点开可以看一下具体是怎么写的,这里不做解释
- 服务service
前期准备工作做好了,可以开始写服务代码了,新建一个类继承Service
public class AIDLService extends Service { List<InfoBean> Infos=new ArrayList<InfoBean>(); private final InfoManager.Stub mInfoManager=new InfoManager.Stub(){//通过InfoManager.Stub新建一个对象,实现自己定义的几个方法,共其他进程调用 @Override public void addInfo(InfoBean info) throws RemoteException { if(Infos==null){ Infos=new ArrayList<InfoBean>(); } if(info==null)return; Infos.add(info); Log.e("ServerAdd",Infos.toString()); } @Override public InfoBean getInfo(int i) throws RemoteException { if(Infos==null){ Log.e("ServerGetInfo","Info is null"); return null; } if(i>=Infos.size()){ Log.e("ServerGetInfo","下标越界"); return null; } return Infos.get(i); } @Override public List<InfoBean> getAllInfo() throws RemoteException { if(Infos==null){ Log.e("ServerGetInfo","Info is null"); return null; } return Infos; } @Override public void changeInfo(InfoBean inInfo, InfoBean outInfo, InfoBean inoutInfo) throws RemoteException { inInfo.setAge(100); outInfo.setAge(100); inoutInfo.setAge(100); Log.e("ServerinInfo",inInfo.toString()); Log.e("ServeroutInfo",outInfo.toString()); Log.e("ServerinoutInfo",inoutInfo.toString()); } } ; @Override public void onCreate() { super.onCreate(); InfoBean info=new InfoBean(); info.setAge(25); info.setName("JY"); Infos.add(info); } @Nullable @Override public IBinder onBind(Intent intent) {//通过bindService启动服务,获得对象。 return mInfoManager; }}
最后在AndroidManifest.xml中声明服务
<service android:name=".AIDLService" android:exported="true"> <intent-filter> <action android:name="com.aidl.server"> </action> <category android:name="android.intent.category.DEFAULT"></category> </intent-filter> </service>
添加action以便外界启动服务
- 客户端代码
首先,把数据对象和aidl文件移植到客户端项目,注意数据对象和aidl文件的包名要和服务端的包名一样
Rebuild 工程后就可以声明一个InfoManager对象,对象的赋值通过启动service返回的IBuild构建
mInfoManager=InfoManager.Stub.asInterface(service);
client代码
public class MainActivity extends AppCompatActivity { private boolean isServerStart=false; private InfoManager mInfoManager; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn=(Button)findViewById(R.id.button); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { sendMessage(); } catch (RemoteException e) { e.printStackTrace(); } } }); } private void sendMessage() throws RemoteException { if(!isServerStart){ BindService(); return; } InfoBean info=new InfoBean(); info.setAge(50); info.setName("张三"); mInfoManager.addInfo(info); List<InfoBean> infos=mInfoManager.getAllInfo(); Log.e("ClientGetAllInfo",infos.toString()); InfoBean bean=mInfoManager.getInfo(0); Log.e("ClientGetInfo",bean.toString()); InfoBean info1=new InfoBean(); info1.setAge(10); info1.setName("李四"); InfoBean info2=new InfoBean(); info2.setAge(20); info2.setName("王五"); mInfoManager.changeInfo(info,info1,info2); Log.e("ClientTagin",info.toString()); Log.e("ClientTagout",info1.toString()); Log.e("ClientTaginout",info2.toString()); } @Override protected void onStart() { super.onStart(); if(!isServerStart){ BindService(); } } @Override protected void onStop() { super.onStop(); if(isServerStart){ unbindService(mServiceConnection); } } private void BindService() { Intent intent = new Intent(); intent.setAction("com.aidl.server");//servcie action intent.setPackage("com.aidl.server");//服务端app包名 bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e("Client","Server连接成功"); mInfoManager=InfoManager.Stub.asInterface(service); isServerStart=true; } @Override public void onServiceDisconnected(ComponentName name) { Log.e("Client","Server断开连接"); isServerStart=false; } };}
最后运行结果:
- 服务端
- 客户端
到这里AIDL的初步探索就结束了,原理什么的都不太懂,用的时候应该就是这样吧,可以根据项目的需求做出改进。
参考
有不对的地方,请大神指证!!!
- AIDL——Android接口定义语言初步探索
- AIDL android接口定义语言
- Android接口定义语言(AIDL)
- Android接口定义语言(AIDL)
- Android AIDL接口定义语言
- aidl(android 接口定义语言)
- Android 接口定义语言 (AIDL)
- Android -- Android 接口定义语言 (AIDL)
- Android 接口定义语言(AIDL)
- Android的接口定义语言(aidl)
- 1、android散记-AIDL接口定义语言
- Android接口定义语言---AIDL(一)
- Android接口定义语言---AIDL(二)
- Android接口定义语言---AIDL(三)
- Android接口定义语言---AIDL(四)
- Android 接口定义语言AIDL使用解说
- AIDL——Android接口描述语言
- AIDL(AndroidInterfaceDefinitionLanguage:接口定义语言)
- Spark SQL与Hive On MapReduce速度比较
- mysql命令行怎么清屏
- LR无法打开浏览器
- 应用全屏状态栏透明
- CentOS 7 内核升级
- AIDL——Android接口定义语言初步探索
- 云计算的三种服务模式(SaaS、PaaS、IaaS)的区别
- 工作后,你悟出什么职场道理?
- PCB布线学习
- 接入 iOS 10.3「应用内评分」新特性
- 需求分析之性能需求
- vue2.0+vue-router2.0+axios+webpack开发webapp项目(一)
- Maven(一)下载与环境变量配置
- C++调用C中的函数