一、创建悬浮窗服务
public class FloatingService extends Service { private static final String TAG = "xuwei"; public static boolean isStarted = false; private WindowManager windowManager; private WindowManager.LayoutParams layoutParams; private View displayView; @Override public void onCreate() { super.onCreate(); isStarted = true; windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); layoutParams = new WindowManager.LayoutParams(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; } else { layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE; } layoutParams.format = PixelFormat.RGBA_8888; layoutParams.gravity = Gravity.LEFT | Gravity.TOP; layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; layoutParams.width = 200; layoutParams.height = 200; layoutParams.x = 540; layoutParams.y = 960; } @Nullable @Override public IBinder onBind(Intent intent) { return new MyBinder(); } public class MyBinder extends Binder { public FloatingService getService() { return FloatingService.this; } } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand: 服务运行"); showFloatingWindow(); return super.onStartCommand(intent, flags, startId); } public void showFloatingWindow() { if (Settings.canDrawOverlays(this)) { LayoutInflater layoutInflater = LayoutInflater.from(this); displayView = layoutInflater.inflate(R.layout.layout_display, null);//悬浮窗口显示的view windowManager.addView(displayView, layoutParams); displayView.setOnTouchListener(new FloatingOnTouchListener()); //悬浮框点击事件 displayView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //在这里实现点击重新回到Activity Intent intent = new Intent(FloatingService.this, FloatActivity.class); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setAction(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); startActivity(intent); } }); } } public void closeFloatingWindow() { if (displayView != null) { // 移除悬浮窗口 windowManager.removeView(displayView); } } //判断悬浮窗口是否移动,这里做个标记,防止移动后松手触发了点击事件 private boolean isMove; private int mStartX, mStartY, mStopX, mStopY; private class FloatingOnTouchListener implements View.OnTouchListener { private int x; private int y; @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // clicks(500);//双击悬浮窗重新进入activiy mStartX = (int) event.getX(); mStartY = (int) event.getY(); isMove = false; x = (int) event.getRawX(); y = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int nowX = (int) event.getRawX(); int nowY = (int) event.getRawY(); int movedX = nowX - x; int movedY = nowY - y; x = nowX; y = nowY; layoutParams.x = layoutParams.x + movedX; layoutParams.y = layoutParams.y + movedY; windowManager.updateViewLayout(view, layoutParams); break; case MotionEvent.ACTION_UP: mStopX = (int) event.getX(); mStopY = (int) event.getY(); if (Math.abs(mStartX - mStopX) >= 1 || Math.abs(mStartY - mStopY) >= 1) { isMove = true; } break; default: break; } //如果是移动事件不触发OnClick事件,防止移动的时候一放手形成点击事件 return isMove; // return false; } } private long firstClickTime = 0; private void clicks(int intervalTime) { //双击重新回到activity, intervalTime:最长间隔时间 if (firstClickTime > 0) { if (System.currentTimeMillis() - firstClickTime < intervalTime) { firstClickTime = 0; // 将第一次点击时间置为0 //唤起activity Intent intent = new Intent(this, FloatActivity.class); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setAction(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); startActivity(intent); } } firstClickTime = System.currentTimeMillis(); } @Override public void onDestroy() { super.onDestroy(); if (displayView != null) { // 移除悬浮窗口 windowManager.removeView(displayView); } } }
二、需要实现悬浮窗的activity
1.FloatActivity的启动模式设置为
android:launchMode="singleInstance"
2.AndroidManifest设置权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
3.FloatActivity
public class FloatActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_float); checkPermission(); } //动态权限申请,其它权限当需要 private void checkPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) { settingPermission(); } else if (ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { //没有权限,向用户请求权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, CODE_FOR_WRITE_PERMISSION); } } private void settingPermission() { new AlertDialog.Builder(this) .setMessage("请到'设置'-‘权限管理'设置相关权限’") .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivityForResult(intent, REQUEST_RECORD_PERMISSION_SETTING); } }) .create() .show(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_RECORD_PERMISSION_SETTING) { checkPermission(); } if (requestCode == 2) { if (!Settings.canDrawOverlays(this)) { Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show(); //startService(new Intent(FloatActivity.this, FloatingService.class)); } } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); //通过requestCode来识别是否同一个请求 if (requestCode == CODE_FOR_WRITE_PERMISSION) { boolean hasPermisson = true; for (int status : grantResults) { if (status != PackageManager.PERMISSION_GRANTED) { hasPermisson = false; break; } } if (!hasPermisson) { //用户不同意,向用户展示该权限作用 settingPermission(); } } } @Override protected void onRestart() {//重新回到activity super.onRestart(); unbindService(mVideoServiceConnection);//不显示悬浮框 iskServStart = false; } private boolean iskServStart = false; FloatingService service1; ServiceConnection mVideoServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 获取服务的操作对象 FloatingService.MyBinder binder = (FloatingService.MyBinder) service; service1 = binder.getService(); service1.showFloatingWindow(); } @Override public void onServiceDisconnected(ComponentName name) { if (service1 != null) { service1.closeFloatingWindow();//关闭悬浮窗 service1 = null; } } }; //按钮的点击事件,开启/关闭悬浮窗 public void ben_float(View view) { if (!Settings.canDrawOverlays(this)) {//需要minSdkVersion23以上 Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT); startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 2); } else { if (!iskServStart) { iskServStart = !iskServStart; Toast.makeText(FloatActivity.this, "开启悬浮窗", Toast.LENGTH_SHORT).show(); moveTaskToBack(true);//最小化Activity Intent intent = new Intent(this, FloatingService.class);//开启服务显示悬浮框 bindService(intent, mVideoServiceConnection, Context.BIND_AUTO_CREATE); } else { iskServStart = !iskServStart; Toast.makeText(FloatActivity.this, "关闭悬浮窗", Toast.LENGTH_SHORT).show(); unbindService(mVideoServiceConnection); } } } }