`
zhangyf1987hb
  • 浏览: 80007 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android服务之Service(其二)关于AIDL进程间通信

阅读更多
上一节中我们讲解了本地Service,这一节主要是讲解远程Service,这里涉及到了AIDL。
好吧,老规矩,先来点基础知识:

一.基础知识

AIDL的作用
    在Android平台,每个应用程序App都运行在自己的进程空间。通常一 个进程不能访问另一个进程的内存空间(一个应用不能访问另一个应用),如果想沟通,需要将对象分解成操作系统可以理解的基本单元,Android提供了AIDL来处理。
 
    AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参 数。换句比较浅显的话来说,就是我这个App应用的activity,需要调用其他App应用的Service.当然同一App应用的activity 与service也可以在不同进程间,这可以设置Service配置中,android:process=":remote"
AIDL的使用

    官方文档特别提醒我们何时使用AIDL是必要的:只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。(太生硬了,不同进程的组件调用吧。)

那么怎么制作AIDL呢?下面步骤

1:创建.aidl文件。新建立个文件并且以.aidl作为后缀保存,在这个文件中编写接口以及方法,这个我们普通java接口声明是一样的,不同的是要显示import 复杂类型,即便复杂类型对象在同一个包内。Java基本数据类型 (int, long, char, boolean等),String和CharSequence,集合接口类型List和Map,不需要import 。

比如:

package com.dongzi;
interface IStockQuoteService{
  double getPrice(String ticker);
}

2:创建好AIDL文件后,刷新下工程,你会发现在gen包下,对应的包下面出现一个与AIDL文件相同的java文件。如:

复制代码
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: D:\\mywordspace\\MyPhone\\src\\com\\dongzi\\IStockQuoteService.aidl
*/
package com.dongzi;

public interface IStockQuoteService extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.dongzi.IStockQuoteService {
private static final java.lang.String DESCRIPTOR = "com.dongzi.IStockQuoteService";

/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}

/**
* Cast an IBinder object into an com.dongzi.IStockQuoteService
* interface, generating a proxy if needed.
*/
public static com.dongzi.IStockQuoteService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.dongzi.IStockQuoteService))) {
return ((com.dongzi.IStockQuoteService) iin);
}
return new com.dongzi.IStockQuoteService.Stub.Proxy(obj);
}

public android.os.IBinder asBinder() {
return this;
}

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getPrice: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
double _result = this.getPrice(_arg0);
reply.writeNoException();
reply.writeDouble(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

private static class Proxy implements com.dongzi.IStockQuoteService {
private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote) {
mRemote = remote;
}

public android.os.IBinder asBinder() {
return mRemote;
}

public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}

public double getPrice(java.lang.String ticker) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
double _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(ticker);
mRemote.transact(Stub.TRANSACTION_getPrice, _data, _reply, 0);
_reply.readException();
_result = _reply.readDouble();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}

static final int TRANSACTION_getPrice = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}

public double getPrice(java.lang.String ticker) throws android.os.RemoteException;
}
复制代码

AIDL工具自动生成了那么多代码,其实我们只需要知道3个就够了。

public static abstract class Stub extends android.os.Binder implements com.dongzi.IStockQuoteService 静态抽象内部类Stub

private static class Proxy implements com.dongzi.IStockQuoteService         AIDL服务代理类

public double getPrice(java.lang.String ticker) throws android.os.RemoteException;     AIDL公布出的接口,就是我们定义的接口方法

3:把AIDL文件存放在其他客户端应用中,我们这个作为服务端。当然我们也可以方便的把这个应用作为客户端以及服务端。其实根本区别就是为了使调用者与被调用者在不同进程中,于是在服务中添加android:process=":remote"即可。省去了再建立应用客户端调用。

4:AIDL只是请定义一个契约,我们这里需要一个服务来提供服务。于是建立服务MyService.

二.实战

既然我们了解一些基础知识后,现在我们开始来代码吧。假设我们需要在一个进程中调用其他应用的服务,这个服务提供一个股票价格查询,或者GPS定位的服务。

并且定义一个类,继承我们AIDL生成的Stub内部类,并实现我们AIDL定义的方法

代码如下:

复制代码
package com.dongzi;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MyService extends Service {
static final String TAG="MyService";

//定义内部类MyServiceImpl继承我们的AIDL文件自动生成的内部类,
//并且实现我们AIDL文件定义的接口方法
private class MyServiceImpl extends IStockQuoteService.Stub{

@Override
public double getPrice(String ticker) throws RemoteException {
Log.e(TAG, "getPrice");
return 10.5;
}

}

@Override
public IBinder onBind(Intent arg0) {
//返回AIDL实现
return new MyServiceImpl();
}


@Override
public void onDestroy(){
Log.e(TAG, "Release MyService");
super.onDestroy();
}
}
复制代码

我们需要在onBind方法中返回我们的AIDL接口实现对象,以便其他进程调用。

当然了,现在AIDL,以及Service都定义好了,就需要在mainfest.xml中设置

复制代码
 <service android:name=".MyService"
android:process=":remote"
>
<intent-filter>
<action android:name="com.dongzi.IStockQuoteService"/>
</intent-filter>
</service>
复制代码

在客户端服务端在两个App中,android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。

那么现在客户端来调用我们的服务了,代码如下:

复制代码
package com.dongzi;

import android.app.Activity;
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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MYyActivity extends Activity {
static final String TAG="MYyActivity";
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btnCall=(Button)findViewById(R.id.btnCall);
if(btnCall!=null)
btnCall.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
//绑定一个服务
bindMyService();
}
});
}

IStockQuoteService iService=null;
private ServiceConnection conn=new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//返回AIDL接口对象,然后可以调用AIDL方法
iService=IStockQuoteService.Stub.asInterface(service);
double value=0.0;
try {
value=iService.getPrice("");
}
catch (RemoteException e) {
Log.e(TAG,"调用出错!");
e.printStackTrace();
}
Log.e(TAG, "返回数值为:"+value);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "释放Service");
}
};

private void bindMyService(){
// Intent intent=new Intent("com.dongzi.IStockQuoteService");
Intent intent=new Intent(this,MyService.class);
startService(intent);

bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
}
复制代码

在按钮点击时候启动service,然后再绑定这个Service.在连接到服务后,我们会发现,调用AIDL中定义的方法成了,打印如下:


项目结构为:

 

分享到:
评论

相关推荐

    Android使用AIDL实现进程间通信

    Android使用AIDL实现进程间通信

    Android安卓AIDL进程间通信Service简单例子

    Android安卓AIDL进程间通信Service简单例子,分为客户端和服务端代码,一看就会,一看就懂,核心还是IBinder.

    Android AIDL进程间通信例子代码

    AndroidAIDL进程间通信例子代码,一个客户端调用,一个服务端Service

    Android AIDL 进程间通信

    Android进程间通信 AIDL Service 一、服务端结构 服务端需要处理的有: 1.处理对象,对象内方法,注意:AIDL 只能对函数起作用; 2.处理服务; 3.配置文件; 二、客户端 配置 1.对象,切记,与服务端的对象完全一致...

    Android Aidl进程间通信,实现3个app共享一个服务

    Aidl进程间通信简单封装了下,AIDL和Service作为一个library,其他3个app调用,实现3个app共享一个服务,3个中任意app打开即可开启服务,其他两个app共用

    AIDL进程间通信(含回调)

    使用AIDL实现进程间通信 两个工程即两个APP,实现数据共享 APP1中有个service 不停的对某一个数进行++操作, APP2通过AIDL 获取APP1的Service中的这个值(通过回调) 当然要使用AIDLAPP1中也要做相应处理

    AIDL Demo源码实现Activity与Service进程间通信

    实现Activity与Service进程间通信 , 不同程序间通讯

    Android 进程间通信机制(六) 手写AIDL文件

     进程间通信涉及到客户端和服务端, 肯定有绑定服务的过程, 所以要阅读一下Android Service相关的知识, 跨进程通信的媒介aidl文件,我们也必须要了解怎么创建的,有什么规则,所以请先阅读一下Android AIDL使用这篇...

    AndroidAIDL

    使用AIDL实现Android进程间通信,Demo包含Service,Client代码。

    Android IPC进程间通信AIDL方式Demo

    这是一个IPC进程间AIDL方式通信的简单Demo。包括服务端和客户端。目的在于协助该博客讲解binder与service之间跨进程通信机制。所有大家读源码时务必同时读该博客。 ...

    android aidl service

    android aidl进程间传递数据的demo。欢迎交流学习。

    Android Studio实现Service AIDL

    为使应用程序之间能够彼此通信,Android提供了IPC (Inter Process Communication,进程间通信)的一种独特实现: AIDL (Android Interface Definition Language, Android接口定义语言)。 建立两个Android项目,...

    aidl-sensor-demo:这是一个Android应用程序,用于演示如何使用AIDL进行进程间通信(IPC)

    这是一个Android应用程序,用于演示如何使用AIDL进行进程间通信(IPC)。 该项目包括一个带有服务(“ SensorService”)的Android库,该服务在清单文件中声明为在单独的进程中运行。 该服务完成了一个简单的任务,...

    Android进程通信之Messenger和AIDL使用详解

    提到的进程间通信(IPC:Inter-Process Communication),在Android系统中,一个进程是不能直接访问另一个进程的内存的,需要提供一些机制在不同的进程之间进行通信,Android官方推出了AIDL(Android Interface ...

    详解Android 进程间通信的几种实现方式

    这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据...

    Android多进程间采用AIDL方式进行通信

    首先我需要解释一下,不同程序进程间采用AIDL方式启动服务,我们可以看作成client客户端与server服务端之间的通信,无非c/s都是安装在了我们的智能手机设备Android系统之上。好了,理解到这里我们就可以继续往下介绍...

    Android AIDL binder WIFI

    学习Android必备技术,AIDL,进程间通信技术,通过binder实现。client.aar于HMI.APK在同一个进程空间,service.apk在另一个进程空间,两者通过AIDL通信。类似于DBUS。

    Android-AIDL文件实现两个工程之间互相传输

    AIDL概述:AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言,设计这门语言的目的是为了实现进程间通信。接下来我写了两个demo(AildeService和AidleClient),他们之间...

    android使用AIDL跨进程通信(IPC)

    AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个...

    Android 进程间通信实现原理分析

    AIDL 是什么 AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)...

Global site tag (gtag.js) - Google Analytics