Android实现在线播放音乐

来源:互联网 时间:1970-01-01

2014年3月10日hello,小伙伴们,3月份珊珊来迟的第一篇博客,最近小巫在找工作,加上又生病了,就没有太多精力去写博客了。今天拖着病发表一篇之前已经实现的在线播放音乐效果,在线播放音乐并不难,也就是传入的Url是一个网络地址。这里我要实现一个可以进行网络缓冲的在线音乐播放。
效果实现:

本篇博客是在多线程下载那篇博客增加在线播放音乐实现,下面是提供项目下载地址:http://download.csdn.net/detail/wwj_748/7018493
下面介绍具体实现过程:
定义一个具有缓冲效果的播放器:Player我们看到的缓冲效果,是通过设置拖动条SeekBar的二级进度实现的,这就要设置MediaPlayer的缓冲更新的监听了。具体代码实现:[java] view plaincopy

  1. package com.wwj.download.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.Timer;  
  5. import java.util.TimerTask;  
  6.   
  7. import android.media.AudioManager;  
  8. import android.media.MediaPlayer;  
  9. import android.media.MediaPlayer.OnBufferingUpdateListener;  
  10. import android.media.MediaPlayer.OnCompletionListener;  
  11. import android.media.MediaPlayer.OnPreparedListener;  
  12. import android.os.Handler;  
  13. import android.util.Log;  
  14. import android.widget.SeekBar;  
  15.   
  16. public class Player implements OnBufferingUpdateListener, OnCompletionListener,  
  17.         OnPreparedListener {  
  18.   
  19.     public MediaPlayer mediaPlayer; // 媒体播放器  
  20.     private SeekBar seekBar; // 拖动条  
  21.     private Timer mTimer = new Timer(); // 计时器  
  22.   
  23.     // 初始化播放器  
  24.     public Player(SeekBar seekBar) {  
  25.         super();  
  26.         this.seekBar = seekBar;  
  27.         try {  
  28.             mediaPlayer = new MediaPlayer();  
  29.             mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);// 设置媒体流类型  
  30.             mediaPlayer.setOnBufferingUpdateListener(this);  
  31.             mediaPlayer.setOnPreparedListener(this);  
  32.         } catch (Exception e) {  
  33.             e.printStackTrace();  
  34.         }  
  35.         // 每一秒触发一次  
  36.         mTimer.schedule(timerTask, 0, 1000);  
  37.     }  
  38.   
  39.     // 计时器  
  40.     TimerTask timerTask = new TimerTask() {  
  41.   
  42.         @Override  
  43.         public void run() {  
  44.             if (mediaPlayer == null)  
  45.                 return;  
  46.             if (mediaPlayer.isPlaying() && seekBar.isPressed() == false) {  
  47.                 handler.sendEmptyMessage(0); // 发送消息  
  48.             }  
  49.         }  
  50.     };  
  51.   
  52.     Handler handler = new Handler() {  
  53.         public void handleMessage(android.os.Message msg) {  
  54.             int position = mediaPlayer.getCurrentPosition();  
  55.             int duration = mediaPlayer.getDuration();  
  56.             if (duration > 0) {  
  57.                 // 计算进度(获取进度条最大刻度*当前音乐播放位置 / 当前音乐时长)  
  58.                 long pos = seekBar.getMax() * position / duration;  
  59.                 seekBar.setProgress((int) pos);  
  60.             }  
  61.         };  
  62.     };  
  63.   
  64.     public void play() {  
  65.         mediaPlayer.start();  
  66.     }  
  67.   
  68.     /** 
  69.      *  
  70.      * @param url 
  71.      *            url地址 
  72.      */  
  73.     public void playUrl(String url) {  
  74.         try {  
  75.             mediaPlayer.reset();  
  76.             mediaPlayer.setDataSource(url); // 设置数据源  
  77.             mediaPlayer.prepare(); // prepare自动播放  
  78.         } catch (IllegalArgumentException e) {  
  79.             e.printStackTrace();  
  80.         } catch (SecurityException e) {  
  81.             e.printStackTrace();  
  82.         } catch (IllegalStateException e) {  
  83.             e.printStackTrace();  
  84.         } catch (IOException e) {  
  85.             e.printStackTrace();  
  86.         }  
  87.     }  
  88.   
  89.     // 暂停  
  90.     public void pause() {  
  91.         mediaPlayer.pause();  
  92.     }  
  93.   
  94.     // 停止  
  95.     public void stop() {  
  96.         if (mediaPlayer != null) {  
  97.             mediaPlayer.stop();  
  98.             mediaPlayer.release();  
  99.             mediaPlayer = null;  
  100.         }  
  101.     }  
  102.   
  103.     // 播放准备  
  104.     @Override  
  105.     public void onPrepared(MediaPlayer mp) {  
  106.         mp.start();  
  107.         Log.e("mediaPlayer", "onPrepared");  
  108.     }  
  109.   
  110.     // 播放完成  
  111.     @Override  
  112.     public void onCompletion(MediaPlayer mp) {  
  113.         Log.e("mediaPlayer", "onCompletion");  
  114.     }  
  115.   
  116.     /** 
  117.      * 缓冲更新 
  118.      */  
  119.     @Override  
  120.     public void onBufferingUpdate(MediaPlayer mp, int percent) {  
  121.         seekBar.setSecondaryProgress(percent);  
  122.         int currentProgress = seekBar.getMax()  
  123.                 * mediaPlayer.getCurrentPosition() / mediaPlayer.getDuration();  
  124.         Log.e(currentProgress + "% play", percent + " buffer");  
  125.     }  
  126.   
  127. }  


[java] view plaincopy
  1. package com.wwj.download;  
  2.   
  3. import java.io.File;  
  4. import java.io.UnsupportedEncodingException;  
  5. import java.net.URLEncoder;  
  6.   
  7. import android.app.Activity;  
  8. import android.os.Bundle;  
  9. import android.os.Environment;  
  10. import android.os.Handler;  
  11. import android.os.Message;  
  12. import android.view.View;  
  13. import android.widget.Button;  
  14. import android.widget.EditText;  
  15. import android.widget.ProgressBar;  
  16. import android.widget.SeekBar;  
  17. import android.widget.SeekBar.OnSeekBarChangeListener;  
  18. import android.widget.TextView;  
  19. import android.widget.Toast;  
  20.   
  21. import com.wwj.download.util.Player;  
  22. import com.wwj.net.download.DownloadProgressListener;  
  23. import com.wwj.net.download.FileDownloader;  
  24.   
  25. public class MainActivity extends Activity {  
  26.     private static final int PROCESSING = 1;  
  27.     private static final int FAILURE = -1;  
  28.   
  29.     private EditText pathText; // url地址  
  30.     private TextView resultView;  
  31.     private Button downloadButton;  
  32.     private Button stopButton;  
  33.     private ProgressBar progressBar;  
  34.     private Button playBtn;  
  35.     private Player player; // 播放器  
  36.     private SeekBar musicProgress; // 音乐进度  
  37.   
  38.     private Handler handler = new UIHandler();  
  39.   
  40.     private final class UIHandler extends Handler {  
  41.         public void handleMessage(Message msg) {  
  42.             switch (msg.what) {  
  43.             case PROCESSING: // 更新进度  
  44.                 progressBar.setProgress(msg.getData().getInt("size"));  
  45.                 float num = (float) progressBar.getProgress()  
  46.                         / (float) progressBar.getMax();  
  47.                 int result = (int) (num * 100); // 计算进度  
  48.                 resultView.setText(result + "%");  
  49.                 if (progressBar.getProgress() == progressBar.getMax()) { // 下载完成  
  50.                     Toast.makeText(getApplicationContext(), R.string.success,  
  51.                             Toast.LENGTH_LONG).show();  
  52.                 }  
  53.                 break;  
  54.             case FAILURE: // 下载失败  
  55.                 Toast.makeText(getApplicationContext(), R.string.error,  
  56.                         Toast.LENGTH_LONG).show();  
  57.                 break;  
  58.             }  
  59.         }  
  60.     }  
  61.   
  62.     @Override  
  63.     protected void onCreate(Bundle savedInstanceState) {  
  64.         super.onCreate(savedInstanceState);  
  65.         setContentView(R.layout.main);  
  66.         pathText = (EditText) findViewById(R.id.path);  
  67.         resultView = (TextView) findViewById(R.id.resultView);  
  68.         downloadButton = (Button) findViewById(R.id.downloadbutton);  
  69.         stopButton = (Button) findViewById(R.id.stopbutton);  
  70.         progressBar = (ProgressBar) findViewById(R.id.progressBar);  
  71.         ButtonClickListener listener = new ButtonClickListener();  
  72.         downloadButton.setOnClickListener(listener);  
  73.         stopButton.setOnClickListener(listener);  
  74.         playBtn = (Button) findViewById(R.id.btn_online_play);  
  75.         playBtn.setOnClickListener(listener);  
  76.         musicProgress = (SeekBar) findViewById(R.id.music_progress);  
  77.         player = new Player(musicProgress);  
  78.         musicProgress.setOnSeekBarChangeListener(new SeekBarChangeEvent());  
  79.     }  
  80.   
  81.     private final class ButtonClickListener implements View.OnClickListener {  
  82.         @Override  
  83.         public void onClick(View v) {  
  84.             switch (v.getId()) {  
  85.             case R.id.downloadbutton: // 开始下载  
  86.                 // http://abv.cn/music/光辉岁月.mp3,可以换成其他文件下载的链接  
  87.                 String path = pathText.getText().toString();  
  88.                 String filename = path.substring(path.lastIndexOf('/') + 1);  
  89.   
  90.                 try {  
  91.                     // URL编码(这里是为了将中文进行URL编码)  
  92.                     filename = URLEncoder.encode(filename, "UTF-8");  
  93.                 } catch (UnsupportedEncodingException e) {  
  94.                     e.printStackTrace();  
  95.                 }  
  96.   
  97.                 path = path.substring(0, path.lastIndexOf("/") + 1) + filename;  
  98.                 if (Environment.getExternalStorageState().equals(  
  99.                         Environment.MEDIA_MOUNTED)) {  
  100.                     // File savDir =  
  101.                     // Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);  
  102.                     // 保存路径  
  103.                     File savDir = Environment.getExternalStorageDirectory();  
  104.                     download(path, savDir);  
  105.                 } else {  
  106.                     Toast.makeText(getApplicationContext(),  
  107.                             R.string.sdcarderror, Toast.LENGTH_LONG).show();  
  108.                 }  
  109.                 downloadButton.setEnabled(false);  
  110.                 stopButton.setEnabled(true);  
  111.                 break;  
  112.             case R.id.stopbutton: // 暂停下载  
  113.                 exit();  
  114.                 Toast.makeText(getApplicationContext(),  
  115.                         "Now thread is Stopping!!", Toast.LENGTH_LONG).show();  
  116.                 downloadButton.setEnabled(true);  
  117.                 stopButton.setEnabled(false);  
  118.                 break;  
  119.             case R.id.btn_online_play:  
  120.                 new Thread(new Runnable() {  
  121.   
  122.                     @Override  
  123.                     public void run() {  
  124.                         player.playUrl(pathText.getText().toString());  
  125.                     }  
  126.                 }).start();  
  127.                 break;  
  128.             }  
  129.         }  
  130.   
  131.         /* 
  132.          * 由于用户的输入事件(点击button, 触摸屏幕....)是由主线程负责处理的,如果主线程处于工作状态, 
  133.          * 此时用户产生的输入事件如果没能在5秒内得到处理,系统就会报“应用无响应”错误。 
  134.          * 所以在主线程里不能执行一件比较耗时的工作,否则会因主线程阻塞而无法处理用户的输入事件, 
  135.          * 导致“应用无响应”错误的出现。耗时的工作应该在子线程里执行。 
  136.          */  
  137.         private DownloadTask task;  
  138.   
  139.         private void exit() {  
  140.             if (task != null)  
  141.                 task.exit();  
  142.         }  
  143.   
  144.         private void download(String path, File savDir) {  
  145.             task = new DownloadTask(path, savDir);  
  146.             new Thread(task).start();  
  147.         }  
  148.   
  149.         /** 
  150.          *  
  151.          * UI控件画面的重绘(更新)是由主线程负责处理的,如果在子线程中更新UI控件的值,更新后的值不会重绘到屏幕上 
  152.          * 一定要在主线程里更新UI控件的值,这样才能在屏幕上显示出来,不能在子线程中更新UI控件的值 
  153.          *  
  154.          */  
  155.         private final class DownloadTask implements Runnable {  
  156.             private String path;  
  157.             private File saveDir;  
  158.             private FileDownloader loader;  
  159.   
  160.             public DownloadTask(String path, File saveDir) {  
  161.                 this.path = path;  
  162.                 this.saveDir = saveDir;  
  163.             }  
  164.   
  165.             /** 
  166.              * 退出下载 
  167.              */  
  168.             public void exit() {  
  169.                 if (loader != null)  
  170.                     loader.exit();  
  171.             }  
  172.   
  173.             DownloadProgressListener downloadProgressListener = new DownloadProgressListener() {  
  174.                 @Override  
  175.                 public void onDownloadSize(int size) {  
  176.                     Message msg = new Message();  
  177.                     msg.what = PROCESSING;  
  178.                     msg.getData().putInt("size", size);  
  179.                     handler.sendMessage(msg);  
  180.                 }  
  181.             };  
  182.   
  183.             public void run() {  
  184.                 try {  
  185.                     // 实例化一个文件下载器  
  186.                     loader = new FileDownloader(getApplicationContext(), path,  
  187.                             saveDir, 3);  
  188.                     // 设置进度条最大值  
  189.                     progressBar.setMax(loader.getFileSize());  
  190.                     loader.download(downloadProgressListener);  
  191.                 } catch (Exception e) {  
  192.                     e.printStackTrace();  
  193.                     handler.sendMessage(handler.obtainMessage(FAILURE)); // 发送一条空消息对象  
  194.                 }  
  195.             }  
  196.         }  
  197.     }  
  198.   
  199.     // 进度改变  
  200.     class SeekBarChangeEvent implements OnSeekBarChangeListener {  
  201.         int progress;  
  202.   
  203.         @Override  
  204.         public void onProgressChanged(SeekBar seekBar, int progress,  
  205.                 boolean fromUser) {  
  206.             // 原本是(progress/seekBar.getMax())*player.mediaPlayer.getDuration()  
  207.             this.progress = progress * player.mediaPlayer.getDuration()  
  208.                     / seekBar.getMax();  
  209.         }  
  210.   
  211.         @Override  
  212.         public void onStartTrackingTouch(SeekBar seekBar) {  
  213.   
  214.         }  
  215.   
  216.         @Override  
  217.         public void onStopTrackingTouch(SeekBar seekBar) {  
  218.             // seekTo()的参数是相对与影片时间的数字,而不是与seekBar.getMax()相对的数字  
  219.             player.mediaPlayer.seekTo(progress);  
  220.         }  
  221.   
  222.     }  
  223.   
  224.     @Override  
  225.     protected void onDestroy() {  
  226.         super.onDestroy();  
  227.         if (player != null) {  
  228.             player.stop();  
  229.             player = null;  
  230.         }  
  231.     }  
  232.   


相关阅读:
Top