android中aidl的使用

本文详细介绍了Android AIDL(Android Interface Definition Language)的使用范围、原理及具体实现步骤,包括服务端和客户端的开发流程。通过示例展示了如何在不同进程间传递复杂对象,以及如何在Android应用中利用AIDL进行高效、安全的进程间通信。

aidl的使用范围

Android使用AIDL来完成进程间通信(IPC),AIDL全程为Android Interface Definition Language。在服务需要接受不同应用多线程的请求时才需要使用AIDL,如果是同一个应用内的请求使用Binder实现即可,见应用内交互的服务;如果只是应用间通信而不是多线程处理的话使用Messenger,当然这两种情况也可以使用AIDL。本地进程和远程进程使用AIDL有所不同,本地进程内调用时会都在调用的线程内执行,远程进程使用是通过Service进程内一个由系统维护的线程池发出调用,所以可能是未知线程同时调用,需要注意线程安全问题

今天要给大家分享的是Android aidl的使用。在Android中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢? 显然, Java中不允许跨进程内存共享. 因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的. 在J2EE中,采用RMI的方式, 可以通过序列化传递对象. 在Android中, 则采用AIDL的方式. 理论上AIDL可以传递Bundle,实际上做起来却比较麻烦.

AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象.

AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.

今天的两个实例用到两个Android工程,一个是AIDL的服务端另一个是客户端。 


示例:

服务端的实现步骤:

首先看一下服务端,工程目录如下:


首先创建IaidlServerService.aidl文件,代码如下(一个简单方法,另一个返回对象方法),当我们点击保存时会在gen目录下生成对应的java文件,如上图红色部分:

[java]
package com.chapter8.aidl;  
import com.chapter8.aidl.Book;  
interface IAIDLServerService {   
      
    String sayHello();  
      
    Book getBook();  
}  

第二步:因为这个接口里有传递对象,所以对象要特殊处理一下,这里继承了Parcelable,Book.java代码如下:

[java]
package com.chapter8.aidl;  
import android.os.Parcel;  
import android.os.Parcelable;  
public class Book implements Parcelable {  
      
    private String bookName;  
    private int bookPrice;  
      
    public Book(){  
          
    }  
      
    public Book(Parcel parcel){  
        bookName = parcel.readString();  
        bookPrice = parcel.readInt();  
    }  
      
    public String getBookName() {  
        return bookName;  
    }  
    public void setBookName(String bookName) {  
        this.bookName = bookName;  
    }  
    public int getBookPrice() {  
        return bookPrice;  
    }  
    public void setBookPrice(int bookPrice) {  
        this.bookPrice = bookPrice;  
    }  
      
    public int describeContents() {  
        return 0;  
    }  
    public void writeToParcel(Parcel parcel, int flags) {  
        parcel.writeString(bookName);  
        parcel.writeInt(bookPrice);  
    }  
      
    public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>() {  
        public Book createFromParcel(Parcel source) {  
              
            return new Book(source);  
        }  
        public Book[] newArray(int size) {  
            return new Book[size];  
        }  
    };  
}  
第三步:写一个与Book类对应的aidl,命名为Book.aidl,代码非常简单,代码如下:
[java]
parcelable Book;  
第四步:新建一个名为AidlServerService的Service.代码如下:

[java]
package com.chapter8.aidl;  
import com.chapter8.aidl.IAIDLServerService.Stub;  
import com.chapter8.aidl.IAIDLServerService;  
import Android.app.Service;  
import android.content.Intent;  
import android.os.IBinder;  
import android.os.RemoteException;  
public class AidlServerService extends Service {  
    @Override  
    public IBinder onBind(Intent intent) {  
        return mBinder;  
    }  
    /** 
     * 在AIDL文件中定义的接口实现。 
     */   
    private IAIDLServerService.Stub mBinder = new Stub() {  
          
        public String sayHello() throws RemoteException {  
            return "Hello";  
        }  
          
        public Book getBook() throws RemoteException {  
            Book mBook = new Book();  
            mBook.setBookName("Android应用开发");  
            mBook.setBookPrice(50);  
            return mBook;  
        }  
    };  
}  
第五步:在AndroidManifest.xml注册Service,代码如下:

[java]
<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
      package="com.chapter8.aidl"  
      android:versionCode="1"  
      android:versionName="1.0">  
    <application android:icon="@drawable/icon" android:label="@string/app_name">  
        <activity android:name="AidlServerActivity"  
                  android:label="@string/app_name">  
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />  
                <category android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  
        <service android:name="AidlServerService"  
                 android:process=":remote">  
            <intent-filter>  
                <action android:name="com.chapter8.aidl.IAIDLServerService"></action>  
            </intent-filter>  
        </service>  
    </application>  
</manifest>  
 这里的android:process=":remote",一开始我没有添加的,在同一个程序里使用IPC,即同一个程序作为客户端/服务器端,结果运行mRemoteService = IMyService.Stub.asInterface(service);时提示空指针异常。观察了人家的在不同程序里进行IPC的代码,也是没有这个android:process=":remote"的。后来在官方文档http://androidappdocs.appspot.com/guide/topics/manifest/service-element.html里了解到(留意第二段文字):
也就是说android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。



第六步:运行服务端工程,到设备上,好让客户端调用,服务端的Activity什么都没做.效果如下:

客户端的具体实现步骤:

第一步:新建客户端工程,目录结构如下:


第二步:引入Aidl文件以及用到的类,如上面的com.chapter8.aidl包。直接从服务端里代码copy过来就OK.

第三步:修改main.xml布局文件,增加一个按钮,代码如下:

[java]
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    >  
<TextView    
    android:id="@+id/textview"  
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"   
    android:text="@string/hello"  
    />  
<Button  
    android:id="@+id/button"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:text="调用AIDL服务"  
    />  
</LinearLayout>  
四步:修改AidlClientActivity.java代码如下:

[java]
package com.chapter8.aidlclient;  
import com.chapter8.aidl.IAIDLServerService;  
import android.app.Activity;  
import android.content.ComponentName;  
import android.content.Intent;  
import android.content.ServiceConnection;  
import android.os.Bundle;  
import android.os.IBinder;  
import android.os.RemoteException;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
import android.widget.TextView;  
public class AidlClientActivity extends Activity {  
   
    private TextView mTextView;  
    private Button mButton;  
      
    private IAIDLServerService mIaidlServerService = null;  
      
    private ServiceConnection mConnection = new ServiceConnection() {  
          
        public void onServiceDisconnected(ComponentName name) {  
            mIaidlServerService = null;  
        }     
        public void onServiceConnected(ComponentName name, IBinder service) {  
            mIaidlServerService = IAIDLServerService.Stub.asInterface(service);  
            //aidl通信   
            try {  
                String mText = "Say hello: " + mIaidlServerService.sayHello() + "/n";  
                mText += "书名: " + mIaidlServerService.getBook().getBookName()+"/n";  
                mText += "价格: " + mIaidlServerService.getBook().getBookPrice();  
                mTextView.setText(mText);  
            } catch (RemoteException e) {  
                e.printStackTrace();  
            }  
        }  
    };  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);        
        //初始化控件   
        mTextView = (TextView)findViewById(R.id.textview);  
        mButton = (Button)findViewById(R.id.button);  
        //增加事件响应   
        mButton.setOnClickListener(new OnClickListener(){  
            public void onClick(View v) {  
                //bindService   
                Intent service = new Intent("com.chapter8.aidl.IAIDLServerService");  
                bindService(service, mConnection,BIND_AUTO_CREATE);                           
            }          
        });  
    }  
}  
第五步:运行客户端工程,效果如下:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值