aidl在android开发中的主要作用就是跨进程通讯来着,说到进程相比很多人都是非常熟悉了,但是为什么会有跨进程通讯这个概念呢?原来在android系统中,有这么一套安全机制,为了各个Apk数据的独立性、安全性,它们彼此之间是不能直接进行数据的访问的。所以为了实现多个APK之间的数据、方法、代码复用,我们通常采用的做法就是定义好AIDL接口,这样就能够既保护现有代码的逻辑性、同时又能够兼顾好封装性,各个团队之间只需要沟通好AIDL接口定义就可以了。

下面让我们直接进入主题吧,在进行AIDL定义的时候,通常会将公用的代码逻辑单独封装到一个独立的APK中,这个APK我们不妨成为服务器Server。当定义好Server断逻辑之后,就可以供其他第三方代码调用了,这个第三方Apk我们不妨成为Client。但是Server和Client方,必须同时保证AIDL文件名称相同,同时又在相同的包名下面。只有同时满足这两点的话,才能利用AIDL进行通讯。

假如有一套公用的计算方法,在多个第三方APK中都需要调用。所以定义两个android project,一个服务端程序AidlServer,一个客户端测试程序TestClient。其中服务端、客户端的AIDL接口文件都位于包“com.example.aidl下面”,定义好ICal.aidl文件,代码如下:

package com.example.aidl;

interface ICal{
double doCal(double x,double y);
}

在定义书写aidl文件代码的时候,语法规则跟java一致,切记不要忘记引入package或者少写了分号。当定义好aidl文件之后,并且没有错误的情况下,按住ctrl+s键保存编译,会发现项目的gen文件夹下面会自动生成一个同名的java文件。如果到这一步正确的生成了java文件的话,那么说明服务端,客户端的AIDL接口部分已经定义完成,那么接下来怎么将服务端的接口暴露给客户端调用呢?答案是通过service,我们先来看一下service端的CalService代码:

package com.example.service;

import com.example.aidl.ICal;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log; public class CalService extends Service { private static final String TAG = CalService.class.getName(); @Override
public IBinder onBind(Intent intent) {
return mBinder;
} @Override
public void onCreate() {
Log.d(TAG,"onCreate action");
super.onCreate();
} @Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, "onStart action");
super.onStart(intent, startId);
} @Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
} @Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return super.onUnbind(intent);
} private final ICal.Stub mBinder=new ICal.Stub() { @Override
public double doCal(double x, double y) throws RemoteException {
CalUtils calUtils=new CalUtils();
double result=calUtils.add(x, y);
return result;
}
}; }

通过CalService可以很好的暴露CalUtils公用类里面的计算方法,CalUtils代码如下:

package com.example.service;

public class CalUtils{

      public double add(double x,double y){
return x+y;
}
}

最后还需要在AndroidManifest.xml文件里面注册CalService,代码如下:

<service
android:name="com.example.service.CalService">
<intent-filter>
<action android:name="com.example.service.CalService"/>
</intent-filter>
</service>

到这里,服务器端的代码逻辑就完了,下面开始Client的测试代码编写。首先定义好一个计算xml页面,里面放置两个EditText、一个TextView、一个Button、一个TextView,这块的xml代码就不放出来了,稍后demo里面有。主要来看看后台的Activity代码,如下:

package com.example.mytestpro;

import com.example.aidl.ICal;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView; public class CalActivity extends Activity implements OnClickListener { private static final String TAG=CalActivity.class.getName(); private EditText etX,etY;
private Button btnCal;
private TextView tvInfo;
private ICal mService; private ServiceConnection mServiceConnection=new ServiceConnection() { @Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "do Disconnected action");
mService=null;
} @Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "do Connected action");
mService=ICal.Stub.asInterface(service);
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calctivity); initView();
setClick();
startBindServiceAction();
} private void startBindServiceAction(){
Bundle args=new Bundle();
Intent intent=new Intent("com.example.service.CalService");
intent.setPackage("com.example.aidlserver");
intent.putExtras(args);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
} private void initView(){
etX=(EditText)findViewById(R.id.etX);
etY=(EditText)findViewById(R.id.etY);
btnCal=(Button)findViewById(R.id.btnCal);
tvInfo=(TextView)findViewById(R.id.tvInfo);
} private void setClick(){
btnCal.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnCal:
excuteCalAction();
break; default:
break;
}
} private void excuteCalAction(){
try {
double x=Double.parseDouble(etX.getText().toString());
double y=Double.parseDouble(etY.getText().toString());
String result="result:"+mService.doCal(x, y);
tvInfo.setText(result);
tvInfo.setTextColor(Color.RED);
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
}
}

有兴趣的读者,可点击下载服务端demo客户端demo

android开发系列之aidl的更多相关文章

  1. Android开发——进程间通信之AIDL(二)

    0.  前言 不论是Android还是其它操作系统.都会有自己的IPC机制.所谓IPC(Inter-Process Communication)即进程间通信.首先线程和进程是非常不同的概念,线程是CP ...

  2. Android 开发系列教程之(一)Android基础知识

    什么是Android Android一词最早是出现在法国作家维里耶德利尔·亚当1986年发表的<未来夏娃>这部科幻小说中,作者利尔·亚当将外表像人类的机器起名为Android,这就是And ...

  3. Android开发-API指南-AIDL

    Android Interface Definition Language (AIDL) 英文原文:http://developer.android.com/guide/components/aidl ...

  4. [Android开发系列]IT博客应用

    1.关于坑 好吧,在此之前先来说一下,之前开的坑,恩,确实是坑,前面开的两个android开发教程的坑,对不起,实在是没什么动力了,不过源码都有的,大家可以参照github这个应用 https://g ...

  5. Android开发系列之按钮事件的4种写法

    经过前两篇blog的铺垫,我们今天热身一下,做个简单的例子. 目录结构还是引用上篇blog的截图. 具体实现代码: public class MainActivity extends Activity ...

  6. Android开发系列之SQLite

    上篇博客提到过SQLite,它是嵌入式数据库,由于其轻巧但功能强大,被广泛的用于嵌入式设备当中.后来在智能手机.平板流行之后,它作为文件型数据库,几乎成为了智能设备单机数据库的必选,可以随着安卓app ...

  7. Android开发系列之Android项目的目录结构

    今天开始正式学习Android开发的种种细节,首先从最基本的概念和操作学起. 首先看一下Android项目的目录结构. 这是我随便建立的一个test项目,我们重点关注一下几个方面的内容: 1.src目 ...

  8. Android开发系列之学习路线图

    通过前面的3篇博客已经简单的介绍了Android开发的过程并写了一个简单的demo,了解了Android开发的环境以及一些背景知识. 接下来这篇博客不打算继续学习Android开发的细节,先停一下,明 ...

  9. Android开发系列之搭建开发环境

    接触Android好久了,记得09年刚在中国大陆有点苗头的时候,我就知道了google有个Android,它是智能机操作系统.后来在Android出1.5版本之后,我第一时间下载了eclipse开发工 ...

随机推荐

  1. luogu P3818 小A和uim之大逃离 II

    题目背景 话说上回……还是参见 https://www.luogu.org/problem/show?pid=1373 吧 小a和uim再次来到雨林中探险.突然一阵南风吹来,一片乌云从南部天边急涌过来 ...

  2. POJ 3264 Balanced Lineup(zkw线段树)

    [题目链接] http://poj.org/problem?id=3264 [题目大意] 求区间最大值和最小值的差值 [题解] 线段树维护区间极值即可 [代码] #include <cstdio ...

  3. 五. 面向对象高级特性6. Java 泛型

    我们知道,使用变量之前要定义,定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 假如我们现在要定义一个类来表示坐标,要求坐标的数据类型可以是整数.小数和字符串,例如: x = 1 ...

  4. 四. Java继承和多态6. 多态对象的类型转换

    这里所说的对象类型转换,是指存在继承关系的对象,不是任意类型的对象.当对不存在继承关系的对象进行强制类型转换时,java 运行时将抛出 java.lang.ClassCastException 异常. ...

  5. tiny4412 串口驱动分析一 --- u-boot中的串口驱动

    作者:彭东林 邮箱:pengdonglin137@163.com 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 ...

  6. django自定义过滤器及模板标签

    创建一个模板库 不管是写自定义标签还是过滤器,第一件要做的事是创建模板库(Django能够导入的基本结构). 创建一个模板库分两步走: 第一,决定模板库应该放在哪个Django应用下. 如果你通过 m ...

  7. (转)指针的引用(*&)与指针的指针(**)

    本文转载而来,转载出处:http://www.cppblog.com/doing5552/archive/2010/09/28/127994.html 在下列函数声明中,为什么要同时使用*和& ...

  8. 15 Basic ‘ls’ Command Examples in Linux

    FROM: http://www.tecmint.com/15-basic-ls-command-examples-in-linux/ ls command is one of the most fr ...

  9. SparkMLlib基础内容

    SparkMLlib基础内容 (一),多种数据类型 1.1 本地向量集 def testVetor: Unit ={ val vd:Vector=Vectors.dense(2,3,6) printl ...

  10. EF使用延迟加载的本质原因

    EF(Entity Framework)是微软的一个ORM框架 使用过EF的同学都知道它有一个延迟加载的功能 那么这个延迟加载的功能到底是什么? 为什么需要延迟加载? 使用延迟加载的优点和缺点又各是什 ...