音樂播放器中綜合了以下内容:
SeekBar、ListView、廣播接收者(以代碼的形式注冊Receiver)、系統服務、MediaPlayer
實作的功能:
1.暫停/播放、下一首/上一首,點選某一首時播放
2.支援拖動進度條快進
3.清單排序
4.來電話時,停止播放,挂斷後繼續播放
5.可在背景播放
效果圖:

界面:
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<SeekBar
android:id="@+id/seekBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
>
<Button
android:layout_width="40dp"
android:layout_height="40dp"
android:text="|◀"
android:onClick="previous"
/>
<Button
android:id="@+id/pp"
android:layout_width="40dp"
android:layout_height="40dp"
android:text="▶"
android:onClick="pp"
/>
<Button
android:layout_width="40dp"
android:layout_height="40dp"
android:text="▶|"
android:onClick="next"
/>
</LinearLayout>
<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp"
>
<TextView
android:id="@+id/mName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
/>
</LinearLayout>
MainActivity:
package cn.test.audio;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class MainActivity extends Activity {
private TextView nameTextView;
private SeekBar seekBar;
private ListView listView;
private List<Map<String, String>> data;
private int current;
private MediaPlayer player;
private Handler handler = new Handler();
private Button ppButton;
private boolean isPause;
private boolean isStartTrackingTouch;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nameTextView = (TextView) findViewById(R.id.name);
seekBar = (SeekBar) findViewById(R.id.seekBar);
listView = (ListView) findViewById(R.id.list);
ppButton = (Button) findViewById(R.id.pp);
//建立一個音樂播放器
player = new MediaPlayer();
//顯示音樂播放清單
generateListView();
//進度條監聽器
seekBar.setOnSeekBarChangeListener(new MySeekBarListener());
//播放器監聽器
player.setOnCompletionListener(new MyPlayerListener());
//意圖過濾器
IntentFilter filter = new IntentFilter();
//播出電話暫停音樂播放
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
registerReceiver(new PhoneListener(), filter);
//建立一個電話服務
TelephonyManager manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
//監聽電話狀态,接電話時停止播放
manager.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
}
/*
* 監聽電話狀态
*/
private final class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
pause();
}
}
/*
* 播放器監聽器
*/
private final class MyPlayerListener implements OnCompletionListener {
//歌曲播放完後自動播放下一首歌曲
public void onCompletion(MediaPlayer mp) {
next();
}
}
/*
* 下一首按鈕
*/
public void next(View view) {
next();
}
/*
* 前一首按鈕
*/
public void previous(View view) {
previous();
}
/*
* 播放前一首歌
*/
private void previous() {
current = current - 1 < 0 ? data.size() - 1 : current - 1;
play();
}
/*
* 播放下一首歌
*/
private void next() {
current = (current + 1) % data.size();
play();
}
/*
* 進度條監聽器
*/
private final class MySeekBarListener implements OnSeekBarChangeListener {
//移動觸發
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
//起始觸發
public void onStartTrackingTouch(SeekBar seekBar) {
isStartTrackingTouch = true;
}
//結束觸發
public void onStopTrackingTouch(SeekBar seekBar) {
player.seekTo(seekBar.getProgress());
isStartTrackingTouch = false;
}
}
/*
* 顯示音樂播放清單
*/
private void generateListView() {
List<File> list = new ArrayList<File>();
//擷取sdcard中的所有歌曲
findAll(Environment.getExternalStorageDirectory(), list);
//播放清單進行排序,字元順序
Collections.sort(list);
data = new ArrayList<Map<String, String>>();
for (File file : list) {
Map<String, String> map = new HashMap<String, String>();
map.put("name", file.getName());
map.put("path", file.getAbsolutePath());
data.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item, new String[] { "name" }, new int[] { R.id.mName });
listView.setAdapter(adapter);
listView.setOnItemClickListener(new MyItemListener());
}
private final class MyItemListener implements OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
current = position;
play();
}
}
private void play() {
try {
//重播
player.reset();
//擷取歌曲路徑
player.setDataSource(data.get(current).get("path"));
//緩沖
player.prepare();
//開始播放
player.start();
//顯示歌名
nameTextView.setText(data.get(current).get("name"));
//設定進度條長度
seekBar.setMax(player.getDuration());
//播放按鈕樣式
ppButton.setText("||");
//發送一個Runnable, handler收到之後就會執行run()方法
handler.post(new Runnable() {
public void run() {
// 更新進度條狀态
if (!isStartTrackingTouch)
seekBar.setProgress(player.getCurrentPosition());
// 1秒之後再次發送
handler.postDelayed(this, 1000);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 查找檔案路徑中所有mp3檔案
* @param file 要找的目錄
* @param list 用來裝檔案的List
*/
private void findAll(File file, List<File> list) {
File[] subFiles = file.listFiles();
if (subFiles != null)
for (File subFile : subFiles) {
if (subFile.isFile() && subFile.getName().endsWith(".mp3"))
list.add(subFile);
else if (subFile.isDirectory())//如果是目錄
findAll(subFile, list); //遞歸
}
}
/*
* 暫停/播放按鈕
*/
public void pp(View view) {
//預設從第一首歌曲開始播放
if (!player.isPlaying() && !isPause) {
play();
return;
}
Button button = (Button) view;
//暫停/播放按鈕
if ("||".equals(button.getText())) {
pause();
button.setText("▶");
} else {
resume();
button.setText("||");
}
}
/*
* 開始操作
*/
private void resume() {
if (isPause) {
player.start();
isPause = false;
}
}
/*
* 暫停操作
*/
private void pause() {
if (player != null && player.isPlaying()) {
player.pause();
isPause = true;
}
}
/*
* 收到廣播時暫停
*/
private final class PhoneListener extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
pause();
}
}
/*
* 恢複播放
* @see android.app.Activity#onResume()
*/
protected void onResume() {
super.onResume();
resume();
}
}
注冊權限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.itcast.audio"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />
<!-- 監聽電話呼出 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<!-- 監聽電話狀态改變 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
</manifest>