需求

  项目需要,将做好的项目作为一个服务提供给另一个公司。我们需要提供一个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 statements interface 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);
}

  2.第二个aidl接口。

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

  3.第三个aidl接口。

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

  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; @Override
public void onCreate() {
super.onCreate();
mBinder = new AIDLImp(this);
} @Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
} @Override
public void onDestroy() {
super.onDestroy();
mBinder.KillAll();
}
}

  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; @Override
public void onCreate() {
super.onCreate();
mBinder = new AIDLImp(this);
} @Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
} @Override
public void onDestroy() {
super.onDestroy();
mBinder.KillAll();
}
}

  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;
} @Override
public int describeContents() {
return 0;
} @Override
public 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>() {
@Override
public Entity createFromParcel(Parcel source) {
return new Entity(source);
} @Override
public Entity[] newArray(int size) {
return new Entity[size];
}
}; @Override
public String toString() {
return "Entity{" +
"name='" + name + '\'' +
", parameter1=" + parameter1 +
", parameter2=" + parameter2 +
'}';
}
}

  7.清单文件。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xf.test1"> <application
android: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>

  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() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIMyAidlInterfaceService = IMyAidlInterface.Stub.asInterface(service);
try {
mIMyAidlInterfaceService.registerCallBack(mIAidlCallBack);
} catch (RemoteException e) {
e.printStackTrace();
}
} @Override
public void onServiceDisconnected(ComponentName name) {
try {
mIMyAidlInterfaceService.unregisterCallBack(mIAidlCallBack);
} catch (RemoteException e) {
e.printStackTrace();
}
mIMyAidlInterfaceService = null;
}
}; private IAidlCallBack mIAidlCallBack = new IAidlCallBack.Stub() {
@Override
public void callBack(String name) throws RemoteException {
Log.e("info---->","服务端给我发消息啦:"+name);
ToastUtil.showShort(MainActivity.this,"服务端给我发消息啦:"+name);
} @Override
public void callBackEntity(Entity entity) {
Log.e("info---->","服务端给我发实体消息啦:"+entity.toString());
ToastUtil.showShort(MainActivity.this,"服务端给我发实体消息啦:"+entity.toString());
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} @Override
protected 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();
}
}
}
}

    下面是布局文件。

<?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"> <RelativeLayout
android:layout_marginTop="100dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"> <Button
android:layout_width="300dp"
android:layout_height="wrap_content"
android:onClick="doClick"
android:text="绑定服务"
android:layout_centerInParent="true"
/> </RelativeLayout> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"> <Button
android:layout_width="300dp"
android:layout_height="wrap_content"
android:onClick="doAction"
android:text="获取消息"
android:layout_centerInParent="true"
/> </RelativeLayout> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"> <Button
android:layout_width="300dp"
android:layout_height="wrap_content"
android:onClick="doActionSetEntity"
android:text="客户端设置实体"
android:layout_centerInParent="true"
/> </RelativeLayout> </LinearLayout>

  

  运行效果是这样的:

        

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

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

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

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

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

个人小结

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

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

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

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

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

AIDL 进程间通信的一个小小的总结的更多相关文章

  1. android aidl 进程间通信需要注意的地方(android.os.TransactionTooLargeException)

    转自:http://blog.sina.com.cn/s/blog_4e1e357d0102wau9.html 1.bus工程实现通过service实现aidl实体类 2.actor工程通过发起bin ...

  2. android中的AIDL进程间通信

    关于IPC应该不用多介绍了,Android系统中的进程之间不能共享内存,那么如果两个不同的应用程序之间需要通讯怎么办呢?比如公司的一个项目要更新,产品的需求是依附于当前项目开发一个插件,但是呢这个插件 ...

  3. Linux 进程间通信(包含一个经典的生产者消费者实例代码)

    前言:编写多进程程序时,有时不可避免的需要在多个进程之间传递数据,我们知道,进程的用户的地址空间是独立,父进程中对数据的修改并不会反映到子进程中,但内核是共享的,大多数进程间通信方式都是在内核中建立一 ...

  4. 无监控不运维——使用 Python 写一个小小的项目监控

    在公司里做的一个接口系统,主要是对接第三方的系统接口,所以,这个系统里会和很多其他公司的项目交互.随之而来一个很蛋疼的问题,这么多公司的接口,不同公司接口的稳定性差别很大,访问量大的时候,有的不怎么行 ...

  5. 基于Node.js实现一个小小的爬虫

    以前一直听说有爬虫这种东西,稍微看了看资料,貌似不是太复杂. 正好了解过node.js,那就基于它来个简单的爬虫. 1.本次爬虫目标: 从拉钩招聘网站中找出“前端开发”这一类岗位的信息,并作相应页面分 ...

  6. hibernate中HQL练习时候一个小小的错误导致语法异常

    package cn.db.po.test; import java.util.List; import cn.db.po.User; import cn.db.po.biz.UserBiz; pub ...

  7. springmvc restful配置有一个小小的坑坑

    首先web.xml配置 <!-- spring-mvc --> <servlet> <servlet-name>springServlet</servlet- ...

  8. [置顶] android AIDL 进程间通信

    1.定义aidl文件 a.ITestService.aidl package com.open.aidl.service; import com.open.aidl.service.ITestServ ...

  9. 46 【golang项目】完成了一个小小的播放器功能

    项目地址:https://github.com/helww/mylab/tree/master/go/player 这个项目中用到了readme说明文件是一个markdown文件. 基础的控制语法,网 ...

随机推荐

  1. windows10 如何关闭快速关机功能电源选项

    点击右下角的电池 -> power and sleep setting -> choose what the power buttons do -> change settings ...

  2. Hibernate、Mybatis与Spring Data JPA

    从零开始集成Springboot+MyBatis+JPA https://www.jianshu.com/p/e14c4a6f6871 MyBatis 与Hibernate的区别 http://xhr ...

  3. 使用Swagger处理Api的显示与隐藏

    一.在SwaggerConfig.cs中配置如下: c.DocumentFilter<ShowApiFilter>(); c.DocumentFilter<HideApiFilter ...

  4. nefu 628 Garden visiting

    //yy:想到昨天一个神题整了几个小时,最后按题解把p拆了用孙子定理..今天这个简单,把C暴力拆了.. 题目链接:nefu 628 Garden visiting 1 <= n, m, p &l ...

  5. Linux 统计文件夹,文件数量的命令

    用的最多的就是: ls -l | grep "^-" | wc -l ls -l 普通文件就是以 - 开头,文件夹以 d 开头 grep 后面接正则表达式:^- 以 - 开头的匹配 ...

  6. 【[USACO09DEC]牛收费路径Cow Toll Paths】

    很妙的一道题,我之前一直是用一个非常暴力的做法 就是枚举点权跑堆优化dijkstra 但是询问次数太多了 于是一直只有50分 今天终于抄做了这道题,不贴代码了,只说一下对这道题的理解 首先点权和边权不 ...

  7. mac 系统安装selenium注意事项

    mac最新系统:OS X EI Captian python: 本机自带的python2.7. (本来想升级3.5,觉得太复杂,放弃了) pip: https://pypi.python.org/py ...

  8. 【luogu P2491 [SDOI2011]消防】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2491 题外话: OI一共只有三种题--会的题,不会的题,二分题. 题解: step 1 求树的直径,把树的直 ...

  9. 图形解析理解 css3 之倾斜属性skew()

    1.作用 改变元素在页面中的形状2.语法 属性:transform 函数: 1.skew(xdeg) 向横向倾斜指定度数 x取值为正,X轴不动,y轴逆时针倾斜一定角度 x取值为负,X轴不动,y轴顺时针 ...

  10. Oracle中转义下划线

    原意是查询出所有的月粒度模型,但是在oracle中,下划线也代表匹配单一任何字符,导致15分钟粒度的模型也被查询出来,在此,需要对下划线做转义,使其只表示下划线的含义,可以使用ESCAPE()函数. ...