public class WindowService extends Service {
public static final String TAG = "WindowService ";
@Override
public IBinder onBind(Intent intent) {
return new WindowBinder();
}
class WindowBinder extends Binder{
public WindowService getService(){
return WindowService.this;
}
}
private WindowManager windowManager;
private WindowManager.LayoutParams layoutParams;
@Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
layoutParams = new WindowManager.LayoutParams();
layoutParams.x = 0;
layoutParams.y = 0;
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
layoutParams.gravity = Gravity.TOP | Gravity.START;
layoutParams.width = 100 ;
layoutParams.height = 100 ;
final CustomLinearLayout customLinearLayout = (CustomLinearLayout) LayoutInflater.from(this).inflate(R.layout.window_layout, null,false);
windowManager.addView(customLinearLayout,layoutParams);
customLinearLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.d(TAG, "onTouch: action == "+ motionEvent.getAction()+ " getRawX=="+motionEvent.getRawX() + " getRawY=="+motionEvent.getRawY() );
int mInScreenX = (int) motionEvent.getRawX();
int mInScreenY = (int) motionEvent.getRawY();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
layoutParams.x += mInScreenX - customLinearLayout.lastX;
layoutParams.y += mInScreenY - customLinearLayout.lastY;
customLinearLayout.lastX = mInScreenX;
customLinearLayout.lastY = mInScreenY;
windowManager.updateViewLayout(view, layoutParams);
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return false;
}
});
HandlerThread handlerThread = new HandlerThread("WorkThread");
handlerThread.start();
final Handler workHandler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
}
};
Button button = (Button) customLinearLayout.findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "onClick: ");
workHandler.sendEmptyMessage(0);
}
});
}
}
public class CustomLinearLayout extends LinearLayout {
public int lastX, lastY;
public static final String TAG = "CustomLinearLayout ";
public CustomLinearLayout(Context context) {
super(context);
}
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomLinearLayout(Context context,AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent: action == " + ev.getAction() + " getRawX==" + ev.getRawX() + " getRawY==" + ev.getRawY());
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = (int) ev.getRawX();
lastY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
return true;
case MotionEvent.ACTION_UP:
break;
}
return super.onInterceptTouchEvent(ev);
}
}
window_layout.xml 的布局
<?xml version="1.0" encoding="utf-8"?>
<com.autochips.bluetooth.myapplication.CustomLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00ff00"/>
</com.autochips.bluetooth.myapplication.CustomLinearLayout>
在 Android9.0 上要加 权限
uses-permission android:name=“android.permission.SYSTEM_ALERT_WINDOW” 并且悬浮窗等级要设置为
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
另外在copy代码时 WindowService 别忘记在 AndroidManifest.xml 里面注册