Android_音视频应用开发
目录
1. 音视频播放
.1. MediaPayler 播放音频
- setOnCompletionListener(MediaPlayer.OnCompletionListener listener):为 MediaPlayer的播放完成事件绑定事件监听器。
- setOnErrorListener(MediaPlayer.OnErrorListener listener):为 MediaPlayer 的播放错误事件绑定事件监听器。
- setOnPreparedListener(MediaPlayer.OnPreparedListener listener):当MediaPlayer 调用prepare()方法时触发该监听器。
- setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener):当MediaPlayer调用seek()方法时触发该监听器。
// 播放应用文件
MediaPlayer mPalyer=MediaPayer.create(this,R.raw.song);
mPlayer.start();
// 播放应用原始资源文件
AssetManager am=getAssets();
AssetFileDescriptor afg=am.openFd(music);
MediaPayer mPlayer=new MediaPayer();
mPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
mPlayer.prepare();
mPayer.start();
// 播放外部存储器上音频文件
MediaPayer mPlayer=new MediaPayer();
mPlayer.setDataSource("/mnt/sdcard/mysong.mp3");
mPlayer.prepare();
mPlayer.start();
// 播放来自网络文件
Uri uir=Uri.parse("http://www.crazyit.org/abc.mp3");
MediaPlayer mPlayer=new MediaPayer();
mPlayer.setDataSource(this,url);
mPlayer.prepare();
mPlayer.start();
- 案例代码
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults)
{
if(requestCode == 0x123 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
// 创建MediaPlayer对象
mPlayer = MediaPlayer.create(this, R.raw.beautiful);
// 初始化示波器
setupVisualizer();
// 初始化均衡控制器
setupEqualizer();
// 初始化重低音控制器
setupBassBoost();
// 初始化预设音场控制器
setupPresetReverb();
// 开始播放音乐
mPlayer.start();
}
}
.2. SoundPool 播放音效
-
播放密集,短促的音效
-
SoundPool(int maxStreams, int streamType, int srcQuality):第一个参数指定支持多少个声音:第二个参数指定声音类型;第三个参数指定声音品质。
-
一旦得到了SoundPool对象之后,接下来就可调用SoundPool 的多个重载的 load方法来加载声音了,SoundPool提供了如下4个load方法。
-
int load(Context context, int resld, int priority):从resld所对应的资源加载声音。int load(FileDescriptor fd, long offset, long length, int priority):加载f似所对应的文件的offset开始、长度为length的声音。
-
int load(AssetFileDescriptor afd, int priority):从afd所对应的文件中加载声音。int load(String path, int priority):从path对应的文件去加载声音。
AudioAttributes attr = new AudioAttributes.Builder().setUsage(
AudioAttributes.USAGE_GAME) // 设置音效使用场景
// 设置音效的类型
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
soundPool = new SoundPool.Builder().setAudioAttributes(attr) // 设置音效池的属性
.setMaxStreams(10) // 设置最多可容纳10个音频流
.build(); // ①
// 使用load方法加载指定的音频文件,并返回所加载的音频ID
// 此处使用HashMap来管理这些音频流
soundMap.put(1, soundPool.load(this, R.raw.bomb, 1)); // ②
soundMap.put(2, soundPool.load(this, R.raw.shot, 1));
soundMap.put(3, soundPool.load(this, R.raw.arrow, 1));
// 定义一个按钮的单击监听器
View.OnClickListener listener = source -> {
// 判断哪个按钮被单击
switch (source.getId())
{
case R.id.bomb:
soundPool.play(soundMap.get(1), 1f, 1f, 0, 0, 1f); // ③
break;
case R.id.shot:
soundPool.play(soundMap.get(2), 1f, 1f, 0, 0, 1f);
break;
case R.id.arrow:
soundPool.play(soundMap.get(3), 1f, 1f, 0, 0, 1f);
break;
}
};
.3. 使用VideoView播放视频
public class MainActivity extends Activity
{
private VideoView videoView;
private MediaController mController;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取界面上的VideoView组件
videoView = findViewById(R.id.video);
// 创建MediaController对象
mController = new MediaController(this);
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0x123);
}
@Override public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults)
{
if (requestCode == 0x123
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 设为横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
File video = new File("/mnt/sdcard/movie.mp4");
if (video.exists()) {
videoView.setVideoPath(video.getAbsolutePath()); // ①
// 设置videoView与mController建立关联
videoView.setMediaController(mController); // ②
// 设置mController与videoView建立关联
mController.setMediaPlayer(videoView); // ③
// 让VideoView获取焦点
videoView.requestFocus();
videoView.start(); // 开始播放
}
}
}
}
.4. 使用MediaPlayer&SurfaceView 播放音频
- 创建MediaPlayer对象,并让它加载指定的视频文件。
- 在界面布局文件中定义SurfaceView组件,或在程序中创建SurfaceView组件。并为Surfaceview的SurfaceHolder添加Callback监听器。
- 调用MediaPlayer对象的setDisplay(SurfaceHolder sh)将所播放的视频图像输出到指定的SurfaceView组件。
- 调用MediaPlayer 对象的start(、stopO和pauseO方法控制视频的播放。
public class MainActivity extends Activity
{
private SurfaceView surfaceView;
private MediaPlayer mPlayer;
private ImageButton playBn, pauseBn, stopBn;
// 记录当前视频的播放位置
int position = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建MediaPlayer
mPlayer = new MediaPlayer();
surfaceView = this.findViewById(R.id.surfaceView);
// 设置播放时打开屏幕
surfaceView.getHolder().setKeepScreenOn(true);
surfaceView.getHolder().addCallback(new SurfaceListener());
// 获取界面上的三个按钮
playBn = findViewById(R.id.play);
pauseBn = findViewById(R.id.pause);
stopBn = findViewById(R.id.stop);
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0x123);
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults)
{
if (requestCode == 0x123 && grantResults[0] ==
PackageManager.PERMISSION_GRANTED) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
View.OnClickListener listener = source -> {
switch (source.getId())
{
// “播放”按钮被单击
case R.id.play:
play();
break;
// “暂停”按钮被单击
case R.id.pause:
if (mPlayer.isPlaying()) {
mPlayer.pause();
} else {
mPlayer.start();
}
break;
// “停止”按钮被单击
case R.id.stop:
if (mPlayer.isPlaying())
mPlayer.stop();
}
};
// 为三个按钮的单击事件绑定事件监听器
playBn.setOnClickListener(listener);
pauseBn.setOnClickListener(listener);
stopBn.setOnClickListener(listener);
}
}
private void play()
{
mPlayer.reset();
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
mPlayer.setAudioAttributes(audioAttributes);
try {
// 设置需要播放的视频
mPlayer.setDataSource(Environment.getExternalStorageDirectory().toString() + "/movie.3gp");
// 把视频画面输出到SurfaceView
mPlayer.setDisplay(surfaceView.getHolder()); // ①
mPlayer.prepare();
}
catch(IOException e)
{ e.printStackTrace(); }
// 获取窗口管理器
WindowManager wManager = getWindowManager();
DisplayMetrics metrics = new DisplayMetrics();
// 获取屏幕大小
wManager.getDefaultDisplay().getMetrics(metrics);
// 设置视频保持纵横比缩放到占满整个屏幕
surfaceView.setLayoutParams(new RelativeLayout.LayoutParams(metrics.widthPixels,
mPlayer.getVideoHeight() * metrics.widthPixels / mPlayer.getVideoWidth()));
mPlayer.start();
}
private class SurfaceListener implements SurfaceHolder.Callback
{
@Override
public void surfaceCreated(SurfaceHolder holder)
{
if (position > 0) {
// 开始播放
play();
// 并直接从指定位置开始播放
mPlayer.seekTo(position);
position = 0;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
}
}
// 当其他Activity被打开时,暂停播放
@Override
public void onPause()
{
super.onPause();
if (mPlayer.isPlaying()) {
// 保存当前的播放位置
position = mPlayer.getCurrentPosition();
mPlayer.stop();
}
}
@Override
public void onDestroy()
{
super.onDestroy();
// 停止播放
if (mPlayer.isPlaying()) mPlayer.stop();
// 释放资源
mPlayer.release();
}
}
2. 视频录制MediaRecorder
public class MainActivity extends Activity
{
// 定义界面上的两个按钮
private ImageButton recordBn;
private ImageButton stopBn;
// 系统的音频文件
private File soundFile;
private MediaRecorder mRecorder;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取程序界面中的两个按钮
recordBn = findViewById(R.id.record);
stopBn = findViewById(R.id.stop);
stopBn.setEnabled(false);
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO,
Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x123);
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults)
{
if (requestCode == 0x123 && grantResults.length == 2
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
View.OnClickListener listener = source ->
{
switch (source.getId()) {
// 单击录音按钮
case R.id.record:
if (!Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(MainActivity.this,
"SD卡不存在,请插入SD卡!",
Toast.LENGTH_SHORT).show();
return;
}
// 创建保存录音的音频文件
soundFile = new File(Environment.getExternalStorageDirectory()
.toString() + "/sound.amr");
mRecorder = new MediaRecorder();
// 设置录音的声音来源
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 设置录制的声音的输出格式(必须在设置声音编码格式之前设置)
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
// 设置声音编码格式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setOutputFile(soundFile.getAbsolutePath());
try {
mRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
// 开始录音
mRecorder.start(); // ①
recordBn.setEnabled(false);
stopBn.setEnabled(true);
break;
// 单击停止录制按钮
case R.id.stop:
if (soundFile != null && soundFile.exists()) {
// 停止录音
mRecorder.stop(); // ②
// 释放资源
mRecorder.release(); // ③
mRecorder = null;
recordBn.setEnabled(true);
stopBn.setEnabled(false);
}
break;
}
};
// 为两个按钮的单击事件绑定监听器
recordBn.setOnClickListener(listener);
stopBn.setOnClickListener(listener);
}
}
@Override
public void onDestroy()
{
if (soundFile != null && soundFile.exists()) {
// 停止录音
mRecorder.stop();
// 释放资源
mRecorder.release();
mRecorder = null;
}
super.onDestroy();
}
}