AIDL——使用步骤

本文详细介绍了Android进程间通信机制AIDL的原理及其应用场景,强调了AIDL在处理多线程及多客户端并发访问的优势,并提供了从服务端到客户端完整的示例代码。

转自http://www.2cto.com/kf/201406/312244.html


1、为什么要有AIDL?

对于AIDL有一些人的浅显概念就是,AIDL可以跨进程访问其他应用程序,和其他应用程序通讯,那我告诉你,很多技术都可以访问,如广播(应用A在 AndroidManifest.xml中注册指定Action的广播)应用B发送指定Action的广播,A就能收到信息,这样也能看成不同应用之间完成了通讯(但是这种通讯是单向的);还如ContentProvider,通过URI接口暴露数据给其他应用访问;但是这种都算不上是应用之间的通讯。可能最让人迷惑的是Android推出来了Messager,它就是完成应用之间的通讯的。那么为什么还要有AIDL呢,官方文档介绍AIDL中有这么一句话:

Note: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.


第一句最重要,“只有当你允许来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL”,其他情况下你都可以选择其他方法,如使用Messager,也能跨进程通讯。可见AIDL是处理多线程、多客户端并发访问的。而Messager是单线程处理。



2、AIDL使用

第一、定义AIDL文件
// 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);
}

这段代码也是官方文档的。命名为IRemoteService.aidl,放在com.example.android包下(这个可以随意),保存后Android编译器会在gen目录下自动生成IRemoteService.java文件

第二、定义我们的服务,DDService.java,并且需要在AndroidManifest.xml中注册,并添加“duanqing.test.aidl” 的ACTION
package com.example.service;

import com.example.android.IRemoteService;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Process;

public class DDService extends Service {
	@Override
	public void onCreate() {
		super.onCreate();
		System.out.println("DDService onCreate........" + "Thread: " + Thread.currentThread().getName());
	}
	@Override
	public IBinder onBind(Intent arg0) {
		System.out.println("DDService onBind");
		return mBinder;
	}

	private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
	    public int getPid(){
	    	System.out.println("Thread: " + Thread.currentThread().getName());
	    	System.out.println("DDService getPid ");
	        return Process.myPid();
	    }
	    public void basicTypes(int anInt, long aLong, boolean aBoolean,
	        float aFloat, double aDouble, String aString) {
	    	System.out.println("Thread: " + Thread.currentThread().getName());
	    	System.out.println("basicTypes aDouble: " + aDouble +" anInt: " + anInt+" aBoolean " + aBoolean+" aString " + aString);
	    }
	};

}

这样我们的服务端就完成了,把服务端运行到模拟器(或者手机上),等一会可以看一下打印信息,重点看“线程名”
第三、实现客户端测试代码新建另一个工程,同样需要添加AIDL协议文件(这是一个标准的协议文件,定义对外服务)
package com.example.aidlclient;

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.Process;
import android.os.RemoteException;
import android.view.View;

import com.example.android.IRemoteService;

public class MainActivity extends Activity {
	private IRemoteService remoteService;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
    ServiceConnection conn = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			remoteService =	IRemoteService.Stub.asInterface(service);
			try {
				int pid = remoteService.getPid();
				int currentPid = Process.myPid();
				System.out.println("currentPID: " + currentPid +"  remotePID: " + pid);
				remoteService.basicTypes(12, 1223, true, 12.2f, 12.3, "我们的爱,我明白");
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			System.out.println("bind success! " + remoteService.toString());
		}
	};
		
    /**
     * 监听按钮点击
     * @param view
     */
    public void buttonClick(View view) {
    	System.out.println("begin bindService");
    	Intent intent = new Intent("duanqing.test.aidl");
    	bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
    	super.onDestroy();
    	unbindService(conn);
    }
}



### 使用AIDL进行Android进程间通信 #### 创建AIDL文件 为了简化复杂的IPC编程,Android提供了一种称为AIDL的语言。这种语言帮助开发者定义客户端和服务端之间的接口[^1]。 在项目中集成AIDL支持的第一步是在`app/src/main/aidl`目录下创建一个新的`.aidl`文件。假设命名为`MyAidlService.aidl`,此操作可以通过IDE菜单完成,在目标位置右键点击并选择新建选项来实现[^2]。 #### 定义远程接口 接下来,在新建立的`.aidl`文件内声明所需的方法签名。这些方法代表了服务端对外公开的功能点。例如: ```aidl package com.test.aidl; interface OpenData { void cycleData(String linData); boolean handshake(int cmdNumber); void listenerData(ActionCallback actionCallback); } interface ActionCallback { void callback(String jsonData); } ``` 上述代码片段展示了如何定义一个简单的双向交互接口——不仅能够发送命令到服务器(`cycleData`, `handshake`),还能接收来自服务器的通知(`listenerData`)[^3]。 #### 实现服务端逻辑 一旦完成了接口的设计,就需要编写实际的服务类去落实具体的业务行为。这一步骤涉及继承自动生成的帮助类,并重写相应的方法体。同时记得配置`AndroidManifest.xml`使得该服务可以被其他应用程序发现和连接: ```xml <service android:name=".OpenDataService" android:exported="true"> </service> ``` 这里设置了属性`android:exported=true`表示允许外部组件绑定至本服务;另外指定独立的工作线程`:remote`有助于提高性能表现[^4]。 #### 构建与部署 当所有的准备工作就绪之后,执行构建任务将会触发编译器自动转换`.aidl`描述成Java源码形式。生成后的存根位于项目的`build/generated/source/aidl/debug/com/test/aidl/OpenData.java`路径之下。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值