Android高级第十讲之AIDL与JNI
来源:互联网 发布:国道知证量化 编辑:程序博客网 时间:2024/04/30 23:46
博客出自:http://blog.csdn.net/liuxian13183,转载注明出处! All Rights Reserved !
什么是AIDL,它有什么作用?
AIDL:Android Interface Defination Language
它是一种Android内部进程通信的描述语言,用它来定义通信接口。
AIDL是安卓的一个伟大设计,它保证不同项目之间资源、数据可以共享,减少冗余开发。
其实它也是RPC机制,客户端和服务端默认共用一套协议,Remote Procedure Call Protocol。
资源共享可以在项目的project.properties文件里写android.library.reference.1=../“项目名”
AIDL的简单实现(一方做服务端,一方做客户端):
目标项目:
1、首先可以在目标项目中声明一个Service A和一个.aidl结尾的接口文件B
2、在Service中实现一个IMyService.Stub实体类 C,其中C实现调用文件中的IInterface实现接口D
2、在Service的onBind()方法里返回B的实现
这样目标项目工作就完成了。
客户端:
1、首先实现一个序列化实体,一般用parcelable
2、然后完善D,写入一个抽象类,声明DESCRIPTOR变量为目标项目的B路径
3、在Activity中先绑定A,再获取A中所持久化的数据。
例:
创建一个ServiceConnection连接,从后台获得
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);}};private void bindService() {// bindServiceIntent service = new Intent("com.chapter8.aidl.IAIDLServerService");service.setPackage("com.blog.aidlserver");bindService(service, mConnection, BIND_AUTO_CREATE);}private Book mBook;private void getTransferSingleData() {if (mIaidlServerService == null) {return;}// aidl通信try {String mText = "Say hello: " + mIaidlServerService.sayHello() + "\n";mBook = mIaidlServerService.getBook();mText += "书名: " + mBook.getBookName() + "\n";mText += "价格: " + mBook.getBookPrice();mTextView.setText(mText);} catch (RemoteException e) {e.printStackTrace();}}
公共部分
Book:
package com.blog.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.aidlparcelable Book;IAIDLServerService.aidlpackage com.blog.aidl;import com.blog.aidl.Book; interface IAIDLServerService {String sayHello();Book getBook();List<Book> getBooks();void getBookList(in List<Book> inBooks,out List<Book> outBooks);}
这里多解释一下,进程间通信的实体类都要实现parcelable接口,aidl里面也有一些格式规范主要是in和out关键字,in代表传入的参数,out代表输出的参数
当然看到这里,也清楚传入传出的参数类型,只能为实体类和容器类包含String,而不包含其他基本数据类型,即使封装类都不可以
服务端:
AidlServerService:
package com.blog.aidlserver;import java.util.ArrayList;import java.util.List;import java.util.Random;import com.blog.aidl.Book;import com.blog.aidl.IAIDLServerService.Stub;import com.blog.aidl.IAIDLServerService;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;public class AidlServerService extends Service {private List<Book> mList = new ArrayList<Book>();@Overridepublic 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应用开发");Random random = new Random();mBook.setBookPrice(50 + random.nextInt(50));mList.add(mBook);return mBook;}@Overridepublic void getBookList(List<Book> inBooks, List<Book> outBooks) throws RemoteException {// TODO Auto-generated method stubBook mBook = new Book();mBook.setBookName("IOS应用开发");mBook.setBookPrice(45);inBooks.add(mBook);outBooks.addAll(inBooks);}@Overridepublic List<Book> getBooks() throws RemoteException {// TODO Auto-generated method stubreturn mList;}};}客户端:package com.blog.aidlclient;import java.util.ArrayList;import java.util.List;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.TextView;import com.blog.aidl.Book;import com.blog.aidl.IAIDLServerService;public class AidlClientActivity extends Activity {private TextView mTextView;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);}};@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// 初始化控件mTextView = (TextView) findViewById(R.id.textview);bindService();findViewById(R.id.button1).setOnClickListener(new OnClickListener() {public void onClick(View v) {getTransferSingleData();}});findViewById(R.id.button2).setOnClickListener(new OnClickListener() {public void onClick(View v) {getTransferMultiData();}});findViewById(R.id.button3).setOnClickListener(new OnClickListener() {public void onClick(View v) {getTransferTempData();}});}private void bindService() {// bindServiceIntent service = new Intent("com.chapter8.aidl.IAIDLServerService");service.setPackage("com.blog.aidlserver");bindService(service, mConnection, BIND_AUTO_CREATE);}private Book mBook;private void getTransferSingleData() {if (mIaidlServerService == null) {return;}// aidl通信try {String mText = "Say hello: " + mIaidlServerService.sayHello() + "\n";mBook = mIaidlServerService.getBook();mText += "书名: " + mBook.getBookName() + "\n";mText += "价格: " + mBook.getBookPrice();mTextView.setText(mText);} catch (RemoteException e) {e.printStackTrace();}}private void getTransferMultiData() {if (mIaidlServerService == null) {return;}// aidl通信try {String mText = "Say hello: " + mIaidlServerService.sayHello() + "\n";List<Book> inBooks = new ArrayList<Book>();if (mBook == null) {mBook = mIaidlServerService.getBook();}inBooks.add(mBook);List<Book> outBooks = new ArrayList<Book>();mIaidlServerService.getBookList(inBooks, outBooks);for (Book book : outBooks) {mText += "书名: " + book.getBookName() + "\n";mText += "价格: " + book.getBookPrice() + "\n";}mTextView.setText(mText);} catch (RemoteException e) {e.printStackTrace();}}private void getTransferTempData() {if (mIaidlServerService == null) {return;}// aidl通信try {String mText = "Say hello: " + mIaidlServerService.sayHello() + "\n";List<Book> books = mIaidlServerService.getBooks();for (Book book : books) {mText += "书名: " + book.getBookName() + "\n";mText += "价格: " + book.getBookPrice() + "\n";}mTextView.setText(mText);} catch (RemoteException e) {e.printStackTrace();}}}按钮1:
按钮2:
按钮1再按钮2
要求客户端与服务端公用模块一样,最好写成依赖包的形式
源码
注:直接启动服务端(只为Service自启动)再调用客户端就可以试验了!
关于JNI,主要用在java调用c或c调用java语言,应用场景分为3类
1、涉及到核心知识库,c的加密性会更好
2、c已经实现逻辑,且比较复杂
3、调用驱动,一般java做不到
如何区分Java类中哪些是调用c语言的方法呢?看到有native加为前缀的方法即是。当然这之前需要先把so库加载进来,否则会报错;例:
static { System.loadLibrary("webp"); }private native final void init();//初始化类的方法对应在c中的方法为(是一种编译规范,可改变)
static void android_content_AssetManager_init(JNIEnv* env,jobject clazz)
规范指,产生的c函数中,前者是JNIEnv对象指虚拟机运行环境,后者是调用函数的对象,指AssetManager;java方法在c中表现为包名+类包+方法名。
关于数据访问,java不可以直接访问c,c默认对java是私有的,可以使用get/set方法来达到访问目的。
有时c也会要访问java,因为一般情况下两者不会使用回调函数,不同于aidl,c语言返回值支持void、object和基本数据类型的封装类,调用分3步
1、获得Java对象的类
cls=env->GetObjectClass(object)
2、获得Java函数id
jmethodId mid= env ->GetMethodId(cls,"method_name","[Ljava/lang/String;)V")
3、调用函数
env->CallXXXMethod(jobject,mid,ret)
如果要获得数据,将上面的method改成field即可,比较奇怪的一个问题是这样,c库里主要进行逻辑运算,而结果的保存,如对象的声明,通常要保存在java中。
- Android高级第十讲之AIDL与JNI
- JNI 与AIDL
- 第六十一讲:Android之AIDL(一)
- 第六十二讲:Android之AIDL(二)
- Android高级之第十一讲Hybird开发
- android开发JNI之高级篇
- Android高级之十三讲之安全方案
- Android JNI 高级篇
- Android JNI 高级编程
- 第十讲 JSP与Servlet
- 第十讲、Jmeter之关联
- android教程学习 第十讲:
- Android高级开发第四讲--API之Service
- Android高级开发第五讲--API之Content Providers
- Android高级第十一讲之不同系统间的区别
- Android JNI + AIDL: 第1篇: Android JNI 编程
- android:JNI与Android VM之关系
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- Maven最佳实践:划分模块
- 2013年4月18日 23:37:54
- HttpServlet详解
- linux中wait与waitpid的差别
- 微软“MSDN”原版资源的“Share MSDN”最新中、英文硬盘版和网络版
- Android高级第十讲之AIDL与JNI
- js
- oracle中的exists 和not exists、in的 用法详解
- Android高级之系统介绍
- [打破常识]“木桶原理”之大谬误!
- Maven多模块布局实例详解
- js2
- NO.1
- JS3