一、继承
java.lang.Object
↳ android.view.View
↳ android.view.SurfaceView
二、公共方法
- applyTransactionToFrame(SurfaceControl.Transaction transaction) 添加将与显示 SurfaceView 的下一个同步应用的事务 框架。
- draw(Canvas canvas) 将此视图(及其所有子视图)手动呈现到给定的画布。
- gatherTransparentRegion(Region region) ViewRoot 使用它在以下情况下执行优化 视图层次结构包含一个或多个 SurfaceView。
- getHolder() 返回提供对此的访问和控制的 SurfaceHolder SurfaceView 的底层表面。
- getHostToken() 用于构造的令牌 SurfaceControlViewHost.
- getImportantForAccessibility() 获取用于确定SurfaceView是否对辅助功能很重要的模式。
- getSurfaceControl() 将可用于父级界面的 SurfaceControl 返回到此 SurfaceView。
- hasOverlappingRendering() 返回SurfaceView是否具有重叠的内容。
- setAlpha(float alpha) 将SurfaceView的不透明度设置为 0 到 1 之间的值,其中 0 表示SurfaceView 完全透明,1 表示SurfaceView完全不透明。
- setChildSurfacePackage(SurfaceControlViewHost.SurfacePackage p) 显示嵌入在 SurfaceControlViewHost.SurfacePackage 在此 SurfaceView 中。
- setClipBounds(Rect clipBounds) 在此视图上设置视图将剪裁到的矩形区域 当它被绘制时。
- setSecure(boolean isSecure) 控制是否应将SurfaceView的内容视为安全视图, 防止它出现在屏幕截图中或被查看 不安全的显示器。
- setSurfaceLifecycle(int lifecycleStrategy) 控制此 SurfaceView 拥有的 Surface 的生命周期。
- setVisibility(int visibility) 设置view 是否显示
- setZOrderMediaOverlay(boolean isMediaOverlay) 控制是否将SurfaceView 放置在另一个view之上 窗口中的规则表面视图(但仍在窗口本身后面)。
- setZOrderOnTop(boolean onTop) 设置将SurfaceView视图显示在窗口顶部
三、播放视频
/**
*
*
* 权限
* 允许应用可以联网
* <uses-permission android:name="android.permission.INTERNET" />
* 写入权限
* <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
* 读取权限
* <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
*
* //视频缓存
* implementation 'com.danikula:videocache:2.7.1'
*
* maven { url "https://maven.aliyun.com/repository/public/" }
* maven { url "https://jitpack.io" }
*
*
* <application android:name=".MyApplication"
*
*/
public class MyApplication extends Application {
private static MyApplication myApplication;
private HttpProxyCacheServer mProxy;
public static MyApplication getInstance() {
return myApplication == null ? (myApplication = new MyApplication()) : myApplication;
}
@Override
public void onCreate() {
super.onCreate();
}
//视频缓存
public HttpProxyCacheServer getProxy() {
MyApplication mApplication = MyApplication.getInstance();
return mApplication.mProxy == null ? (mApplication.mProxy = mApplication.newProxy()) : mApplication.mProxy;
}
/**
* maxCacheSize 设置最大缓存大小(以字节为单位)。默认值为512 Mb
* 1024B=1KB,1024KB=1MB,1024MB=1GB
* maxCacheFilesCount 设置最大缓存文件数
* cacheDirectory
* 覆盖用于缓存文件的默认缓存文件夹。
* 默认情况下,
* 如果安装了卡并且应用程序具有适当的权限,
* 则AndroidVideoCache使用“/Android/data/[app_package_name]/cache/video-cache/”,
* 否则在默认应用程序的缓存目录中使用“视频缓存”子目录。
*/
private HttpProxyCacheServer newProxy() {
return new HttpProxyCacheServer.Builder(MyApplication.getInstance().getApplicationContext())
.maxCacheSize(1024 * 1024 * 1024)
.maxCacheFilesCount(3)
.cacheDirectory(getSaveVideoFile())
.build();
}
public File getSaveVideoFile() {
File esd = Environment.getExternalStorageDirectory();
File f1 = new File(esd.getPath() + "/TestDemo");
if (!f1.exists()) {
f1.mkdir();
}
File file = new File(esd.getPath() + "/TestDemo/video/");
if (!file.exists()) {
file.mkdir();
}
return file;
}
}
public class MainActivity extends AppCompatActivity {
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private MediaPlayer mMediaPlayer;
private HttpProxyCacheServer mProxy;
private ArrayList<String> videoURL;
private int playIndex = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initView() {
mSurfaceView = findViewById(R.id.surfaceView);
}
private void initData() {
playIndex = 0;
videoURL = new ArrayList<>();
mProxy = MyApplication.getInstance().getProxy();
initMediaPlayer();
initSurfaceHolder();
updateAD();
// 缓存视频
// String videoPath = mProxy.getProxyUrl("https://xxx");
// videoURL.add(videoPath);
// loopPlayback();
}
private void initSurfaceHolder() {
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
//在创建时调用
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (null != mMediaPlayer) {
mMediaPlayer.setDisplay(holder);
}
}
//surface的格式或大小发生改变时调用
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (null != mMediaPlayer) {
mMediaPlayer.setDisplay(holder);
}
}
//销毁时调用
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
}
private void initMediaPlayer() {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
private void loopPlayback() {
if (videoURL.size() > 0) {
setMediaPlayer(videoURL.get(0));
} else {
updateAD();
}
mMediaPlayer.setOnCompletionListener(player -> {
playIndex++;
if (playIndex < videoURL.size()) {
setMediaPlayer(videoURL.get(playIndex));
} else {
playIndex = 0;
loopPlayback();
}
});
}
private void setMediaPlayer(String path) {
try {
mMediaPlayer.reset();
//添加音频/视频数据源
mMediaPlayer.setDataSource(path);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
private void updateAD() {
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/TestDemo/video/");
if (file.exists()) {
File[] files = file.listFiles();
if (null != files) {
if (null == videoURL) {
videoURL = new ArrayList<>();
} else {
videoURL.clear();
}
for (int i = 0; i < files.length; i++) {
videoURL.add(files[i].getPath());
}
if (videoURL.size() > 0) {
loopPlayback();
}
}
}
}
}
<?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"
android:orientation="vertical"
tools:context=".MainActivity">
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>