MediaPlayer MediaController

最近为了比较全面的了解一下Android的知识体系结构,买了一个Android4 高级编程研读一下,在学习第十五章音频、视频以及摄像头的使用的时候,书本上的MediaPlayer和MediaController联合使用的例子没有调通。搜索良久找到答案在此记录一下。

1.MediaPlayer 播放视频

使用的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<!-- Listing 15-3: Sample layout using a Surface View -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="30" />
    <LinearLayout
        android:id="@+id/ll"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:orientation="horizontal" >
    </LinearLayout>
</LinearLayout>

相关Java代码如下:

package com.paad.mediaplayer;

import java.io.IOException;

import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.MediaController;
import constant.Constants;

public class AudioPlayer extends Activity implements OnPreparedListener,
        MediaController.MediaPlayerControl {
    private static final String TAG = "AudioPlayer";
    private MediaPlayer mediaPlayer;
    private MediaController mediaController;
    private Handler handler = new Handler();

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.surfaceviewvideoviewer);
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setOnPreparedListener(this);
        try {
            //TODO 这里填写你的本地视频文件路径
            mediaPlayer.setDataSource(Constants.PATH_VEDIO);
            mediaPlayer.prepare();
            mediaPlayer.start();
        } catch (IOException e) {
            Log.e(TAG, "Could not open file xxx for playback.", e);
        }

        final SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        surfaceView.setKeepScreenOn(true);
        SurfaceHolder surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                mediaPlayer.release();
            }

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

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format,
                    int width, int height) {
                // TODO Auto-generated method stub

            }
        });
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.setFixedSize(400, 300);

    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // the MediaController will hide after 3 seconds - tap the screen to
        // make it appear again
        mediaController.show();
        return false;
    }

    // --MediaPlayerControl
    // methods----------------------------------------------------
    public void start() {
        mediaPlayer.start();
    }

    public void pause() {
        mediaPlayer.pause();
    }

    public int getDuration() {
        return mediaPlayer.getDuration();
    }

    public int getCurrentPosition() {
        return mediaPlayer.getCurrentPosition();
    }

    public void seekTo(int i) {
        mediaPlayer.seekTo(i);
    }

    public boolean isPlaying() {
        return mediaPlayer.isPlaying();
    }

    public int getBufferPercentage() {
        return 0;
    }

    public boolean canPause() {
        return true;
    }

    public boolean canSeekBackward() {
        return true;
    }

    public boolean canSeekForward() {
        return true;
    }

    // --------------------------------------------------------------------------------

    public void onPrepared(MediaPlayer mediaPlayer) {
        Log.d(TAG, "onPrepared");
        mediaController = new MediaController(this);
        mediaController.setMediaPlayer(this);
        mediaController.setAnchorView(findViewById(R.id.ll));
        mediaController.setEnabled(true);

        handler.post(new Runnable() {
            public void run() {
                mediaController.show();
            }
        });
    }

    @Override
    public int getAudioSessionId() {
        // TODO Auto-generated method stub
        return 0;
    }
}

代码罗列在这里了,我还想啰嗦几句:
1.OnPreparedListener不是必须的,主要是为mediaController.show();服务的,将onPrepared中的代码块移动到onCreate里面也是ok的,但是,要做稍微的调整,将handler.post修改为了handler.postDelayed,设置一个延迟执行的时间(让mediaPlayer完成播放前的初始化)也是ok的。
2.至于为什么在代码初始化后,调用mediaController.show()必须放到handler.post中,我猜想是因为mediaController的初始化也是通过handler机制进行更新的,通过handler是通过队列机制对消息进行处理了,这样就保证了mediaController的初始化和mediaController.show的顺序。
3.至于为什么将mediaPlayer.setDisplay(holder);设置放到surfaceCreated方法中,SurfaceView的创建是异步的,实例化后,并没有完成创建。

2.MediaPlayer播放音频

这个就要简单的多了,不需要SurfaceView来展示视频了,下面贴一下代码:

package com.paad.mediaplayer;

import java.io.IOException;

import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.MediaController;
import constant.Constants;

public class AudioPlayer extends Activity implements OnPreparedListener,
        MediaController.MediaPlayerControl {
    private static final String TAG = "AudioPlayer";
    private MediaPlayer mediaPlayer;
    private MediaController mediaController;
    private Handler handler = new Handler();
    private LinearLayout mControllLayout;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mControllLayout=new LinearLayout(this);
        setContentView(mControllLayout);
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setOnPreparedListener(this);
        try {
            //TODO 这里写你的音频路径
            mediaPlayer.setDataSource(Constants.PATH_AUDIO);
            mediaPlayer.prepare();
            mediaPlayer.start();
        } catch (IOException e) {
            Log.e(TAG, "Could not open file xxx for playback.", e);
        }

    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // the MediaController will hide after 3 seconds - tap the screen to
        // make it appear again
        mediaController.show();
        return false;
    }

    // --MediaPlayerControl
    // methods----------------------------------------------------
    public void start() {
        mediaPlayer.start();
    }

    public void pause() {
        mediaPlayer.pause();
    }

    public int getDuration() {
        return mediaPlayer.getDuration();
    }

    public int getCurrentPosition() {
        return mediaPlayer.getCurrentPosition();
    }

    public void seekTo(int i) {
        mediaPlayer.seekTo(i);
    }

    public boolean isPlaying() {
        return mediaPlayer.isPlaying();
    }

    public int getBufferPercentage() {
        return 0;
    }

    public boolean canPause() {
        return true;
    }

    public boolean canSeekBackward() {
        return true;
    }

    public boolean canSeekForward() {
        return true;
    }

    public void onPrepared(MediaPlayer mediaPlayer) {
        Log.d(TAG, "onPrepared");
        mediaController = new MediaController(this);
        mediaController.setMediaPlayer(this);
        mediaController.setAnchorView(mControllLayout);
        mediaController.setEnabled(true);
        handler.post(new Runnable() {
            public void run() {
                mediaController.show();
            }
        });
    }

    @Override
    public int getAudioSessionId() {
        // TODO Auto-generated method stub
        return 0;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的实现: 首先,在 AndroidManifest.xml 文件中添加外部存储权限: ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ``` 然后,在 Activity 的布局文件中添加一个按钮和一个 SurfaceView: ```xml <Button android:id="@+id/select_file_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="选择文件" /> <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 接下来,在 Activity 的 Java 文件中实现按钮点击和视频播放功能: ```java import android.Manifest; import android.content.pm.PackageManager; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Environment; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; import android.widget.MediaController; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.io.IOException; public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, MediaController.MediaPlayerControl, MediaPlayer.OnBufferingUpdateListener { private static final int REQUEST_EXTERNAL_STORAGE = 1; private static final String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; private MediaPlayer mediaPlayer; private MediaController mediaController; private SurfaceHolder surfaceHolder; private String videoPath; private boolean bufferUpdating; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 检查外部存储权限 int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } // 获取 SurfaceView 和按钮 SurfaceView surfaceView = findViewById(R.id.surface_view); Button selectFileButton = findViewById(R.id.select_file_button); // 设置 SurfaceView 的 Holder 和 Callback surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); // 设置按钮的点击事件 selectFileButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 打开文件选择框 // 选择相应的音频文件,返回文件路径 videoPath = Environment.getExternalStorageDirectory() + "/video.mp4"; } }); } @Override protected void onPause() { super.onPause(); if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } @Override protected void onDestroy() { super.onDestroy(); if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } } @Override public void surfaceCreated(SurfaceHolder holder) { // 初始化 MediaPlayerMediaController mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setOnBufferingUpdateListener(this); mediaController = new MediaController(this); mediaController.setMediaPlayer(this); mediaController.setAnchorView(findViewById(R.id.surface_view)); try { mediaPlayer.setDataSource(videoPath); } catch (IOException e) { e.printStackTrace(); } // 设置 MediaPlayer 的 Surface 和 PrepareAsync mediaPlayer.setDisplay(holder); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mediaController.setEnabled(true); mediaPlayer.start(); } }); mediaPlayer.prepareAsync(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // Do nothing } @Override public void surfaceDestroyed(SurfaceHolder holder) { // Do nothing } @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { // 更新缓存状态 bufferUpdating = true; mediaController.show(); mediaController.setSecondaryProgress(percent * mediaPlayer.getDuration() / 100); bufferUpdating = false; } @Override public boolean onTouchEvent(MotionEvent event) { // 显示或隐藏 Controller mediaController.show(); return false; } @Override public void start() { mediaPlayer.start(); } @Override public void pause() { mediaPlayer.pause(); } @Override public int getDuration() { return mediaPlayer.getDuration(); } @Override public int getCurrentPosition() { return mediaPlayer.getCurrentPosition(); } @Override public void seekTo(int pos) { mediaPlayer.seekTo(pos); } @Override public boolean isPlaying() { return mediaPlayer.isPlaying(); } @Override public int getBufferPercentage() { return bufferUpdating ? 0 : 100; } @Override public boolean canPause() { return true; } @Override public boolean canSeekBackward() { return true; } @Override public boolean canSeekForward() { return true; } @Override public int getAudioSessionId() { return mediaPlayer.getAudioSessionId(); } } ``` 注意,在点击播放按钮时,应该先检查视频路径是否为空,以及 MediaPlayer 是否已经准备好了。如果没有准备好,应该等待 OnPreparedListener 回调再开始播放。同时,应该在 onPause() 和 onDestroy() 中分别暂停和释放 MediaPlayer,以免造成资源浪费和内存泄漏。此外,实现 MediaController.MediaPlayerControl 接口可以让 Controller 自动显示和隐藏,并且可以通过 Controller 控制视频的播放和暂停,以及拖动进度条跳转到指定时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值