Android IPC进程间通信详解最新AndroidStudio的AIDL *** 作)

Android IPC进程间通信详解最新AndroidStudio的AIDL *** 作),第1张

概述前言前面梳理了Android的线程间的通信《Thread、Handler和HandlerThread关系何在?》,这些都是在同一个进程中,那进程间的通信,或者说不同的应用间的通信该如何实现呢?这个时候就要用到AIDL(AndroidInterfaceDe

前言

前面梳理了AndroID的线程间的通信《Thread、Handler和HandlerThread关系何在?》 ,这些都是在同一个进程中,那进程间的通信,或者说不同的应用间的通信该如何实现呢?这个时候就要用到AIDL(AndroID Interface DeFinition LanguageAndroID接口定义语言 )。

使用方法(AndroIDStudio)

我发现现在AIDL的教程基本上还是eclipse的,但是在AndroIDStudio里面使用AIDL还是有一些不同的,来看看怎么用,首先新建一个工程当做server服务端:

创建好后在任意文件夹右键New-->AIDL-->AIDL file,编辑文件名后会自动在src/main目录下面新建aIDl文件夹,包的目录结构如下:

main
aIDl
com.example.tee.testapplication.aIDl
java
com.example.tee.testapplication
res
AndroIDManifest.xml

自动生成的aIDl文件如下:

// AIDlinterface.aIDlpackage com.example.tee.testapplication.aIDl;// Declare any non-default types here with import statementsinterface AIDlinterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ voID basicTypes(int anInt,long aLong,boolean aBoolean,float afloat,double aDouble,String aString);}

我们可以看到aIDl文件的代码格式跟java很像,支持java的基础类型以及List、Map等,如果是@R_419_6942@类的话需要手动导入,我们后面再说,先来最简单的,新建一个 IMyAIDlinterface.aIDl文件,修改如下:

package com.example.tee.testapplication.aIDl;interface IMyAIDlinterface { String getValue();}

在接口中定义一个getValue方法,返回一个字符串,现在可以编译一下工程,找到app/build/generated/source/aIDl/deBUG目录,在我们应用包名下会发现生成了一个Interface类,名字跟我们定义的aIDl的文件名字一样,这说明其实aIDl文件在最后还是会转换成接口来实现,而且这个文件不需要我们维护,在编译后自动生成。

然后新建一个类继承Service:

public class MAIDLService extends Service{ public class MAIDLServiceImpl extends IMyAIDlinterface.Stub{ @OverrIDe public String getValue() throws remoteexception { return "get value"; } } @Nullable @OverrIDe public IBinder onBind(Intent intent) { return new MAIDLServiceImpl(); }}

在MAIDLService类中定义一个内部类继承IMyAIDlinterface.Stub,并且重写我们在aIDl也就是在接口中定义的getValue方法,返回字符串get value。

到了这里,我们就新建好了这个服务端,作用是在调用后返回一个字符串,最后在AndroIDManifest文件中声明:

<service androID:name=".MAIDLService" androID:process=":remote"//加上这句的话客户端调用会创建一个新的进程 androID:exported="true"//默认就为true,可去掉,声明是否可以远程调用 > <intent-filter> <category androID:name="androID.intent.category.DEFAulT" /> <action androID:name="com.example.tee.testapplication.aIDl.IMyAIDlinterface" /> </intent-filter></service>

androID:process=":remote"这一行的作用是声明是否调用时新建进程,接下来写客户端代码,新建一个工程,将刚才创建的aIDl文件拷贝到这个工程中,注意同样也是要放在aIDl文件夹下,然后在MainActivity中编写代码如下:

public class MainActivity extends AppCompatActivity { private TextVIEw mValueTV; private IMyAIDlinterface mAIDlinterface = null; private ServiceConnection mServiceConnection = new ServiceConnection() { @OverrIDe public voID onServiceConnected(Componentname name,IBinder service) { mAIDlinterface = IMyAIDlinterface.Stub.asInterface(service); } @OverrIDe public voID onServicedisconnected(Componentname name) { } }; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { Intent intent = new Intent("com.example.tee.testapplication.aIDl.IMyAIDlinterface"); bindService(intent,mServiceConnection,BIND_auto_CREATE); mValueTV = (TextVIEw) findVIEwByID(R.ID.tv_test_value); mValueTV.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { try {  mValueTV.setText(mAIDlinterface.getValue()); } catch (remoteexception e) {  e.printstacktrace(); } } }); } @OverrIDe protected voID onDestroy() { if(mAIDlinterface != null){ unbindService(mServiceConnection); } super.onDestroy(); }}

注意这里新建Intent的传入的参数字符串是在manifest里面@R_419_6942@的action标签,并且在onDestroy记得取消绑定服务。

执行结果就是我们在点击TextVIEw时会显示服务端给我们返回的get value字符串

@R_419_6942@的对象

刚才我们使用的是基础类型String,在使用我们自己定义的类的时候用上面的方法是不行的,用我们@R_419_6942@的类需要手动导入,修改刚才我们创建的作为服务端的工程

首先在开始生成的aIDl包下(所有aIDl相关的文件都要放在这个包下)新建Student.java

public class Student implements Parcelable{ public String name; public int age; protected Student(Parcel in) { readFromParcel(in); } public Student() { } 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(age); dest.writeString(name); } public voID readFromParcel(Parcel in){ age = in.readInt(); name = in.readString(); } @OverrIDe public String toString() { return String.format(Locale.ENGliSH,"STUDENT[%s:%d]",name,age); }}

需要实现Parcelable序列化接口,AndroIDStudio会自动生成静态内部类CREATOR和describeContents方法,这些部分我们都不需要修改,用自动生成的就好。然后重写writetoParcel方法,@R_419_6942@readFromParcel方法,注意这两个方法里面的属性顺序必须一致,一个是写入,一个是读取。在构造方法Student(Parcel in)中调用readFromParcel(in)方法。

接下来新建Student.aIDl文件(也是在aIDl包中):

// Student.aIDlpackage com.example.tee.testapplication.aIDl;// Declare any non-default types here with import statementsparcelable Student;

注意这里Student前面的关键字parcelable首字母是小写哦,再修改IMyAIDlinterface.aIDl文件如下:

// IMyAIDlinterface.aIDlpackage com.example.tee.testapplication.aIDl;// Declare any non-default types here with import statementsimport com.example.tee.testapplication.aIDl.Student;interface IMyAIDlinterface { Student getStudent(); voID setStudent(in Student student); String getValue();}

定义了两个方法,一个是设置Student,一个是获取Student,在setStudent这个方法注意参数在类型前面有个in关键字,在aIDl里参数分为in输入,out输出

现在在MAIDLService.java中重写新加的两个方法:

private Student mStudent;public class MAIDLServiceImpl extends IMyAIDlinterface.Stub{ @OverrIDe public Student getStudent() throws remoteexception { return mStudent; } @OverrIDe public voID setStudent(Student student) throws remoteexception { mStudent = student; } @OverrIDe public String getValue() throws remoteexception { return "get value : " + Thread.currentThread().getname() + Thread.currentThread().getID(); }}

服务端代码修改完毕,来到客户端工程,同样要把刚才的aIDl包下的文件拷贝覆盖过来,保持两边一致,然后在MainActivity.java中修改如下:

mValueTV = (TextVIEw) findVIEwByID(R.ID.tv_test_value);mStudentTV = (TextVIEw) findVIEwByID(R.ID.tv_test_student);mValueTV.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { try { mValueTV.setText(mAIDlinterface.getValue()); } catch (remoteexception e) { e.printstacktrace(); } }});mStudentTV.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { try { Student student = new Student(); student.age = 10; student.name = "Tom"; mAIDlinterface.setStudent(student); mStudentTV.setText(mAIDlinterface.getStudent().toString()); } catch (remoteexception e) { e.printstacktrace(); } }});

现在编译工程,会发现工程会报错,找不到类Student,我们需要在app目录下的build.gradle文件添加代码如下:

androID { sourceSets { main { manifest.srcfile 'src/main/AndroIDManifest.xml' java.srcDirs = ['src/main/java','src/main/aIDl'] resources.srcDirs = ['src/main/java','src/main/aIDl'] aIDl.srcDirs = ['src/main/aIDl'] res.srcDirs = ['src/main/res'] assets.srcDirs = ['src/main/assets'] } }}

也就是指定一下文件目录,现在再编译就没有问题了

总结

AndroID的IPC使用起来还是挺简单的,AIDL文件的语法也跟我们平时使用接口的时候很相似,但是它只支持基础类型,只能引用AIDL文件,需要使用@R_419_6942@类的时候要稍微麻烦一点。

以上就是对AndroID IPC 进程通信的资料整理,后续继续补充相关资料谢谢大家对本站的支持!

总结

以上是内存溢出为你收集整理的Android IPC进程间通信详解最新AndroidStudio的AIDL *** 作)全部内容,希望文章能够帮你解决Android IPC进程间通信详解最新AndroidStudio的AIDL *** 作)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1148132.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存