編輯:Android開發實例
Service是android 系統中的一種組件,它跟Activity的級別差不多,但是他不能自己運行,只能後台運行,並且可以和其他組件進行交互。Service的啟動有兩種方式:context.startService() 和 context.bindService()。
使用context.startService() 啟動Service是會會經歷:
context.startService() ->onCreate()- >onStart()->Service running
context.stopService() | ->onDestroy() ->Service stop
如果Service還沒有運行,則android先調用onCreate()然後調用onStart();如果Service已經運行,則只調用onStart(),所以一個Service的onStart方法可能會重復調用多次。
stopService的時候直接onDestroy,如果是調用者自己直接退出而沒有調用stopService的話,Service會一直在後台運行。該Service的調用者再啟動起來後可以通過stopService關閉Service。
所以調用startService的生命周期為:onCreate --> onStart(可多次調用) --> onDestroy
使用使用context.bindService()啟動Service會經歷:
context.bindService()->onCreate()->onBind()->Service running
onUnbind() -> onDestroy() ->Service stop
onBind將返回給客戶端一個IBind接口實例,IBind允許客戶端回調服務的方法,比如得到Service運行的狀態或其他操作。這個時候把調用者(Context,例如Activity)會和Service綁定在一起,Context退出了,Srevice就會調用onUnbind->onDestroy相應退出。
所以調用bindService的生命周期為:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。
在Service每一次的開啟關閉過程中,只有onStart可被多次調用(通過多次startService調用),其他onCreate,onBind,onUnbind,onDestory在一個生命周期中只能被調用一次。
service可以在和多場合的應用中使用,比如播放多媒體的時候用戶啟動了其他Activity這個時候程序要在後台繼續播放,比如檢測SD卡上文件的變化,再或者在後台記錄你地理信息位置的改變等等,總之服務嘛,總是藏在後頭的。
下面我做了一個簡單的音樂播放的應用,分別使用startService和bindService來啟動本地的服務。
而在下一篇《android service 學習(下) 》會介紹通過AIDL對Service進行遠程調用。
下面是整個應用啟動界面:
先從使用startService啟動Service學起
首先編寫一個Activity
public class PlayMusic extends Activity implements OnClickListener {
private static final String TAG = "PlayMusic";
private Button playBtn;
private Button stopBtn;
private Button pauseBtn;
private Button exitBtn;
private Button closeBtn;
//....(詳見源碼)
@Override
public void onClick(View v) {
int op = -1;
Intent intent = new Intent("org.allin.android.musicService");
//廣播用
// Intent intent = new Intent("org.allin.android.musicReceiver");
switch (v.getId()) {
case R.id.play:
Log.d(TAG, "onClick: playing muic");
op = 1;
break;
case R.id.stop:
Log.d(TAG, "onClick: stoping music");
op = 2;
break;
case R.id.pause:
Log.d(TAG, "onClick: pausing music");
op = 3;
break;
case R.id.close:
Log.d(TAG, "onClick: close");
this.finish();
break;
case R.id.exit:
Log.d(TAG, "onClick: exit");
op = 4;
stopService(intent);
this.finish();
break;
}
Bundle bundle = new Bundle();
bundle.putInt("op", op);
intent.putExtras(bundle);
startService(intent);
// sendBroadcast(intent);
}
}
通過重寫onClick方法來實現對播放音樂的控制。這裡把播放音樂的各種操作用數字的方式通過Intent傳遞給service。
構造一個Intent ,ntent intent = new Intent("org.allin.android.musicService");
"org.allin.android.musicService"是在AndroidManifest.xml文件中對service類的定義
<service android:enabled="true" android:name=".MusicService"> <intent-filter> <action android:name="org.allin.android.musicService" /> </intent-filter> </service>
把操作碼放在Bundle中
Bundle bundle = new Bundle();
bundle.putInt("op", op);
intent.putExtras(bundle);
最後使用startService(intent);啟動服務。
下面看看Service是怎麼實現的。
MusicService.java
/**
* @author allin.dev
* http://allin.cnblogs.com/
*
*/
public class MusicService extends Service {
private static final String TAG = "MyService";
private MediaPlayer mediaPlayer;
/*
* (non-Javadoc)
*
* @see android.app.Service#onBind(android.content.Intent)
*/
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
Log.v(TAG, "onCreate");
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(this, R.raw.tmp);
mediaPlayer.setLooping(false);
}
}
@Override
public void onDestroy() {
Log.v(TAG, "onDestroy");
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
@Override
public void onStart(Intent intent, int startId) {
Log.v(TAG, "onStart");
if (intent != null) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
int op = bundle.getInt("op");
switch (op) {
case 1:
play();
break;
case 2:
stop();
break;
case 3:
pause();
break;
}
}
}
}
public void play() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
public void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
public void stop() {
if (mediaPlayer != null) {
mediaPlayer.stop();
try {
// 在調用stop後如果需要再次通過start進行播放,需要之前調用prepare函數
mediaPlayer.prepare();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
服務 使用了系統自帶MediaPlayer進行音樂的播放控制。 當調用了startService後服務會先調用onCreate,我們在裡面對MediaPlayer進行初始化。接著會調用onStart,可以看到傳遞給startService()的Intent對象會傳遞給onStart()方法,這樣我們就可以得到intent裡面的操作碼:
Iundle bundle = intent.getExtras();
int op = bundle.getInt("op");
然後更具定義好的操作碼進行相應的f播放操作。啟動後界面如下圖:
圖中的”close”和“exit”是不同的,close只是調用finish()退出當前的Activity,但是Service並沒有關掉,音樂會繼續播放。而exit就是調用了stopService(intent);來停止服務,Service會調用onDestroy()方法來對mediaPlayer進行停止和釋放資源。
有時候如果服務只提供一些操作接口,我們也可以通過廣播的g方式來啟動服務。
首先要定義一個Receiver,並繼承BroadcastReceiver,然後在AndroidManifest.xml中進行注冊:
<receiver android:name=".MusicReceiver"> <intent-filter> <action android:name="org.allin.android.musicReceiver" /> </intent-filter> </receiver>
Receiver的實現:
MusicReceiver.java
/**
* @author allin.dev
* http://allin.cnblogs.com/
*
*/
public class MusicReceiver extends BroadcastReceiver {
private static final String TAG = "MusicReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive");
Intent it = new Intent("org.allin.android.musicService");
Bundle bundle = intent.getExtras();
it.putExtras(bundle);
if(bundle != null){
int op = bundle.getInt("op");
if(op == 4){
context.stopService(it);
}else{
context.startService(it);
}
}
}
}
然後對PlayMusic中的onclick方法進行些改造,把Intent指向Receiver
Intent intent = new Intent("org.allin.android.musicReceiver");
intent中綁定的操作碼都不變,再調用sendBroadcast(intent);把intentg廣播出去。
當MusicReceiver接受到廣播後根據操作碼進行相應的操作。
接下來的例子就是使用bindService來啟動Service
首先一樣是寫一個Activity
public class PlayBindMusic extends Activity implements OnClickListener {
private static final String TAG = "PlayBindMusic";
private Button playBtn;
private Button stopBtn;
private Button pauseBtn;
private Button exitBtn;
private BindMusicService musicService;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.play:
Log.d(TAG, "onClick: binding srvice");
musicService.play();
break;
case R.id.stop:
Log.d(TAG, "onClick: stoping srvice");
if(musicService != null){
musicService.stop();
}
break;
case R.id.pause:
Log.d(TAG, "onClick: pausing srvice");
if(musicService != null){
musicService.pause();
}
break;
case R.id.exit:
Log.d(TAG, "onClick: exit");
this.finish();
break;
}
}
private void connection(){
Log.d(TAG, "connecting.....");
Intent intent = new Intent("org.allin.android.bindService");
bindService(intent, sc, Context.BIND_AUTO_CREATE);
}
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 = ((BindMusicService.MyBinder)(service)).getService();
if(musicService != null){
musicService.play();
}
Log.d(TAG, "in onServiceConnected");
}
};
}
這裡使用了bindService(intent, sc, Context.BIND_AUTO_CREATE);來啟動服務的,
我們需要定義ServiceConnectionnn,並實現裡面的方法,當服務綁定成功後會調用ServiceConnectionnn中的回調函數:
public void onServiceConnected(ComponentName name, IBinder service),
回調函數裡面使用musicService = ((BindMusicService.MyBinder)(service)).getService();來獲取BindMusicService服務對象,有了BindMusicService實例對象,就可以調用服務提供的各種控制音樂播放的哦功能。
下面看看BindMusicService.java的實現:
/**
* @author allin.dev
* http://allin.cnblogs.com/
*/
public class BindMusicService extends Service {
private static final String TAG = "MyService";
private MediaPlayer mediaPlayer;
private final IBinder binder = new MyBinder();
public class MyBinder extends Binder {
BindMusicService getService() {
return BindMusicService.this;
}
}
/*
* (non-Javadoc)
*
* @see android.app.Service#onBind(android.content.Intent)
*/
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
play();
return binder;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show();
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT);
if(mediaPlayer != null){
mediaPlayer.stop();
mediaPlayer.release();
}
}
public void play() {
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(this, R.raw.tmp);
mediaPlayer.setLooping(false);
}
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
public void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
public void stop() {
if (mediaPlayer != null) {
mediaPlayer.stop();
try {
// 在調用stop後如果需要再次通過start進行播放,需要之前調用prepare函數
mediaPlayer.prepare();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
我們看到Service中有個返回IBinder對象的onBind方法,這個方法會在Service被綁定到其他程序上時被調用,而這個IBinder對象和之前看到的onServiceConnected方法中傳入的那個IBinder是同一個東西。應用和Service間就依靠這個IBinder對象進行通信。
啟動後的界面如下圖:
[源碼下載]
Android開發自學筆記(一):Hello,world!
Android當道,現在學習Android開發還晚嗎?寫下這個問題的時間是–2014年6月15號,我會回答:不晚,Android至少還能在活躍10年!所以答應自己
Android MediaPlayer(多媒體播放)
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
Android支付寶支付開發實例
在移動應用滿天飛的時代,隨著移動支付的盛行,很多應用中都集成了支付功能。之前的支付一直不是我負責,近期這個項目我負責訂單模塊少不了要做支付,每每提起
Android本地化
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我