当前位置: 代码迷 >> 综合 >> AIDL 进程间通信的一个小小的总结
  详细解决方案

AIDL 进程间通信的一个小小的总结

热度:66   发布时间:2024-01-21 05:08:51.0

 

需求

  项目需要,将做好的项目作为一个服务提供给另一个公司。我们需要提供一个apk,所以设计到进程间交互,不得不了解一下AIDL了。

 

 

了解一下AIDL

  之前准备面试的时候,或多或少的了解了一点AIDL,不过现在忘记得差不多了。

  所以网上随便找了几篇不错的文章。

  1.进程通信之AIDL的使用。

  2.学习AIDL,这一篇就够了。

 

 

一个简单的demo

  自己搞了一个简单的demo。

  实现了进程间通信,可以传输普通类型和实体类型。

  首先是服务端。

  1.第一个aidl接口。

// IMyAidlInterface.aidl
package com.xf.test1;import com.xf.test1.IAidlCallBack;
import com.xf.test1.Entity;
// Declare any non-default types here with import statementsinterface IMyAidlInterface {/*** 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);String getStr(String str);int getPid();Entity getEntity();Entity setEntity(in Entity entity);void registerCallBack(IAidlCallBack callback);void unregisterCallBack(IAidlCallBack callback);
}
View Code

  2.第二个aidl接口。

// IAidlCallBack.aidl
package com.xf.test1;import com.xf.test1.Entity;// Declare any non-default types here with import statementsinterface IAidlCallBack {void callBack(String name);void callBackEntity(in Entity entity);
}
View Code

  3.第三个aidl接口。

// Person.aidl
package com.xf.test1;parcelable Entity;
View Code

  4.封装的一个IBinder。

package com.xf.test1;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;public class AIDLService extends Service {private AIDLImp mBinder;@Overridepublic void onCreate() {super.onCreate();mBinder = new AIDLImp(this);}@Nullable@Overridepublic IBinder onBind(Intent intent) {return mBinder;}@Overridepublic void onDestroy() {super.onDestroy();mBinder.KillAll();}
}
View Code

  5.AIDL服务。

package com.xf.test1;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;public class AIDLService extends Service {private AIDLImp mBinder;@Overridepublic void onCreate() {super.onCreate();mBinder = new AIDLImp(this);}@Nullable@Overridepublic IBinder onBind(Intent intent) {return mBinder;}@Overridepublic void onDestroy() {super.onDestroy();mBinder.KillAll();}
}
View Code

  6.实体类型。

package com.xf.test1;import android.os.Parcel;
import android.os.Parcelable;/*** Description: 简单实体类** @version V1.0.0* Createdate: 2018/6/22* @author: wja 1211241203@qq.com*/
public class Entity implements Parcelable {private String name;private int parameter1;private double parameter2;public Entity(String name){this.name=name;}public Entity(String name, int parameter1, double parameter2) {this.name = name;this.parameter1 = parameter1;this.parameter2 = parameter2;}public int getParameter1() {return parameter1;}public void setParameter1(int parameter1) {this.parameter1 = parameter1;}public double getParameter2() {return parameter2;}public void setParameter2(double parameter2) {this.parameter2 = parameter2;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(this.name);dest.writeInt(this.parameter1);dest.writeDouble(this.parameter2);}protected Entity(Parcel in) {this.name = in.readString();this.parameter1 = in.readInt();this.parameter2 = in.readDouble();}public static final Creator<Entity> CREATOR = new Creator<Entity>() {@Overridepublic Entity createFromParcel(Parcel source) {return new Entity(source);}@Overridepublic Entity[] newArray(int size) {return new Entity[size];}};@Overridepublic String toString() {return "Entity{" +"name='" + name + '\'' +", parameter1=" + parameter1 +", parameter2=" + parameter2 +'}';}
}
View Code

  7.清单文件。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.xf.test1"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><!--<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /><data android:scheme="com.xf.aidl.test" /></intent-filter>--></activity><service android:name=".AIDLService"><intent-filter><action android:name="com.xf.aidl" /><category android:name="android.intent.category.DEFAULT" /><!--<action android:name="android.intent.action.MAIN" />--><!--<category android:name="android.intent.category.LAUNCHER" />--></intent-filter></service></application></manifest>
View Code

  8.服务端如何运行(不使用启动图标的方式)

   

  然后点击进去

  

  9.最后点击运行,服务就安装在手机啦。

  

  其次,是客户端。

  1.客户端的aidl文件和服务端的完全一样。(当然路径可以不一样,为了方便我直接copy的,路径不一样也是可以的,测试过的)

  2.然后注意实体类型所在的包一定要和服务端的一致,负责找不到这个实体的。

  3.最后是客户端的主页面。

package com.xf.test2;import android.content.ComponentName;
import android.content.Context;
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.util.Log;
import android.view.View;import com.xf.test1.Entity;
import com.xf.test1.IAidlCallBack;
import com.xf.test1.IMyAidlInterface;import java.util.Random;public class MainActivity extends AppCompatActivity {private IMyAidlInterface mIMyAidlInterfaceService;private ServiceConnection mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mIMyAidlInterfaceService = IMyAidlInterface.Stub.asInterface(service);try {mIMyAidlInterfaceService.registerCallBack(mIAidlCallBack);} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {try {mIMyAidlInterfaceService.unregisterCallBack(mIAidlCallBack);} catch (RemoteException e) {e.printStackTrace();}mIMyAidlInterfaceService = null;}};private IAidlCallBack mIAidlCallBack = new IAidlCallBack.Stub() {@Overridepublic void callBack(String name) throws RemoteException {Log.e("info---->","服务端给我发消息啦:"+name);ToastUtil.showShort(MainActivity.this,"服务端给我发消息啦:"+name);}@Overridepublic void callBackEntity(Entity entity) {Log.e("info---->","服务端给我发实体消息啦:"+entity.toString());ToastUtil.showShort(MainActivity.this,"服务端给我发实体消息啦:"+entity.toString());}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Overrideprotected void onDestroy() {super.onDestroy();if (mServiceConnection != null)unbindService(mServiceConnection);}/*** 绑定服务* @param view*/public void doClick(View view) {Intent intent = new Intent();intent.setAction("com.xf.aidl");intent.setPackage("com.xf.test1");bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);}/*** 获取服务器发送过来的消息* @param v*/public void doAction(View v) {if (mIMyAidlInterfaceService != null) {try {String newstr = mIMyAidlInterfaceService.getStr("Hello world");int pid = mIMyAidlInterfaceService.getPid();Log.e("info---->", newstr + " pid:" + pid);} catch (RemoteException e) {e.printStackTrace();}}}/*** 客户端自己设置实体,发送给服务端* 通过随机数设置实体参数* @param v*/public void doActionSetEntity(View v){if (mIMyAidlInterfaceService != null) {try {Random random=new Random();mIMyAidlInterfaceService.setEntity(new Entity("客户端",random.nextInt(100),random.nextDouble()));} catch (RemoteException e) {e.printStackTrace();}}}
}
View Code

    下面是布局文件。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><RelativeLayoutandroid:layout_marginTop="100dp"android:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:layout_width="300dp"android:layout_height="wrap_content"android:onClick="doClick"android:text="绑定服务"android:layout_centerInParent="true"/></RelativeLayout><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:layout_width="300dp"android:layout_height="wrap_content"android:onClick="doAction"android:text="获取消息"android:layout_centerInParent="true"/></RelativeLayout><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:layout_width="300dp"android:layout_height="wrap_content"android:onClick="doActionSetEntity"android:text="客户端设置实体"android:layout_centerInParent="true"/></RelativeLayout></LinearLayout>
View Code

  

  运行效果是这样的:

        

 

   这里客户端首先需要绑定服务

  点击了获取消息:直接获取服务端创建好的实体类。

  点击了客户端设置实体:通过产生随机数,客户端调用aidl接口设置实体。

  如果再次点击获取消息:在服务端进行判断,如果客户端设置过实体,就把该实体发送回客户端。

 

  demo地址:https://github.com/JasonToJan/AIDLDemo

 

 

个人小结

  1.首先要理解aidl是干什么的:进程间交互。不同apk实现通信。

  2.为什么可以做到进程间通信了,谁给两个进程之间搭起了一座桥梁呢?AIDL,其实就是一个接口,实现进程之间对接的功能。

  3.两个进程要做到通信,aidl一定要保证一致,不然就是牛头不对马嘴了。

  4.aidl如何实现数据传输了,binder。所以demo就把binder直接封装起来,基本所有逻辑都在这个封装类中进行即可。

  5.再深入底层,binder是如何实现数据传输的呢?这就涉及到操作系统的知识了,binder处于一个内存共享区域,可以实现进程间通信。

 

转载于:https://www.cnblogs.com/Jason-Jan/p/9214570.html