-
Notifications
You must be signed in to change notification settings - Fork 246
FloatingVideoPlaying
xinbaicheng edited this page Apr 1, 2017
·
1 revision
本文档简要介绍使用KSYMediaPlayer实现悬浮窗播放的功能的方法
退出播放页面(Activity)但并不退出播放,在观看视频的同时可浏览其他信息
因Player独立于UI页面,实现此功能须使用KSYMediaPlayer
,而不能使用KSYTextureView
需新加权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
特别提醒:小米手机需在 应用授权 中手动开启相应权限方可实现浮窗功能
将KSYMediaPlayer
封装为一个单例
public class KSYFloatingPlayer {
private KSYMediaPlayer mKsyMediaPlayer;
private static KSYFloatingPlayer _instance;
private KSYFloatingPlayer() {}
public static KSYFloatingPlayer getInstance() {
if (_instance == null) {
synchronized (KSYFloatingPlayer.class) {
if (_instance == null)
_instance = new KSYFloatingPlayer();
}
}
return _instance;
}
public void init(Context context) {
if (mKsyMediaPlayer != null) {
mKsyMediaPlayer.release();
mKsyMediaPlayer = null;
}
mKsyMediaPlayer = new KSYMediaPlayer.Builder(context).build();
}
public KSYMediaPlayer getKSYMediaPlayer() {
return mKsyMediaPlayer;
}
public void destroy() {
if (mKsyMediaPlayer != null)
mKsyMediaPlayer.release();
mKsyMediaPlayer = null;
}
}
/**
* Created by xbc on 2017/3/15.
* 悬浮窗
*/
public class KSYFloatingWindowView extends RelativeLayout {
private static final String TAG = "KSYFloatingWindowView";
private static final int JUST_CLICK = 5;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mLayoutParams;
private TextureView mTextureView;
private Surface mSurface;
private ImageView mQuit;
private Handler mHandler;
private int statusBarHeight;
private float xInScreen, yInScreen; //当前手指位置
private float xDownInScreen, yDownInScreen; //手指按下位置
private float xInView, yInView; //手指相对于悬浮窗位置
public KSYFloatingWindowView(Context context) {
super(context);
init(context);
}
public KSYFloatingWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public KSYFloatingWindowView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
LayoutInflater.from(context).inflate(R.layout.floating_window, this);
mTextureView = (TextureView) findViewById(R.id.floating_window_player_view);
mQuit = (ImageView) findViewById(R.id.floating_window_quit);
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
mQuit.setOnClickListener(mOnClickListener);
}
public void updateViewLayoutParams(WindowManager.LayoutParams params) {
mLayoutParams = params;
}
public void setHandler(Handler handler) {
mHandler = handler;
}
// 在此处重写 onTouchEvent 处理相应的事件
// 必须返回 true 表示在此已处理相应事件
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
if (Math.abs(xDownInScreen - xInScreen) < JUST_CLICK && Math.abs(yDownInScreen - yInScreen) < JUST_CLICK) {
if (mHandler != null)
mHandler.obtainMessage(FloatingPlayingActivity.LEAVE_FLOATING_WINDOW_PLAYING).sendToTarget();
}
break;
case MotionEvent.ACTION_DOWN:
xInView = event.getX(); //相对于view的坐标
yInView = event.getY();
//getRaw()返回相对于屏幕左上角坐标
xDownInScreen = event.getRawX();
yDownInScreen = event.getRawY() - getStatusBarHeight();
xInScreen = xDownInScreen;
yInScreen = yDownInScreen;
break;
case MotionEvent.ACTION_MOVE:
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
updateViewPosition();
break;
}
return true;
}
private void updateViewPosition() {
mLayoutParams.x = (int) (xInScreen - xInView);
mLayoutParams.y = (int) (yInScreen - yInView);
mWindowManager.updateViewLayout(this, mLayoutParams);
}
private int getStatusBarHeight() {
if (statusBarHeight == 0) {
try {
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object o = c.newInstance();
Field field = c.getField("status_bar_height");
int x = (Integer) field.get(o);
statusBarHeight = getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
}
return statusBarHeight;
}
private OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View view) {
if (mHandler != null)
mHandler.obtainMessage(FloatingPlayingActivity.REMOVE_FLOATING_WINDOW).sendToTarget();
}
};
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
if (mSurface == null)
mSurface = new Surface(surfaceTexture);
KSYFloatingPlayer.getInstance().getKSYMediaPlayer().setSurface(mSurface);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
if (mSurface != null) {
mSurface.release();
mSurface = null;
}
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
}
关闭旧页面, 需调用如下代码
KSYFloatingPlayer.getInstance().getKSYMediaPlayer().setSurface(null);
开启新页面后, 需设置新的Surface
, 播放器会继续渲染视频
KSYFloatingPlayer.getInstance().getKSYMediaPlayer().setSurface(newSurface);