Android AIDL实例
16lz
2021-01-23
AIDL(Android 接口定义语言),可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。 在 Android 上,一个进程通常无法访问另一个进程的内存。 尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。 编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理。 接下来会新建两个Android Project,client和service通过AIDL进行通信。 首先新建service端project MyAidlService,我们首先创建一个aidl文件,android studio已经提供了新建aidl文件,可以直接生成对应的Binder类。提供可调用的方法,假设我们以下有三个方法:
// ISchool.aidlpackage com.example.aidldemo.myaidlservice;// Declare any non-default types here with import statementsimport com.example.aidldemo.myaidlservice.Student;interface ISchool { String getSchoolName(); int getStudentNum(); Student getStudent();}
String、int是java的原始数据类型,可以直接引用,但Student是引用数据类型,我们必须自己定义。想通过AIDL传递Student类,必须定义一个Student类的aidl文件:
// Student.aidlpackage com.example.aidldemo.myaidlservice;parcelable Student;
这里直接写parcelable加类名。
这样aidl文件已经生成。
接下来新建我们将要传递的Student类并实现Parcelable接口,确保Student通过IPC通道另一端可用,必须实现Parcelable接口。
public class Student implements Parcelable { public String name; public 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 "Student{" + "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 Student() { } protected Student(Parcel in) { this.name = in.readString(); this.age = in.readInt(); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public Student createFromParcel(Parcel source) { return new Student(source); } @Override public Student[] newArray(int size) { return new Student[size]; } };}
rebuild project,生成aidl文件可链接的类,供其它类引用。
新建service文件,在service文件中新建内部类继承ISchool.Stub,实现三个方法,并通过onBind方法返回:
public class MyService extends Service { private MySchoolBinder mySchoolBinder; public MyService() { } @Override public IBinder onBind(Intent intent) { return mySchoolBinder; } @Override public void onCreate() { super.onCreate(); mySchoolBinder = new MySchoolBinder(); } private class MySchoolBinder extends ISchool.Stub { @Override public String getSchoolName() throws RemoteException { return "第一高级中学"; } @Override public int getStudentNum() throws RemoteException { return 3000; } @Override public Student getStudent() throws RemoteException { Student student = new Student(); student.setName("xiaohong"); student.setAge(18); return student; } }}
最后在AndroidManifest.xml文件中为service添加action
<service android:name=".MyService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.aidldemo.myaidlservice.school" /> intent-filter> service>
这样service端的代码就结束了,运行到真机。
下面是client代码,新建工程MyAidlClient,将MyAidlService工程中的aidl目录整体copy到MyAidlClient工程的main目录下,同时将Student.java类也copy到aidl目录下。
在build.gradle中android{}下添加代码:
sourceSets { main { java.srcDirs = ['src/main/java', 'src/main/aidl'] } }
这样设置会到aidl目录下找java文件,也就是Student.java文件。
最后是MainActivity文件:
package com.example.aidldemo.myaidlclient;import android.app.Service;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.view.View;import android.widget.TextView;import com.example.aidldemo.myaidlservice.ISchool;public class MainActivity extends AppCompatActivity { private ISchool iSchool; private Intent intent; private TextView schoolText; private boolean isBind = false; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iSchool = ISchool.Stub.asInterface(service); isBind = true; } @Override public void onServiceDisconnected(ComponentName name) { isBind = false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); schoolText = (TextView) findViewById(R.id.tv_school); intent = new Intent(); intent.setAction("com.example.aidldemo.myaidlservice.school"); intent.setPackage("com.example.aidldemo.myaidlservice"); bind(); } private void bind() { bindService(intent, connection, Service.BIND_AUTO_CREATE); } public void getSchool(View view) { try { if (!isBind) { bind(); } schoolText.setText("schoolName:" + iSchool.getSchoolName() + "schoolNum:" + iSchool.getStudentNum() + " student:" + iSchool.getStudent()); } catch (RemoteException e) { e.printStackTrace(); } }}
初始化绑定service,拿到ISchool对象就可以取到我们service端设置的值了。运行结果:
github MyAidlService
github MyAidlClient
csdn aidlDemo.zip
更多相关文章
- Android多语言支持以及各国语言Values文件夹命名规则
- Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流
- android之播放多媒体文件一(播放音频)
- Android下修改hosts文件-重启有效
- android进程间服务通信示例
- Android——文件路径(/mnt/sdcard/...)、Uri(content://media/ex