編輯:關於Android編程
關於startService的基本使用概述及其生命周期可參見《Android中startService基本使用方法概述》。
本文通過播放背景音樂的簡單示例,演示startService的基本使用流程,具體內容如下
系統界面如下:
界面上面就兩個按鈕,”播放音樂並退出Activity” 和 “停止播放音樂”。我們在該示例中,通過操縱Activity的按鈕控制MusicService播放或停止播放音樂。
我將一個名為music.mp3的放到資源目錄/res/raw文件夾下面,這樣我們在程序中就可以通過R.raw.music引用該音樂文件,放入/res/raw文件夾中的資源文件會保持原來的面貌不會被編譯成二進制。
MusicService是用於播放背景音樂的Service,其代碼如下所示:
package com.ispring.startservicedemo; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; import android.widget.Toast; import java.io.IOException; public class MusicService extends Service { private MediaPlayer mediaPlayer = null; private boolean isReady = false; @Override public void onCreate() { //onCreate在Service的生命周期中只會調用一次 super.onCreate(); //初始化媒體播放器 mediaPlayer = MediaPlayer.create(this, R.raw.music); if(mediaPlayer == null){ return; } mediaPlayer.stop(); mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { mp.release(); stopSelf(); return false; } }); try{ mediaPlayer.prepare(); isReady = true; } catch (IOException e) { e.printStackTrace(); isReady = false; } if(isReady){ //將背景音樂設置為循環播放 mediaPlayer.setLooping(true); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { //每次調用Context的startService都會觸發onStartCommand回調方法 //所以onStartCommand在Service的生命周期中可能會被調用多次 if(isReady && !mediaPlayer.isPlaying()){ //播放背景音樂 mediaPlayer.start(); Toast.makeText(this, "開始播放背景音樂", Toast.LENGTH_LONG).show(); } return START_STICKY; } @Override public IBinder onBind(Intent intent) { //該Service中不支持bindService方法,所以此處直接返回null return null; } @Override public void onDestroy() { //當調用Context的stopService或Service內部執行stopSelf方法時就會觸發onDestroy回調方法 super.onDestroy(); if(mediaPlayer != null){ if(mediaPlayer.isPlaying()){ //停止播放音樂 mediaPlayer.stop(); } //釋放媒體播放器資源 mediaPlayer.release(); Toast.makeText(this, "停止播放背景音樂", Toast.LENGTH_LONG).show(); } } }
MusicActivity的代碼如下所示:
package com.ispring.startservicedemo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MusicActivity extends Activity implements Button.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_music); } @Override public void onClick(View v) { if(v.getId() == R.id.btnStart){ //播放背景音樂 Intent intent = new Intent(this, MusicService.class); startService(intent); //退出當前Activity this.finish(); }else if(v.getId() == R.id.btnStop){ //停止播放音樂 Intent intent = new Intent(this, MusicService.class); stopService(intent); } } }
當我們單擊了按鈕”播放音樂並退出Activity”之後,我們首先通過Activity的startService啟動MusicService,然後我們立即調用了Activity的finish方法銷毀了當前的Activity。可能大家會問為什麼要銷毀當前的Activity?我們此處之所以調用Activity的finish方法不是從功能的角度出發的,而是從理解代碼運行的角度故意這麼寫的: 執行完Activity的finish方法之後,當前的Activity就銷毀了, 在界面上看起來就是當前UI消失了,應用程序退出了,但稍等片刻你會聽到背景音樂響起。這從側面印證了Service的一個特性: Service與Activity等一樣,也是一種基本的應用程序組件,Service無需依賴任何的Activity便可獨自在沒有任何UI界面的情況下悠閒地在Android後台默默運行。
調用了startService之後,Android Framework接收到了intent信息,第一次會先創建MusicService的實例,執行MusicService的onCreate回調方法,onCreate在Service的生命周期中只會調用一次,我們在其onCreate方法中將R.raw.music初始化為媒體播放器,並調用媒體播放器的prepare方法。然後我們將播放器設置為循環播放狀態。需要注意的是,在實際生產環境中,我們應該注冊播放器的setOnPreparedListener並調用prepareAsync()方法,為了簡化代碼起見,我們只調用了播放器的同步方法prepare()。
調用了onCreate方法後,Android會自動回調其onStartCommand方法,其實每次調用Context的startService都會觸發onStartCommand回調方法,所以onStartCommand在Service的生命周期中可能會被調用多次。所以我們在MusicService的onStartCommand中做了判斷,判斷播放器是否是在播放中,如果當前播放器沒有播放我們才調用播放器的start方法播放背景音樂。
當我們單擊了按鈕”播放音樂並退出Activity”之後,MusicService啟動起來,播放背景音樂,但是Activity卻銷毀了,程序的UI界面不見了。為了能夠停止播放背景音樂,我們需要再次單擊應用程序圖標,重新打開MusicActivity,然後單擊界面上的”停止播放音樂”按鈕,此時我們會調用Activity的stopService方法,Android Framework接收到要停止服務的intent之後會回調MusicService的onDestroy方法,在該方法中我們停止播放音樂並釋放媒體播放器資源。
本文只是通過播放背景音樂這一簡單示例演示通過startService啟動Service基本使用流程,代碼沒有進行優化,希望對大家學習Service有所幫助。
前言 上一篇文章揭開RecyclerView的神秘面紗(一):RecyclerView的基本使用中,主要講述了RecyclerView的基本使用方法,不同的布局管理器而
昨天給大家粗略的介紹了一下我那個簡單的項目:Android之基於XMPP協議即時通訊軟件(一) 從今天開始,就詳細展開的介紹設計思路,一是給自己做個總結,二
繪制曲線類:public class BaseFundChartView extends View { Paint linePaint; Paint text
在android app開發中,有的時候會有這樣的需求,就是當用戶卸載了我們的app的時候,如果可以搜集用戶的反饋信息,那樣是極好的,今天帶大家手把手實現這樣的功能,先說