Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 高級開發 >> 寫給初學者,Android AIDL必看內容

寫給初學者,Android AIDL必看內容

編輯:高級開發

 更好的設計android軟件應該熟悉掌握AIDL IPC機制,可以讓你編寫的組件類似Windows ActiveX COM一樣更好的復用,提供類似像SymBian那樣的服務器機制。服務可以很好的解決在後台運行無UI的窗口。我們創建一個aidl文件名為android123.aidl下面是示例代碼,修改於android SDK文檔。

一、創建AIDL文件

package cn.com.android123;

引入聲明 import cn.com.android123.IAtmService;

// 聲明一個接口,這裡演示的是銀行ATM程序
interface IBankAccountService {

int getAccountBalance(); //返回整數,無參數
void setOwnerNames(in List<String> names); //不返回,包含一個傳入List參數
BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService); //返回一個自定義類型
int getCustomerList(in String branch, out String[] customerList); //返回整形,輸入一個分支,輸出一個客戶列表
}

二、實現一個接口

顯示的提供一個導出接口,為客戶端提供綁定。

public class RemoteService extends Service {    @Override    public IBinder onBind(Intent intent) {        if (IRemoteService.class.getName().equals(intent.getAction())) {            return mBinder;        }        if (ISecondary.class.getName().equals(intent.getAction())) {            return mSecondaryBinder;        }        return null;    }
 //第一個接口    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {        public void registerCallback(IRemoteServiceCallback cb) {            if (cb != null) mCallbacks.register(cb);        }        public void unregisterCallback(IRemoteServiceCallback cb) {            if (cb != null) mCallbacks.unregister(cb);        }    };
//第二個接口    private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {        public int getPid() {            return Process.myPid();        }        public void basicTypes(int anInt, long aLong, boolean aBoolean,                float aFloat, double aDouble, String aString) {        }    };}

三、客戶端交互

通過android.os提供的Parcelable類型來傳遞數據,通常我們使用Eclipse+ADT插件來完成,在Eclipse中在Package Explorer vIEw視圖上單擊鼠標右鍵,選擇Create Aidl preprocess file for Parcelable classes(創建aidl預編譯文件),最終我們創建一個名為android123.aidl文件

import android.os.Parcel;
import android.os.Parcelable;

public final class Rect implements Parcelable {
public int left;
public int top;
public int right;
public int bottom;

public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect>() {
public Rect createFromParcel(Parcel in) {
return new Rect(in);
}

public Rect[] newArray(int size) {
return new Rect[size];
}
};

public Rect() {
}

private Rect(Parcel in) {
readFromParcel(in);
}

public void writeToParcel(Parcel out) { //當前數據寫入到Parcel中
out.writeInt(left);
out.writeInt(top);
out.writeInt(right);
out.writeInt(bottom);
}

public void readFromParcel(Parcel in) { //從Parcel中讀取數據
left = in.readInt();
top = in.readInt();
right = in.readInt();
bottom = in.readInt();
}
}

IPC調用方式

public class RemoteServiceBinding extends Activity {
/** The primary interface we will be calling on the service. */
IRemoteService mService = null;
/** Another interface we use on the service. */
ISecondary mSecondaryService = null;

Button mKillButton;
TextVIEw mCallbackText;

private boolean mIsBound;

/**
* Standard initialization of this activity. Set up the UI, then wait
* for the user to poke it before doing anything.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentVIEw(R.layout.remote_service_binding);

// Watch for button clicks.
Button button = (Button)findVIEwById(R.id.bind);
button.setOnClickListener(mBindListener);
button = (Button)findVIEwById(R.id.unbind);
button.setOnClickListener(mUnbindListener);
mKillButton = (Button)findVIEwById(R.id.kill);
mKillButton.setOnClickListener(mKillListener);
mKillButton.setEnabled(false);

mCallbackText = (TextVIEw)findVIEwById(R.id.callback);
mCallbackText.setText("Not attached.");
}

/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a clIEnt-side
// representation of that from the raw service object.
mService = IRemoteService.Stub.asInterface(service);
mKillButton.setEnabled(true);
mCallbackText.setText("Attached.");

// We want to monitor the service for as long as we are
// connected to it.
try {
mService.registerCallback(mCallback);
} catch (RemoteException e) {
// In this case the service has crashed before we could even
// do anything with it; we can count on soon being
// disconnected (and then reconnected if it can be restarted)
// so there is no need to do anything here.
}

// As part of the sample, tell the user what happened.
Toast.makeText(RemoteServiceBinding.this, R.string.remote_service_connected,
Toast.LENGTH_SHORT).show();
}

public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mKillButton.setEnabled(false);
mCallbackText.setText("Disconnected.");

// As part of the sample, tell the user what happened.
Toast.makeText(RemoteServiceBinding.this, R.string.remote_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};

/**
* Class for interacting with the secondary interface of the service.
*/
private ServiceConnection mSecondaryConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
// Connecting to a secondary interface is the same as any
// other interface.
mSecondaryService = ISecondary.Stub.asInterface(service);
mKillButton.setEnabled(true);
}

public void onServiceDisconnected(ComponentName className) {
mSecondaryService = null;
mKillButton.setEnabled(false);
}
};

private OnClickListener mBindListener = new OnClickListener() {
public void onClick(VIEw v) {
// Establish a couple connections with the service, binding
// by interface names. This allows other applications to be
// installed that replace the remote service by implementing
// the same interface.
bindService(new Intent(IRemoteService.class.getName()),
mConnection, Context.BIND_AUTO_CREATE);
bindService(new Intent(ISecondary.class.getName()),
mSecondaryConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
mCallbackText.setText("Binding.");
}
};

private OnClickListener mUnbindListener = new OnClickListener() {
public void onClick(VIEw v) {
if (mIsBound) {
// If we have received the service, and hence registered with
// it, then now is the time to unregister.
if (mService != null) {
try {
mService.unregisterCallback(mCallback);
} catch (RemoteException e) {
// There is nothing special we need to do if the service
// has crashed.
}
}

// Detach our existing connection.
unbindService(mConnection);
unbindService(mSecondaryConnection);
mKillButton.setEnabled(false);
mIsBound = false;
mCallbackText.setText("Unbinding.");
}
}
};

private OnClickListener mKillListener = new OnClickListener() {
public void onClick(VIEw v) {
// To kill the process hosting our service, we need to know its
// PID. ConvenIEntly our service has a call that will return
// to us that information.
if (mSecondaryService != null) {
try {
int pid = mSecondaryService.getPid();
// Note that, though this API allows us to request to
// kill any process based on its PID, the kernel will
// still impose standard restrictions on which PIDs you
// are actually able to kill. Typically this means only
// the process running your application and any additional
// processes created by that app as shown here; packages
// sharing a common UID will also be able to kill each
// other's processes.
Process.killProcess(pid);
mCallbackText.setText("Killed service process.");
} catch (RemoteException ex) {
// Recover gracefully from the process hosting the
// server dying.
// Just for purposes of the sample, put up a notification.
Toast.makeText(RemoteServiceBinding.this,
R.string.remote_call_failed,
Toast.LENGTH_SHORT).show();
}
}
}
};

// ----------------------------------------------------------------------
// Code showing how to deal with callbacks.
// ----------------------------------------------------------------------

/**
* This implementation is used to receive callbacks from the remote
* service.
*/
private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
/**
* This is called by the remote service regularly to tell us about
* new values. Note that IPC calls are dispatched through a thread
* pool running in each process, so the code executing here will
* NOT be running in our main thread like most other things -- so,
* to update the UI, we need to use a Handler to hop over there.
*/
public void valueChanged(int value) {
mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0));
}
};

private static final int BUMP_MSG = 1;

private Handler mHandler = new Handler() {
@Override public void handleMessage(Message msg) {
switch (msg.what) {
case BUMP_MSG:
mCallbackText.setText("Received from service: " + msg.arg1);
break;
default:
super.handleMessage(msg);
}
}

};
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved