视频直播,点播,悬浮小窗口播放demo (使用阿里云sdk)

视频直播,点播,悬浮小窗口播放demo (使用阿里云sdk)

使用阿里云直播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(".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);//添加toucherlayoutif(isInit) {windowManager.addView(toucherLayout,params);} else {windowManager.updateViewLayout(toucherLayout,params);}//主动计算出当前View的宽高信息.toucherLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);//处理touchtoucherLayout.setOnTouchListener(new View.OnTouchListener() {@Overridepublic 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() {@Overridepublic 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;}
}

github地址

发布者:admin,转转请注明出处:http://www.yc00.com/news/1702470744a1222504.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信