需求

  项目需要,将做好的项目作为一个服务提供给另一个公司。我们需要提供一个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. February 6 2017 Week 6 Monday

    There are no shortcuts to any place worth going. 任何值得去的地方,都没有捷径. Several years ago, I climbed the Hu ...

  2. Java基础之二维数组的回顾

    class ArrayWork { /* * 二维数组的复习! * * 2014年4月2日 21:45:50 * * * **/ public static void main(String[] ar ...

  3. 哈哈,原来IOC容器的bean是存在DefaultSingletonBeanRegistry的一个Map类型的属性当中。

    经过查看源代码发现IOC容器中的bean实例(不知道是不是所有的bean)是存储在一个DefaultSingletonBeanRegistry类实例的一个Map类型的属性当中. 下面是DefaultS ...

  4. js获取昨天今天和明天

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/UP19910522/article/details/30028299 <html> &l ...

  5. Mybatis 和Spring整合之原始dao开发

    F:\Aziliao\mybatis\代码\31.mybatis与spring整合-开发原始dao 1.1. SqlMapConfig.xml <?xml version="1.0&q ...

  6. building for production...Killed

    npm run build报错 building for production...Killed 原理 按照他人的说法是,服务器内存不够用了,这样就给他配置一个单独的内存出来就解决了 解决方法 sud ...

  7. MVC学习八:MVC View提交数据

    学习编程最主要的就是数据交互,MVC中数据交互是怎么样的呢? 1.Controller向View传输数据在http://www.cnblogs.com/WarBlog/p/7127574.html中有 ...

  8. EF Core 2.0中Transaction事务会对DbContext底层创建和关闭数据库连接的行为有所影响

    数据库 我们先在SQL Server数据库中建立一个Book表: CREATE TABLE [dbo].[Book]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Cr ...

  9. Winodws SNMP服务安装和配置(Windows 2003 & 2008 R2)

    简单网络管理协议SNMP服务起着代理的作用,它会收集可以向SNMP管理站或控制台报告的信息.您可以使用SNMP服务来收集数据,并且在整个公司网络范围内管理基于Windows Server 2003.M ...

  10. Oracle session相关数据字典(一)

    (一)session相关视图 (1)视图 v$session v$active_session_history dba_hist_active_session_history 如果是多节点数据库,v$ ...