android服務的應用,在Activity中實現背景音樂播放

在android應用程序裡,有一種沒有UI的類(android.app.Service)——Service。簡單來說,Service是一個 background process(背景程序),通過背景程序,可以實現一些不需要UI的功能,比如播放背景音樂。

下面是一個實現播放背景音樂的例程:

在上個工程的基礎上,在Activity中添加音樂播放功能。

在工程中添加一個新類yypService(File->New->Class):

[java]  </pre><pre name="code" class="java">import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
 
public class yypService extends Service { 
 
    @Override 
    public IBinder onBind(Intent intent) { 
        // TODO Auto-generated method stub  
        return null; 
    } 
 

</pre><pre name="code" class="java">import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class yypService extends Service {

 @Override
 public IBinder onBind(Intent intent) {
  // TODO Auto-generated method stub
  return null;
 }

}

yypService 類繼承 android.app.Service,幾個有關Service 的重要概念如下:

1. Service 對象以 separated process 的方式執行,這表示 Service 與 UI(Activity)並不在同一個 process 裡執行,而是各自在不同的 process 執行。

2. Android應用程序是在 Activity 啟動與停止 Service。

3. 重載(override)onStart() 方法(method)在 Service 被啟動,執行我們想要的背景功能。

4. 重載 onDestroy() 方法在 Service 被停止時,停止執行中的背景功能。

下面是Service的具體實現:

[java] package com.android; 
 
import java.io.IOException; 
 
import android.app.Service; 
import android.content.Intent; 
import android.media.MediaPlayer; 
import android.os.IBinder; 
 
public class yypService extends Service { 
    private MediaPlayer mp; 
 
    @Override 
    public void onStart(Intent intent, int startId) { 
        // TODO Auto-generated method stub  
        // 開始播放音樂  
        mp.start(); 
        // 音樂播放完畢的事件處理  
        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
 
            public void onCompletion(MediaPlayer mp) { 
                // TODO Auto-generated method stub  
                // 循環播放  
                try { 
                    mp.start(); 
                } catch (IllegalStateException e) { 
                    // TODO Auto-generated catch block  
                    e.printStackTrace(); 
                } 
            } 
        }); 
        // 播放音樂時發生錯誤的事件處理  
        mp.setOnErrorListener(new MediaPlayer.OnErrorListener() { 
 
            public boolean onError(MediaPlayer mp, int what, int extra) { 
                // TODO Auto-generated method stub  
                // 釋放資源  
                try { 
                    mp.release(); 
                } catch (Exception e) { 
                    e.printStackTrace(); 
                } 
 
                return false; 
            } 
        }); 
 
        super.onStart(intent, startId); 
    } 
 
    @Override 
    public void onCreate() { 
        // TODO Auto-generated method stub  
        // 初始化音樂資源  
        try { 
            // 創建MediaPlayer對象  
            mp = new MediaPlayer(); 
            // 將音樂保存在res/raw/xingshu.mp3,R.java中自動生成{public static final int xingshu=0x7f040000;}  
            mp = MediaPlayer.create(yypService.this, R.raw.xingshu); 
            // 在MediaPlayer取得播放資源與stop()之後要準備PlayBack的狀態前一定要使用MediaPlayer.prepeare()  
            mp.prepare(); 
        } catch (IllegalStateException e) { 
            // TODO Auto-generated catch block  
            e.printStackTrace(); 
        } catch (IOException e) { 
            // TODO Auto-generated catch block  
            e.printStackTrace(); 
        } 
 
        super.onCreate(); 
    } 
 
    @Override 
    public void onDestroy() { 
        // TODO Auto-generated method stub  
        // 服務停止時停止播放音樂並釋放資源  
        mp.stop(); 
        mp.release(); 
 
        super.onDestroy(); 
    } 
 
    @Override 
    public IBinder onBind(Intent intent) { 
        // TODO Auto-generated method stub  
        return null; 
    } 
 

package com.android;

import java.io.IOException;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;

public class yypService extends Service {
 private MediaPlayer mp;

 @Override
 public void onStart(Intent intent, int startId) {
  // TODO Auto-generated method stub
  // 開始播放音樂
  mp.start();
  // 音樂播放完畢的事件處理
  mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

   public void onCompletion(MediaPlayer mp) {
    // TODO Auto-generated method stub
    // 循環播放
    try {
     mp.start();
    } catch (IllegalStateException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  });
  // 播放音樂時發生錯誤的事件處理
  mp.setOnErrorListener(new MediaPlayer.OnErrorListener() {

   public boolean onError(MediaPlayer mp, int what, int extra) {
    // TODO Auto-generated method stub
    // 釋放資源
    try {
     mp.release();
    } catch (Exception e) {
     e.printStackTrace();
    }

    return false;
   }
  });

  super.onStart(intent, startId);
 }

 @Override
 public void onCreate() {
  // TODO Auto-generated method stub
  // 初始化音樂資源
  try {
   // 創建MediaPlayer對象
   mp = new MediaPlayer();
   // 將音樂保存在res/raw/xingshu.mp3,R.java中自動生成{public static final int xingshu=0x7f040000;}
   mp = MediaPlayer.create(yypService.this, R.raw.xingshu);
   // 在MediaPlayer取得播放資源與stop()之後要準備PlayBack的狀態前一定要使用MediaPlayer.prepeare()
   mp.prepare();
  } catch (IllegalStateException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

  super.onCreate();
 }

 @Override
 public void onDestroy() {
  // TODO Auto-generated method stub
  // 服務停止時停止播放音樂並釋放資源
  mp.stop();
  mp.release();

  super.onDestroy();
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO Auto-generated method stub
  return null;
 }

}
至此,一個完整的服務生成,接下來是在Activity中啟動服務。

修改 AndroidManifest.xml

在 Package Explorer 視窗裡找到目前 Android 項目的資訊描述檔,名稱為 AndroidManifest.xml。這是一個用來描述 Android 應用程序「整體資訊」的文件,每個 Android 應用程序項目都會有一個。在這裡修改 Androidmanifest.xml 的目的是為瞭「 Android 應用程序加入一個 Service 類別」,這樣才有辦法驅動 Service。

[html] <?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.android" 
    android:versionCode="1" 
    android:versionName="1.0" > 
 
    <uses-sdk android:minSdkVersion="10" /> 
 
    <application 
        android:icon="@drawable/ic_launcher" 
        android:label="@string/app_name" > 
        <activity 
            android:name=".WebTestActivity" 
            android:label="@string/app_name" > 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
        </activity> 
        <service 
            android:name=".yypService" 
            android:exported="true" 
            android:process=":remote"> 
             
        </service> 
         
    </application> 
 
</manifest> 
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".WebTestActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
   android:name=".yypService"
   android:exported="true"
   android:process=":remote">
           
        </service>
       
    </application>

</manifest>
配置好之後,接下來就是在Activity中添加啟動服務代碼 Service – startService()。

在OnCreate()中添加如下代碼:

[java] Intent intent = new Intent(WebTestActivity.this,yypService.class); 
startService(intent); 
        Intent intent = new Intent(WebTestActivity.this,yypService.class);
        startService(intent);

Activity 類裡有一個 method 叫做 startService:

startService(Intent service)
調用 startService() 即可啟動一個 Service ,隻是,startService() 的參數是一個「Intent」型,並不是所要啟動的類名。「Intent」是一個很像「Event」的類,暫時還沒對Intent做深入研究,就先把它當作一個"Event"看吧?

現在,其實已經可以在Activity中播放背景音樂瞭,但有一個小問題,就是Activity已經被掛起或是被銷毀時,背景音樂還是在繼續播放的,這也說明Service與Activity是兩個不同的進程,我們收下尾,讓Activity在OnStop時把背景音樂也停止播放,重載Activity的OnStop:

[java] @Override 
protected void onStop() { 
    // TODO Auto-generated method stub  
    Intent intent = new Intent(WebTestActivity.this,yypService.class); 
    stopService(intent); 
    super.onStop(); 

 @Override
 protected void onStop() {
  // TODO Auto-generated method stub
  Intent intent = new Intent(WebTestActivity.this,yypService.class);
  stopService(intent);
  super.onStop();
 }
備註:eclipse的使用小技巧,快速補全重載代碼(快捷鍵Alt+Shift+s ->  Override/implement Mothods)。

至此,一個完整的播放背景音樂功能已經全部完成。

 

 

摘自 Young的專欄

發佈留言