MediaPlayer和SurfaceView高级应用-播放视频和弹幕
效果展示
1.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=".MainActivity"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<SurfaceView
android:id="@+id/sufaceView"
android:layout_width="match_parent"
android:layout_height="400dp" />
<SurfaceView
android:id="@+id/sufaceView2"
android:layout_width="match_parent"
android:layout_height="400dp" />
</FrameLayout>
<SeekBar
android:id="@+id/progeressBar"
android:layout_width="match_parent"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/bt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂停"/>
<Button
android:id="@+id/bt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放"/>
</LinearLayout>
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="要发送的弹幕"/>
<Button
android:id="@+id/bt3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送弹幕"/>
</LinearLayout>
2.MediaPlayer服务
package com.example.app2;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import java.io.IOException;
public class MyService extends Service {
public static MediaPlayer mediaPlayer=new MediaPlayer();
@Override
public void onCreate() {
super.onCreate();
if (mediaPlayer!=null){
try {
mediaPlayer.reset();
mediaPlayer.setDataSource("http://uvideo.spriteapp.cn/video/2019/0512/56488d0a-7465-11e9-b91b-1866daeb0df1_wpd.mp4");
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
class MyBinder extends Binder{
public void pause(){
if (mediaPlayer!=null){
mediaPlayer.pause();
}
}
public void start(){
if (mediaPlayer!=null){
mediaPlayer.start();
}
}
public long getDuration(){
return mediaPlayer.getDuration();
}
public int getCurrent(){
return mediaPlayer.getCurrentPosition();
}
public void seeTo(int postion){
mediaPlayer.seekTo(postion);
}
}
}
3.DanMu类
package com.example.app2;
public class DanMu {
String text;
int x;
int y;
int size;
int color;
public DanMu(String text, int x, int y, int size, int color) {
this.text = text;
this.x = x;
this.y = y;
this.size = size;
this.color = color;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
}
4.Java代码
package com.example.app2;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import com.example.app2.R;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
Button bt_pause, bt_play, bt_danmu;
SeekBar seekBar;
ArrayList<DanMu> list=new ArrayList<>();
int x = 0;
EditText editText;
MyService.MyBinder myBinder;
String string="";
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@SuppressLint("HandlerLeak")
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==101){
long duration = myBinder.getDuration();
seekBar.setMax((int) duration);
int current = myBinder.getCurrent();
seekBar.setProgress(current);
}
}
};
SurfaceHolder surfaceHolder,surfaceHolder2;
SurfaceView surfaceView,surfaceView2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
initView();
init();
}
private void init() {
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
long duration = myBinder.getDuration();
seekBar.setMax((int) duration);
int progress = seekBar.getProgress();
myBinder.seeTo(progress);
}
});
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if (myBinder!=null){
handler.sendEmptyMessage(101);
}
}
},0,1000);
}
private void initView() {
editText=findViewById(R.id.editText);
bt_pause = findViewById(R.id.bt1);
bt_play = findViewById(R.id.bt2);
bt_danmu = findViewById(R.id.bt3);
seekBar = findViewById(R.id.progeressBar);
bt_danmu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
string=editText.getText().toString();
int y= (int) (Math.random()*100);
list.add(new DanMu(string,0,y,50,Color.BLUE));
}
});
bt_pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myBinder.pause();
}
});
bt_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myBinder.start();
}
});
surfaceView = findViewById(R.id.sufaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceView2 = findViewById(R.id.sufaceView2);
surfaceHolder2 = surfaceView2.getHolder();
surfaceHolder2.addCallback(this);
surfaceView2.setZOrderOnTop(true);
surfaceHolder2.setFormat(PixelFormat.TRANSLUCENT);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (holder==surfaceHolder){
MyService.mediaPlayer.setDisplay(surfaceHolder);
}else if (holder==surfaceHolder2){
new Thread(){
@Override
public void run() {
super.run();
while (true){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setColor(Color.RED);
paint.setTextSize(30);
Canvas canvas = surfaceHolder2.lockCanvas();
if (canvas==null){
break;
}
canvas.drawColor(PixelFormat.TRANSPARENT,PorterDuff.Mode.CLEAR);
for (int i=0;i<list.size();i++){
DanMu danMu = list.get(i);
paint.setColor(danMu.getColor());
paint.setTextSize(danMu.getSize());
int x = danMu.getX();
danMu.setX(x+=50);
canvas.drawText(danMu.getText(),danMu.getX(),danMu.getY(),paint);
}
surfaceHolder2.unlockCanvasAndPost(canvas);
}
}
}.start();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}