Android AIDL的使用
文章来源:http://blog.csdn.net/luoyanglizi/article/details/51980630
在Activity和Sevice之间跨进程通信获取自定义对象数据类型
1、在Activity新建Book类,要实现Parcelable接口
package com.aidl.entity;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
private String name;
private int price;
public Book() {
}
protected Book(Parcel in) {
name = in.readString();
price = in.readInt();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
@Override
public int describeContents() {
return 0;
}
/**
* 默认生成的模板类的对象只支持为 in 的定向 tag 。为什么呢?因为默认生成的类里面只有 writeToParcel() 方法
*
* @param dest
* @param flags
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(price);
}
/**
* 如果要支持为 out 或者 inout 的定向 tag 的话,还需要实现 readFromParcel() 方法——而这个方法其实并没有在 Parcelable 接口里面,所以需要我们从头写
*
* @param dest 参数是一个Parcel,用它来存储与传输数据
*/
public void readFromParcel(Parcel dest) {
//注意,此处的读值顺序应当是和writeToParcel()方法中一致的
name = dest.readString();
price = dest.readInt();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
}
2、新建AIDL File Book.aidl和 BookManager.aidl
// Book.aidl
//第一类AIDL文件
//这个文件的作用是引入了一个序列化对象 Book 供其他的AIDL文件使用
//注意:Book.aidl与Book.java的包名应当是一样的
package com.aidl.entity;
//interface Book {
// /**
// * 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);
//}
//注意parcelable是小写
parcelable Book;
// BookManager.aidl
//第二类AIDL文件
//作用是定义方法接口
package com.aidl.entity;
//导入所需要使用的非默认支持数据类型的包
import com.aidl.entity.Book;
interface BookManager {
/**
* 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);
//所有的返回值前都不需要加任何东西,不管是什么数据类型
List<Book> getBooks();
//传参时除了Java基本类型以及String,CharSequence之外的类型
//都需要在前面加上定向tag,具体加什么量需而定 in表从客户端到服务端
void addBook(in Book book);
}
package com.aidl.Service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.aidl.entity.Book;
import com.aidl.entity.BookManager;
import java.util.ArrayList;
import java.util.List;
public class AIDLService extends Service {
private static final String TAG = "AIDL2222";
public AIDLService() {
}
private List<Book> mBooks = new ArrayList<>();
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: AIDLService");
Book book = new Book();
book.setName("Android开发艺术探索000");
book.setPrice(28);
mBooks.add(book);
Log.i(TAG, "onCreate: AIDLService " + book.toString());
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.i(TAG, "onBind: AIDLService");
return mBookManagerStub;
}
//由AIDL文件生成的BookManager
private final BookManager.Stub mBookManagerStub = new BookManager.Stub() {
@Override
public List<Book> getBooks() throws RemoteException {
synchronized (this) {
Log.i(TAG, "getBooks: " + mBooks.toString());
return mBooks;
}
}
@Override
public void addBook(Book book) throws RemoteException {
Log.i(TAG, "Service addBook(Book book) -- : " + book.toString());
synchronized (this) {
if (mBooks == null) {
mBooks = new ArrayList<>();
}
if (book == null) {
Log.i(TAG, "Book is null in In");
book = new Book();
}
//尝试修改book的参数,主要是为了观察其到客户端的反馈
book.setPrice(2333);
if (!mBooks.contains(book)) {
mBooks.add(book);
}
//打印mBooks列表,观察客户端传过来的值
Log.i(TAG, "Service addBook(Book book)-- " + mBooks.toString());
}
}
};
}
注意在AndroidManifest.xml中Service的配置
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.aidl.main">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="com.aidl.Service.AIDLService"
android:enabled="true"
android:exported="true"
android:process=".aidlService"
>
<intent-filter>
<action android:name="com.aidl.Service.AIDLService"/>
</intent-filter>
</service>
</application>
</manifest>
4、写Activity
package com.aidl.main;
import android.app.Service;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.aidl.Utils;
import com.aidl.entity.Book;
import com.aidl.entity.BookManager;
import java.util.List;
/*
* http://blog.csdn.net/luoyanglizi/article/details/51980630
* http://blog.csdn.net/luoyanglizi/article/details/52029091
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = "AIDL2222";
//由AIDL文件生成的Java类
private BookManager mBookManager = null;
//标志当前与服务端连接状况的布尔值,false为未连接,true为连接中
private boolean isOnBind = false;
//包含Book对象的list
private List<Book> mBooks;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
private static int verson = 1;
public void addBook(View view) {
boolean isStart = Utils.isServiceWork(this, "com.aidl.Service.AIDLService");
Log.i(TAG, "addBook: isStart = " + isStart);
if (!isOnBind) {
attemptToBindService();
Toast.makeText(this, "当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show();
return;
}
if (mBookManager == null)
return;
Book book = new Book();
book.setName("APP研发宝典" + verson);
verson++;
book.setPrice(30 + verson);
Log.i(TAG, "Activity addBook: " + book.toString());
try {
mBookManager.addBook(book);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void getBooks(View view) {
if (!isOnBind) {
attemptToBindService();
Toast.makeText(this, "当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show();
return;
}
if (mBookManager == null)
return;
try {
List<Book> books = mBookManager.getBooks();
Log.i(TAG, "getBooks: " + books.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
private void attemptToBindService() {
Log.i(TAG, "attemptToBindService: ");
/* 显示启动Service,行
Intent intent = new Intent(MainActivity.this,AIDLService.class);
Log.i(TAG, "bindService()");
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
*/
final Intent intent = new Intent();
intent.setAction("com.aidl.Service.AIDLService");
// intent.setPackage("com.aidl.Service");//这样是不行的,要使用下面eintent
final Intent eintent = new Intent(Utils.createExplicitFromImplicitIntent(this, intent));
bindService(eintent, mServiceConnection, Service.BIND_AUTO_CREATE);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected: ");
mBookManager = BookManager.Stub.asInterface(service);
isOnBind = true;
if (mBookManager != null) {
try {
mBooks = mBookManager.getBooks();
Log.i(TAG, "onServiceConnected: " + mBooks.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: ");
isOnBind = false;
}
};
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.aidl.main.MainActivity"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="addBook"
android:text="添加一本书"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="getBooks"
android:text="查看所有书"/>
</LinearLayout>