美文网首页
Android 多媒体基础实践

Android 多媒体基础实践

作者: 酷酷的Demo | 来源:发表于2019-07-08 21:48 被阅读0次

Android三种播放视频的方式(以下内容大多使用真机测试,所以没有运行图片,大家可以自己实战看看)

1、使用其自带的播放器。指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。

2、使用VideoView来播放。在布局文件中使用VideoView结合MediaController来实现对其控制。

3、使用MediaPlayer类和SurfaceView来实现,这种方式很灵活。

使用前先添加权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

1、调用其自带的播放器:

Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/Movie.mp4");     
//调用系统自带的播放器    
    Intent intent = new Intent(Intent.ACTION_VIEW);    
    Log.v("URI:::::::::", uri.toString());    
    intent.setDataAndType(uri, "video/mp4");    
    startActivity(intent);    

2、使用VideoView来播放)

使VideoView主要有以下方法:

方法名 作用
setVideoPath() 设置要播放的视频的文件路径
start() 开始或继续播放
pause() 暂定播放
resume() 重新从头开始播放
seekTo() 从指定位置开始播放
isPlaying() 判断当前是否正在播放视频
getDuration() 获取载入视频的播放时长
  • 做个小Demo练练手吧:

布局文件里放了三个Button,分别为播放,暂停,重新播放,在下面是一个VideoView控件,上代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity">
 
 <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal">
 
  <Button
   android:id="@+id/btn_play"
   android:layout_width="0dp"
   android:layout_height="wrap_content"
   android:layout_weight="1"
   android:text="Play"
   android:textAllCaps="false" />
 
  <Button
   android:id="@+id/btn_pause"
   android:layout_width="0dp"
   android:layout_height="wrap_content"
   android:layout_weight="1"
   android:text="Pause"
   android:textAllCaps="false" />
 
  <Button
   android:id="@+id/btn_replay"
   android:layout_width="0dp"
   android:layout_height="wrap_content"
   android:layout_weight="1"
   android:text="Replay"
   android:textAllCaps="false" />
 </LinearLayout>
 <VideoView
  android:id="@+id/video_view"
  android:layout_width="match_parent"
  android:layout_height="wrap_content" />
 
</LinearLayout>

再看完整java代码实例:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 
 private VideoView videoView;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  //在 onCreate 里,对界面的按钮和显示位置实例化,并检查权限
  videoView = (VideoView)findViewById(R.id.video_view);
  Button btn_play = (Button)findViewById(R.id.btn_play);
  Button btn_pause = (Button)findViewById(R.id.btn_pause);
  Button btn_replay = (Button)findViewById(R.id.btn_replay);
 
  btn_play.setOnClickListener(this);
  btn_pause.setOnClickListener(this);
  btn_replay.setOnClickListener(this);
 
  if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
   ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
  }else {
   initVideoPath();//初始化MediaPlayer
  }
 }

单独写一个方法做视频播放的初始化

 private void initVideoPath() {
  File file = new File(Environment.getExternalStorageDirectory(), "movie.mp4");
  videoView.setVideoPath(file.getPath());//指定视频文件路径
  videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
   @Override
   public void onPrepared(MediaPlayer mp) {
    mp.setLooping(true);//让电影循环播放
   }
  });
 }
 
 @Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  switch (requestCode){
   case 1:
    if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
     initVideoPath();
    }else{
     Toast.makeText(this, "拒绝权限,无法使用程序。", Toast.LENGTH_LONG).show();
     finish();
    }
    break;
   default:
    break;
  }
 }

在一个 onClick 方法中,统一处理 Play(播放)、Pause(暂停)、Replay(重新播放)的逻辑。

    @Override
    public void onClick(View v) {
     switch (v.getId()){
       case R.id.btn_play:
        if(!videoView.isPlaying()){
     videoView.start();//播放
    }
    break;
        case R.id.btn_pause:
    if(videoView.isPlaying()){
     videoView.pause();//暂停
    }
    break;
      case R.id.btn_replay:
    if(videoView.isPlaying()){
     videoView.resume();//重新播放
    }
    break;
    }
    }

由于视频播放属于比较占用资源,所以程序最后要释放资源

 //执行完毕,释放所有资源。
 @Override
 protected void onDestroy() {
  super.onDestroy();
  if(videoView != null){
   videoView.suspend();
  }
 }
}

3、使用MediaPlayer,MediaPlayer优点多,灵活性强,但是难度较大。一般我们都使用surfaceview+mediaplayer的方式来播放视频,让我们来好好看看如何使用它:

  • 步骤:

1)获得MediaPlayer实例:
可以使用直接new的方式:

MediaPlayer mp = new MediaPlayer();

也可以使用create的方式,如:

MediaPlayer mp = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了

调用player.setDataSource()方法设置要播放的资源,可以是文件、文件路径、或者URL。
MediaPlayer的setDataSource一共四个方法:

setDataSource (String path) 
setDataSource (FileDescriptor fd) 
setDataSource (Context context, Uri uri) 
setDataSource (FileDescriptor fd, long offset, long length)
  1. 如何设置要播放的文件:
    MediaPlayer要播放的文件主要包括3个来源:
    a. 用户在应用中事先自带的resource资源
    例如:MediaPlayer.create(this, R.raw.test);
    b. 存储在SD卡或其他文件路径下的媒体文件
    例如:mp.setDataSource("/sdcard/test.mp3");
    c. 网络上的媒体文件
    例如:mp.setDataSource("http://www.citynorth.cn/music/confucius.mp3");(该网址可能已经失效)

3)调用MediaPlayer.setDisplay(holder)设置surfaceHolder,surfaceHolder可以通过surfaceview的getHolder()方法获得。
4)调用MediaPlayer.prepare()来准备。
5)调用MediaPlayer.start()来播放视频。

这是大致步骤,但只有这些是不够的
在第二步之前需要确保surfaceHolder已经准备好了。因此需要给surfaceHolder设置一个callback,

调用addCallback()方法。Callback 有三个回调函数,如下:

SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
        }
    }

surfaceCreated()会在SurfaceHolder被创建的时候回调,在这里可以做一些初始化的操作,surfaceDestroyed()会在SurfaceHolder被销毁的时候回调,在这里可以做一些释放资源的操作,防止内存泄漏。

一般,会在surfaceCreated中给MediaPlayer设置surfaceHolder。

 @Override
        public void surfaceCreated(SurfaceHolder holder) {
            player.setDisplay(holder);
        }

那么具体如何操作呢,看代码:

public class MainActivity extends AppCompatActivity {

    private SurfaceView surfaceView;
    private MediaPlayer player;
    private SurfaceHolder holder;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        progressBar= (ProgressBar) findViewById(R.id.progressBar);

      
        player=new MediaPlayer();
        try {
             File file = new File(Environment.getExternalStorageDirectory(),
                    "2d1c41ae2482271297c2b6b4e6abf2cf.mp4");//播放手机相册里的视频
             player.setDataSource(file.getPath());
            holder=surfaceView.getHolder();
            holder.addCallback(new MyCallBack());
            //player.prepare();
            player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    progressBar.setVisibility(View.INVISIBLE);
                    player.start();
                    player.setLooping(true);
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class MyCallBack implements SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            player.setDisplay(holder);
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }
    }
}

MediaPlayer的具体方法介绍:

方法名 功能描述
void setDataSource(String path) 通过一个具体的路径来设置MediaPlayer的数据源,path可以是本地的一个路径,也可以是一个网络路径
void setDataSource(Context context, Uri uri) 通过给定的Uri来设置MediaPlayer的数据源,这里的Uri可以是网络路径或是一个ContentProvider的Uri。
void setDataSource(MediaDataSource dataSource) 通过提供的MediaDataSource来设置数据源
void setDataSource(FileDescriptor fd) 通过文件描述符FileDescriptor来设置数据源
int getCurrentPosition() 获取当前播放的位置
int getAudioSessionId() 返回音频的session ID
int getDuration() 得到文件的时间
TrackInfo[] getTrackInfo() 返回一个track信息的数组
boolean isLooping () 是否循环播放
boolean isPlaying() 是否正在播放
void pause() 暂停
void start() 开始
void stop() 停止
void prepare() 同步的方式装载流媒体文件。
void prepareAsync() 异步的方式装载流媒体文件。
void reset() 重置MediaPlayer至未初始化状态。
void release () 回收流媒体资源。
void seekTo(int msec) 指定播放的位置(以毫秒为单位的时间)
void setAudioStreamType(int streamtype) 指定流媒体类型
void setLooping(boolean looping) 设置是否单曲循环
void setNextMediaPlayer(MediaPlayer next) 当 当前这个MediaPlayer播放完毕后,MediaPlayer next开始播放
void setWakeMode(Context context, int mode) 设置CPU唤醒的状态。
setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener) 网络流媒体的缓冲变化时回调
setOnCompletionListener(MediaPlayer.OnCompletionListener listener) 网络流媒体播放结束时回调
setOnErrorListener(MediaPlayer.OnErrorListener listener) 发生错误时回调
setOnPreparedListener(MediaPlayer.OnPreparedListener listener) 当装载流媒体完毕的时候回调。

用MediaPlayer播放音频

音频一般也是用MediaPlayer播放的,MediaPlayer的使用上面已经讲过了,在音频的使用和视频大同小异,所以我们不再赘述,实战感受一下吧。

我们来写个播放音频的项目试试

  • 布局文件很简单,就三个Button,分别为播放,暂停,停止。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/btn_play"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击播放"/>
    <Button
        android:id="@+id/btn_pause"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击暂停"/>
    <Button
        android:id="@+id/btn_stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击停止播放"/>
</LinearLayout>
  • 再到java文件里实现代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button playBtn,resumeBtn,pauseBtn;
private MediaPlayer mediaPlayer ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pauseBtn = findViewById(R.id.btn_pause);
        stopBtn = findViewById(R.id.btn_stop);
        playBtn = findViewById(R.id.btn_play);

        playBtn.setOnClickListener(this);
        pauseBtn.setOnClickListener(this);
        stopBtn.setOnClickListener(this);
        if (ContextCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this,new String[]{
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            },1);
        }else {
             init();
        }
    }

    private void init(){
       try{
       File file = new File(Envioronment.getExternalStorageDirectory(),"2d1c41ae2482271297c2b6b4e6abf2cf.mp4");
       mediaPlayer.setDataSource(file.getPath());
       mediaPlayer.setprepare();
      
       } catch (Exception e) {
       e.printStackTrace();
       }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
            int[] grantResults) {
        switch (requestCode){
            case 1:
                if (grantResults.length >0 &&
                        grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    init();
                }else{
                    Toast.makeText(this,"拒绝权限将无法使用程序",
                            Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
                default:
        }
    }

    @Override
    public void onClick(View v) {
     switch (v.getId()){
         case R.id.btn_play:
             if (!mediaPlayer.isPlaying()){
                 mediaPlayer.start();//开始播放
             }
             break;
         case R.id.btn_pause:
             if (mediaPlayer.isPlaying()){
                 mediaPlayer.pause();//暂停播放
             }
             break;
         case R.id.btn_stop:
             if (mediaPlayer.isPlaying()){
                 mediaPlayer.reset();//停止播放
                 init();
             }
             break;
             default:
                 break;
     }
    }

    //释放相关资源
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null){
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    }
}
  • 最后千万不要忘了权限声明

相关文章

网友评论

      本文标题:Android 多媒体基础实践

      本文链接:https://www.haomeiwen.com/subject/hfdzhctx.html