概述
Android多媒体框架支持各种常见的媒体类型,可以很容易地将音频、视频和图像集成到App中。通过MediaPlayer Api,可以从应用程序资源(RAW)、文件系统或网络上数据流资源来播放音频或视频。本文演示了如何通过Api播放音频和视频文件,来获得良好性能和愉快的用户体验,仅供学习分享使用,如有不足之处,还请指正。
涉及知识点
- MediaPlayer 可以用来控制audio/video文件或流播放的类。通过此类,可以方便的控制音频/视频文件的播放,暂停和停止等操作。
- Uri 统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串。
- VideoView 自带的一种播放视频的组件。
- SurfaceView 可以通过后台绘制显示的视图组件。
Activity中播放音频
页面上播放音频文件,步骤如下:
1. 准备资源文件,并播放
- 1 private MediaPlayer mMediaPlayer;
- 2
- 3 /**
- 4 * 开始
- 5 * @param v
- 6 */
- 7 public void bn_start(View v){
- 8 if(mMediaPlayer==null) {
- 9 ready();
- 10 }
- 11 mMediaPlayer.start();
- 12 }
- 13
- 14 /**
- 15 * 创建MediaPlayer并到prepare状态
- 16 */
- 17 private void ready(){
- 18 if(mMediaPlayer==null){
- 19 mMediaPlayer=new MediaPlayer();//Idle
- 20 //Log.i("TAG", "ready: "+filePath);
- 21 File file=new File(Environment.getExternalStorageDirectory(),"goldfallen.mp3");
- 22 Log.i("TAG", "ready: "+file.getPath());
- 23 Log.i("TAG", "ready: "+file.exists());
- 24 Uri uri= Uri.fromFile(file);
- 25 try {
- 26 mMediaPlayer.setDataSource(AudioActivity.this,uri);
- 27 mMediaPlayer.prepare();//Prepared
- 28 } catch (IOException e) {
- 29 Log.i("TAG", "ready: "+ e.getMessage());
- 30 e.printStackTrace();
- 31 }
- 32 }
- 33 }
2. 暂停播放
- 1 /**
- 2 * 暂停
- 3 * @param v
- 4 */
- 5 public void bn_pause(View v){
- 6 if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
- 7 mMediaPlayer.pause();
- 8 }
- 9 }
3. 停止
- 1 /**
- 2 * 停止
- 3 * @param v
- 4 */
- 5 public void bn_stop(View v){
- 6 if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
- 7 mMediaPlayer.stop();
- 8 mMediaPlayer.release();
- 9 mMediaPlayer=null;
- 10 }
- 11 }
4. 释放资源(当页面销毁时,播放资源也要同时释放)
- 1 @Override
- 2 protected void onDestroy() {
- 3 if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
- 4 mMediaPlayer.stop();
- 5 mMediaPlayer.release();
- 6 mMediaPlayer=null;
- 7 }
- 8 super.onDestroy();
- 9 }
5. 通过静态函数创建对象
- 1 /**
- 2 * D:\Android\Project\DemoMedia\app\src\main\res\raw\A2012.mp3:
- 3 * Error: 'A' is not a valid file-based resource name character:
- 4 * File-based resource names must contain only lowercase a-z, 0-9, or underscore
- 5 */
- 6 private void ready2(){
- 7 if(mMediaPlayer==null){
- 8 mMediaPlayer= MediaPlayer.create(this,R.raw.ab2012);
- 9 }
- 10 }
通过服务来播放音频
当页面关闭时,音频文件还可以在后台播放。步骤如下:
1. 定义后台服务,当服务启动时,创建MediaPlayer对象,并注册服务接收对象。
- 1 public class AudioService extends Service {
- 2
- 3 private MediaPlayer mMediaPlayer;
- 4
- 5 private OperatorReceiver mReceiver;
- 6
- 7 public AudioService() {
- 8 }
- 9
- 10 @Override
- 11 public void onCreate() {
- 12 super.onCreate();
- 13 mMediaPlayer=new MediaPlayer();
- 14 mReceiver=new OperatorReceiver();
- 15 IntentFilter filter=new IntentFilter("operator.receiver");
- 16 registerReceiver(mReceiver,filter);
- 17 }
- 18
- 19 @Override
- 20 public IBinder onBind(Intent intent) {
- 21 return null;
- 22 }
- 23
- 24 @Override
- 25 public int onStartCommand(Intent intent, int flags, int startId) {
- 26 Log.i("TAG", "onStartCommand: ----ready ");
- 27 ready();
- 28 return super.onStartCommand(intent, flags, startId);
- 29 }
- 30
- 31 @Override
- 32 public void onDestroy() {
- 33 if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
- 34 mMediaPlayer.stop();
- 35 }
- 36 if(mMediaPlayer!=null){
- 37 mMediaPlayer.release();
- 38 mMediaPlayer=null;
- 39 }
- 40 unregisterReceiver(mReceiver);
- 41 super.onDestroy();
- 42 }
- 43
- 44 private void start(){
- 45 mMediaPlayer.start();
- 46 }
- 47
- 48 private void pause(){
- 49 mMediaPlayer.pause();
- 50 }
- 51
- 52 private void stop(){
- 53 mMediaPlayer.stop();
- 54 ready();
- 55 }
- 56
- 57 private void ready(){
- 58 mMediaPlayer.reset();
- 59 try {
- 60 String filePath= Environment.getExternalStorageDirectory()+"/ab2012.mp3";
- 61 Log.i("TAG", "ready: "+filePath);
- 62 File file=new File(filePath);
- 63 if(file.exists()) {
- 64 mMediaPlayer.setDataSource(filePath);
- 65 mMediaPlayer.prepare();
- 66 }else{
- 67 Log.i("TAG", "ready: 文件不存在 ");
- 68 }
- 69 } catch (IOException e) {
- 70 Log.i("TAG", "ready: "+e.getMessage());
- 71 e.printStackTrace();
- 72 }
- 73 }
- 74 }
2. 操作接收者定义如下:
- 1 /**
- 2 * 操作接收器
- 3 */
- 4 class OperatorReceiver extends BroadcastReceiver
- 5 {
- 6 @Override
- 7 public void onReceive(Context context, Intent intent) {
- 8 int cmd=intent.getIntExtra("cmd",-1);
- 9 Log.i("TAG", "onReceive: "+cmd);
- 10 switch (cmd){
- 11 case Tools.PLAY:
- 12 start();
- 13 break;
- 14 case Tools.PAUSE:
- 15 pause();
- 16 break;
- 17 case Tools.STOP:
- 18 stop();
- 19 break;
- 20 default:
- 21 start();
- 22 break;
- 23
- 24 }
- 25 }
- 26 }
3. 启动服务
- 1 Intent intent =new Intent(this,AudioService.class);
- 2 startService(intent);
4. 前台Activity通过发送广播命令进行控制音频的播放与暂停
- 1 /**
- 2 * 开始
- 3 * @param v
- 4 */
- 5 public void bn_start(View v){
- 6 Intent intent=new Intent("operator.receiver");
- 7 intent.putExtra("cmd",Tools.PLAY);
- 8 sendBroadcast(intent);
- 9 Log.i("TAG", "bn_start: "+"service");
- 10 }
- 11
- 12 /**
- 13 * 暂停
- 14 * @param v
- 15 */
- 16 public void bn_pause(View v){
- 17 Intent intent=new Intent("operator.receiver");
- 18 intent.putExtra("cmd",Tools.PAUSE);
- 19 sendBroadcast(intent);
- 20 }
- 21
- 22 /**
- 23 * 停止
- 24 * @param v
- 25 */
- 26 public void bn_stop(View v){
- 27 Intent intent=new Intent("operator.receiver");
- 28 intent.putExtra("cmd",Tools.STOP);
- 29 sendBroadcast(intent);
- 30 }
5.通过后台服务的方式,需要在AndroidManifest.xml文件中进行注册
- 1 <service
- 2 android:name=".AudioService"
- 3 android:enabled="true"
- 4 android:exported="true">
- 5 </service>
通过VideoView来播放视频
通过VideoView进行播放视频文件,只需要设置资源URI即可,具体如下:
- 1 private VideoView mVideoView;
- 2 @Override
- 3 protected void onCreate(Bundle savedInstanceState) {
- 4 super.onCreate(savedInstanceState);
- 5 setContentView(R.layout.activity_video);
- 6 mVideoView= (VideoView) this.findViewById(R.id.vv_info);
- 7 //设置路径
- 8 File file=new File(Environment.getExternalStorageDirectory(),"DCIM/Camera/VID20190629142614.mp4");
- 9 Log.i("TAG", "onCreate: "+file.getPath());
- 10 if(!file.exists()){
- 11 Log.i("TAG", "onCreate: 文件不存在");
- 12 }
- 13 Uri uri=Uri.fromFile(file);
- 14 mVideoView.setVideoURI(uri);
- 15 //设置Media Controller
- 16 MediaController controller=new MediaController(this);
- 17 mVideoView.setMediaController(controller);
- 18 //获取焦点
- 19 mVideoView.requestFocus();
- 20 mVideoView.start();
- 21 //设置播放完成事件
- 22 mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
- 23 @Override
- 24 public void onCompletion(MediaPlayer mp) {
- 25 Toast.makeText(VideoActivity.this, "播放完毕", Toast.LENGTH_SHORT).show();
- 26 }
- 27 });
- 28 }
通过MediaPlayer来播放视频
通过MediaPlayer来播放视频文件,然后通过SurfaceView来显示视频内容,具体步骤如下:
1.启动,通过setDisplay来设置显示内容
- 1 public void bn_start(View view) {
- 2 mMediaPlayer.reset();//到Idle状态
- 3 //设置路径
- 4 File file=new File(Environment.getExternalStorageDirectory(),"DCIM/Camera/VID20190629142614.mp4");
- 5 Log.i("TAG", "onCreate: "+file.getPath());
- 6 if(!file.exists()){
- 7 Log.i("TAG", "onCreate: 文件不存在");
- 8 } else {
- 9 Log.i("TAG", "onCreate: 文件存在 ");
- 10 }
- 11 Uri uri=Uri.fromFile(file);
- 12 try {
- 13 mMediaPlayer.setDataSource(this,uri);
- 14 mMediaPlayer.setDisplay(mSurfaceView.getHolder());
- 15 mMediaPlayer.prepare();
- 16 mMediaPlayer.start();
- 17 } catch (IOException e) {
- 18 e.printStackTrace();
- 19 }
- 20 }
2. 暂停与停止
- 1 public void bn_pause(View view){
- 2 if(mMediaPlayer.isPlaying()){
- 3 mMediaPlayer.pause();
- 4 }
- 5 }
- 6
- 7 public void bn_stop(View view){
- 8 if(mMediaPlayer.isPlaying()){
- 9 mMediaPlayer.stop();
- 10 }
- 11 }
3. 资源释放
- 1 @Override
- 2 protected void onDestroy() {
- 3 if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
- 4 mMediaPlayer.stop();
- 5 }
- 6 if(mMediaPlayer!=null){
- 7 mMediaPlayer.release();
- 8 mMediaPlayer=null;
- 9 }
- 10 super.onDestroy();
- 11 }
权限设置
如果要播放视频,需要相应的权限设置,并在安装时获取请求权限
- 1 <uses-permission android:name="android.permission.INTERNET"/>
- 2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- 3 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- 4 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
备注
合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。