Android多媒体操作

若如初见. 提交于 2019-12-10 13:11:29

MediaPlayer

实现思路
  • 本地音频资源播放

播放本地音频资源实例化MediaPlayer对象,依次调用:setDataSource、prepare()、start()方法,获取资源文件路径及准备资源文件,最后播放音频文件。

  • 网络音频资源播放

播放网络资源首先需要得到网络访问权限。(代码见下方),使用prepareAsync()方法准备音频资源,使用setOnPreparedListener()方法监听资源准备情况,最后于onPrepared()方法中执行start()方法播放音频资源。

<uses-permission android:name="android.permission.INTERNET"/>
代码实现
  • Layout
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/player_path"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入音乐文件路径" />

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

        <Button
            android:id="@+id/btn_start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="&gt;" />

        <Button
            android:id="@+id/btn_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="||" />

        <Button
            android:id="@+id/btn_stop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="口" />
    </LinearLayout>
</LinearLayout>
  • Activity
package cn.ybxy.applicaition;

import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

public class MediaPlayerActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText player_path;
    private Button btn_start;
    private Button btn_pause;
    private Button btn_stop;
    MediaPlayer player;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.player_layout);
        player_path = findViewById(R.id.player_path);
        btn_start = findViewById(R.id.btn_start);
        btn_pause = findViewById(R.id.btn_pause);
        btn_stop = findViewById(R.id.btn_stop);
        btn_start.setOnClickListener(this);
        btn_pause.setOnClickListener(this);
        btn_stop.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_start:
                try {
                    // 构造多媒体对象
                    player = new MediaPlayer();
                    // 音乐加载时构造进度条对话框
                    final ProgressDialog pd = new ProgressDialog(this);
                    pd.setMessage("正在加载");
                    // 重置player对象资源
                    player.reset();
                    player.setDataSource(player_path.getText().toString().trim());
                    // 同步准备方法(主线程执行)
//                     player.prepare();
                    // 异步准备方法(子线程执行 -> 网络请求)
                    player.prepareAsync();
                    // 显示进度条对话框
                    pd.show();
                    // 异步资源准备情况监听器
                    player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            // 音乐资源文件加载完毕后隐藏对话框
                            pd.dismiss();
                            // 异步执行播放
                            player.start();
                        }
                    });
                    // 播放出现异常监听器
                    player.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                        @Override
                        public boolean onError(MediaPlayer mp, int what, int extra) {
                            Toast.makeText(MediaPlayerActivity.this, "播放出现异常" + what, Toast.LENGTH_SHORT).show();
                            return false;
                        }
                    });
                    // 播放完毕监听器
                    player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            Toast.makeText(MediaPlayerActivity.this, "播放完毕", Toast.LENGTH_SHORT).show();
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 同步执行执行播放 -> 异步播放时需要屏蔽这段代码,否则会出现(0,-38)资源未准备就绪错误
//                player.start();
                break;
            case R.id.btn_pause:
                // 正在播放中暂停
                if (player != null && player.isPlaying()) {
                    player.pause();
                }
                // 暂停后继续播放
                if (player != null) {
                    player.start();
                }
                System.out.println("播放暂停");
                break;
            case R.id.btn_stop:
                // 停止播放
                if (player != null) {
                    player.stop();
                    // 释放多媒体资源
                    player.release();
                    // 将对象初始化 -> 释放内存
                    player = null;
                }
                System.out.println("播放停止");
                break;
            default:
                break;
        }
    }
}

SoundPool

功能介绍

当很多个音频文件需要播放时,需要prepared()准备资源,在单位时间内准备资源消耗时间过长,使用SoundPool可以规避这个问题。

SoundPool提前将音频资源加载到内存,使用时直接从内存中读取,从而降低响应时间。

代码实现
  • Layout
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_play"
        android:onClick="play_voice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="播放"/>
</LinearLayout>
  • Activity
package cn.ybxy.applicaition;

import androidx.appcompat.app.AppCompatActivity;

import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;

public class SoundPoolActivity extends AppCompatActivity {
    private SoundPool soundPool;
    private int soundID;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pool_layout);
        // 声音池最大线程数、声音类型(STREAM_MUSIC占用内存最大)、声音质量
        soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC,0);
        soundID = soundPool.load(this,R.raw.boom,0);
    }
    public void play_voice(View view){
        // 声音池中的线程ID、左声道音量、右声道音量、优先级、是否循环、声音速率
        soundPool.play(soundID,1.0f,1.0f,0,0,1.0f);
    }
}

视频播放

实现思路
  • Layout
    首先需要设置屏幕显示方向为横向,且设置Layout布局为没有标题栏及全屏显示,然后使用VideoView放置视频媒体。
  • Activity

设置视频媒体源,如果需要视频控制控件,则使用MediaController对象,通过setAnchorView()方法为父元素(这里代指VideoView)添加控制控件,最后为VideoView对象添加MediaControl对象,将视频控制控件添加到视频源中。

代码实现

首先需要在styles.xml中自定义一个无标题栏及全屏显示的主题样式,代码如下:

<style name="BasicTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowNoTitle">true</item>
</style>

然后在AndroidManifest.xml中对应的Activity中引用该主题样式,并设置屏幕方向横屏。

<activity
    android:name=".VideoActivity"
    android:screenOrientation="landscape"
    android:theme="@style/BasicTheme"></activity>
  • Layout
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <VideoView
        android:id="@+id/vv_video"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
  • Activity
package cn.ybxy.applicaition;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.MediaController;
import android.widget.VideoView;

public class VideoActivity extends AppCompatActivity {
    private VideoView vv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.video_layout);
        // 初始化视频VideoView对象
        vv = findViewById(R.id.vv_video);
        vv.setVideoPath("/mnt/sdcard/Download/1.mp4");
        // 实例化控制组件 -> 视频控制组件
        MediaController mc = new MediaController(this);
        mc.setAnchorView(vv);
        // 给视频源设置控制源
        vv.setMediaController(mc);
        vv.start();
    }
}

SurfaceView实现多媒体渲染播放

实现原理
代码实现
  • Layout
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_playsv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:onClick="start_surf"
        android:text="播放" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <SurfaceView
            android:id="@+id/sv_surf"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</LinearLayout>
  • Activity
package cn.ybxy.applicaition;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

public class SurfaceViewActivity extends AppCompatActivity {
    private SurfaceView sv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.surface_layout);
        sv = findViewById(R.id.sv_surf);
        // surfaceView回调方法
        sv.getHolder().addCallback(new SurfaceHolder.Callback() {
            // surface准备成功后调用方法
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // 遍历100次,绘制半径主键扩大的圆
                        for (int i = 0; i < 100; i++) {
                            SurfaceHolder holder = sv.getHolder();
                            // 锁定画布
                            Canvas canvas = holder.lockCanvas();
                            // 100次遍历执行完毕后设置画布颜色为黑色,清空画布已画元素实现画布刷新。
                            canvas.drawColor(Color.BLACK);
                            // 绘画半径
                            int radius = 5 + i;
                            // 创建画笔对象
                            Paint paint = new Paint();
                            paint.setColor(Color.RED);
                            // 于画布中画圆(圆心坐标(x,y)、半径、画笔)
                            canvas.drawCircle(250, 250, radius, paint);
                            // 解锁画布提交数据
                            holder.unlockCanvasAndPost(canvas);
                            // 休眠0.1s给程序时间加载画布
                            SystemClock.sleep(100);
                        }
                    }
                }).start();
            }

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

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });
    }
    public void start_surf(View view){
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 遍历100次,绘制半径主键扩大的圆
                for (int i = 0; i < 100; i++) {
                    SurfaceHolder holder = sv.getHolder();
                    // 锁定画布
                    Canvas canvas = holder.lockCanvas();
                    // 100次遍历执行完毕后设置画布颜色为黑色,清空画布已画元素实现画布刷新。
                    canvas.drawColor(Color.BLACK);
                    // 绘画半径
                    int radius = 5 + i;
                    // 创建画笔对象
                    Paint paint = new Paint();
                    paint.setColor(Color.RED);
                    // 于画布中画圆(圆心坐标(x,y)、半径、画笔)
                    canvas.drawCircle(250, 250, radius, paint);
                    // 解锁画布提交数据
                    holder.unlockCanvasAndPost(canvas);
                    // 休眠0.1s给程序时间加载画布
//                    SystemClock.sleep(100);
                }
            }
        }).start();
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!