Android Service AIDL的学习,传递对象
2017-03-24 18:49
411 查看
Android Service的学习,AIDL传递对象
Service有两种:1,本地服务(Local Service):用于应用程序内部
2,远程服务(Remote Service):用于android系统内部的应用程序之间 。
使用区别:
本地服务:主要是平时做一些耗时,或者要长时间运行,影响UI线程的时候到到。如,播放音乐,下载等。
远程服务:则用于多应用之间的相互访问。比如做个天气预报的,做个健康数据的。
一开始我们学习使用Service可能会是因为播放多音乐的时候,用户启动了其他Activity这个时候程序要在后台继续播放。我们把MediaPlayer在Local Service里。然后通过bindService()在ServiceConnection里通过IBinder返回一个Service的实例。通过Service实例去操作MediaPlayer的开始和停止等等。例如这样:
Intent intent = new Intent(mContext, TestService.class); mContext.bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mTestService = ((TestService.MyBinder) service).getService(); } @Override public void onServiceDisconnected(ComponentName name) { mTestService = null; } };
当某天用到远程Service的时候,上面这种方式报错了。
将一个普通的Service转换成远程Service其实非常简单,只需要在注册Service的时候将它的android:process属性指定成:remote就可以了。当然这个remote是自定义的。
为什么这里用个“:”呢?
如果被设置的进程名是以一个冒号开头的,则这个新的进程对于这个应用来说是私有的,当它被需要或者这个服务需要在新进程中运行的时候,这个新进程将会被创建。如果这个进程的名字是以小写字符开头的,则这个服务将运行在一个以这个名字命名的全局的进程中,当然前提是它有相应的权限。这将允许在不同应用中的各种组件可以共享一个进程,从而减少资源的占用。
当一个Service被设置为Remote Service时候我们又怎么通信呢?
我们再复习下线程通信与进程通信
线程通信:
- 1)共享变量(内存)
- 2)管道
- 3)handle机制 平时熟悉的runOnUiThread,view.post(Runnable)都是Handle机制
进程通信:
- 1)bind机制(IPC->AIDL)
- 2)Content Provider
- 3)Broadcast
- 4)Intent (有没试过用Intent打开别的应用。。)
这篇文章主要学习AIDL,AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。关于AIDL是怎么实现跨进程通信的,网上不少资料,关心的小伙伴可以自己查阅。强大的Android Studio为开发者省了很大的工夫。
第一步:创建AIDL:右键New-选择AIDL,输入你的接口名如IMyAidlInterface,点击Finish。
IDE会在src->main目录下新建一个aidl目录与java同级的。
第二步:自定义方法
interface IMyAidlInterface { void addStudent(inout Student student); void showTip(String tip); }
第三步:Rebuild Project
在项目的 build/generated/source/aidl/debug/包名/下能找到IDE帮你生成的接口
第四步:在Service里返回一个IMyAidlInterface.Sub
“`
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
private class MyBinder extends IMyAidlInterface.Stub{
@Override
public void add(Student student) throws RemoteException {
} }
第五步:在BindService()
private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mIMyAidlInterface = null; } };
“`
通过上边的五步我们就拿到了一个IMyAidlInterface实例。这时候可能欢呼了。
当你通过这个接口传一个对象过去的时候,崩了!!!!
查看资料发现AIDL默认支持的数据类型包括:
Java中的八种基本数据类型,包括 byte,short,int,long,float,double,boolean,char。
String 类型。
CharSequence类型。
List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable(下文关于这个会有详解)。List可以使用泛型。
Map类型:Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。Map是不支持泛型的。
AIDL传送对象
由于Aidl只支持Java基本类型数据传递,因此是不能直接传递一个复杂类型对象的,所以为了解决这个问题,Android提供了一套机制—-将需要传递的对象序列化,然后在反序列化。
序列化:把Java对象转换为字节序列的过程。
反序列化:把字节序列恢复为Java对象的过程。
第一步:创建一个Student类 implements Parcelable。按提示添加所有方法。(鼠标移动类名ALT+Enter–>add Parcelable implementation)
public class Student implements Parcelable { int id; String name; public Student(int id, String name) { this.id = id; this.name = name; } protected Student(Parcel in) { id = in.readInt(); name = in.readString(); } public static final Creator<Student> CREATOR = new Creator<Student>() { @Override public Student createFromParcel(Parcel in) { return new Student(in); } @Override public Student[] newArray(int size) { return new Student[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id); dest.writeString(name); } public void readFromParcel(Parcel source) { id = source.readInt(); name = source.readString(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "id=" + id + ", name=" + name + '}'; } }
第二步:在AIDL目录下里和你类放的路径一样的地方创建一个Student.AIDL
package com.example.yang.testaidl; parcelable Student; //parcelable 要小写,网上说的,我也不明真相。
注意目录一定要相同
例如,你在java/包名/beans/下创建的Student 你在aidl/包名/下再创建一个beans文件夹再这个beans下创建Student.aidl。要不然之前定义的IMyAidlInterface引用Student会报错。。。。
第三步:在IMyAidlInterface里加上
import com.example.yang.testaidl.Student;
interface IMyAidlInterface { void addStudent(inout Student student); void showTip(String tip); }
这里传对象用的是in/out/inout
Parcelable 还有这个方法是隐式的要自己写上来。这样就实现out了
public void readFromParcel(Parcel source) {
id = source.readInt();
name = source.readString();
}
好了。到了这里基本学习完毕。边学边写,有不足之处望批评指正。附Demo
https://github.com/YangKee/TestAIDL.git
相关文章推荐
- android之Service介绍之三 AIDL与传递对象
- android之Service介绍之三 AIDL与传递对象
- android之Service介绍之三 AIDL与传递对象
- android之Service介绍之三 AIDL与传递对象
- Android--Service之AIDL传递复杂对象
- 学习笔记-Android AIDL传递对象数据
- android之Service介绍之三 AIDL与传递对象
- Android--Service之AIDL传递复杂对象
- Android--Service之AIDL传递复杂对象
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- 一个简单的demo学习Android远程Service(AIDL的使用)
- Android学习札记11:利用Parcelable在Activity之间传递对象参数的官方解释和示例
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- Android Service学习之AIDL, Parcelable和远程服务
- 一个简单的demo学习Android远程Service(AIDL的使用)
- Android Service学习之AIDL, Parcelable和远程服务
- Android 将activity中的对象传递到service中
- Android Service学习之AIDL, Parcelable和远程服务