关于AIDL使用的一些心得
2016-12-19 16:09
513 查看
大家好!首先很感谢大家能阅读我的博客。这是我的第一篇博客,以后还会继续写下去,之前一直都是查阅别人的博客,其实很早以前就有自己写博客的想法,但是由于时间原因,一直没能亲自写。
OK!废话不多说,进入今天的正题,近几天在研究AIDL的用法,之前看过类似的例子,感觉不是特别懂,今天就自己亲自写了一个demo,发现自己写和看别人的代码有很大不同,也遇到了很多很多坑,今天就来分享下自己的感想,并和大家一起共勉。希望自己和大家能早日成为行业大牛,哈哈!
首先,我们要明白的一点是为啥要有AIDL?
对于AIDL有一些人的浅显概念就是,AIDL可以跨进程访问其他应用程序,和其他应用程序通讯,那我告诉你,很多技术都可以访问,如广播(应用A在AndroidManifest.xml中注册指定Action的广播)应用B发送指定Action的广播,A就能收到信息,这样也能看成不同应用之间完成了通讯(但是这种通讯是单向的);还如ContentProvider,通过URI接口暴露数据给其他应用访问;但是这种都算不上是应用之间的通讯。可能最让人迷惑的是Android推出来了Messager,它就是完成应用之间的通讯的。那么为什么还要有AIDL呢,官方文档介绍AIDL中有这么一句话:
?
第一句最重要,“只有当你允许来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL”,其他情况下你都可以选择其他方法,如使用Messager,也能跨进程通讯。可见AIDL是处理多线程、多客户端并发访问的。而Messager是单线程处理。还是官方文档说的明白,一句话就可以理解为什么要有AIDL。那么是不是这样的写个AIDL试试。
那么,具体怎么使用AIDL呢?
首先,我们需要在“服务端”和“客户端”(这里是我这样叫的,你也可以有其他的称呼,总之就是对应两个进程啦)创建两个完全一样的.aidl文件,注意了,是“完全一样的”哦,甚至于这两个aidl文件所在包的包名都要完全一致。创建完成后我们还要在“服务端”创建一个服务类,这个服务类很重要,两个进程之所以能够通信,就靠他了。
然后,我们需要在客户端的MainActivity.java中对.aidl文件进行一些操作了,这一部分我们需要绑定刚才创建的服务。具体代码如下:
上面的代码中需要提醒的一点是:自从Android 5.0以后,Android就不允许隐式启动一个服务了,我们必须显式的启动,我的代码中已经有很详细的解释了。
到这里,AIDL的最基本的使用已经介绍完了,这个Demo做的是一个最简单的两数相加的例子,整个aidl需要的代码并不多:“服务端”的.aidl文件、自定义的Service类、“客户端”的Activity以及与“服务端”完全一样的.aidl文件,当然本demo中还有一些简单的布局文件,在这里就不贴出来了。由于我的github账号出了点问题,暂时不能将代码上传,等日后解决了这个问题会及时把代码上传,各位看官就先将就着看下这个博客吧。后面还会添加自定义类型,即实现Parcelable接口的对象类型的用法。
最后,再次感谢您能看完这篇很不完美的博客,这是我的第一篇博客,我相信以后随着我技术的提升会越写越好。谢谢大家!
OK!废话不多说,进入今天的正题,近几天在研究AIDL的用法,之前看过类似的例子,感觉不是特别懂,今天就自己亲自写了一个demo,发现自己写和看别人的代码有很大不同,也遇到了很多很多坑,今天就来分享下自己的感想,并和大家一起共勉。希望自己和大家能早日成为行业大牛,哈哈!
首先,我们要明白的一点是为啥要有AIDL?
对于AIDL有一些人的浅显概念就是,AIDL可以跨进程访问其他应用程序,和其他应用程序通讯,那我告诉你,很多技术都可以访问,如广播(应用A在AndroidManifest.xml中注册指定Action的广播)应用B发送指定Action的广播,A就能收到信息,这样也能看成不同应用之间完成了通讯(但是这种通讯是单向的);还如ContentProvider,通过URI接口暴露数据给其他应用访问;但是这种都算不上是应用之间的通讯。可能最让人迷惑的是Android推出来了Messager,它就是完成应用之间的通讯的。那么为什么还要有AIDL呢,官方文档介绍AIDL中有这么一句话:
?
那么,具体怎么使用AIDL呢?
首先,我们需要在“服务端”和“客户端”(这里是我这样叫的,你也可以有其他的称呼,总之就是对应两个进程啦)创建两个完全一样的.aidl文件,注意了,是“完全一样的”哦,甚至于这两个aidl文件所在包的包名都要完全一致。创建完成后我们还要在“服务端”创建一个服务类,这个服务类很重要,两个进程之所以能够通信,就靠他了。
package com.example.aidldemo; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import java.util.ArrayList; import java.util.List; public class AIDLService extends Service{ private ArrayList<Person> list; @Override public IBinder onBind(Intent intent){ return mBuilder; } MyAidl.Stub mBuilder = new MyAidl.Stub(){ @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException{ } @Override public int add(int num1, int num2) throws RemoteException{ return num1 + num2; } }; }有人可能会有疑问了,MyAidl.Stub是从哪里来的呢?没错,它是从我们刚刚创建的.aidl文件经过IDE编译后自动生成的,具体路径在
然后,我们需要在客户端的MainActivity.java中对.aidl文件进行一些操作了,这一部分我们需要绑定刚才创建的服务。具体代码如下:
package com.example.aidldemo; 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.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.TextView; import java.util.List; public class MainActivity extends AppCompatActivity{ private MyAidl client; private EditText mEt_num1; private EditText mEt_num2; private TextView mSum; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindViews(); bindService(); testDemo1(); } private void testDemo1(){ findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view){ /** * 下面这两句话放外面会导致NumberFormatException,放里面就不会 * 原因是在代码执行时,当我们什么内容都没有输入时相当于输入了空字符串, * 但是空字符串无法转换成int型,就导致了此异常的发生。 * 注意了:代码是从上至下依次执行 */ final int num1 = Integer.parseInt(mEt_num1.getText().toString()); final int num2 = Integer.parseInt(mEt_num2.getText().toString()); try{ int sumNum = client.add(num1,num2); mSum.setText(sumNum+""); }catch(RemoteException e){ e.printStackTrace(); } } }); } private void bindService(){ Intent intent = new Intent(); /** * 从Android5.0以后就不支持隐式启动service了,需要使用以下的方式显示启动 */ intent.setComponent(new ComponentName("com.example.aidldemo", "com.example.aidldemo.AIDLService")); bindService(intent, conn, BIND_AUTO_CREATE); } ServiceConnection conn = new ServiceConnection(){ @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder){ //将aidl中的stub类当做借口来处理 client = MyAidl.Stub.asInterface(iBinder); } @Override public void onServiceDisconnected(ComponentName componentName){ } }; private void bindViews(){ mEt_num1 = (EditText)findViewById(R.id.et_num1); mEt_num2 = (EditText)findViewById(R.id.et_num2); mSum = (TextView)findViewById(R.id.sum); } @Override protected void onDestroy(){ super.onDestroy(); unbindService(conn); } }
上面的代码中需要提醒的一点是:自从Android 5.0以后,Android就不允许隐式启动一个服务了,我们必须显式的启动,我的代码中已经有很详细的解释了。
到这里,AIDL的最基本的使用已经介绍完了,这个Demo做的是一个最简单的两数相加的例子,整个aidl需要的代码并不多:“服务端”的.aidl文件、自定义的Service类、“客户端”的Activity以及与“服务端”完全一样的.aidl文件,当然本demo中还有一些简单的布局文件,在这里就不贴出来了。由于我的github账号出了点问题,暂时不能将代码上传,等日后解决了这个问题会及时把代码上传,各位看官就先将就着看下这个博客吧。后面还会添加自定义类型,即实现Parcelable接口的对象类型的用法。
最后,再次感谢您能看完这篇很不完美的博客,这是我的第一篇博客,我相信以后随着我技术的提升会越写越好。谢谢大家!
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析