视频直播,点播,悬浮小窗口播放demo (使用阿里云sdk)
2018-12-03 本文已影响0人
庞哈哈哈12138
使用阿里云直播sdk demo ,支持直播,点播 视频直播与悬浮窗小窗口无缝衔接切换(一般拉流格式 rtmp m3u8等)
直播点播提示,监听,各种状态返回以及各种提示
视频播放基础库 支持全屏,快进,手势基础操作
全局视频小窗口 权限判断,高斯模糊背景(可以加深颜色)
飘心效果,还有列表单例播放视频 ,列表全屏视频,视频支持手势,进度,亮度,声音
demo下载地址
效果图:
007.gif 002.gif 003.gif 004.gif 005.gif 006.gif 007.gif这里对直播与悬浮窗直播无缝切换说一下实现原理:
1 ,直播组件做成单例,通过addview的形式,在悬浮窗的framelayout上增加直播view,切换正常模式也是在原页面留下的framelayout站位增加这个直播view
/**
* Description:初始化直播弹窗工具
* Created by PangHaHa on 18-7-18.
* Copyright (c) 2018 PangHaHa All rights reserved.
*/
public class LiveUtils {
//布局参数.
private static WindowManager.LayoutParams params;
//实例化的WindowManager.
private static WindowManager windowManager;
private static int statusBarHeight =-1;
private static FrameLayout toucherLayout;
private static ImageView imageViewClose;
private static int count = 0;//点击次数
private static long firstClick = 0;//第一次点击时间
private static long secondClick = 0;//第二次点击时间
private static float start_X = 0;
private static float start_Y = 0;
// 记录上次移动的位置
private static float lastX = 0;
private static float lastY = 0;
private static int offset;
// 是否是移动事件
private static boolean isMoved = false;
/**
* 两次点击时间间隔,单位毫秒
*/
private static final int totalTime = 1000;
private static boolean isInit = true;
public static void initLive(final Context context ){
try {
windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
//赋值WindowManager&LayoutParam.
params = new WindowManager.LayoutParams();
//设置type.系统提示型窗口,一般都在应用程序窗口之上.
if (Build.VERSION.SDK_INT >= 26) {//8.0新特性
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
//设置效果为背景透明.
params.format = PixelFormat.RGBA_8888;
//设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
//设置窗口坐标参考系
params.gravity = Gravity.LEFT | Gravity.TOP;
//用于检测状态栏高度.
int resourceId = context.getResources().getIdentifier("status_bar_height",
"dimen","android");
if (resourceId > 0) {
statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
offset = DensityUtil.dp2px(context, 2);//移动偏移量
//设置原点
params.x = getScreenWidth(context) - DensityUtil.dp2px(context, 170);
params.y = getScreenHeight(context) - DensityUtil.dp2px(context, 100+72) ;
//设置悬浮窗口长宽数据.
params.width = DensityUtil.dp2px(context, 180);
params.height = DensityUtil.dp2px(context, 100);
//获取浮动窗口视图所在布局.
toucherLayout = new FrameLayout(context);
AliyunVodPlayerView playerView = new AliyunVodPlayerView(context);
playerView.initVideoView(true);
playerView.setAutoPlay(true);
playerView.setKeepScreenOn(true);
playerView.setTitleBarCanShow(false);
playerView.setControlBarCanShow(false);
AliyunLocalSource.AliyunLocalSourceBuilder alsb = new AliyunLocalSource.AliyunLocalSourceBuilder();
alsb.setSource("http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8");
AliyunLocalSource localSource = alsb.build();
playerView.setLiveSource(localSource);
toucherLayout.addView(playerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
imageViewClose = new ImageView(context);
imageViewClose.setImageResource(R.drawable.icon_close);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
DensityUtil.dp2px(context, 16), DensityUtil.dp2px(context, 16));
layoutParams.gravity = Gravity.TOP | Gravity.RIGHT;
layoutParams.rightMargin = DensityUtil.dp2px(context, 3);
layoutParams.topMargin = DensityUtil.dp2px(context, 3);
imageViewClose.setLayoutParams(layoutParams);
toucherLayout.addView(imageViewClose,layoutParams);
//添加toucherlayout
if(isInit) {
windowManager.addView(toucherLayout,params);
} else {
windowManager.updateViewLayout(toucherLayout,params);
}
//主动计算出当前View的宽高信息.
toucherLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
//处理touch
toucherLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isMoved = false;
// 记录按下位置
lastX = event.getRawX();
lastY = event.getRawY();
start_X = event.getRawX();
start_Y = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
isMoved = true;
// 记录移动后的位置
float moveX = event.getRawX();
float moveY = event.getRawY();
// 获取当前窗口的布局属性, 添加偏移量, 并更新界面, 实现移动
params.x += (int) (moveX - lastX);
params.y += (int) (moveY - lastY);
if (toucherLayout!=null){
windowManager.updateViewLayout(toucherLayout,params);
}
lastX = moveX;
lastY = moveY;
break;
case MotionEvent.ACTION_UP:
float fmoveX = event.getRawX();
float fmoveY = event.getRawY();
if (Math.abs(fmoveX-start_X)<offset && Math.abs(fmoveY-start_Y)<offset){
isMoved = false;
Intent intent = new Intent(context,MainActivity.class);
context.startActivity(intent);
}else {
isMoved = true;
}
break;
}
// 如果是移动事件, 则消费掉; 如果不是, 则由其他处理, 比如点击
return isMoved;
}
});
//删除
imageViewClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
remove(context);
}
});
}catch (Exception e){
e.printStackTrace();
}
isInit = false;
}
private static void remove(Context context) {
if(windowManager != null && toucherLayout != null) {
windowManager.removeView(toucherLayout);
isInit = true;
}
}
/**
* 获取屏幕宽度(px)
*/
private static int getScreenWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
/**
* 获取屏幕高度(px)
*/
private static int getScreenHeight(Context context){
return context.getResources().getDisplayMetrics().heightPixels;
}
}
2,对弹窗初始化时权限的判断 魅族和小米需要特殊处理
private void showLiveWindow() {
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(getContext())) {
//没有悬浮窗权限,跳转申请
Toast.makeText(getApplicationContext(), "请开启悬浮窗权限", Toast.LENGTH_LONG).show();
//魅族不支持直接打开应用设置
if (!MEIZU.isMeizuFlymeOS()) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
} else {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivityForResult(intent, 0);
}
} else {
LiveUtils.initLive(MainActivity.this);
finish();
}
} else {
//6.0以下 只有MUI会修改权限
if (MIUI.rom()) {
if (PermissionUtils.hasPermission(getContext())) {
LiveUtils.initLive(MainActivity.this);
finish();
} else {
MIUI.req(getContext());
}
} else {
LiveUtils.initLive(MainActivity.this);
finish();
}
}
}
下面是判断各种rom机型工具类
import android.os.Build;
import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class OsUtils {
public static final String ROM_MIUI = "MIUI";
public static final String ROM_EMUI = "EMUI";
public static final String ROM_FLYME = "FLYME";
public static final String ROM_OPPO = "OPPO";
public static final String ROM_SMARTISAN = "SMARTISAN";
public static final String ROM_VIVO = "VIVO";
public static final String ROM_QIKU = "QIKU";
private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name";
private static final String KEY_VERSION_EMUI = "ro.build.version.emui";
private static final String KEY_VERSION_OPPO = "ro.build.version.opporom";
private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version";
private static final String KEY_VERSION_VIVO = "ro.vivo.os.version";
private static String sName;
private static String sVersion;
public static boolean isEmui() {
return check(ROM_EMUI);
}
public static boolean isMiui() {
return check(ROM_MIUI);
}
public static boolean isVivo() {
return check(ROM_VIVO);
}
public static boolean isOppo() {
return check(ROM_OPPO);
}
public static boolean isFlyme() {
return check(ROM_FLYME);
}
public static boolean is360() {
return check(ROM_QIKU) || check("360");
}
public static boolean isSmartisan() {
return check(ROM_SMARTISAN);
}
public static String getName() {
if (sName == null) {
check("");
}
return sName;
}
public static String getVersion() {
if (sVersion == null) {
check("");
}
return sVersion;
}
public static boolean check(String rom) {
if (sName != null) {
return sName.equals(rom);
}
if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) {
sName = ROM_MIUI;
} else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) {
sName = ROM_EMUI;
} else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) {
sName = ROM_OPPO;
} else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) {
sName = ROM_VIVO;
} else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) {
sName = ROM_SMARTISAN;
} else {
sVersion = Build.DISPLAY;
if (sVersion.toUpperCase().contains(ROM_FLYME)) {
sName = ROM_FLYME;
} else {
sVersion = Build.UNKNOWN;
sName = Build.MANUFACTURER.toUpperCase();
}
}
return sName.equals(rom);
}
public static String getProp(String name) {
String line = null;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + name);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return line;
}
}