1. Create .aidl文件
    定义Service接口

Caution: AIDL 做的任何改变,都必须保持后向兼容
方法支持参数和返回值,参数和返回值可以是任意类型。
1. 所有Java原型都支持(int, long, float, char ,boolean等)
2. String
3. Charsequence
4. List,元素必须是支持的数据类型,也可是其他AIDL所申明的,或者是parcelables。同时也可使用泛型申明。实际使用ArrayList来存储元素。
5. Map,也list要求相同。但不可使用泛型,实际使用HashMap来存储。

如果要使用除以上数据的类型其他类型数据,则必须使用import进行申明。

此外,在定义接口时,还需注意的有:
1. 方法可为0个或多个参数,可返回值或者void
2. 所有非原型参数,需要方向标签,in,out,inout。
3. 所有代码注释都会被生成到java接口中,除了import和package申明之前的。
4. 只支持方法,不支持静态成员变量的申明。

案例

// IRemoteService.aidl
package com.example.android;// Declare any non-default types here with import statements/** Example service interface */
interface IRemoteService {/** Request the process ID of this service, to do evil things with it. */int getPid();/** 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);
}
  1. 实现一个接口
    Android SDK tools会根据aidl文件自动生成一个java语言的编程接口,这个接口包含一个继承于Binder的抽象类和aidl中的接口方法实现。必须继承Stub然后实现方法。

保存到/src目录下,ADT tool 会在/gen目录下生成IBinder接口文件。注意包名。
生成的接口包含一个子类Stub, 是对接口的抽象实现。因此,需要继承该Stub,然后实现抽象方法。
其中Stub还有一个助手方法asInterface(),传递IBinder并返回stub接口实例。
实例代码如下:

private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {public int getPid(){return Process.myPid();}public void basicTypes(int anInt, long aLong, boolean aBoolean,float aFloat, double aDouble, String aString) {// Does nothing}
};

Caution: 注意多线程,要确保方法是线程安全的。RPC calls 通常是同步的,所以在client调用时,请使用子线程避免hand up the main thread and encounter ANR.此外,Server端不会返回Exception。

  1. Expose the interface to the clients
    继承Service,重写onBind(),然后返回Stub 类的实现,即mBinder。
public class RemoteService extends Service {@Overridepublic void onCreate() {super.onCreate();}@Overridepublic IBinder onBind(Intent intent) {// Return the interfacereturn mBinder;}
}

Client调用,如果与Server不再同一个Application下,那么需要将aidl文件拷贝到Client,并且保持包名的一致。

Passing Objects over IPC

支持Parcelable,将允许Android系统decompose objects into primitives that can be marshalled over processes, 意思就是允许Android系统将objects 解耦成primitives,而这些primitives可在进程间传递。
Step:
1. 让需要传递的类实现Parcelable接口,
2. 实现writeToParcel()方法,它将把对象的当前状态写到一个Parcel
3. 添加静态字段CREATOR,它时实现Parcelable.Creator接口。
4. create a aidl, 然后申明这个Parcelable 类。

aidl 申明Rect类代码如下:

package android.graphics;// Declare Rect so AIDL can find it and knows that it implements
// the parcelable protocol.
parcelable Rect;

接下来是Rect类实现Parcelable接口代码:

import android.os.Parcel;
import android.os.Parcelable;public final class Rect implements Parcelable {public int left;public int top;public int right;public int bottom;public static final Parcelable.Creator<Rect> CREATOR = new
Parcelable.Creator<Rect>() {public Rect createFromParcel(Parcel in) {return new Rect(in);}public Rect[] newArray(int size) {return new Rect[size];}};public Rect() {}private Rect(Parcel in) {readFromParcel(in);}public void writeToParcel(Parcel out) {out.writeInt(left);out.writeInt(top);out.writeInt(right);out.writeInt(bottom);}public void readFromParcel(Parcel in) {left = in.readInt();top = in.readInt();right = in.readInt();bottom = in.readInt();}
}

Calling an IPC Method

调用远程服务的实例,在之前的Service节中已经出现过了。这里不妨再赘上,有效长,:)

public static class Binding extends Activity {/** The primary interface we will be calling on the service. */IRemoteService mService = null;/** Another interface we use on the service. */ISecondary mSecondaryService = null;Button mKillButton;TextView mCallbackText;private boolean mIsBound;/*** Standard initialization of this activity.  Set up the UI, then wait* for the user to poke it before doing anything.*/@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.remote_service_binding);// Watch for button clicks.Button button = (Button)findViewById(R.id.bind);button.setOnClickListener(mBindListener);button = (Button)findViewById(R.id.unbind);button.setOnClickListener(mUnbindListener);mKillButton = (Button)findViewById(R.id.kill);mKillButton.setOnClickListener(mKillListener);mKillButton.setEnabled(false);mCallbackText = (TextView)findViewById(R.id.callback);mCallbackText.setText("Not attached.");}/*** Class for interacting with the main interface of the service.*/private ServiceConnection mConnection = new ServiceConnection() {public void onServiceConnected(ComponentName className,IBinder service) {// This is called when the connection with the service has been// established, giving us the service object we can use to// interact with the service.  We are communicating with our// service through an IDL interface, so get a client-side// representation of that from the raw service object.mService = IRemoteService.Stub.asInterface(service);mKillButton.setEnabled(true);mCallbackText.setText("Attached.");// We want to monitor the service for as long as we are// connected to it.try {mService.registerCallback(mCallback);} catch (RemoteException e) {// In this case the service has crashed before we could even// do anything with it; we can count on soon being// disconnected (and then reconnected if it can be restarted)// so there is no need to do anything here.}// As part of the sample, tell the user what happened.Toast.makeText(Binding.this, R.string.remote_service_connected,Toast.LENGTH_SHORT).show();}public void onServiceDisconnected(ComponentName className) {// This is called when the connection with the service has been// unexpectedly disconnected -- that is, its process crashed.mService = null;mKillButton.setEnabled(false);mCallbackText.setText("Disconnected.");// As part of the sample, tell the user what happened.Toast.makeText(Binding.this, R.string.remote_service_disconnected,Toast.LENGTH_SHORT).show();}};/*** Class for interacting with the secondary interface of the service.*/private ServiceConnection mSecondaryConnection = new ServiceConnection() {public void onServiceConnected(ComponentName className,IBinder service) {// Connecting to a secondary interface is the same as any// other interface.mSecondaryService = ISecondary.Stub.asInterface(service);mKillButton.setEnabled(true);}public void onServiceDisconnected(ComponentName className) {mSecondaryService = null;mKillButton.setEnabled(false);}};private OnClickListener mBindListener = new OnClickListener() {public void onClick(View v) {// Establish a couple connections with the service, binding// by interface names.  This allows other applications to be// installed that replace the remote service by implementing// the same interface.bindService(new Intent(IRemoteService.class.getName()),mConnection, Context.BIND_AUTO_CREATE);bindService(new Intent(ISecondary.class.getName()),mSecondaryConnection, Context.BIND_AUTO_CREATE);mIsBound = true;mCallbackText.setText("Binding.");}};private OnClickListener mUnbindListener = new OnClickListener() {public void onClick(View v) {if (mIsBound) {// If we have received the service, and hence registered with// it, then now is the time to unregister.if (mService != null) {try {mService.unregisterCallback(mCallback);} catch (RemoteException e) {// There is nothing special we need to do if the service// has crashed.}}// Detach our existing connection.unbindService(mConnection);unbindService(mSecondaryConnection);mKillButton.setEnabled(false);mIsBound = false;mCallbackText.setText("Unbinding.");}}};private OnClickListener mKillListener = new OnClickListener() {public void onClick(View v) {// To kill the process hosting our service, we need to know its// PID.  Conveniently our service has a call that will return// to us that information.if (mSecondaryService != null) {try {int pid = mSecondaryService.getPid();// Note that, though this API allows us to request to// kill any process based on its PID, the kernel will// still impose standard restrictions on which PIDs you// are actually able to kill.  Typically this means only// the process running your application and any additional// processes created by that app as shown here; packages// sharing a common UID will also be able to kill each// other's processes.Process.killProcess(pid);mCallbackText.setText("Killed service process.");} catch (RemoteException ex) {// Recover gracefully from the process hosting the// server dying.// Just for purposes of the sample, put up a notification.Toast.makeText(Binding.this,R.string.remote_call_failed,Toast.LENGTH_SHORT).show();}}}};// ----------------------------------------------------------------------// Code showing how to deal with callbacks.// ----------------------------------------------------------------------/*** This implementation is used to receive callbacks from the remote* service.*/private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {/*** This is called by the remote service regularly to tell us about* new values.  Note that IPC calls are dispatched through a thread* pool running in each process, so the code executing here will* NOT be running in our main thread like most other things -- so,* to update the UI, we need to use a Handler to hop over there.*/public void valueChanged(int value) {mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0));}};private static final int BUMP_MSG = 1;private Handler mHandler = new Handler() {@Override public void handleMessage(Message msg) {switch (msg.what) {case BUMP_MSG:mCallbackText.setText("Received from service: " + msg.arg1);break;default:super.handleMessage(msg);}}};
}

Android Service 之 AIDL相关推荐

  1. Android Service和Binder、AIDL

    为什么80%的码农都做不了架构师?>>>    Android Service和Binder.AIDL 人收藏此文章, 关注此文章发表于3个月前 , 已有 206次阅读 共 个评论  ...

  2. 简单音乐播放实例的实现,Android Service AIDL 远程调用服务

    2019独角兽企业重金招聘Python工程师标准>>> Android Service是分为两种: 本地服务(Local Service): 同一个apk内被调用 远程服务(Remo ...

  3. Android Service学习之AIDL, Parcelable和远程服务

    AIDL的作用 由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象.在Android平台,一个进程通常不能访问另一个进程的内存空间,所以 ...

  4. Android Service AIDL 远程调用服务 【简单音乐播放实例】

    Android Service是分为两种: 本地服务(Local Service): 同一个apk内被调用 远程服务(Remote Service):被另一个apk调用 远程服务需要借助AIDL来完成 ...

  5. Android service 和 client的进程通信和消息回调--AIDL

    2019独角兽企业重金招聘Python工程师标准>>> (一)项目介绍 Launcher上播放小视屏和独立的视频应用.小视屏是视频应用的裁剪版,只有播放的功能,两者使用相同的底层系统 ...

  6. Android四大组件Service之AIDL详解

    Android四大组件Service之AIDL详解 前言 简介 基础知识 AIDL 服务端 定义AIDL文件规则 创建 .aidl 文件 清单注册 通过 IPC 传递对象 调用 IPC 方法 Andr ...

  7. android service 学习(上)

    转载自:http://www.cnblogs.com/allin/archive/2010/05/15/1736458.html Service是android 系统中的一种组件,它跟Activity ...

  8. android service 学习(下)

    android service 学习(下) 通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的service.在android ...

  9. Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

最新文章

  1. AI一分钟 | 厉害了!英特尔正式发布电动飞行汽车;贝佐斯笑了,多家PC厂商结盟亚马逊Alexa,直怼微软Cortana
  2. Django Web开发学习笔记(4)
  3. 014_html折行
  4. Linux安装技巧--安装Uuntu与windows8/10共存
  5. 对于数据库表排他更新的理解
  6. CreateJS基础 学习笔记(上)
  7. Dynamics AX 2012–HR-离职
  8. NVIDIA SMI 无法与 nvidia driver 通信
  9. eclipse优化方案
  10. oracle 中的Ipad()函数
  11. 找到解决办法了,特回来写总结,the import cannot be resolved问题可以通过以下方法解决
  12. 找不到java是什么意思_“无法找到或加载主类”是什么意思?
  13. 马云谈年轻人压力大:年轻人怕压力就白活了
  14. 互动媒体技术——对十二个“一”的文艺创作作业进行文本分析、统计和可视化
  15. 为什么苹果4s用电信卡显示无服务器,电信4G卡插入苹果4S,提示“无服务”
  16. 171029 windows10 桌面美化
  17. ios 绘制线框_16款值得一用的iPhone线框图模板 (PSD Sketch)
  18. oracle cloud技术帖,Oracle Cloud初体验
  19. Python3 实现淘女郎照片爬虫
  20. 新版SEO按天扣费系统PHP源码

热门文章

  1. nGQL中vid值过长被截断的处理方法
  2. char-embedding是如何输入到模型的
  3. 复用 TensorFlow 模型
  4. 稀疏矩阵快速转置c语言代码(详解)
  5. python中如何将数字改成字符串_python中如何将数字转字符串
  6. LeetCode-175. 组合两个表(SQL语句中的LEFT JOIN)
  7. 《系统集成项目管理工程师》必背100个知识点-67工作说明书和范围说明书
  8. Mysql悲观锁乐观锁区别使用区别
  9. Leaflet中原生方式实现测距
  10. 一行Java代码判断文件夹是否存在,不存在则新建