android service 學習(下)
android service 學習(下)
通常每個應用程式都在它自己的程序內執行,但有時需要在程序間傳遞物件,你可以通過應用程式UI的方式寫個執行在一個不同的程序中的service。在android平臺中,一個程序通常不能訪問其他程序中的記憶體區域。所以,他們需要把物件拆分成作業系統能理解的簡單形式,以便偽裝成物件跨越邊界訪問。編寫這種偽裝程式碼相當的枯燥乏味,好在android為我們提供了AIDL工具可以來做這件事。
AIDL(android介面描述語言)是一個IDL語言,它可以生成一段程式碼,可以使在一個android裝置上執行的兩個程序使用內部通訊程序進行互動。如果你需要在一個程序中(例如:在一個Activity中)訪問另一個程序中(例如:一個Service)某個物件的方法,你就可以使用AIDL來生成這樣的程式碼來偽裝傳遞各種引數。
要使用AIDL,Service需要以aidl檔案的方式提供服務介面,AIDL工具將生成一個相應的java介面,並且在生成的服務介面中包含一個功能呼叫的stub服務樁類。Service的實現類需要去繼承這個stub服務樁類。Service的onBind方法會返回實現類的物件,之後你就可以使用它了,參見下例:
先建立一個IMyRemoteService.aidl檔案
package org.allin.android.remote; interface IMusicControlService{ void play(); void stop(); void pause(); }
如果你正在使用eclipse的Android外掛,則它會根據這個aidl檔案生成一個Java介面類。生成的介面類中會有一個內部類Stub類,你要做的事就是去繼承該Stub類:
/** * @author allin.dev * http://allin.cnblogs.com/ * */ public class RemoteMusicService extends Service { private static final String TAG = "RemoteMusicService"; private MediaPlayer mediaPlayer; /* * (non-Javadoc) * * @see android.app.Service#onBind(android.content.Intent) */ @Override public IBinder onBind(Intent intent) { return binder; } private final IMusicControlService.Stub binder = new IMusicControlService.Stub() { @Override public void stop() throws RemoteException { Log.d(TAG,"stop...."); if (mediaPlayer != null) { mediaPlayer.stop(); try { // 在呼叫stop後如果需要再次通過start進行播放,需要之前呼叫prepare函式 mediaPlayer.prepare(); } catch (IOException ex) { ex.printStackTrace(); } } } @Override public void play() throws RemoteException { Log.d(TAG,"play...."); if (mediaPlayer == null) { mediaPlayer = MediaPlayer.create(RemoteMusicService.this, R.raw.tmp); mediaPlayer.setLooping(false); } if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } } @Override public void pause() throws RemoteException { Log.d(TAG,"pause...."); if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } }; @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); if(mediaPlayer != null){ mediaPlayer.stop(); mediaPlayer.release(); } } }
當客戶端應用連線到這個Service時,onServiceConnected方法將被呼叫,客戶端就可以獲得IBinder物件。參看下面的客戶端onServiceConnected方法:
private ServiceConnection sc = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
musicService = null;
Log.d(TAG, "in onServiceDisconnected");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
musicService = IMusicControlService.Stub.asInterface(service);
Log.d(TAG, "in onServiceConnected");
}
};
啟動後的介面如下
[原始碼下載]