免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1388 | 回复: 2

[Android] 安卓简单mp3播放器 [复制链接]

论坛徽章:
1
操作系统版块每日发帖之星
日期:2015-07-07 22:20:00
发表于 2015-07-06 14:36 |显示全部楼层
使用MediaPlayer播放mp3,mp3文件使用线程搜索出来,并显示在列表上,点击列表播放
按钮有4个,可以控制暂停,播放,重新播放,停止。
进度条可以监控播放进度,也可以拖动进度条快进,快退功能。

[Java]代码
  1. package com.yongzheng.mymusic;

  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.util.ArrayList;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Timer;
  9. import java.util.TimerTask;

  10. import android.media.AudioManager;
  11. import android.media.MediaPlayer;
  12. import android.media.MediaPlayer.OnCompletionListener;
  13. import android.media.MediaPlayer.OnErrorListener;
  14. import android.media.MediaPlayer.OnPreparedListener;
  15. import android.os.Bundle;
  16. import android.os.Environment;
  17. import android.os.Handler;
  18. import android.os.Message;
  19. import android.annotation.SuppressLint;
  20. import android.app.Activity;
  21. import android.content.DialogInterface;
  22. import android.view.Menu;
  23. import android.view.View;
  24. import android.view.View.OnClickListener;
  25. import android.widget.AdapterView;
  26. import android.widget.AdapterView.OnItemClickListener;
  27. import android.widget.Button;
  28. import android.widget.ListView;
  29. import android.widget.SeekBar;
  30. import android.widget.SimpleAdapter;
  31. import android.widget.TextView;
  32. import android.widget.Toast;

  33. public class MainActivity extends Activity{
  34.      
  35.     private TextView musicName ;//歌曲名称
  36.     private TextView startTime;//播放时间
  37.     private TextView endTime;//结束时间
  38.     private SeekBar seekbar;//进度条
  39.      
  40.     private Button start;//开始按钮
  41.     private Button pause;//暂停按钮
  42.     private Button restart;//重新开始
  43.     private Button stop;//停止按钮
  44.      
  45.     private ListView mylist;//列表
  46.     private SimpleAdapter adapter = null;   // 适配器
  47.      
  48.     private Timer timer;
  49.      
  50.     private MediaPlayer media = null;
  51.     private List<Map<String, String>> musicListData;
  52.      
  53.     private String lastPlayName = null;//记录最后一次播放的歌曲
  54.      
  55.     @Override
  56.     protected void onCreate(Bundle savedInstanceState) {
  57.         super.onCreate(savedInstanceState);
  58.         setContentView(R.layout.activity_main);
  59.         init();
  60.     }

  61.     //初始化
  62.     private void init(){
  63.          
  64.         musicListData =
  65.                 new ArrayList<Map<String, String>>();   // 保存所有的List数据
  66.          
  67.         this.musicName = (TextView) this.findViewById(R.id.musicName);
  68.         this.startTime = (TextView)this.findViewById(R.id.startTime);
  69.         this.endTime = (TextView)this.findViewById(R.id.endTime);
  70.         this.seekbar = (SeekBar)this.findViewById(R.id.seekbar);
  71.         this.start = (Button)this.findViewById(R.id.start);
  72.         this.pause = (Button)this.findViewById(R.id.pause);
  73.         this.restart = (Button)this.findViewById(R.id.restart);
  74.         this.stop = (Button)this.findViewById(R.id.stop);
  75.         this.mylist = (ListView)this.findViewById(R.id.mylist);
  76.         addList();
  77.         //点击事件
  78.         this.start.setOnClickListener(new MyClickListener());
  79.         this.pause.setOnClickListener(new MyClickListener());
  80.         this.restart.setOnClickListener(new MyClickListener());
  81.         this.stop.setOnClickListener(new MyClickListener());
  82.          
  83.         this.seekbar.setOnSeekBarChangeListener(new SeekBarOnClickListenerImpl());
  84.         //开启搜索sd卡中MP3文件的线程
  85.         new Thread(){
  86.         public void run(){
  87.             getMusicDate();//搜索sd卡下面的mp3后缀的文件
  88.         }
  89.     }.start();
  90.     }
  91.      
  92.     //待搜索线程完成后,执行这个添加数据到界面上
  93.     public void addList(){
  94.         this.adapter = new SimpleAdapter(this,this.musicListData,R.layout.list,
  95.                 new String[]{"name","size"},new int[]{R.id.name,R.id.size});
  96.         this.mylist.setAdapter(adapter);
  97.         this.mylist.setOnItemClickListener(new OnItemClickListener() {
  98.             @Override
  99.             public void onItemClick(AdapterView<?> adapt, View v, int postition,
  100.                     long id) {
  101.                 Map<String,String> map = MainActivity.this.musicListData.get(postition);
  102.                 if(MainActivity.this.media!=null){
  103.                     stop();
  104.                 }
  105.                 play(map.get("path"));
  106.             }
  107.         });
  108.     }
  109.      
  110.     //获取播放列表
  111.     public void getMusicDate(){
  112.          
  113.         if(!(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))){
  114.             //如果不sd卡存在
  115.             return;
  116.         }
  117.         File rootPath = Environment.getExternalStorageDirectory();
  118.         File[] listFile = rootPath.listFiles();
  119.         if(listFile!=null){
  120.             for(File f : listFile){
  121.                 if(f.isDirectory()){//如果是目录
  122.                     System.out.println("根文件夹:"+f.getName());
  123.                     getFile(f);
  124.                 }else{//如果是文件
  125.                     getAFile(f);
  126.                 }
  127.             }
  128.         }
  129.          
  130.         Message message = new Message();
  131.         message.what = 3;
  132.         MainActivity.this.handler.sendMessage(message);
  133.         return;
  134.     }
  135.      
  136.     //文件
  137.     private void getAFile(File f){
  138.         String fName = f.getName();
  139.         if(!fName.endsWith("mp3")){
  140.             return;
  141.         }
  142.         Map<String,String> map = new HashMap<String,String>();
  143.         map.put("name",fName);
  144.         map.put("size", String.valueOf(f.length()/1024/1024)+"MB");
  145.         map.put("path",f.getAbsolutePath());
  146.         musicListData.add(map);
  147.         System.out.println("音乐文件路径:"+f.getAbsolutePath());
  148.     }
  149.     //路径
  150.     private void getFile(File f){
  151.         if(!f.isDirectory()){
  152.             getAFile(f);
  153.             return;
  154.         }
  155.         File[] listFile = f.listFiles();
  156.         if(listFile!=null){
  157.             for(File ff : listFile){
  158.                 if(f.isDirectory()){//如果是目录
  159.                     System.out.println("文件夹:"+ff.getName());
  160.                     getFile(ff);
  161.                 }else{//如果是文件
  162.                     System.out.println("文件:"+ff.getName());
  163.                     getAFile(ff);
  164.                 }
  165.             }
  166.         }
  167.     }
  168.      
  169.     //进度条监听回调
  170.     private class SeekBarOnClickListenerImpl implements SeekBar.OnSeekBarChangeListener {

  171.         @Override
  172.         public void onProgressChanged(SeekBar seekBar, int progress,
  173.                 boolean fromUser) {
  174.             if(!fromUser)return;
  175.             if(MainActivity.this.media!=null){
  176.                  
  177.                 Message message = new Message();
  178.                 Bundle b = new Bundle();
  179.                 b.putInt("p", progress);
  180.                 message.setData(b);
  181.                 message.what = 2;
  182.                 MainActivity.this.handler.sendMessage(message);
  183.                 MainActivity.this.media.seekTo(progress);
  184.             }      
  185.         }

  186.         @Override
  187.         public void onStartTrackingTouch(SeekBar seekBar) {
  188.             // TODO Auto-generated method stub
  189.             
  190.         }

  191.         @Override
  192.         public void onStopTrackingTouch(SeekBar seekBar) {
  193.             
  194.         }

  195.     }
  196.      
  197.     //播放控制的按钮事件
  198.     class MyClickListener implements OnClickListener{

  199.         @Override
  200.         public void onClick(View v) {
  201.             switch(v.getId()){
  202.                 case R.id.start:
  203.                     play(Environment.getExternalStorageDirectory()+File.separator+"my.mp3");
  204.                     break;
  205.                 case R.id.pause:
  206.                     pause();break;
  207.                 case R.id.restart:
  208.                     restart();break;
  209.                 case R.id.stop:
  210.                     stop();break;
  211.             }
  212.         }
  213.          
  214.     }
  215.      
  216.      
  217.     @Override
  218.     public boolean onCreateOptionsMenu(Menu menu) {
  219.         // Inflate the menu; this adds items to the action bar if it is present.
  220.         getMenuInflater().inflate(R.menu.main, menu);
  221.         return true;
  222.     }

  223.     //停止播放
  224.     private void stop(){
  225.         if(MainActivity.this.media!=null){
  226.             MainActivity.this.start.setClickable(true);
  227.             MainActivity.this.media.release();
  228.             MainActivity.this.media = null;
  229.         }
  230.     }
  231.      
  232.     //从头开始播放
  233.     private void restart(){
  234.         if(MainActivity.this.media!=null){
  235.             MainActivity.this.media.seekTo(0);
  236.         }
  237.     }
  238.      
  239.     //暂停获取继续播放
  240.     private void pause(){
  241.         if(MainActivity.this.media==null){
  242.             MainActivity.this.pause.setText("暂停");
  243.             return;
  244.         }
  245.         if("继续".equals(MainActivity.this.pause.getText().toString())){
  246.             MainActivity.this.media.start();
  247.             MainActivity.this.pause.setText("暂停");
  248.         }else if(MainActivity.this.media.isPlaying()){
  249.             MainActivity.this.media.pause();
  250.             MainActivity.this.pause.setText("继续");
  251.         }
  252.     }

  253.     //开始播放
  254.     private void play(String path){
  255.         if(path==null||"".equals(path)){
  256.             Toast.makeText(this, "请选择播放文件", Toast.LENGTH_SHORT);
  257.             return;
  258.         }
  259.         this.musicName.setText(path.substring(path.lastIndexOf("/")+ 1));
  260.         File file = new File(path);
  261.         if(file.exists()&&file.length()>0){
  262.             try {
  263.                 this.media = new MediaPlayer();
  264.                 this.media.setAudioStreamType(AudioManager.STREAM_MUSIC);//设置播放类型
  265.                 this.media.setDataSource(path);
  266.                 this.media.setOnCompletionListener(new MediaCompletionListener());
  267.                 this.media.setOnErrorListener(new MediaErrorListener());
  268.                 this.media.prepare();
  269.                 this.media.start();
  270.                 this.start.setClickable(false);
  271.                 //启动事件更新及进度条更新任务,每0.5s更新一次
  272.                 MainActivity.this.timer = new Timer();
  273.                 MainActivity.this.timer.schedule(new MyTask(), 0, 1000);
  274.             } catch (Exception e) {
  275.                 e.printStackTrace();
  276.                 Toast.makeText(this, "播放文件错误", Toast.LENGTH_SHORT).show();
  277.             }
  278.             
  279.         }else{
  280.             Toast.makeText(this, "播放文件不存在", Toast.LENGTH_SHORT).show();
  281.         }
  282.     }
  283.      
  284.     @Override
  285.     protected void onDestroy() {
  286.         super.onDestroy();
  287.             
  288.         if(this.media != null) {  //如果播放器对象不为空
  289.             this.media.release();    //释放播放器资源
  290.             this.media = null;        //设置对象为空
  291.         }
  292.     }
  293.      
  294.     @SuppressLint("HandlerLeak")
  295.     private Handler handler = new Handler() {
  296.         public void handleMessage(Message msg) {
  297.             switch(msg.what) {
  298.             case 1:
  299.                 if(MainActivity.this.media != null) {
  300.                     int progress = MainActivity.this.media.getCurrentPosition();  //当前播放毫秒
  301.                     int allTime = MainActivity.this.media.getDuration();      //总毫秒            
  302.                     MainActivity.this.seekbar.setMax(allTime);//设置进度条
  303.                     MainActivity.this.startTime.setText(getTimeFormat(progress));
  304.                     MainActivity.this.endTime.setText(getTimeFormat(allTime));
  305.                     MainActivity.this.seekbar.setProgress(progress);
  306.                 }
  307.                 break;
  308.             case 2:
  309.                 break;
  310.             case 3:
  311.                 addList();
  312.                 break;
  313.             }
  314.             
  315.             super.handleMessage(msg);
  316.         }
  317.     };
  318.      
  319.     private String getTimeFormat(int time) {
  320.         String timeStr = "00:00:00";
  321.         int s = time/1000;   //秒
  322.         int h = s / 3600;    //求整数部分 ,小时
  323.         int r = s % 3600;    //求余数
  324.         int m = 0;
  325.         if(r > 0) {
  326.             m = r / 60;    //分
  327.             r = r % 60;    //求分后的余数,即为秒
  328.         }
  329.          
  330.         if(h < 10) {
  331.             timeStr = "0" + h;
  332.         } else {
  333.             timeStr = "" + h;
  334.         }
  335.          
  336.         if(m < 10) {
  337.             timeStr = timeStr + ":" + "0" + m;
  338.         } else {
  339.             timeStr = timeStr + ":" + m;
  340.         }
  341.          
  342.         if(r < 10) {
  343.             timeStr = timeStr + ":" + "0" + r;
  344.         } else {
  345.             timeStr = timeStr + ":" + r;
  346.         }
  347.          
  348.         return timeStr;
  349.     }

  350.      
  351.     private class MyTask extends TimerTask {

  352.         @Override
  353.         public void run() {
  354.             Message message = new Message();
  355.             message.what = 1;
  356.             MainActivity.this.handler.sendMessage(message);
  357.         }      
  358.     }

  359.     //播放时候错误回调
  360.     private class MediaErrorListener implements OnErrorListener{
  361.         @Override
  362.         public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
  363.             MainActivity.this.media.stop();
  364.             MainActivity.this.media.release();
  365.             MainActivity.this.media = null;
  366.             Toast.makeText(MainActivity.this, "播放时候遇到错误,播放停止", Toast.LENGTH_LONG).show();
  367.             return false;
  368.         }
  369.     }
  370.     //播放完成事件
  371.     private class MediaCompletionListener implements OnCompletionListener{
  372.         @Override
  373.         public void onCompletion(MediaPlayer arg0) {
  374.             MainActivity.this.media.stop();
  375.             MainActivity.this.media.release();
  376.             MainActivity.this.media = null;
  377.             MainActivity.this.musicName.setText("当前没有播放");
  378.             MainActivity.this.startTime.setText("00:00");
  379.             MainActivity.this.endTime.setText("00:00");
  380.             MainActivity.this.start.setClickable(true);
  381.         }
  382.          
  383.     }
  384. }
复制代码
MyMp3.rar (1.22 MB, 下载次数: 12)

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
发表于 2015-07-11 20:56 |显示全部楼层
支持后台播放就更好了。

论坛徽章:
80
20周年集字徽章-庆
日期:2020-10-28 14:09:1215-16赛季CBA联赛之北京
日期:2020-10-28 13:32:5315-16赛季CBA联赛之北控
日期:2020-10-28 13:32:4815-16赛季CBA联赛之天津
日期:2020-10-28 13:13:35黑曼巴
日期:2020-10-28 12:29:1520周年集字徽章-周	
日期:2020-10-31 15:10:0720周年集字徽章-20	
日期:2020-10-31 15:10:07ChinaUnix元老
日期:2015-09-29 11:56:3020周年集字徽章-年
日期:2020-10-28 14:14:56
发表于 2015-07-14 10:26 |显示全部楼层
楼主把他做成一个服务的形式就可以了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP