一、使用Android自带的MediaPlay(这种不支持http)
1. 布局文件 activity_video_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<SurfaceView
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/surfaceView"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
2. Activity中具体实现,这是用kotlin实现的
import android.animation.ObjectAnimator;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.loyalquality.smartfirefighting.R;
/**
* rtsp流是可以支持的,http不支持
*/
public class VideoTest2Activity extends AppCompatActivity
{
private MediaPlayer mediaPlayer;
private SurfaceView surfaceView;
private ImageView img;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_test2);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
// img = findViewById(R.id.iv_img);
surfaceView.setZOrderOnTop(true);
surfaceView.getHolder().setFormat(Color.TRANSPARENT);
initView();
}
//图片渐变消失
public void animationView() {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(img, "alpha", 1f, 0f);
objectAnimator.setDuration(2000);
objectAnimator.start();
}
private void initView() {
mediaPlayer = new MediaPlayer();
//获取SurfaceHolder 可以通过该接口来操作SurfaceView中的Surface
SurfaceHolder surfaceHolder = surfaceView.getHolder();
//设置Meiaplayer的准备监听
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
//准备完成后播放
mediaPlayer.start();
}
});
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
//当SurfaceView中Surface创建时回掉
//该方法表示Surface已经创建完成,可以在该方法中进行绘图操作
@Override
public void surfaceCreated(SurfaceHolder holder) {
mediaPlayer.reset();
try {
//设置视屏文件图像的显示参数
mediaPlayer.setDisplay(holder);
// 本地视频文件
// String videoUrl1 = "android.resource://" + getPackageName() + "/" + R.raw.handwrite_tutorial_animation;
Uri uri = Uri.parse("rtsp://*****@***/h264/ch1/main/av_stream");
// String uri = "http://********?port=1980&app=myapp&stream=video0";
//file.getAbsolutePath()本地视频
//uri 网络视频
mediaPlayer.setDataSource(VideoTest2Activity.this,uri);
// mediaPlayer.setDataSource(uri);
//获取第一帧图片
// MediaMetadataRetriever retriever = new MediaMetadataRetriever();
// retriever.setDataSource(VideoTest2Activity.this,uri);
// Bitmap bitmap = retriever.getFrameAtTime(1+1L,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
img.setImageBitmap(bitmap);
// animationView();
// retriever.release();
// mediaPlayer.setOnPreparedListener(mediaPlayer -> {
// mediaPlayer.setOnInfoListener((mp, what, extra) -> {
// if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START)
// surfaceView.setBackgroundColor(Color.TRANSPARENT);
// return true;
// });
// });
//prepare();表示准备工作同步进行,(准备工作在UI线程中进行)
//当播放网络视频时,如果网络不要 会报ARN 所以不采用该方法
//mediaPlayer.prepare();
//异步准备 准备工作在子线程中进行 当播放网络视频时候一般采用此方法
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
//当SurfaceView的大小发生改变时候触发该方法
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
//Surface销毁时回掉
//当Surface销毁时候,同时把MediaPlayer也销毁
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mediaPlayer!=null) {
mediaPlayer.stop();
//释放资源
mediaPlayer.release();
}
}
});
//设置 surfaceView点击监听
surfaceView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
} else {
mediaPlayer.start();
}
break;
}
//返回True代表事件已经处理了
return true;
}
});
}
@Override
protected void onResume() {
super.onResume();
initView();
}
}
二、使用webview+H5来实现,http格式视频播放
1. 用H5写的视频播放页面,video.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flv视频流播放</title>
<style>
html,
body {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
margin: 0 auto;
/* text-align: center; */
}
.video{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
object-fit:fill;
}
video::-webkit-media-controls-fullscreen-button {
display: none;
}
video::-webkit-media-controls-play-button {
display: none;
}
video::-webkit-media-controls-timeline {
display: none;
}
video::-webkit-media-controls-current-time-display{
display: none;
}
video::-webkit-media-controls-time-remaining-display {
display: none;
}
video::-webkit-media-controls-mute-button {
display: none;
}
video::-webkit-media-controls-toggle-closed-captions-button {
display: none;
}
video::-webkit-media-controls-volume-slider {
display: none;
}
video::-webkit-media-controls-enclosure{
display: none;
}
</style>
</head>
<body>
<!-- 会自动播放 -->
<video id="video"
class="video"
poster="video_bg.png"
autoplay
controlsList="nodownload nofullscreen noremoteplayback noplaybackrate disablePictureInPicture"
muted></video>
<!-- 需手动播放 controls这个属性会显示播放键-->
<!--<video id="video"-->
<!-- class="video"-->
<!-- poster="bg_daily.png"-->
<!-- controlsList="nodownload nofullscreen noremoteplayback noplaybackrate"-->
<!-- controls-->
<!-- muted></video>-->
<script id="flvjs" src="flv.js"></script>
<!--<script id="flvjs" src="http://bilibili.github.io/flv.js/dist/flv.js"></script>-->
<script>
function initPlayer(path) {
if (flvjs.isSupported()) {
var flvPlayer = flvjs.createPlayer({
enableWorker: true,
enableStashBuffer: false,
stashInitialSize: 128,
type: "flv", // => 媒体类型 flv 或 mp4
isLive: true, // => 是否为直播流
hasAudio: false, // => 是否开启声音
url: path
});
flvPlayer.attachMediaElement(video);
flvPlayer.load();
}
}
</script>
</body>
</html>
2. 布局文件 activity_video_text.xml, 其中X5WebViewSampl是自己重新的webview
<?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" >
<com.test.widget.x5web.X5WebViewSample
android:id="@+id/web_storage"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
3. activity的具体实现
import android.os.Build;
import android.os.Handler;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebSettings;
import android.widget.Toast;
import com.loyalquality.R;
import com.loyalquality.widget.x5web.BaseX5WebActivity;
import com.loyalquality.widget.x5web.X5WebViewSample;
public class CampVideoActivity extends BaseX5WebActivity
{
public static String VIDEO_URL = "videoUrl";
private X5WebViewSample webStorage;
String path = "";
private Handler mHandler = new Handler();
@Override
protected void initView() {
path = getIntent().getStringExtra(VIDEO_URL);
setContentView(R.layout.activity_daily_camp_video);
webStorage = findViewById(R.id.wv_video);
initWebStorage();
webStorage.loadUrl("file:///android_asset/videoA.html");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
goJsInitPlayer();
}
});
}
}, 2000);
// 设置响应JS的Alert()函数
// webStorage.setWebChromeClient(new WebChromeClient() {
// @Override
// public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
// AlertDialog.Builder b = new AlertDialog.Builder(CampVideoTestActivity.this);
// b.setTitle("Alert");
// b.setMessage(message);
// b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface dialog, int which) {
// result.confirm();
// }
// });
// b.setCancelable(false);
// b.create().show();
// return true;
// }
// });
findViewById(R.id.iv_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
private void initWebStorage()
{
//声明WebSettings子类
WebSettings webSettings = webStorage.getSettings();
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
webSettings.setJavaScriptEnabled(true);
// 设置允许js弹框
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
//缩放操作
webSettings.setSupportZoom(false); //支持缩放,默认为true。是下面那个的前提。
// webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
// webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
//其他细节操作
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
// webSettings.setAllowFileAccess(true); //设置可以访问文件
// webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
}
@Override
protected X5WebViewSample getmX5WebView() {
return webStorage;
}
@Override
protected void start() {
}
private void goJsInitPlayer(){
if(path.isEmpty()){
Toast.makeText(this,"videoUrl is null",Toast.LENGTH_SHORT).show();
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webStorage.evaluateJavascript("javascript:initPlayer('"+path+"')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
// 此处为JS返回的结果
}
});
} else {
webStorage.loadUrl("javascript:initPlayer('"+path+"')");
}
}
@Override
protected void onPause() {
if(null != webStorage) {
webStorage.onPause();
}
super.onPause();
}
}