- callback作为函数参数进行回调
- RemoteCallbackList注册回调
//实现了Parcelable接口的类
package com.example.xiaopeng.androiddemo.Service;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by xiaopeng on 13/01/2017.
*/
public class Book implements Parcelable {
String name;
int price;
public Book(){}
protected Book(Parcel in) {
name = in.readString();
price = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(price);
}
/**
* 参数是一个Parcel,用它来存储与传输数据
* @param dest
*/
public void readFromParcel(Parcel dest) {
//注意,此处的读值顺序应当是和writeToParcel()方法中一致的
name = dest.readString();
price = dest.readInt();
}
@Override
public int describeContents() {
return 0;
}
//方便打印数据
@Override
public String toString() {
return "name : " + name + " , price : " + price;
}
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];
}
};
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;
}
}
// Book.aidl
//第一类AIDL文件
//这个文件的作用是引入了一个序列化对象 Book 供其他的AIDL文件使用
//注意:Book.aidl与Book.java的包名应当是一样的
package com.example.xiaopeng.androiddemo.Service;
parcelable Book;
// BookManager.aidl
//第二类AIDL文件
//作用是定义方法接口
package com.example.xiaopeng.androiddemo.Service;
//导入所需要使用的非默认支持数据类型的包
import com.example.xiaopeng.androiddemo.Service.Book;
import com.example.xiaopeng.androiddemo.Service.ISimpleCallback;
interface BookManager {
//所有的返回值前都不需要加任何东西,不管是什么数据类型
List<Book> getBooks();
//传参时除了Java基本类型以及String,CharSequence之外的类型
//都需要在前面加上定向tag,具体加什么量需而定
void addBook(in Book book);
//演示简单的回调
void startCount(int to, ISimpleCallback callback);
//可以脱离函数,注册多个回调
void registerCallback(int id, ISimpleCallback callback);
void unregisterCallback(int id, ISimpleCallback callback);
}
// ISimpleCallback.aidl
//第三类AIDL文件
//作用是定义回调接口
package com.example.xiaopeng.androiddemo.Service;
// Declare any non-default types here with import statements
interface ISimpleCallback {
void handleCount(int count);
}
// Service
package com.example.xiaopeng.androiddemo.Service;
import android.app.Service;
import android.content.Intent;
import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Created by xiaopeng on 13/01/2017.
*/
public class AIDLService extends Service {
private final String TAG = AIDLService.class.getSimpleName();
private List<Book> mBooks = new ArrayList<>();
private RemoteCallbackList<ISimpleCallback> mCallbacks = new RemoteCallbackList<>();
private BookManager.Stub bookManager = new BookManager.Stub() {
@Override
public List<Book> getBooks() throws RemoteException {
return mBooks;
}
@Override
public void addBook(Book book) throws RemoteException {
// TODO
}
@Override
public void startCount(final int to, final ISimpleCallback callback) throws RemoteException {
Thread t = new Thread()
{
/*睡! */
public void preciseSleep(long millis)
{
long endTime = System.currentTimeMillis() + millis;
do {
try
{
Thread.sleep(endTime - System.currentTimeMillis());
}
catch (InterruptedException e)
{}
} while (System.currentTimeMillis() < endTime);
}
public void run()
{
for (int i = 1; i <= to; i++)
{
preciseSleep(1000);
//simpleCallbackToClient(callback, i);
callbackToClient(i);
}
}
};
t.start();
}
private void simpleCallbackToClient(ISimpleCallback callback, int counter){
try
{
// simple callback
callback.handleCount(counter);
}
// AIDL中唯一可能抛出的异常
catch (DeadObjectException e)
{
Log.d(TAG, "Dead peer, aborting...", e);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private void callbackToClient(int counter){
int count = mCallbacks.beginBroadcast();
try {
for (int i = 0; i < count; i++) {
Log.d(TAG, "callbackToClient...");
mCallbacks.getBroadcastItem(i).handleCount(counter);
}
} catch (RemoteException e) {
Log.e(TAG, "E/onUpdateMetaDatas", e);
} finally {
mCallbacks.finishBroadcast();
}
}
@Override
public void registerCallback(int id, ISimpleCallback callback) throws RemoteException {
mCallbacks.register(callback);
}
@Override
public void unregisterCallback(int id, ISimpleCallback callback) throws RemoteException {
mCallbacks.unregister(callback);
}
};
@Override
public void onCreate() {
super.onCreate();
Book book = new Book();
book.setName("Android开发艺术探索");
book.setPrice(28);
mBooks.add(book);
}
@Override
public void onDestroy() {
super.onDestroy();
// 取消掉所有的回调
mCallbacks.kill();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return bookManager;
}
}
// Client
package com.exstudio.testing;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.xiaopeng.androiddemo.Service.Book;
import com.example.xiaopeng.androiddemo.Service.BookManager;
import com.example.xiaopeng.androiddemo.Service.ISimpleCallback;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private final String TAG = MainActivity.class.getSimpleName();
Button get_books_btn;
Button service_simle_callback_btn;
//由AIDL文件生成的Java类
private BookManager mBookManager = null;
//标志当前与服务端连接状况的布尔值,false为未连接,true为连接中
private boolean mBound = false;
//包含Book对象的list
private List<Book> mBooks;
private Handler mHandler = new Handler();
private boolean mCounting = false;
private TextView mCounterText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
get_books_btn = (Button) this.findViewById(R.id.get_books_btn);
service_simle_callback_btn = (Button) this.findViewById(R.id.service_simle_callback);
mCounterText = (TextView) this.findViewById(R.id.counter_text);
get_books_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mBound == true){
for (Book book : mBooks) {
Log.i(getLocalClassName(), book.getName());
}
}
}
});
service_simle_callback_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mBookManager == null)
{
Log.d(TAG, "Nothing to do!");
return;
}
if (mCounting)
{
Log.d(TAG, "mCounter is implemented globally and cannot be reused while counting is in progress.");
return;
}
try
{
mCounting = true;
mBookManager.startCount(10, serviceCallback);
Log.d(TAG, "Counting has begun...");
}
catch (DeadObjectException e)
{
mCounting = false;
Log.d(TAG, Log.getStackTraceString(e));
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onStart() {
super.onStart();
if (!mBound) {
attemptToBindService();
}
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mServiceConnection);
mBound = false;
}
}
/**
* 尝试与服务端建立连接
*/
private void attemptToBindService() {
Intent intent = new Intent();
intent.setAction("com.example.xiaopeng.androiddemo.Service.AIDLService");
intent.setPackage("com.example.xiaopeng.androiddemo");
boolean ret = bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
if(ret == false){
Log.d("main activity", "failed to binding remote service !");
}
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(getLocalClassName(), "service connected");
mBookManager = BookManager.Stub.asInterface(service);
mBound = true;
if (mBookManager != null) {
try {
mBookManager.registerCallback(0, serviceCallback);
mBooks = mBookManager.getBooks();
Log.e(getLocalClassName(), mBooks.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
try {
mBookManager.unregisterCallback(0, serviceCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
Log.e(getLocalClassName(), "service disconnected");
mBound = false;
}
};
//mService.startCount(10, mCounter)中的参数,回调之后用来刷新界面
// 此处用来setText, 该stub 也是IAsyncServiceCounter里的内部类。
private ISimpleCallback.Stub serviceCallback = new ISimpleCallback.Stub()
{
public void handleCount(final int n)
{
Log.d(TAG, "handleCount(" + n + ")");
mHandler.post(new Runnable()
{
public void run()
{
// 不要这样写立即数
if (n == 10)
{
mCounterText.setText("Done!");
mCounting = false;
}
else
mCounterText.setText(String.valueOf(n));
}
});
}
};
}