android 四大元件service 音樂播放器的實現
阿新 • • 發佈:2018-12-30
- 新建立一個Android工程《音樂播放器》,包名:com.itheima.musicPlayer。
在res目錄下新建一個資料夾raw(名字必須為raw,約定大於配置的原則),然後在raw目錄中拷貝進一個音樂檔案,注意檔名必須遵循Android資原始檔的命名規則。 - 在src目錄下,新建一個MediaService繼承Service類,在該類中實現核心服務的方法。
private static MediaPlayer player;
public static int ispb;
@Override
public IBinder onBind(Intent intent) {
System.out.println("服務返回了MediaContoller物件。。。。" );
return new MediaContoller();
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("建立一個服務,並初始化MediaPlayer");
player = MediaPlayer.create(getApplicationContext(), R.raw.a);
}
public static class MediaContoller extends Binder {
//開始播放
public int play(){
player.start();
return 0;
}
//暫停播放
public int puse(){
player.pause();
return 1;
}
//停止播放
public void stop(){
player.stop();
}
//音樂的總時長
public int getDuration(){
return player.getDuration();
}
//當前播放的位置
public int getCurrentPosition(){
return player.getCurrentPosition();
}
//判斷是否播放
public boolean isplaying(){
return player.isPlaying();
}
}
- 這是使用系統預設的佈局檔案,activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="10dp"
android:text="音樂播放器"
android:textSize="20sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="play"
android:text="播放" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="puse"
android:text="暫停" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="stop"
android:text="停止" />
</LinearLayout>
<ProgressBar
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dp" />
</LinearLayout>
- 使用預設的MainActivity類,在該類中完成業務的控制
package com.example.servicemusic;
import com.example.service.MusicService;
import com.example.service.MusicService.MediaContoller;
import android.support.v7.app.ActionBarActivity;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
private ProgressBar pb;
// 宣告自定義的MediaController物件
private MediaContoller controller;
private boolean isrunning;
private static int ispb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pb = (ProgressBar) findViewById(R.id.pb);
// 如何繫結服務?
// 建立一個用於啟動服務的顯示意圖,指向我們自定義的MediaService類
Intent service = new Intent(this, MusicService.class);
// 繫結服務,同時服務開啟,如果成功則返回true否則返回false
isrunning = bindService(service, new MediaConnection(),
BIND_AUTO_CREATE);
if (isrunning) {
System.out.println("服務繫結成功!");
} else {
System.out.println("服務繫結失敗!");
}
}
/**
* 播放
*
* @param v
*/
@SuppressLint("ShowToast")
public void play(View v) {
if (controller != null) {
if (controller.isplaying()) {
Toast.makeText(this, "音樂正在播放中......", 1).show();
return;
}else{
controller.play();
System.out.println("開始播放音樂");
}
}
}
/**
* 暫停
*
* @param v
*/
public void puse(View v) {
if (controller != null) {
controller.puse();
System.out.println("音樂暫停");
}
}
/**
* 停止
*
* @param v
*/
public void stop(View v) {
if (controller != null) {
pb.setProgress(0);
controller.stop();
//unbindService(new MediaConnection());//終止繫結
System.out.println("音樂停止");
}
}
/**
* 更新進度條
*/
private void updatePro() {
new Thread() {
public void run() {
while (true) {
SystemClock.sleep(400);
pb.setProgress(controller.getCurrentPosition());
if (controller.getCurrentPosition() == controller
.getDuration()) {
break;
}
}
};
}.start();
}
/**
* 實現ServiceConnection 類
*
* @author Blake
*
*/
class MediaConnection implements ServiceConnection {
/**
* 當service被繫結的時候回撥該函式
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 返回的ibinder物件其實就是我們自定義的MediaContoller
controller = (MediaContoller) service;
// 設定進度條的最大值
pb.setMax(controller.getDuration());
// 更新進度條
updatePro();
System.out.println("伺服器已經連線......");
}
/**
* 伺服器斷開或關閉的時候呼叫該方法
*/
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("伺服器斷開或關閉");
}
}
}
- 在AndroidManifest.xml中註冊Service
- 將工程部署到模擬器上,點選播放,發現成功播放了音樂。點選暫停,發現音樂暫停了,然後點選播放,音樂再次響起。點選停止,問題來了,我們發現點選停止後再次點選播放音樂沒能再次播放,因為這裡面直接呼叫MediaPlayer的stop方法是有bug的。因此為了解決這樣的問題,我們應該將停止呼叫層pause方法,同時只需呼叫MediaPlayer的seekTo(int)方法將音樂設定到開始位置。
//停止播放
public void stop(){
player.pause();
player.seekTo(0);
}