以下将通过一个案例具体去介绍通过AIDL来实现跨进程进行通信的方式。具备知识点:bindService启动服务,aidl文件类型 数据类型等
<service android:name=".ipc.service.RemoteService" android:process=":remote" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.zxl.service.remote" /> </intent-filter> </service>Activity.java代码
findViewById(R.id.btnEnd).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != mIMusic){ try { mIMusic.stop(); } catch (RemoteException e) { e.printStackTrace(); } } } }); private void startService(){ Intent intent = new Intent(); intent.setAction("com.zxl.service.remote"); // 服务所在包名 intent.setPackage("com.example.mydairytestproject"); mActyServiceConn = new ActyServiceConn(); bindService(intent,mActyServiceConn, Context.BIND_AUTO_CREATE); } private void stopService(){ if (mActyServiceConn != null){ unbindService(mActyServiceConn); mActyServiceConn = null; } } private class ActyServiceConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { mIMusic = IMusic.Stub.asInterface(service); // 设置回调方法的方式,让service回调Activity方法 // 记得注册的是 x.Stub()方法 try { mIMusic.registerStop(new IStopBackAction.Stub() { @Override public void stopCallBack(ProgressData progressData) throws RemoteException { Log.e("返回数据", "stopCallBack: "+progressData.getName() ); if (progressData.getProgress() == 100){ stopService(); ServiceActivity.this.finish(); } } }); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } } @Override protected void onResume() { super.onResume(); Log.e("线程", Thread.currentThread().getId()+""); } @Override protected void onDestroy() { if (mActyServiceConn != null){ stopService(); } super.onDestroy(); }ProgressData实体类
package com.example.mydairytestproject.ipc.IInterface; import android.os.Parcel; import android.os.Parcelable; /** * Created by apple on 2019-10-31. * description: */ public class ProgressData implements Parcelable { private int progress; private String name; public ProgressData(int progress, String name) { this.progress = progress; this.name = name; } public int getProgress() { return progress; } public void setProgress(int progress) { this.progress = progress; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static Creator<ProgressData> getCREATOR() { return CREATOR; } private ProgressData(Parcel in) { progress = in.readInt(); name = in.readString(); } public static final Creator<ProgressData> CREATOR = new Creator<ProgressData>() { @Override public ProgressData createFromParcel(Parcel in) { return new ProgressData(in); } @Override public ProgressData[] newArray(int size) { return new ProgressData[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(progress); dest.writeString(name); } public void readFromParcel(Parcel in) { progress = in.readInt(); name = in.readString(); } } // IMusic.aidl package com.example.mydairytestproject.ipc.IInterface; // Declare any non-default types here with import statements // aidl文件里的变量类型得用parcelable import com.example.mydairytestproject.ipc.IInterface.IStopBackAction; // 方法得实现parcelable interface IMusic { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void play(); void pause(); void stop(); void registerStop(in IStopBackAction iStopBackAction); } // IStopBackAction.aidl package com.example.mydairytestproject.ipc.IInterface; // Declare any non-default types here with import statements import com.example.mydairytestproject.ipc.IInterface.ProgressData; interface IStopBackAction { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void stopCallBack(in ProgressData progressData); } // ProgressData.aidl // 先查创建再修改名字 package com.example.mydairytestproject.ipc.IInterface; // Declare any non-default types here with import statements parcelable ProgressData;Service.java
public class RemoteService extends Service { public RemoteService() { } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e("线程", Thread.currentThread().getId()+""); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return new MusicClass(); } private class MusicClass extends IMusic.Stub { @Override public void play() { Log.e("服务运行", "play: 音乐开启" ); } @Override public void pause() { Log.e("服务运行", "play: 音乐暂停" ); } @Override public void stop() { Log.e("服务运行", "play: 音乐结束" ); // 回调Activity进行传值 if (mIStopBackAction != null){ try { mIStopBackAction.stopCallBack(new ProgressData(100,"数据")); } catch (RemoteException e) { e.printStackTrace(); } } } IStopBackAction mIStopBackAction; @Override public void registerStop(IStopBackAction iStopBackAction) { this.mIStopBackAction = iStopBackAction; } } }in:参数由客户端设置,或者理解成客户端传入参数值。 out:参数由服务端设置,或者理解成由服务端返回值。 inout:客户端输入端都可以设置,或者理解成可以双向通信。
Proxy.pause(): 写入方法参数等,然后调用 transact来发送RPC(远程过程调用)请求,同时当前线程挂起,然后服务端的onTranscat 会根据具体方法的key进行调用进行返回,当前线程继续执行,返回数据。 如果远程方法很耗时,那么不能在UI线程发起远程请求。
1、binder c/s交互有个宏观的认识 但这里面最后一张图讲述的,binder通过共享内存的方法存放数据有问题 Android-彻底地理解Binder