編輯:關於Android編程
關於startService的基本使用概述及其生命周期可參見博客《Android中startService的使用及Service生命周期》。
本文通過播放背景音樂的簡單示例,演示startService的基本使用流程。
系統界面如下:
界面上面就兩個按鈕,”播放音樂並退出Activity” 和 “停止播放音樂”。我們在該示例中,通過操縱Activity的按鈕控制MusicService播放或停止播放音樂。
我將一個名為music.mp3的放到資源目錄/res喎?/kf/ware/vc/" target="_blank" class="keylink">vcmF3zsS8/rzQz8LD5qOs1eLR+c7Sw8fU2rPM0PLW0L7Nv8nS1M2ouf1SLnJhdy5tdXNpY9L908O4w9L0wNbOxLz+o6y3xcjrL3Jlcy9yYXfOxLz+vNDW0LXE18rUtM7EvP674bGjs9bUrcC0tcTD5sOysru74bG7seDS67PJtv69+NbGoaM8L3A+DQo8cD5NdXNpY1NlcnZpY2XKytPD09qypbfFsbO+sNL0wNa1xFNlcnZpY2WjrMbktPrC68jnz8LL+cq+OjwvcD4NCjxwcmUgY2xhc3M9"brush:java;">
package com.ispring.startservicedemo;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
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();
}
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();
}
}
}
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有所幫助。
我們在開發中經常用到倒計時的功能,比如發送驗證碼後,倒計時60s再進行驗證碼的獲取,為了方便以後使用,這裡做個記錄,講講倒計時器的實現。 1、先進行倒計時工具類
識別身份證信息需要用到圖像處理的知識,無奈水平不夠,於是尋找第三方接口,但是找到的都是收費的,後來找到一個叫雲脈的產品http://ocr.ccyunmai.com/,發
先來看看效果圖跳動的小球做這個動畫,需掌握: 1、屬性動畫 2、Path類
最近開發App,美工設計了一個有鋸齒邊沿效果的背景圖,只給了我一個鋸齒,然後需要平鋪展示鋸齒效果: android中實現平鋪圖片有兩種方式:(1)在drawable中的d