Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例

前言:
前面我们介绍MediaPlayer相关方法,有人说,没有实际例子,看得不是很明白,
今天在分析MediaPlayer时,顺带一个播放网络视频例子。
可以自行试试。

同样先看下今天的Agenda:
(1)Android中的MediaPlayer框架
(2)MediaPlayer播放视频主要模块
(3)播放主要模块对应组件
(4)MediaPlayer方法对应有效状态及无效状态
(5)案例:Mediaplayer播放网络视频

Android中的MediaPlayer框架

Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例_第1张图片

MediaPlayer播放视频主要模块

Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例_第2张图片

播放主要模块对应组件

Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例_第3张图片

MediaPlayer方法对应有效状态及无效状态

Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例_第4张图片

Mediaplayer播放网络视频效果图

Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例_第5张图片
为演示,我在本地搭建了一个服务器,将视频文件放在tomcat中的ROOT目录下。名字为sanpan.mp4的一个视频。


案例代码

设置播放相关的方法:在上一篇中MediaPlayer各状态的理解。

MediaPlayerSample/app/src/main/java/com/hejunlin/mediaplayersample/MainActivity.java

package com.hejunlin.mediaplayersample;


import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Toast;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.app.Activity;


public class MainActivity extends Activity implements OnSeekBarChangeListener, OnCompletionListener {

    private boolean isStopUpdatingProgress=false;
    private EditText etPath;
    private MediaPlayer mMediapPlayer;
    private SeekBar mSeekbar;
    private TextView tvCurrentTime;
    private TextView tvTotalTime;

    private final int NORMAL=0;//闲置
    private final int PLAYING=1;//播放中
    private final int PAUSING=2;//暂停
    private final int STOPING=3;//停止中

    private  int currentstate=NORMAL;//播放器当前的状态,默认是空闲状态

    //用行动打消忧虑
    private SurfaceHolder holder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        etPath=(EditText)findViewById(R.id.et_path);
        mSeekbar=(SeekBar) findViewById(R.id.sb_progress);
        tvCurrentTime=(TextView)findViewById(R.id.tv_current_time);
        tvTotalTime=(TextView)findViewById(R.id.tv_total_time);

        mSeekbar.setOnSeekBarChangeListener(this);

        SurfaceView mSurfaceView=(SurfaceView) findViewById(R.id.surfaceview);
        holder=mSurfaceView.getHolder();//SurfaceView帮助类对象

        //是采用自己内部的双缓冲区,而是等待别人推送数据

        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    /**
     * 开始
     * @param v
     */
    public void start(View v){
        if(mMediapPlayer!=null){
            if(currentstate!=PAUSING){
                mMediapPlayer.start();
                currentstate=PLAYING;
                isStopUpdatingProgress=false;//每次在调用刷新线程时,都要设为false
                return ;
                //下面这个判断完美的解决了停止后重新播放的,释放两个资源的问题
            }else if(currentstate==STOPING){
                mMediapPlayer.reset();
                mMediapPlayer.release();
            }
        }
        play();

    }
    /**
     * 停止
     * @param v
     */
    public void stop(View v){
        if(mMediapPlayer!=null){
            mMediapPlayer.stop();
        }
    }

    /**
     * 播放输入框的文件
     */
    private void play(){
        String path=etPath.getText().toString().trim();
        mMediapPlayer=new MediaPlayer();
        try {
            //设置数据类型
            mMediapPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            //设置以下播放器显示的位置
            mMediapPlayer.setDisplay(holder);

            mMediapPlayer.setDataSource(path);
            mMediapPlayer.prepare();
            mMediapPlayer.start();

            mMediapPlayer .setOnCompletionListener(this);
            //把当前播放器的状诚置为:播放中
            currentstate=PLAYING;

            //把音乐文件的总长度取出来,设置给seekbar作为最大值
            int duration=mMediapPlayer.getDuration();//总时长
            mSeekbar.setMax(duration);
            //把总时间显示textView上
            int m=duration/1000/60;
            int s=duration/1000%60;
            tvTotalTime.setText("/"+m+":"+s);
            tvCurrentTime.setText("00:00");

            isStopUpdatingProgress=false;
            new Thread(new UpdateProgressRunnable()).start();

        }catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂停
     * @param v
     */
    public void pause(View v){
        if(mMediapPlayer!=null&&currentstate==PLAYING){

            mMediapPlayer.pause();
            currentstate=PAUSING;
            isStopUpdatingProgress=true;//停止刷新主线程
        }
    }

    /**
     * 重播
     * @param v
     */
    public void restart(View v){
        if(mMediapPlayer!=null){
            mMediapPlayer.reset();
            mMediapPlayer.release();
            play();
        }
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress,
                                  boolean fromUser) {
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        isStopUpdatingProgress=true;//当开始拖动时,那么就开始停止刷新线程
    }


    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        int progress=seekBar.getProgress();
        //播放器切换到指定的进度位置上
        mMediapPlayer.seekTo(progress);
        isStopUpdatingProgress=false;
        new Thread(new UpdateProgressRunnable()).start();
    }

    /**
     * 当播放完成时回调此方法
     */
    @Override
    public void onCompletion(MediaPlayer mp) {
        Toast.makeText(this, "播放完了,重新再播放", 0).show();
        mp.start();
    }

    /**
     * 刷新进度和时间的任务
     * @author hjl
     *
     */
    class  UpdateProgressRunnable implements Runnable{

        @Override
        public void run() {
            //每隔1秒钟取一下当前正在播放的进度,设置给seekbar
            while(!isStopUpdatingProgress){
                //得到当前进度
                int currentPosition=mMediapPlayer.getCurrentPosition();
                mSeekbar.setProgress(currentPosition);
                final int m=currentPosition/1000/60;
                final int s=currentPosition/1000%60;

                //此方法给定的runable对象,会执行主线程(UI线程中)
                runOnUiThread(new Runnable(){

                    @Override
                    public void run() {
                        tvCurrentTime.setText(m+":"+s);
                    }
                });
                SystemClock.sleep(1000);
            }
        }
    }
}

Xml文件:

MediaPlayerSample/app/src/main/res/layout/activity_main.xml

<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" >

    <EditText
        android:id="@+id/et_path"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="请输入视频文件的路径"
        android:text="http://192.168.0.100/sanpan.mp4" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="start"
            android:text="播放" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="pause"
            android:text="暂停" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="stop"
            android:text="停止" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="restart"
            android:text="重播" />
    LinearLayout>

    <SeekBar
        android:id="@+id/sb_progress"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/tv_current_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="00:03"
            android:textColor="#FF0000" />

        <TextView
            android:id="@+id/tv_total_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="/03:33"
            android:textColor="#FF0000" />
    LinearLayout>

    <SurfaceView
        android:id="@+id/surfaceview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

LinearLayout>

由于是网络视频,记得在Manifest加上访问网络的权限

MediaPlayerSample/app/src/main/AndroidManifest.xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.hejunlin.mediaplayersample" >

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>
    application>

manifest>

上面代码摘自 Github:https://github.com/hejunlin2013/MultiMediaSample

本文转自:Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例

你可能感兴趣的:(Android,Media)