Android Studio新手开发第三十一天

利用MediaPlayer播放音频

MediaPlayer 是 Android 系统中用于播放音频和视频文件的核心组件,它提供了一套完整的API,能够以较小的代价处理多媒体播放任务。它常用的方法说明如下:

1.reset:重置播放器。

2.prepare:准备播放。

3.start:开始播放。

4.pause:暂停播放。

5.create:创建指定Uri或者资源编号的播放器。

6.setDateSource:设置播放器数据来源的文件路径,它与create只需调用一次即可。

7.setVolume:设置音量。它有两个参数,分别是左右声道的音量,取值范围0~1。

8.setAudioStreamType:设置音频流的类型。

9.setLooping:设置是否循环播放,true为循环播放,false为播放一次。

10.isPlaying:判断是否正在播放。

11.getCurrentPosition:获取当前播放进度所在位置。

12.getDuration:获取播放时长,单位为毫秒。

下面以播放音频为例,现在res/raw目录下添加一个音频文件,没有raw目录可以自行新建一个。示例代码如下,在布局文件中添加了三个按钮已经一个进度条。

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MultiMedia.MediaPlayerActivity"
    android:orientation="vertical">

    <Button
        android:id="@+id/button_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="START"/>
    <Button
        android:id="@+id/button_pause"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="PAUSE"/>
    <Button
        android:id="@+id/button_stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="STOP"/>

    <SeekBar
        android:id="@+id/seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

部分Java代码如下,重点在于进度条监听器的逻辑处理代码,runnable的逻辑处理代码,按钮监听器的逻辑处理代码。

java 复制代码
public class MediaPlayerActivity extends AppCompatActivity implements View.OnClickListener {
    private Button button_start, button_pause, button_stop;
    private SeekBar seekbar;
    private MediaPlayer mediaPlayer;
    private boolean if_seek = false;
    private Time time;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_media_player);
        button_start = findViewById(R.id.button_start);
        button_pause = findViewById(R.id.button_pause);
        button_stop = findViewById(R.id.button_stop);
        seekbar = findViewById(R.id.seekbar);
        button_start.setOnClickListener(this);
        button_pause.setOnClickListener(this);
        button_stop.setOnClickListener(this);
        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                Log.d(TAG, "onProgressChanged: ");
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                Log.d(TAG, "onStartTrackingTouch: ");
                if_seek = true;
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Log.d(TAG, "onStopTrackingTouch: ");
                if (mediaPlayer != null) {
                    mediaPlayer.seekTo(seekBar.getProgress());
                }
                if_seek = false;
            }
        });

    }

    private Handler mHandler = new Handler();
    private Runnable mUpdateProgressRunnable = new Runnable() {
        @Override
        public void run() {
            if (mediaPlayer != null && !if_seek) { // 用户未拖动时才更新
                int currentPosition = mediaPlayer.getCurrentPosition(); // 获取当前播放位置[citation:5]
                seekbar.setProgress(currentPosition); // 更新SeekBar进度[citation:5]
                Log.d(TAG, "run: ");
            }
            //音乐播放结束,停止更新进度条,进度条重置
            if (mediaPlayer.getDuration() == seekbar.getProgress()){
                mHandler.removeCallbacks(mUpdateProgressRunnable);
                seekbar.setProgress(0);
            }
            // 每隔一定时间(如500毫秒)更新一次
            mHandler.postDelayed(this, 1000);
        }
    };

    // 开始更新进度
    private void startProgressUpdate() {
        mHandler.post(mUpdateProgressRunnable);
    }

    // 停止更新进度
    private void stopProgressUpdate() {
        mHandler.removeCallbacks(mUpdateProgressRunnable);
        mediaPlayer = null;
        seekbar.setMax(0);
    }

    //暂停更新进度
    private void pauseProgressUpdate() {
        mHandler.removeCallbacks(mUpdateProgressRunnable);
    }


    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.button_start) {
            if (mediaPlayer == null){
                mediaPlayer = MediaPlayer.create(this, R.raw.hsf);
                seekbar.setMax(mediaPlayer.getDuration());
            }
            if (!mediaPlayer.isPlaying()) {
                mediaPlayer.start();
                Log.d(TAG, "START");
            }
            startProgressUpdate();

        } else if (view.getId() == R.id.button_pause) {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
                Log.d(TAG, "PAUSE");
            }
            if (mediaPlayer == null){return;}
            pauseProgressUpdate();

        }else if (view.getId() == R.id.button_stop){
            mediaPlayer.stop();
            stopProgressUpdate();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mediaPlayer.release();
        mediaPlayer = null;
    }
}

效果图如下,点击对应的按钮实现音频的开始,暂停以及结束,点击进度条跳转至对应播放位置。注意在调用MediaPlayer的stop方法后若要开始音频则需要重新设置MediaPlayer的数据源。在退出APP时建议在onDestroy方法或者onStop方法上调用MediaPlayer的release方法释放系统资源或者在不使用MediaPlayer时调用该方法以减少系统资源占用。

利用MediaPlayer播放视频

MediaPlayer除了可以用来播放音频,它也可以用来播放视频,不过它还需要配合其他视图来展示视频。利用MediaPlayer播放音频可以知道它是没有在页面上显示的,只有通过其他视图来控制播放等操作。而MediaPlayer播放视频就需要一个能够承载视频的视图SurfaceView。一般情况下可以使用视图VideoView直接展示视频,不过这种方式占用系统资源较大。利用MediaPlayer结合SurfaceView可以减少系统资源占用。示例代码如下,

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<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=".MultiMedia.MediaPlayerActivity">

    <Button
        android:id="@+id/button_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="START" />

    <Button
        android:id="@+id/button_pause"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="PAUSE" />

    <Button
        android:id="@+id/button_stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="STOP" />


    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:layout_marginTop="10dp"
        android:layout_gravity="center"/>

</LinearLayout>

部分Java代码如下。

java 复制代码
public class MediaPlayerActivity extends AppCompatActivity implements View.OnClickListener, SurfaceHolder.Callback {
    private Button button_start, button_pause, button_stop;
    private SurfaceView surfaceView;
    private MediaPlayer  mediaPlayer_surface;
    private SurfaceHolder surfaceHolder;

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

        button_start = findViewById(R.id.button_start);
        button_pause = findViewById(R.id.button_pause);
        button_stop = findViewById(R.id.button_stop);
        surfaceView = findViewById(R.id.surfaceView);

        button_start.setOnClickListener(this);
        button_pause.setOnClickListener(this);
        button_stop.setOnClickListener(this);

        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
    }


    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.button_start) {

            mediaPlayer_surface.start();

        } else if (view.getId() == R.id.button_pause) {

            mediaPlayer_surface.pause();
        } else if (view.getId() == R.id.button_stop) {
            mediaPlayer_surface.stop();
        }
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        mediaPlayer_surface = MediaPlayer.create(this, R.raw.hby);
        mediaPlayer_surface.setDisplay(surfaceHolder);
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
    }
}

效果图如下。

相关推荐
Dev7z3 小时前
基于Swin Transformer的宠物皮肤病诊断系统
1024程序员节
王老师青少年编程3 小时前
AtCoder真题及详细题解 ABC427C: Bipartize
c++·题解·1024程序员节·atcoder·csp·abc·信奥赛
gAlAxy...3 小时前
面试JAVASE基础(五)——Java 集合体系
java·python·面试·1024程序员节
B站计算机毕业设计之家4 小时前
计算机视觉python口罩实时检测识别系统 YOLOv8模型 PyTorch 和PySide6界面 opencv (建议收藏)✅
python·深度学习·opencv·计算机视觉·cnn·1024程序员节
大肘子咒你4 小时前
数字狂潮来袭
数据结构·c++·1024程序员节
Lethehong4 小时前
首个多院区异构多活容灾架构,浙人医创新开新篇
1024程序员节·kingbasees
呆呆的猫4 小时前
【多模态】46、DeepSeek-OCR | 一张图片是否真能抵千词
ocr·1024程序员节
唯鹿5 小时前
Copilot使用体验
ai·1024程序员节
蔚蓝星辰mic5 小时前
数据库运维查询SQL语句集合
数据库·sql·1024程序员节