AIDL跨进程通信
AIDL作用
用于生成可以在Android设备上两个进程之间进行进程间通信。
支持的数据类型
1.基本类型:int、char、boolean、double、float、byte、long、string) 但不支持short
2.String、CharSequence.
3.List和Map(注意List和Map里面的数据类型必须是AIDL支持的)
4.序列化的对象(Parcelable)
使用
1.建一个工程,在main创建aidl包,然后创建IMyService.aidl
,Student.aidl
,Student.java
三个文件,三个文件放在同一个文件加下如图:
2.Student.java必须序列化,里面就有一个name
package com.example.cb.test.aidl;import android.os.Parcel;import android.os.Parcelable;public class Student implements Parcelable { public String name; protected Student(Parcel in) { name = in.readString(); } public Student() { } public static final Creator CREATOR = new Creator() { @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.writeString(name); }}
3.student.aidl
// Student.aidl//注意这个地方的包名必须和Student.java的包名一样package com.example.cb.test.aidl;parcelable Student;
4.IMyService.aidl
// IMyService.aidlpackage com.example.cb.test.aidl;import com.example.cb.test.aidl.Student;interface IMyService { List getStudent(); void addStudent(in Student student);}
注意:其他类型必须标识其方向:到底是输入还是输出抑或两者兼之,用in,out或者inout来表示,上面的代码我用in标记,因为它是输入型参数。
5.创建IStudentService.java,在main/java/xxxxx/xxx/下创建就可以不需要和aidl文件在同一目录
package com.example.cb.test.service;import android.app.Service;import android.content.Intent;import android.os.IBinder;import com.example.cb.test.aidl.IMyService;import com.example.cb.test.aidl.Student;import java.util.ArrayList;import java.util.List;import androidx.annotation.Nullable;import cb.xlibrary.utils.XLogUtils;public class IStudentService extends Service { private List mList = new ArrayList<>(); private boolean mCanRun = true; private final IMyService.Stub stub = new IMyService.Stub() { @Override public List getStudent() { synchronized (mList) { return mList; } } @Override public void addStudent(Student student) { synchronized (mList) { if (!mList.contains(student)) { mList.add(student); } } } }; @Override public void onCreate() { super.onCreate(); Thread thread = new Thread(null, new ServiceWork(), "testThread"); thread.start(); synchronized (mList) { for (int i = 1; i < 6; i++) { Student student = new Student(); student.name = "student#" + i; mList.add(student); } } } @Nullable @Override public IBinder onBind(Intent intent) { return stub; } class ServiceWork implements Runnable { long count = 0; @Override public void run() { while (mCanRun) { XLogUtils.d("线程 " + count); count++; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } @Override public void onDestroy() { mCanRun = false; super.onDestroy(); }}
IMyService.Stub stub是个Binder对象,Binder对象在跨进程通信尤其重要,有兴趣的可以去看看点我;只是简单的使用AIDL我们并不需要知道其工作原理。
6.在manifest注册我们写的IStudentService
android:process=":remote"
指定当前service是运行在其他进程中的,具体可以看其他博客
点我;这里service相当于AIDL的服务端。
7.接下来我们写客户端代码,就在这个工程下。
package com.example.cb.test.ui;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.util.Log;import android.view.View;import com.example.cb.test.R;import com.example.cb.test.aidl.IMyService;import com.example.cb.test.aidl.Student;import com.example.cb.test.base.BaseActivity;import com.example.cb.test.service.IStudentService;public class TestActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.start).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intentService = new Intent(TestActivity.this, IStudentService.class); bindService(intentService, mServiceConnection, BIND_AUTO_CREATE); } }); } private IMyService mIMyService; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mIMyService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { //通过服务端onBind方法返回的binder对象得到IMyService的实例,得到实例就可以调用它的方法了 mIMyService = IMyService.Stub.asInterface(service); try { Student student = mIMyService.getStudent().get(0); Log.d("aaa ", student.name); } catch (RemoteException e) { e.printStackTrace(); } } };} @Override protected void onDestroy() { super.onDestroy(); if (mIMyService != null) { unbindService(mServiceConnection); } }
别忘了unbindService()
养成好习惯
8.来看下日志
remote代表另一个进程打印的日志,也就是IStudentService
,到此一个简单的夸进程通信就完了。我也是看了任玉刚的博客跟着敲了一遍就了解了,还是要自己动手敲一遍才能记住任玉刚博客
更多相关文章
- android启动一个应用程序大概流程
- Android中杀死进程的方法
- Android(安卓)Activity 图形化生成简读
- Android之JAVASe基础篇-面向对象-类集(十)
- Android(安卓)Application Addon(插件) 架构及管理
- Android中Application分析
- android eclipse中经常遇到的the connection to adb is down and
- 在Android中创建一种新的输入法(Creating an Input Method))
- android webkit 内核