• Android--MediaPlayer(实现列表选歌,上一首,下一首,清空播放列表,搜索本地音乐文件)


    Android--MediaPlayer(实现列表选歌,上一首,下一首,清空播放列表,搜索本地音乐文件)

    下载链接:http://download.csdn.net/detail/zlqqhs/5079025

    MediaPlayerActivity类:

    1. <span style="font-size:14px;">package com.vince.media;
    2. import java.io.File;
    3. import java.io.IOException;
    4. import java.util.ArrayList;
    5. import java.util.List;
    6. import java.util.concurrent.ExecutorService;
    7. import java.util.concurrent.Executors;
    8. import android.app.Activity;
    9. import android.app.ProgressDialog;
    10. import android.media.MediaPlayer;
    11. import android.media.MediaPlayer.OnCompletionListener;
    12. import android.media.MediaPlayer.OnErrorListener;
    13. import android.os.Bundle;
    14. import android.os.Environment;
    15. import android.os.Handler;
    16. import android.os.Message;
    17. import android.view.Menu;
    18. import android.view.MenuItem;
    19. import android.view.View;
    20. import android.view.ViewGroup;
    21. import android.widget.AdapterView;
    22. import android.widget.AdapterView.OnItemClickListener;
    23. import android.widget.BaseAdapter;
    24. import android.widget.ImageButton;
    25. import android.widget.ListView;
    26. import android.widget.SeekBar;
    27. import android.widget.SeekBar.OnSeekBarChangeListener;
    28. import android.widget.TextView;
    29. import android.widget.Toast;
    30. public class MediaPlayerActivity extends Activity implements OnCompletionListener,OnErrorListener,OnSeekBarChangeListener,OnItemClickListener,Runnable{
    31. protected static final int SEARCH_MUSIC_SUCCESS = 0;// 搜索成功标记
    32. private SeekBar seekBar;
    33. private ListView listView;
    34. private ImageButton btnPlay;
    35. private TextView tv_currTime,tv_totalTime,tv_showName;
    36. private List<String> list;
    37. private ProgressDialog pd; // 进度条对话框
    38. private MusicListAdapter ma;// 适配器
    39. private MediaPlayer mp;
    40. private int currIndex = 0;// 表示当前播放的音乐索引
    41. private boolean flag = true;//控制进度条线程标记
    42. // 定义当前播放器的状态״̬
    43. private static final int IDLE = 0;
    44. private static final int PAUSE = 1;
    45. private static final int START = 2;
    46. private static final int CURR_TIME_VALUE = 1;
    47. private int currState = IDLE; // 当前播放器的状态
    48. //定义线程池(同时只能有一个线程运行)
    49. ExecutorService es = Executors.newSingleThreadExecutor();
    50. @Override
    51. protected void onCreate(Bundle savedInstanceState) {
    52. super.onCreate(savedInstanceState);
    53. setContentView(R.layout.mediaplayer_layout);
    54. list = new ArrayList<String>();
    55. mp = new MediaPlayer();
    56. mp.setOnCompletionListener(this);
    57. mp.setOnErrorListener(this);
    58. initView();
    59. }
    60. @Override
    61. protected void onDestroy() {
    62. if (mp != null) {
    63. mp.stop();
    64. flag= false;
    65. //释放资源
    66. mp.release();
    67. }
    68. super.onDestroy();
    69. }
    70. /**
    71. * 初始化UI组件
    72. */
    73. private void initView() {
    74. btnPlay = (ImageButton) findViewById(R.id.media_play);
    75. seekBar = (SeekBar) findViewById(R.id.seekBar1);
    76. seekBar.setOnSeekBarChangeListener(this);
    77. listView = (ListView) findViewById(R.id.listView1);
    78. listView.setOnItemClickListener(this);
    79. tv_currTime = (TextView) findViewById(R.id.textView1_curr_time);
    80. tv_totalTime = (TextView) findViewById(R.id.textView1_total_time);
    81. tv_showName = (TextView) findViewById(R.id.tv_showName);
    82. }
    83. @Override
    84. public boolean onCreateOptionsMenu(Menu menu) {
    85. //从xml文件中装载菜单
    86. getMenuInflater().inflate(R.menu.media_menu, menu);
    87. return super.onCreateOptionsMenu(menu);
    88. }
    89. private Handler hander = new Handler() {
    90. public void handleMessage(android.os.Message msg) {
    91. switch (msg.what) {
    92. case SEARCH_MUSIC_SUCCESS:
    93. //搜索音乐文件结束时
    94. ma = new MusicListAdapter();
    95. listView.setAdapter(ma);
    96. pd.dismiss();
    97. break;
    98. case CURR_TIME_VALUE:
    99. //设置当前时间
    100. tv_currTime.setText(msg.obj.toString());
    101. break;
    102. default:
    103. break;
    104. }
    105. };
    106. };
    107. @Override
    108. public boolean onOptionsItemSelected(MenuItem item) {
    109. switch (item.getItemId()) {
    110. //搜索本地音乐菜单
    111. case R.id.item1_search:
    112. list.clear();
    113. //是否有外部存储设备
    114. if (Environment.getExternalStorageState().equals(
    115. Environment.MEDIA_MOUNTED)) {
    116. pd = ProgressDialog.show(this, "", "正在搜索音乐文件...", true);
    117. new Thread(new Runnable() {
    118. String[] ext = { ".mp3" };
    119. File file = Environment.getExternalStorageDirectory();
    120. public void run() {
    121. search(file, ext);
    122. hander.sendEmptyMessage(SEARCH_MUSIC_SUCCESS);
    123. }
    124. }).start();
    125. } else {
    126. Toast.makeText(this, "请插入外部存储设备..", Toast.LENGTH_LONG).show();
    127. }
    128. break;
    129. //清除播放列表菜单
    130. case R.id.item2_clear:
    131. list.clear();
    132. ma.notifyDataSetChanged();
    133. break;
    134. //退出菜单
    135. case R.id.item3_exit:
    136. flag = false;
    137. this.finish();
    138. break;
    139. }
    140. return super.onOptionsItemSelected(item);
    141. }
    142. // 搜索音乐文件
    143. private void search(File file, String[] ext) {
    144. if (file != null) {
    145. if (file.isDirectory()) {
    146. File[] listFile = file.listFiles();
    147. if (listFile != null) {
    148. for (int i = 0; i < listFile.length; i++) {
    149. search(listFile[i], ext);
    150. }
    151. }
    152. } else {
    153. String filename = file.getAbsolutePath();
    154. for (int i = 0; i < ext.length; i++) {
    155. if (filename.endsWith(ext[i])) {
    156. list.add(filename);
    157. break;
    158. }
    159. }
    160. }
    161. }
    162. }
    163. class MusicListAdapter extends BaseAdapter {
    164. public int getCount() {
    165. return list.size();
    166. }
    167. public Object getItem(int position) {
    168. return list.get(position);
    169. }
    170. public long getItemId(int position) {
    171. return position;
    172. }
    173. public View getView(int position, View convertView, ViewGroup parent) {
    174. if (convertView == null) {
    175. convertView = getLayoutInflater().inflate(R.layout.list_item,
    176. null);
    177. }
    178. TextView tv_music_name = (TextView) convertView
    179. .findViewById(R.id.textView1_music_name);
    180. tv_music_name.setText(list.get(position));
    181. return convertView;
    182. }
    183. }
    184. private void play() {
    185. switch (currState) {
    186. case IDLE:
    187. start();
    188. break;
    189. case PAUSE:
    190. mp.pause();
    191. btnPlay.setImageResource(R.drawable.ic_media_play);
    192. currState = START;
    193. break;
    194. case START:
    195. mp.start();
    196. btnPlay.setImageResource(R.drawable.ic_media_pause);
    197. currState = PAUSE;
    198. }
    199. }
    200. //上一首
    201. private void previous() {
    202. if((currIndex-1)>=0){
    203. currIndex--;
    204. start();
    205. }else{
    206. Toast.makeText(this, "当前已经是第一首歌曲了", Toast.LENGTH_SHORT).show();
    207. }
    208. }
    209. //下一自首
    210. private void next() {
    211. if(currIndex+1<list.size()){
    212. currIndex++;
    213. start();
    214. }else{
    215. Toast.makeText(this, "当前已经是最后一首歌曲了", Toast.LENGTH_SHORT).show();
    216. }
    217. }
    218. //开始播放
    219. private void start() {
    220. if (list.size() > 0 && currIndex < list.size()) {
    221. String SongPath = list.get(currIndex);
    222. mp.reset();
    223. try {
    224. mp.setDataSource(SongPath);
    225. mp.prepare();
    226. mp.start();
    227. initSeekBar();
    228. es.execute(this);
    229. tv_showName.setText(list.get(currIndex));
    230. btnPlay.setImageResource(R.drawable.ic_media_pause);
    231. currState = PAUSE;
    232. } catch (IOException e) {
    233. e.printStackTrace();
    234. }
    235. }else{
    236. Toast.makeText(this, "播放列表为空", Toast.LENGTH_SHORT).show();
    237. }
    238. }
    239. //播放按钮
    240. public void play(View v){
    241. play();
    242. }
    243. //上一首按钮
    244. public void previous(View v){
    245. previous();
    246. }
    247. //下一首按钮
    248. public void next(View v){
    249. next();
    250. }
    251. //监听器,当当前歌曲播放完时触发,播放下一首
    252. public void onCompletion(MediaPlayer mp) {
    253. if(list.size()>0){
    254. next();
    255. }else{
    256. Toast.makeText(this, "播放列表为空", Toast.LENGTH_SHORT).show();
    257. }
    258. }
    259. //当播放异常时触发
    260. public boolean onError(MediaPlayer mp, int what, int extra) {
    261. mp.reset();
    262. return false;
    263. }
    264. //初始化SeekBar
    265. private void initSeekBar(){
    266. seekBar.setMax(mp.getDuration());
    267. seekBar.setProgress(0);
    268. tv_totalTime.setText(toTime(mp.getDuration()));
    269. }
    270. private String toTime(int time){
    271. int minute = time / 1000 / 60;
    272. int s = time / 1000 % 60;
    273. String mm = null;
    274. String ss = null;
    275. if(minute<10)mm = "0" + minute;
    276. else mm = minute + "";
    277. if(s <10)ss = "0" + s;
    278. else ss = "" + s;
    279. return mm + ":" + ss;
    280. }
    281. public void run() {
    282. flag = true;
    283. while(flag){
    284. if(mp.getCurrentPosition()<seekBar.getMax()){
    285. seekBar.setProgress(mp.getCurrentPosition());
    286. Message msg = hander.obtainMessage(CURR_TIME_VALUE, toTime(mp.getCurrentPosition()));
    287. hander.sendMessage(msg);
    288. try {
    289. Thread.sleep(500);
    290. } catch (InterruptedException e) {
    291. e.printStackTrace();
    292. }
    293. }else{
    294. flag = false;
    295. }
    296. }
    297. }
    298. //SeekBar监听器
    299. public void onProgressChanged(SeekBar seekBar, int progress,
    300. boolean fromUser) {
    301. //是否由用户改变
    302. if(fromUser){
    303. mp.seekTo(progress);
    304. }
    305. }
    306. public void onStartTrackingTouch(SeekBar seekBar) {
    307. }
    308. public void onStopTrackingTouch(SeekBar seekBar) {
    309. }
    310. //ListView监听器
    311. public void onItemClick(AdapterView<?> parent, View view, int position,
    312. long id) {
    313. currIndex = position;
    314. start();
    315. }
    316. }
    317. </span>


    mediaplayer_layout.xml布局文件:

    1. <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. android:layout_width="match_parent"
    4. android:layout_height="match_parent"
    5. android:orientation="vertical" >
    6. <ListView
    7. android:id="@+id/listView1"
    8. android:layout_width="match_parent"
    9. android:layout_height="0dp"
    10. android:layout_weight="1" >
    11. </ListView>
    12. <TextView
    13. android:id="@+id/tv_showName"
    14. android:layout_width="match_parent"
    15. android:layout_height="wrap_content"
    16. android:gravity="center" />
    17. <LinearLayout
    18. android:id="@+id/linearLayout2"
    19. android:layout_width="match_parent"
    20. android:layout_height="wrap_content"
    21. android:gravity="center" >
    22. <TextView
    23. android:id="@+id/textView1_curr_time"
    24. android:layout_width="wrap_content"
    25. android:layout_height="wrap_content"
    26. android:layout_marginRight="5dp"
    27. android:text="00:00" />
    28. <SeekBar
    29. android:id="@+id/seekBar1"
    30. android:layout_width="fill_parent"
    31. android:layout_height="wrap_content"
    32. android:layout_weight="1" />
    33. <TextView
    34. android:id="@+id/textView1_total_time"
    35. android:layout_width="wrap_content"
    36. android:layout_height="wrap_content"
    37. android:layout_marginLeft="5dp"
    38. android:text="00:00" />
    39. </LinearLayout>
    40. <LinearLayout
    41. android:id="@+id/linearLayout1"
    42. android:layout_width="match_parent"
    43. android:layout_height="wrap_content"
    44. android:gravity="center" >
    45. <ImageButton
    46. android:layout_width="wrap_content"
    47. android:layout_height="wrap_content"
    48. android:onClick="previous"
    49. android:src="@drawable/ic_media_previous" />
    50. <ImageButton
    51. android:id="@+id/media_play"
    52. android:layout_width="wrap_content"
    53. android:layout_height="wrap_content"
    54. android:onClick="play"
    55. android:src="@drawable/ic_media_play" />
    56. <ImageButton
    57. android:layout_width="wrap_content"
    58. android:layout_height="wrap_content"
    59. android:onClick="next"
    60. android:src="@drawable/ic_media_next" />
    61. </LinearLayout>
    62. </LinearLayout></span>


    media_menu.xml文件:

    1. <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
    2. <menu xmlns:android="http://schemas.android.com/apk/res/android" >
    3. <item
    4. android:id="@+id/item1_search"
    5. android:icon="@drawable/ic_menu_search"
    6. android:orderInCategory="100"
    7. android:title="@string/search">
    8. </item>
    9. <item
    10. android:id="@+id/item2_clear"
    11. android:icon="@drawable/ic_menu_delete"
    12. android:orderInCategory="200"
    13. android:title="@string/clear_music_list">
    14. </item>
    15. <item
    16. android:id="@+id/item3_exit"
    17. android:icon="@drawable/ic_menu_close_clear_cancel"
    18. android:orderInCategory="300"
    19. android:title="@string/exit">
    20. </item>
    21. </menu></span>


    strings.xml文件:

      1. <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
      2. <resources>
      3. <string name="hello">Hello World, MediaActivity!</string>
      4. <string name="app_name">Media</string>
      5. <string name="search">搜索本地音乐</string>
      6. <string name="clear_music_list">清除播放列表</string>
      7. <string name="exit">退出</string>
      8. </resources></span>
  • 相关阅读:
    策略模式Strategy
    flex项目
    模板方法Template Method
    timer与ScheduledExecutorService
    java两个字符串的相似度
    一个简单的webshell
    状态模式State
    Java性能优化
    责任链模式China of Responsibility
    ns2.34下mflood协议的完美移植
  • 原文地址:https://www.cnblogs.com/yangkai-cn/p/4016832.html
Copyright © 2020-2023  润新知