編輯: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當道,現在學習Android開發還晚嗎?寫下這個問題的時間是–2014年6月15號,我會回答:不晚,Android至少還能在活躍10年!所以答應自己
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
在移動應用滿天飛的時代,隨著移動支付的盛行,很多應用中都集成了支付功能。之前的支付一直不是我負責,近期這個項目我負責訂單模塊少不了要做支付,每每提起
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我