andriod 提供的进程间通信方式为AIDL,其中实现的原理就不说了。现在我们有两个进程A进程和B进程,A进程可以提供数据,而B进程获取数据。
A进程(发送) -> B进程 (获取)
A进程提供数据
整个A进程,如果我们想要给其他进程提供数据的化,我们就需要三个角色才能完成。
IWorkAidl.aidl - 文件,说一个接口,定义能提供的方法 (当编译的时候,该文件的序列化等操作,都说系统自动生成的)
WorkAidl.class - 此类需要继承aidl文件,实现aidl文件中声明的方法
WorkAidlService.class - 继承Service的服务类,在oBind()方法中返回WorkAidl的实体;这个服务开着,其他进程就可以通过这个服务获取Binder对象。
B进程获取数据
通过绑定服务的方式,获取发送进程的binder对象,然后调用其中的方法。
第一步:创建一个aidl文件(这个包名很重要,当B进程也创建aidl文件的时候,也必须是这个包名)
在com.malei.demo包下,我们来创建对外提供服务的aidl文件,MyIWorkAidl.aidl文件
interface MyIWorkAidl { String getName(); void setName(String name); }
以上就创建了一个aidl文件,可以看到这是一个接口类,当我们编译的时候,我们发现他会自动的创建一个java文件接口类,继承了
android.os.IInterface类,同时内部也提供类一个名字叫Stub的内部类,这个内部类继承了Binder,同时实现了MyIWorkAidl接口。
同时这个内部类Stub是一个抽象的方法,其中接口的方法并没有实现,而是让继承的子类去实现。
第二步:创建Stub的子类
/** * Created by malei on 2018/6/22. */ public class MyWorkAidl extends MyIWorkAidl.Stub { private String name; @Override public String getName() throws RemoteException { return name; } @Override public void setName(String name) throws RemoteException { this.name = name; } }
第三步:创建一个服务,提供其他进程一个binder对象。
/** * Created by malei on 2018/6/22. */ public class MyWorkAidlService extends Service{ private MyIWorkAidl.Stub stub = new MyWorkAidl(); @Nullable @Override public IBinder onBind(Intent intent) { return stub; } }
创建的服务还需要在注册文件中进行注册处理,如下:
<service android:name=".aidl.MyWorkAidlService" > <intent-filter > <action android:name="forServiceAidl" > </action> </intent-filter> </service>
第四步:启动该aidl的服务
我们在oncreate()中通过绑定服务的方式启动该服务,然后将值赋值到binder中,如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); bindService(new Intent("forServiceAidl"), conn, Service.BIND_AUTO_CREATE); setContentView(R.layout.activity_main); } private ServiceConnection conn = new ServiceConnection() { // 断开连接时调用 @Override public void onServiceDisconnected(ComponentName arg0) { } // 连接时调用 @Override public void onServiceConnected(ComponentName arg0, IBinder binder) { mMyAIDL = MyIWorkAidl.Stub.asInterface(binder); if (mMyAIDL != null) { try { mMyAIDL.setName("Service AIDL"); Toast.makeText(MainActivity.this, "赋值成功!", Toast.LENGTH_LONG).show(); } catch (RemoteException e) { e.printStackTrace(); Toast.makeText(MainActivity.this, "赋值失败!", Toast.LENGTH_LONG).show(); } } } };
这样a进程要做的事情就都完成了
第五步:B进程获取数据,先创建一个aidl文件(这个包名要和A进程的aidl包名相同才行):
interface MyIWorkAidl { String getName(); void setName(String name); }
然后通过绑定服务的方式获取A进程的binder对象。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService(new Intent("forServiceAidl"), conn, Service.BIND_AUTO_CREATE); this.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(mMyWorkAidl != null){ try { //RPC方法调用 String name = mMyWorkAidl.getName(); Toast.makeText(MainActivity.this, "远程进程调用成功!值为 : "+name, Toast.LENGTH_LONG).show(); } catch (RemoteException e) { e.printStackTrace(); Toast.makeText(MainActivity.this, "远程进程调用失败! ", Toast.LENGTH_LONG).show(); } } } }); } private MyIWorkAidl mMyWorkAidl; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName arg0) { Toast.makeText(MainActivity.this, "远程进程调用失败! ", Toast.LENGTH_LONG).show(); } //因为有可能有多个应用同时进行RPC操作,所以同步该方法 @Override public synchronized void onServiceConnected(ComponentName arg0, IBinder binder) { //获得IPerson接口 Toast.makeText(MainActivity.this, "远程进程调用成功! ", Toast.LENGTH_LONG).show(); mMyWorkAidl = MyIWorkAidl.Stub.asInterface(binder); } };