Android-MediaPlayer

MediaPlayer

播放音频

①页面布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:text="播放"
android:id="@+id/main2_btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="暂停"
android:id="@+id/main2_btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="结束"
android:id="@+id/main2_btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

②程序设计

1.实例化MediaPlayer

1
2
//  创建MediaPlayer对象
mediaPlayer = new MediaPlayer();

2.设置它要播放的音频并准备音频

1
2
3
4
5
6
7
8
9
10
//  创建一个文件对象
File file = new File(getExternalFilesDir(""),"lbw.aac");
try {
// 设置MediaPlayer的文件路径
mediaPlayer.setDataSource(file.getAbsolutePath());
// 准备音频
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}

3.在按钮的单击事件中播放、暂停或停止

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  public void onClick(View v) {
switch (v.getId()){
case R.id.main2_btn1:
// 播放
mediaPlayer.start();
break;
// 暂停
case R.id.main2_btn2:
mediaPlayer.pause();
break;
// 结束
case R.id.main2_btn3:
mediaPlayer.stop();
break;
}
}

4.当页面销毁时,释放MediaPlayer的缓存

1
2
3
4
5
6
7
  protected void onDestroy() {
super.onDestroy();
// 停止播放
mediaPlayer.stop();
// 释放缓存
mediaPlayer.release();
}

5.整体预览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import androidx.appcompat.app.AppCompatActivity;

import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import java.io.File;
import java.io.IOException;

public class MainActivity2 extends AppCompatActivity implements View.OnClickListener {
private Button main2_btn1,main2_btn2,main2_btn3;
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);

main2_btn1 = findViewById(R.id.main2_btn1);
main2_btn2 = findViewById(R.id.main2_btn2);
main2_btn3 = findViewById(R.id.main2_btn3);

main2_btn1.setOnClickListener(this);
main2_btn2.setOnClickListener(this);
main2_btn3.setOnClickListener(this);

// 创建MediaPlayer对象
mediaPlayer = new MediaPlayer();
// 创建一个文件对象
File file = new File(getExternalFilesDir(""),"lbw.aac");
try {
// 设置MediaPlayer的文件路径
mediaPlayer.setDataSource(file.getAbsolutePath());
// 准备音频
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
// 停止播放
mediaPlayer.stop();
// 释放缓存
mediaPlayer.release();
}

@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.main2_btn1:
// 播放
mediaPlayer.start();
break;
// 暂停
case R.id.main2_btn2:
mediaPlayer.pause();
break;
// 结束
case R.id.main2_btn3:
mediaPlayer.stop();
break;
}
}
}

播放视频

①页面布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextureView
android:layout_weight="1"
android:id="@+id/player_textureView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:text="开始播放"
android:id="@+id/player_btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

②程序设计

1.创建MediaPlayer对象

1
2
//  创建mediaPlayer的对象
mediaPlayer = new MediaPlayer(); //mediaPlayer已经事先声明实例变量

2.指定视频源地址,调用prepare()方法使MediaPlayer对象进入准备完成状态

prepare()不适用于较大的视频或网络视频,因为prepare()会在准备完成进入“准备完成”状态后才会继续向下执行、播放,延迟较大

1
2
3
4
5
6
7
8
  try {
// 指定视频源地址,可以是本地资源、内部Uri、外部网址
mediaPlayer.setDataSource(new File(getExternalFilesDir(""),"test.mp4").getAbsolutePath());
// prepare()准备声音
// mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}

当视频较大或播放网络视频时,通常不使用prepare(),而是在异常捕获外使用prepareAsync()进行异步准备

1
2
//  如果视频比较大或者是网络视频,建议使用prepareAsync进行异步准备
mediaPlayer.prepareAsync();

3.设置TextureView控件显示视频,得到控件的Surface并设置显示

1
2
3
4
//  创建Surface对象,得到TextureView的Surface
Surface surface = new Surface(player_textureView.getSurfaceTexture()); //player_textureView是TextureView的findViewById后的变量
// 设置mediaPlayer播放在surface
mediaPlayer.setSurface(surface);

4.对prepare()或prepareAsync()进行监听,当视频准备完毕时调用,视频准备完毕就开始播放

1
2
3
4
5
6
7
8
//  设置“视频准备”监听,当视频准备完毕时调用
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// 开始播放
mediaPlayer.start();
}
});

5.视频播放完毕,结束MediaPlayer播放和释放缓存

1
2
3
4
5
6
7
8
9
//  视频播放完毕时调用
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
player_btn1.setText("开始播放");
mediaPlayer.stop();
mediaPlayer.release();
}
});

6.另外有

1
2
3
4
5
6
7
8
//  开始播放
mediaPlayer.start();
// 暂停播放
mediaPlayer.pause();
// 结束播放
mediaPlayer.stop();
// 释放缓存
mediaPlayer.release();

7.完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import androidx.appcompat.app.AppCompatActivity;

import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;

import java.io.File;
import java.io.IOException;

public class MyMediaPlayer extends AppCompatActivity {
private Button player_btn1;
private TextureView player_textureView;
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_media_player);

player_btn1 = findViewById(R.id.player_btn1);
player_textureView = findViewById(R.id.player_textureView);

player_btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String str = player_btn1.getText().toString();
if (str.equals("开始播放")){
player_btn1.setText("停止播放");
// 创建mediaPlayer的对象
mediaPlayer = new MediaPlayer();
try {
// 指定视频源地址,可以是本地地址、apk内的文件、网络地址
mediaPlayer.setDataSource(new File(getExternalFilesDir(""),"test.mp4").getAbsolutePath());
// 进入准备完成阶段,也可以在线程外调用prepareAsync进入“准备中”状态
// mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
// 如果视频比较大或者是网络视频,建议使用prepareAsync进行异步准备
mediaPlayer.prepareAsync();
// 设置视频显示的控件
Surface surface = new Surface(player_textureView.getSurfaceTexture());
mediaPlayer.setSurface(surface);
// 设置“视频准备”监听,当视频准备完毕时调用
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// 开始播放
mediaPlayer.start();
}
});
// 视频播放完毕时调用
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
player_btn1.setText("开始播放");
mediaPlayer.stop();
mediaPlayer.release();
}
});
}
else {
player_btn1.setText("开始播放");
// 结束播放
mediaPlayer.stop();
// 释放
mediaPlayer.release();
}
}
});
}
}

8.补充
    TextureView与SurfaceView不同,它不会在WMS中单独创建窗口,而是作为View hierachy中的一个普通View,因此可以和其它普通View一样进行移动,旋转,缩放,动画等变化。
    TextureView必须在硬件加速的窗口中。它显示的内容流数据可以来自App进程或是远端进程。TextureView继承自View,它与其它的View一样在View hierachy中管理与绘制。

VideoView播放视频

VideoView是官方帮我们封装的TextureView,实现一些简单的操作,自定义程度较低

①页面布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<VideoView
android:id="@+id/videoView"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:text="开始播放"
android:id="@+id/video_btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

②程序设计

1.findViewById找到VideoView后直接对它操作就好了

1
videoView = findViewById(R.id.videoView);

2.设置本地播放路径

1
2
//  设置本地路径
videoView.setVideoPath(new File(getExternalFilesDir(""),"test.mp4").getAbsolutePath());

3.VideoView有官方封装的控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//  创建VideoView的控制器
MediaController mediaController = new MediaController(MyVideoView.this);
// 给控制器设置上一个下一个视频
mediaController.setPrevNextListeners(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MyVideoView.this,"上一个视频",Toast.LENGTH_SHORT).show();
}
},
new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MyVideoView.this,"下一个视频",Toast.LENGTH_SHORT).show();
}
});
// 添加控制器到VideoView
videoView.setMediaController(mediaController);

4.播放就好了…

1
videoView.start();