1.悬浮窗权限申请:
悬浮窗口的权限为Settings.ACTION_MANAGE_OVERLAY_PERMISSION
需要在代码中动态申请,而且需要用户到设置页面自行确认,然后在activity或者其他申请的位置使用回调,继续判断该权限是否申请成功。
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(getApplicationContext())) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivityForResult(intent, 0);
} else {
mIntent = new Intent(MainActivity.this/*需要启动service的activity*/, FloatWindowService.class/*需要启动的service*/);
bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);//直接启动服务方式启动
}
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
在Activity回调申请权限的结果:
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data){
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(this)) {
Intent mIntent = new Intent(MainActivity.this,FloatWindowService.class);
startService(mIntent);//直接启动服务方式启动
}
}
}
}
Intent mIntent = new Intent(MainActivity.this,XXXXXX.class);
startService(mIntent);//直接启动服务方式启动
2.创建悬浮窗:
使用创建service页面getSystemService(WINDOW_SERVICE),然后创建View
LayoutInflater.from(getApplication())加载自定义布局
wp = new WindowManager.LayoutParams();
mWindowManager = (WindowManager) getApplication().getSystemService(WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
wp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
wp.type = WindowManager.LayoutParams.TYPE_PHONE;
}
wp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;//悬浮窗外部可点击
wp.gravity = Gravity.LEFT | Gravity.TOP;//悬浮窗弹出显示位置
wp.x = 0;
wp.y = 0;
wp.width = WindowManager.LayoutParams.WRAP_CONTENT;
wp.height = WindowManager.LayoutParams.WRAP_CONTENT;
LayoutInflater inflater = LayoutInflater.from(getApplication());
mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_window, null, false);
View view = mFloatLayout.findViewById(R.id.playMonitor);//自定义悬浮窗布局
view.setOnTouchListener(this);//设置移动监听,此处view是自定义充满布局的控件
mWindowManager.addView(mFloatLayout, wp);
3.设置滑动监听:
如果要移动悬浮窗口的位置,还需要重新onTouch方法或者dispatchTouchEvent方法,然后通过开始触摸点和移动触摸点计算出最终停留的位置
private int mTouchStartX, mTouchStartY, mStartX, mStartY, mTouchCurrentX, mTouchCurrentY;
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTouchStartX = (int) event.getRawX();
mTouchStartY = (int) event.getRawY();
mStartX = (int) event.getX();
mStartY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
mTouchCurrentX = (int) event.getRawX();
mTouchCurrentY = (int) event.getRawY();
wp.x += mTouchCurrentX - mTouchStartX;
wp.y += mTouchCurrentY - mTouchStartY;
mWindowManager.updateViewLayout(mFloatLayout, wp);
mTouchStartX = mTouchCurrentX;
mTouchStartY = mTouchCurrentY;
}
return true;
}