1. Introduce the common methods of MediaPlay class and SurfaceView:
Common methods of the MediaPlay class:
Method name | function |
void seDataSource(String path) | set data source (http/rtsp address) |
void seDataSource(FileDescriptor fd,long offset,long length ) | Set data source |
void seDataSource(Context context,Uri uri) | Set a Uri data source |
static MediaPlayercreate(Context context,int resid) | Conveniently create MediaPlayer according to a given resource id Object method |
static MediaPlayercreate(Context context,Uri uri,SurfaceHolder holder) | Create a MediaPlayer object according to a given URI |
boolean isPlaying() | Determine whether MediaPlayer is playing |
getCurrentPosition() | Get the current position Play position |
getDuration() | Get the time of the file |
isLooping(boolean b) | Whether to play in a loop |
getVideoHeight(), getVideoWidth() | Get the width and height of the video |
pause() | Pause |
prepare() | Prepare (synchronous) |
prepareAsync() | Prepare (asynchronous) |
release() | Release the MediaPlayer object Related Resources |
reset() | Reset the MediaPlayer object to the state it just created |
seekTo(int seek) | Specify the playback position (time in milliseconds) |
setAudioStreamType(int type) | Set the type of streaming media |
setDisplay(SurfaceHolder sh) | Set SurfaceHolder to display multimedia |
stop() | Stop playing |
setVolume(float leftVolume,float rightVolume) | Set volume |
setScreenOnWhilePlaying(boolean b) | Set whether to use SurfaceHolder to keep the screen displayed |
start() | Start playing |
Monitoring method:
setOnButteringUpdateListener | Internet streaming media buffer monitoring |
setOnErrorListener | setting error Information monitoring |
setOnVideoSizeChangedListener | Video size monitoring |
Common methods of the SurfaceView class:
Construction method |
Function |
purblic SurfaceView(Context context) | Create a SurfaceView object |
purblic SurfaceView (Context context, AttributeSet attrs) | Create SurfaceView object |
purblic SurfaceView(Context context, AttributeSet attrs, int defStyle) | Create a SurfaceView object |
Common methods | Function |
public SurfaceHolder getHolder() | Get the SurfaceHolder object to manage surfaceview |
public void setVisibility(int visibility) | Set whether it is visible |
SurfaceHolder is an interface, similar to a Surface listener. There are three callback methods to monitor the creation, destruction and change of Surface.
@Override public void surfaceCreated(@NonNull SurfaceHolder holder) { // create } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { // Change } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { // destroy }
2. Example:
MainActivity:
package com.example.surfaceview; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.content.ContentResolver; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.CountDownTimer; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.Toast; import java.util.Timer; import java.util.TimerTask; public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener,SurfaceHolder.Callback, View.OnClickListener { private SurfaceView sv; private SurfaceHolder mHolder; private MediaPlayer mPlayer; private RelativeLayout rl; private Timer mTimer; private TimerTask mTimerTask; private SeekBar sbar; private ImageView play, forward, backward, loop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R. layout. activity_main); initView(); mTimer = new Timer(); // The task of the timer: mTimerTask = new TimerTask() { @Override public void run() { if (mPlayer!=null & &mPlayer.isPlaying()){ // Get the length of the video and set the maximum value of the progress bar int total = mPlayer. getDuration(); sbar.setMax(total); // get the current position int progress = mPlayer. getCurrentPosition(); sbar.setProgress(progress); } } }; // start the timer mTimer.schedule(mTimerTask,500,500); } private void initView() { sv = findViewById(R.id.sv); loop = findViewById(R.id.loop_Im); loop.setOnClickListener(this); forward = findViewById(R.id.backward_Im); forward.setOnClickListener(this); backward = findViewById(R.id.forward_Im); backward. setOnClickListener(this); // Get the SurfaceHolder object for managing SurfaceView mHolder = sv. getHolder(); mHolder. setType(3); mHolder. addCallback(this); rl = findViewById(R.id.rl); play = findViewById(R.id.play); play.setOnClickListener(this); sbar = findViewById(R.id.sbar); sbar.setOnSeekBarChangeListener(this); } @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { mPlayer = new MediaPlayer(); mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getPackageName() + "/" + R.raw.video); try { // set the data source mPlayer.setDataSource(MainActivity.this,uri); // surfaceView is associated with MediaPlay mPlayer.setDisplay(mHolder); mPlayer.prepareAsync(); // Prepare to play (asynchronous) mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mPlayer.start(); } }); }catch (Exception e){ Toast.makeText(MainActivity.this,"Play failed!",Toast.LENGTH_LONG).show(); e.printStackTrace(); } } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mPlayer!=null) mPlayer. stop(); } / // When the progress of the progress bar changes @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (seekBar. getProgress()==seekBar. getMax()){ play.setBackgroundResource(R.drawable.stop); } } // Triggered when the progress bar is dragged @Override public void onStartTrackingTouch(SeekBar seekBar) { } // Triggered when the progress bar stops dragging @Override public void onStopTrackingTouch(SeekBar seekBar) { int position = seekBar. getProgress(); if (mPlayer!=null){ mPlayer. seekTo(position); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event. getAction()){ case MotionEvent. ACTION_DOWN: if (rl. getVisibility() == INVISIBLE) { rl. setVisibility(VISIBLE); CountDownTimer cdt = new CountDownTimer(3000, 1000) { @Override public void onTick(long millisUntilFinished) { System.out.println(millisUntilFinished); } @Override public void onFinish() { // hide progress bar and play button rl. setVisibility(INVISIBLE); } }; cdt.start(); }else if(rl. getVisibility() == VISIBLE){ rl. setVisibility(INVISIBLE); } break; } return super.onTouchEvent(event); } @Override protected void onDestroy() { // Release resources mTimerTask. cancel(); mTimer. cancel(); mTimer = null; mTimerTask = null; mPlayer. release(); mPlayer=null; super. onDestroy(); } @Override public void onClick(View v) { switch (v. getId()){ case R.id.backward_Im: int bPosition = mPlayer.getCurrentPosition()-100; mPlayer.seekTo(bPosition); sbar.setProgress(bPosition); break; case R.id.forward_Im: int fPosition = mPlayer.getCurrentPosition() + 200; mPlayer.seekTo(fPosition); sbar.setProgress(fPosition); break; case R.id.loop_Im: if (mPlayer.isPlaying()){ loop.setBackgroundResource(R.drawable.floooping); Toast.makeText(this, "1111", Toast.LENGTH_SHORT).show(); mPlayer. setLooping(false); } else { loop.setBackgroundResource(R.drawable.tlooping); Toast.makeText(this, "1222", Toast.LENGTH_SHORT).show(); mPlayer. setLooping(true); } break; case R.id.play: if (mPlayer!=null & &mPlayer.isPlaying()){ mPlayer. pause(); play.setImageResource(R.drawable.stop); } else { mPlayer.start(); play.setImageResource(R.drawable.start); } break; } } }
activity_main:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <SurfaceView android:id="@ + id/sv" android:layout_width="match_parent" android:layout_height="match_parent" /> <RelativeLayout android:id="@ + id/rl" android:layout_width="match_parent" android:layout_height="match_parent" > <SeekBar android:id="@ + id/sbar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:max="100" android:progress="0" /> <ImageView android:id="@ + id/play" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerInParent="true" android:background="@drawable/start" /> <ImageView android:id="@ + id/backward_Im" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerInParent="true" android:layout_toLeftOf="@ + id/play" android:background="@drawable/backward" /> <ImageView android:id="@ + id/forward_Im" android:layout_width="50dp" android:layout_height="50dp" android:layout_toRightOf="@ + id/play" android:layout_centerInParent="true" android:background="@drawable/forward" /> <ImageView android:id="@ + id/loop_Im" android:layout_width="50dp" android:layout_height="50dp" android:layout_below="@ + id/forward_Im" android:layout_centerInParent="true" android:background="@drawable/floooping" /> </RelativeLayout> </FrameLayout>