From e1009c5003a2e962104c52518b4e121a45fe3420 Mon Sep 17 00:00:00 2001 From: TonyJiangWJ Date: Sun, 16 Jan 2022 17:23:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=89=E5=8D=9312=E6=82=AC=E6=B5=AE=E7=AA=97?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BF=AE=E6=94=B9=EF=BC=9ARawWindow=E5=9C=A8?= =?UTF-8?q?=E6=9C=89=E6=97=A0=E9=9A=9C=E7=A2=8D=E6=9D=83=E9=99=90=E6=97=B6?= =?UTF-8?q?=E6=8C=82=E8=BD=BD=E5=9C=A8=E6=97=A0=E9=9A=9C=E7=A2=8DWindowMan?= =?UTF-8?q?ager=20=E9=81=BF=E5=85=8DsetTouchable(false)=20=E5=A4=B1?= =?UTF-8?q?=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 1 + .../autojs/autojs/ui/main/MainActivity.java | 2 - autojs/build.gradle | 1 - autojs/src/main/AndroidManifest.xml | 4 +- .../accessibility/AccessibilityService.kt | 13 + .../floaty/AccessibilityFloatyService.java | 66 ---- .../autojs/core/floaty/RawWindow.java | 5 +- .../stardust/autojs/runtime/api/Floaty.java | 5 +- .../enhancedfloaty/FloatyService.java | 95 ++++++ .../stardust/enhancedfloaty/FloatyWindow.java | 116 +++++++ .../ResizableExpandableFloaty.java | 141 ++++++++ .../ResizableExpandableFloatyWindow.java | 302 ++++++++++++++++++ .../enhancedfloaty/ResizableFloaty.java | 34 ++ .../enhancedfloaty/ResizableFloatyWindow.java | 92 ++++++ .../stardust/enhancedfloaty/ViewStack.java | 54 ++++ .../stardust/enhancedfloaty/WindowBridge.java | 94 ++++++ .../enhancedfloaty/gesture/DragGesture.java | 132 ++++++++ .../enhancedfloaty/gesture/ResizeGesture.java | 109 +++++++ .../util/FloatingWindowPermissionUtil.java | 57 ++++ .../enhancedfloaty/util/WindowTypeCompat.java | 25 ++ .../com/stardust/widget/ViewSupplier.java | 20 ++ .../com/stardust/widget/ViewSwitcher.java | 63 ++++ .../taobao/idlefish/AccessibilityService.kt | 7 +- .../layout/ef_expandable_floaty_container.xml | 6 + .../main/res/layout/ef_floaty_container.xml | 7 + .../accessibility/AccessibilityService.kt | 9 + .../AccessibilityServiceUtils.kt | 2 - 27 files changed, 1383 insertions(+), 79 deletions(-) delete mode 100644 autojs/src/main/java/com/stardust/autojs/core/floaty/AccessibilityFloatyService.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/FloatyService.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/FloatyWindow.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/ResizableExpandableFloaty.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/ResizableExpandableFloatyWindow.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/ResizableFloaty.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/ResizableFloatyWindow.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/ViewStack.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/WindowBridge.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/gesture/DragGesture.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/gesture/ResizeGesture.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/util/FloatingWindowPermissionUtil.java create mode 100644 autojs/src/main/java/com/stardust/enhancedfloaty/util/WindowTypeCompat.java create mode 100644 autojs/src/main/java/com/stardust/widget/ViewSupplier.java create mode 100644 autojs/src/main/java/com/stardust/widget/ViewSwitcher.java create mode 100644 autojs/src/main/res/layout/ef_expandable_floaty_container.xml create mode 100644 autojs/src/main/res/layout/ef_floaty_container.xml diff --git a/app/build.gradle b/app/build.gradle index c5054e93..84df5951 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -145,6 +145,7 @@ dependencies { implementation 'androidx.cardview:cardview:1.0.0' implementation 'com.google.android.material:material:1.4.0' implementation 'androidx.multidex:multidex:2.0.1' + implementation 'androidx.activity:activity-ktx:1.4.0' // Personal libraries implementation 'com.github.hyb1996:MutableTheme:1.0.0' // Material Dialogs diff --git a/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java b/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java index b7178ad3..81e16f90 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java @@ -22,7 +22,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.tabs.TabLayout; import com.stardust.app.FragmentPagerAdapterBuilder; import com.stardust.app.OnActivityResultDelegate; -import com.stardust.autojs.core.floaty.AccessibilityFloatyService; import com.stardust.autojs.core.permission.OnRequestPermissionsResultCallback; import com.stardust.autojs.core.permission.PermissionRequestProxyActivity; import com.stardust.autojs.core.permission.RequestPermissionCallbacks; @@ -273,7 +272,6 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega FloatyWindowManger.hideCircularMenu(); ForegroundService.stop(this); stopService(new Intent(this, FloatyService.class)); - stopService(new Intent(this, AccessibilityFloatyService.class)); AutoJs.getInstance().getScriptEngineService().stopAll(); } diff --git a/autojs/build.gradle b/autojs/build.gradle index 5e4dab4f..de0dc79b 100644 --- a/autojs/build.gradle +++ b/autojs/build.gradle @@ -53,7 +53,6 @@ dependencies { exclude group: 'com.android.support' }) api 'com.google.android.material:material:1.4.0' - api 'com.github.hyb1996:EnhancedFloaty:0.31' api 'com.makeramen:roundedimageview:2.3.0' // OpenCv api project(path: ':autojs-aar:opencv') diff --git a/autojs/src/main/AndroidManifest.xml b/autojs/src/main/AndroidManifest.xml index ac0a0a01..c268c1d0 100644 --- a/autojs/src/main/AndroidManifest.xml +++ b/autojs/src/main/AndroidManifest.xml @@ -50,11 +50,9 @@ android:resource="@xml/accessibility_service_config"/> - - + diff --git a/autojs/src/main/java/com/stardust/autojs/core/accessibility/AccessibilityService.kt b/autojs/src/main/java/com/stardust/autojs/core/accessibility/AccessibilityService.kt index f8ecd297..75335905 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/accessibility/AccessibilityService.kt +++ b/autojs/src/main/java/com/stardust/autojs/core/accessibility/AccessibilityService.kt @@ -2,11 +2,15 @@ package com.stardust.autojs.core.accessibility import android.accessibilityservice.AccessibilityServiceInfo import android.os.Build +import android.view.WindowManager import com.stardust.autojs.core.pref.Pref +import com.stardust.enhancedfloaty.FloatyService import com.stardust.view.accessibility.AccessibilityService class AccessibilityService : AccessibilityService() { + private lateinit var windowManager: WindowManager + override fun onServiceConnected() { val serviceInfo = serviceInfo if (Pref.isStableModeEnabled) { @@ -21,7 +25,16 @@ class AccessibilityService : AccessibilityService() { serviceInfo.flags = serviceInfo.flags and AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE.inv() } } + windowManager = getSystemService(WINDOW_SERVICE) as WindowManager setServiceInfo(serviceInfo) super.onServiceConnected() } + + override fun getWindowManager() : WindowManager { + return windowManager + } + + override fun refreshFloatyService() { + FloatyService.getInstance()?.refreshAccessWindowManager() + } } \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/core/floaty/AccessibilityFloatyService.java b/autojs/src/main/java/com/stardust/autojs/core/floaty/AccessibilityFloatyService.java deleted file mode 100644 index f12902f7..00000000 --- a/autojs/src/main/java/com/stardust/autojs/core/floaty/AccessibilityFloatyService.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.stardust.autojs.core.floaty; - -import android.content.Context; -import android.content.Intent; -import android.os.IBinder; -import android.view.WindowManager; - -import androidx.annotation.Nullable; - -import com.stardust.enhancedfloaty.FloatyService; -import com.stardust.enhancedfloaty.FloatyWindow; -import com.taobao.idlefish.AccessibilityService; - -import java.util.concurrent.CopyOnWriteArraySet; - -public class AccessibilityFloatyService extends FloatyService { - - private static final CopyOnWriteArraySet windows = new CopyOnWriteArraySet(); - private static AccessibilityFloatyService instance; - private WindowManager mWindowManager; - - public static void addWindow(FloatyWindow window) { - if (windows.add(window) && instance != null) { - window.onCreate(instance, instance.mWindowManager); - } - - } - - public static void removeWindow(FloatyWindow window) { - windows.remove(window); - } - - public void onCreate() { - super.onCreate(); - if (AccessibilityService.Companion.getInstance() != null) { - this.mWindowManager = AccessibilityService.Companion.getInstance().getWindowManager(); - } - if (this.mWindowManager == null) { - this.mWindowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE); - } - for (FloatyWindow delegate : windows) { - delegate.onCreate(this, this.mWindowManager); - } - - instance = this; - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - if (AccessibilityService.Companion.getInstance() == null) { - return null; - } - return AccessibilityService.Companion.getInstance().onBind(intent); - } - - public void onDestroy() { - super.onDestroy(); - instance = null; - - for (FloatyWindow delegate : windows) { - delegate.onServiceDestroy(this); - } - - } -} diff --git a/autojs/src/main/java/com/stardust/autojs/core/floaty/RawWindow.java b/autojs/src/main/java/com/stardust/autojs/core/floaty/RawWindow.java index 02479080..e32e4463 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/floaty/RawWindow.java +++ b/autojs/src/main/java/com/stardust/autojs/core/floaty/RawWindow.java @@ -84,7 +84,7 @@ public class RawWindow extends FloatyWindow { private int getWindowType() { if (AccessibilityService.Companion.getInstance()!= null - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { return WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; } return WindowTypeCompat.getWindowType(); @@ -116,6 +116,9 @@ public class RawWindow extends FloatyWindow { @Override public void close() { super.close(); + if (mContentView == null) { + return; + } ViewExtras.recycle(mContentView); ViewParent parent = mContentView.getParent(); if (parent instanceof View) { diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java index 6432cfe3..757e5e4a 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java @@ -7,7 +7,6 @@ import android.view.ContextThemeWrapper; import android.view.View; import com.stardust.autojs.R; -import com.stardust.autojs.core.floaty.AccessibilityFloatyService; import com.stardust.autojs.core.floaty.BaseResizableFloatyWindow; import com.stardust.autojs.core.floaty.RawWindow; import com.stardust.autojs.core.ui.JsViewHelper; @@ -112,8 +111,8 @@ public class Floaty { public JsRawWindow(RawWindow.RawFloaty floaty) { mWindow = new RawWindow(floaty); mUiHandler.post(() -> { - mUiHandler.getContext().startService(new Intent(mUiHandler.getContext(), AccessibilityFloatyService.class)); - AccessibilityFloatyService.addWindow(mWindow); + mUiHandler.getContext().startService(new Intent(mUiHandler.getContext(), FloatyService.class)); + FloatyService.addWindow(mWindow); }); RuntimeException exception = mWindow.waitForCreation(); if (exception != Exceptions.NO_EXCEPTION && exception != null) { diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/FloatyService.java b/autojs/src/main/java/com/stardust/enhancedfloaty/FloatyService.java new file mode 100644 index 00000000..f9c89754 --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/FloatyService.java @@ -0,0 +1,95 @@ +package com.stardust.enhancedfloaty; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.IBinder; +import android.view.WindowManager; + +import androidx.annotation.Nullable; + +import com.stardust.autojs.core.floaty.RawWindow; +import com.taobao.idlefish.AccessibilityService; + +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * Created by Stardust on 2017/5/1. + */ +public class FloatyService extends Service { + + private static CopyOnWriteArraySet windows = new CopyOnWriteArraySet<>(); + + private static FloatyService instance; + private WindowManager mWindowManager; + private WindowManager accessibilityWindowManager; + + public static void addWindow(FloatyWindow window) { + if (windows.add(window) && instance != null) { + instance.appendWindow(window); + } + } + + public static void removeWindow(FloatyWindow window) { + windows.remove(window); + } + + public static FloatyService getInstance() { + return instance; + } + + /** + * 根据无障碍链接情况刷新windowManager + */ + public void refreshAccessWindowManager() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { + // 仅仅针对安卓12优化 + return; + } + if (AccessibilityService.Companion.getInstance() != null) { + accessibilityWindowManager = AccessibilityService.Companion.getInstance().getWindowManager(); + } else { + accessibilityWindowManager = null; + } + // TODO 目前设计当无障碍服务丢失后 RawWindow会自动移除 后续考虑将window重新添加 但是目前没有完美的方法 + } + + @Override + public void onCreate() { + super.onCreate(); + mWindowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE); + refreshAccessWindowManager(); + instance = this; + for (FloatyWindow delegate : windows) { + appendWindow(delegate); + } + } + + private void appendWindow(FloatyWindow window) { + if (instance == null) { + return; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + instance.accessibilityWindowManager != null && window instanceof RawWindow) { + window.onCreate(instance, instance.accessibilityWindowManager); + } else { + window.onCreate(instance, instance.mWindowManager); + } + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onDestroy() { + super.onDestroy(); + instance = null; + for (FloatyWindow delegate : windows) { + delegate.onServiceDestroy(this); + } + } +} diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/FloatyWindow.java b/autojs/src/main/java/com/stardust/enhancedfloaty/FloatyWindow.java new file mode 100644 index 00000000..3fe773cf --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/FloatyWindow.java @@ -0,0 +1,116 @@ +package com.stardust.enhancedfloaty; + +import android.view.View; +import android.view.WindowManager; + +import androidx.annotation.CallSuper; + +/** + * Created by Stardust on 2017/5/1. + */ + +public abstract class FloatyWindow { + private WindowManager mWindowManager; + private FloatyService mFloatyService; + + private WindowBridge mWindowBridge; + private WindowManager.LayoutParams mWindowLayoutParams; + private View mWindowView; + + @CallSuper + public void onCreate(FloatyService service, WindowManager manager) { + mFloatyService = service; + mWindowManager = manager; + onCreateWindow(service, manager); + } + + + protected void onCreateWindow(FloatyService service, WindowManager manager) { + setWindowLayoutParams(onCreateWindowLayoutParams()); + setWindowView(onCreateView(service)); + setWindowBridge(onCreateWindowBridge(getWindowLayoutParams())); + + onViewCreated(getWindowView()); + + //attach to window + attachToWindow(getWindowView(), getWindowManager()); + } + + protected void onViewCreated(View view) { + + } + + protected void attachToWindow(View view, WindowManager manager){ + getWindowManager().addView(view, getWindowLayoutParams()); + onAttachToWindow(view, manager); + } + + protected void onAttachToWindow(View view, WindowManager manager) { + + } + + protected abstract View onCreateView(FloatyService service); + + protected WindowBridge onCreateWindowBridge(WindowManager.LayoutParams params) { + return new WindowBridge.DefaultImpl(params, getWindowManager(), getWindowView()); + + } + + protected abstract WindowManager.LayoutParams onCreateWindowLayoutParams(); + + public void updateWindowLayoutParams(WindowManager.LayoutParams params) { + setWindowLayoutParams(params); + mWindowManager.updateViewLayout(getWindowView(), getWindowLayoutParams()); + } + + + protected void setWindowManager(WindowManager windowManager) { + mWindowManager = windowManager; + } + + public WindowManager.LayoutParams getWindowLayoutParams() { + return mWindowLayoutParams; + } + + protected void setWindowLayoutParams(WindowManager.LayoutParams windowLayoutParams) { + mWindowLayoutParams = windowLayoutParams; + } + + public View getWindowView() { + return mWindowView; + } + + protected void setWindowView(View windowView) { + mWindowView = windowView; + } + + public FloatyService getFloatyService() { + return mFloatyService; + } + + public WindowManager getWindowManager() { + return mWindowManager; + } + + public WindowBridge getWindowBridge() { + return mWindowBridge; + } + + protected void setWindowBridge(WindowBridge windowBridge) { + mWindowBridge = windowBridge; + } + + public void onServiceDestroy(FloatyService service) { + close(); + } + + + public void close() { + try { + getWindowManager().removeView(getWindowView()); + FloatyService.removeWindow(this); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableExpandableFloaty.java b/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableExpandableFloaty.java new file mode 100644 index 00000000..f7e15344 --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableExpandableFloaty.java @@ -0,0 +1,141 @@ +package com.stardust.enhancedfloaty; + +import android.view.View; + +import androidx.annotation.Nullable; + +/** + * Created by Stardust on 2017/4/19. + */ + +public interface ResizableExpandableFloaty { + + + View inflateCollapsedView(FloatyService service, ResizableExpandableFloatyWindow window); + + View inflateExpandedView(FloatyService service, ResizableExpandableFloatyWindow window); + + @Nullable + View getResizerView(View expandedView); + + @Nullable + View getMoveCursorView(View expandedView); + + float getCollapsedHiddenWidthRadio(); + + float getCollapsedViewUnpressedAlpha(); + + float getCollapsedViewPressedAlpha(); + + + boolean shouldRequestFocusWhenExpand(); + + + int getInitialX(); + + + int getInitialY(); + + int getInitialHeight(); + + int getInitialWidth(); + + boolean isInitialExpanded(); + + abstract class AbstractResizableExpandableFloaty implements ResizableExpandableFloaty { + private float mCollapsedHiddenWidthRadio = 0f; + private float mCollapsedViewUnpressedAlpha = 0.7f; + private float mCollapsedViewPressedAlpha = 1.0f; + private boolean mShouldRequestFocusWhenExpand = true; + private int mInitialX; + private int mInitialY; + private boolean mInitialExpanded = false; + private int mInitialHeight; + private int mInitialWidth; + + @Nullable + public View getResizerView(View expandedView) { + return null; + } + + @Nullable + public View getMoveCursorView(View expandedView) { + return null; + } + + public float getCollapsedHiddenWidthRadio() { + return mCollapsedHiddenWidthRadio; + } + + public void setCollapsedHiddenWidthRadio(float collapsedHiddenWidthRadio) { + this.mCollapsedHiddenWidthRadio = collapsedHiddenWidthRadio; + } + + public float getCollapsedViewUnpressedAlpha() { + return mCollapsedViewUnpressedAlpha; + } + + public void setCollapsedViewUnpressedAlpha(float collapsedViewUnpressedAlpha) { + mCollapsedViewUnpressedAlpha = collapsedViewUnpressedAlpha; + } + + public float getCollapsedViewPressedAlpha() { + return mCollapsedViewPressedAlpha; + } + + public void setCollapsedViewPressedAlpha(float collapsedViewPressedAlpha) { + mCollapsedViewPressedAlpha = collapsedViewPressedAlpha; + } + + public boolean shouldRequestFocusWhenExpand() { + return mShouldRequestFocusWhenExpand; + } + + public void setShouldRequestFocusWhenExpand(boolean requestFocusWhenExpand) { + mShouldRequestFocusWhenExpand = requestFocusWhenExpand; + } + + + public int getInitialX() { + return mInitialX; + } + + public void setInitialX(int initialX) { + mInitialX = initialX; + } + + public int getInitialY() { + return mInitialY; + } + + public void setInitialY(int initialY) { + mInitialY = initialY; + } + + public boolean isInitialExpanded() { + return mInitialExpanded; + } + + public void setInitialExpanded(boolean initialExpanded) { + mInitialExpanded = initialExpanded; + } + + @Override + public int getInitialHeight() { + return mInitialHeight; + } + + public void setInitialHeight(int initialHeight) { + mInitialHeight = initialHeight; + } + + @Override + public int getInitialWidth() { + return mInitialWidth; + } + + public void setInitialWidth(int initialWidth) { + mInitialWidth = initialWidth; + } + } +} diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableExpandableFloatyWindow.java b/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableExpandableFloatyWindow.java new file mode 100644 index 00000000..3063419a --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableExpandableFloatyWindow.java @@ -0,0 +1,302 @@ +package com.stardust.enhancedfloaty; + +import android.graphics.PixelFormat; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; + +import com.stardust.autojs.R; +import com.stardust.enhancedfloaty.gesture.DragGesture; +import com.stardust.enhancedfloaty.gesture.ResizeGesture; +import com.stardust.enhancedfloaty.util.WindowTypeCompat; + +import com.stardust.widget.ViewSwitcher; + +/** + * Created by Stardust on 2017/4/18. + */ + +public class ResizableExpandableFloatyWindow extends FloatyWindow { + + private static final int INITIAL_WINDOW_PARAM_FLAG = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; + private static final String TAG = "ExpandableFloatyService"; + + + private ResizableExpandableFloaty mFloaty; + private ViewSwitcher mCollapseExpandViewSwitcher; + private View mCollapsedView; + private View mExpandedView; + private View mResizer; + private View mMoveCursor; + private DragGesture mDragGesture; + private int mCollapsedViewX, mCollapsedViewY; + private int mExpandedViewX, mExpandedViewY; + + private ViewStack mViewStack = new ViewStack(new ViewStack.CurrentViewSetter() { + @Override + public void setCurrentView(View v) { + mCollapseExpandViewSwitcher.setSecondView(v); + } + }); + + + public ResizableExpandableFloatyWindow(ResizableExpandableFloaty floaty) { + if (floaty == null) { + throw new NullPointerException("floaty == null"); + } + mFloaty = floaty; + } + + + @Override + protected View onCreateView(FloatyService service) { + inflateWindowViews(service); + View windowView = View.inflate(service, R.layout.ef_expandable_floaty_container, null); + windowView.setFocusableInTouchMode(true); + mCollapseExpandViewSwitcher = windowView.findViewById(R.id.container); + mCollapseExpandViewSwitcher.setMeasureAllChildren(false); + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + mCollapseExpandViewSwitcher.addView(mCollapsedView, params); + mCollapseExpandViewSwitcher.addView(mExpandedView, params); + mViewStack.setRootView(mExpandedView); + return windowView; + } + + @Override + protected void onAttachToWindow(View view, WindowManager manager) { + super.onAttachToWindow(view, manager); + initGesture(); + setKeyListener(); + setInitialState(); + } + + public View getCollapsedView() { + return mCollapsedView; + } + + public View getExpandedView() { + return mExpandedView; + } + + public View getResizer() { + return mResizer; + } + + public View getMoveCursor() { + return mMoveCursor; + } + + protected ViewStack getViewStack() { + return mViewStack; + } + + protected int getCollapsedViewX() { + return mCollapsedViewX; + } + + protected void setCollapsedViewX(int collapsedViewX) { + mCollapsedViewX = collapsedViewX; + } + + protected int getCollapsedViewY() { + return mCollapsedViewY; + } + + protected void setCollapsedViewY(int collapsedViewY) { + mCollapsedViewY = collapsedViewY; + } + + protected int getExpandedViewX() { + return mExpandedViewX; + } + + protected void setExpandedViewX(int expandedViewX) { + mExpandedViewX = expandedViewX; + } + + protected int getExpandedViewY() { + return mExpandedViewY; + } + + protected void setExpandedViewY(int expandedViewY) { + mExpandedViewY = expandedViewY; + } + + protected void setInitialState() { + ResizableExpandableFloaty floaty = getFloaty(); + boolean expand = floaty.isInitialExpanded(); + if (expand) { + setExpandedViewX(floaty.getInitialX()); + setExpandedViewY(floaty.getInitialY()); + expand(); + } else { + setCollapsedViewX(floaty.getInitialX()); + setCollapsedViewX(floaty.getInitialY()); + getWindowBridge().updatePosition(getCollapsedViewX(), getCollapsedViewY()); + } + } + + @Override + protected WindowBridge onCreateWindowBridge(WindowManager.LayoutParams params) { + return new WindowBridge.DefaultImpl(params, getWindowManager(), getWindowView()) { + @Override + public void updatePosition(int x, int y) { + super.updatePosition(x, y); + if (getViewSwitcher().getCurrentView() == getExpandedView()) { + setExpandedViewX(x); + setExpandedViewY(y); + } else { + setCollapsedViewX(x); + setCollapsedViewY(y); + } + } + + }; + } + + protected void inflateWindowViews(FloatyService service) { + ResizableExpandableFloaty floaty = getFloaty(); + mExpandedView = floaty.inflateExpandedView(service, this); + mCollapsedView = floaty.inflateCollapsedView(service, this); + mResizer = floaty.getResizerView(getExpandedView()); + mMoveCursor = floaty.getMoveCursorView(getExpandedView()); + } + + protected WindowManager.LayoutParams onCreateWindowLayoutParams() { + WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.WRAP_CONTENT, + WindowTypeCompat.getPhoneWindowType(), + INITIAL_WINDOW_PARAM_FLAG, + PixelFormat.TRANSLUCENT); + layoutParams.gravity = Gravity.TOP | Gravity.START; + return layoutParams; + } + + protected void initGesture() { + enableResize(); + enableMove(); + } + + protected void enableResize() { + if (getResizer() != null) { + ResizeGesture.enableResize(getResizer(), getExpandedView(), getWindowBridge()); + } + } + + public ResizableExpandableFloaty getFloaty() { + return mFloaty; + } + + protected void enableMove() { + if (getMoveCursor() != null) { + DragGesture gesture = new DragGesture(getWindowBridge(), getMoveCursor()); + gesture.setPressedAlpha(1.0f); + } + DragGesture dragGesture = new DragGesture(getWindowBridge(), getCollapsedView()); + dragGesture.setUnpressedAlpha(getFloaty().getCollapsedViewUnpressedAlpha()); + dragGesture.setPressedAlpha(getFloaty().getCollapsedViewPressedAlpha()); + dragGesture.setKeepToSide(true); + dragGesture.setKeepToSideHiddenWidthRadio(getFloaty().getCollapsedHiddenWidthRadio()); + dragGesture.setOnDraggedViewClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + expand(); + } + }); + setDragGesture(dragGesture); + } + + protected void setDragGesture(DragGesture dragGesture) { + mDragGesture = dragGesture; + } + + protected DragGesture getDragGesture() { + return mDragGesture; + } + + public void expand() { + getViewSwitcher().showSecond(); + //enableWindowLimit(); + if (getFloaty().shouldRequestFocusWhenExpand()) { + requestWindowFocus(); + } + getDragGesture().setKeepToSide(false); + getWindowBridge().updatePosition(getExpandedViewX(), getExpandedViewY()); + } + + protected ViewSwitcher getViewSwitcher() { + return mCollapseExpandViewSwitcher; + } + + public void collapse() { + getViewSwitcher().showFirst(); + disableWindowFocus(); + setWindowLayoutNoLimit(); + getDragGesture().setKeepToSide(true); + getWindowBridge().updatePosition(getCollapsedViewX(), getCollapsedViewY()); + } + + protected void setKeyListener() { + getWindowView().setOnKeyListener(new View.OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { + onBackPressed(); + return true; + } + if (keyCode == KeyEvent.KEYCODE_HOME) { + onHomePressed(); + return true; + } + return false; + } + + + }); + } + + private void onBackPressed() { + ViewStack viewStack = getViewStack(); + if (viewStack.canGoBack()) { + viewStack.goBack(); + } else { + collapse(); + } + } + + private void onHomePressed() { + getViewStack().goBackToFirst(); + collapse(); + } + + + public void disableWindowFocus() { + WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams(); + windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + updateWindowLayoutParams(windowLayoutParams); + } + + public void setWindowLayoutInScreen() { + WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams(); + windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + updateWindowLayoutParams(windowLayoutParams); + } + + public void requestWindowFocus() { + WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams(); + windowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + updateWindowLayoutParams(windowLayoutParams); + getWindowView().requestFocus(); + } + + public void setWindowLayoutNoLimit() { + WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams(); + windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; + updateWindowLayoutParams(windowLayoutParams); + } + +} + diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableFloaty.java b/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableFloaty.java new file mode 100644 index 00000000..dbace6c9 --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableFloaty.java @@ -0,0 +1,34 @@ +package com.stardust.enhancedfloaty; + +import android.view.View; + +import androidx.annotation.Nullable; + +/** + * Created by Stardust on 2017/4/30. + */ + +public interface ResizableFloaty { + + + View inflateView(FloatyService floatyService, ResizableFloatyWindow service); + + @Nullable + View getResizerView(View view); + + @Nullable + View getMoveCursorView(View view); + + abstract class AbstractResizableFloaty implements ResizableFloaty { + @Nullable + public View getResizerView(View view) { + return null; + } + + @Nullable + public View getMoveCursorView(View view) { + return null; + } + + } +} diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableFloatyWindow.java b/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableFloatyWindow.java new file mode 100644 index 00000000..e83d715a --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/ResizableFloatyWindow.java @@ -0,0 +1,92 @@ +package com.stardust.enhancedfloaty; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; + +import com.stardust.autojs.R; +import com.stardust.enhancedfloaty.gesture.DragGesture; +import com.stardust.enhancedfloaty.gesture.ResizeGesture; +import com.stardust.enhancedfloaty.util.WindowTypeCompat; + +/** + * Created by Stardust on 2017/4/30. + */ + +public class ResizableFloatyWindow extends FloatyWindow { + + private static final String TAG = "ResizableFloatyWindow"; + + private View mView; + private View mResizer; + private View mMoveCursor; + private ResizableFloaty mFloaty; + + public ResizableFloatyWindow(ResizableFloaty floaty) { + if (floaty == null) { + throw new NullPointerException("floaty == null"); + } + mFloaty = floaty; + } + + @Override + public void onCreate(FloatyService service, WindowManager manager) { + super.onCreate(service, manager); + } + + @Override + protected View onCreateView(FloatyService service) { + Context context = service.getApplicationContext(); + ViewGroup windowView = (ViewGroup) View.inflate(context, R.layout.ef_floaty_container, null); + mView = mFloaty.inflateView(service, this); + mResizer = mFloaty.getResizerView(mView); + mMoveCursor = mFloaty.getMoveCursorView(mView); + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + windowView.addView(mView, params); + windowView.setFocusableInTouchMode(true); + return windowView; + } + + @Override + protected void onViewCreated(View view) { + super.onViewCreated(view); + initGesture(); + } + + protected WindowManager.LayoutParams onCreateWindowLayoutParams() { + WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.WRAP_CONTENT, + WindowTypeCompat.getPhoneWindowType(), + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, + PixelFormat.TRANSLUCENT); + layoutParams.gravity = Gravity.TOP | Gravity.START; + return layoutParams; + } + + public View getRootView() { + return mView; + } + + public View getResizer() { + return mResizer; + } + + public View getMoveCursor() { + return mMoveCursor; + } + + private void initGesture() { + if (mResizer != null) { + ResizeGesture.enableResize(mResizer, mView, getWindowBridge()); + } + if (mMoveCursor != null) { + DragGesture gesture = new DragGesture(getWindowBridge(), mMoveCursor); + gesture.setPressedAlpha(1.0f); + } + } + +} diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/ViewStack.java b/autojs/src/main/java/com/stardust/enhancedfloaty/ViewStack.java new file mode 100644 index 00000000..d9b87304 --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/ViewStack.java @@ -0,0 +1,54 @@ +package com.stardust.enhancedfloaty; + +import android.view.View; + +import java.util.Stack; + +/** + * Created by Stardust on 2017/3/11. + */ + +public class ViewStack { + + public interface CurrentViewSetter { + void setCurrentView(View v); + } + + public interface NavigableView { + void goBack(); + } + + private Stack mStack = new Stack<>(); + private CurrentViewSetter mCurrentViewSetter; + + public ViewStack(CurrentViewSetter currentViewSetter) { + mCurrentViewSetter = currentViewSetter; + } + + public void navigateTo(View v) { + mStack.push(v); + mCurrentViewSetter.setCurrentView(v); + } + + public boolean canGoBack() { + return mStack.size() > 1; + } + + public void goBack() { + mCurrentViewSetter.setCurrentView(mStack.pop()); + } + + public void goBackToFirst() { + while (mStack.size() > 1) { + mStack.pop(); + } + mCurrentViewSetter.setCurrentView(mStack.peek()); + } + + public void setRootView(View view) { + mStack.clear(); + mStack.push(view); + } + + +} diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/WindowBridge.java b/autojs/src/main/java/com/stardust/enhancedfloaty/WindowBridge.java new file mode 100644 index 00000000..2c0deda1 --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/WindowBridge.java @@ -0,0 +1,94 @@ +package com.stardust.enhancedfloaty; + +import android.util.DisplayMetrics; +import android.view.View; +import android.view.WindowManager; + +/** + * Created by Stardust on 2017/4/18. + */ + +public interface WindowBridge { + int getX(); + + int getY(); + + void updatePosition(int x, int y); + + int getWidth(); + + int getHeight(); + + void updateMeasure(int width, int height); + + int getScreenWidth(); + + int getScreenHeight(); + + class DefaultImpl implements WindowBridge { + + DisplayMetrics mDisplayMetrics; + private WindowManager.LayoutParams mWindowLayoutParams; + private WindowManager mWindowManager; + private View mWindowView; + + public DefaultImpl(WindowManager.LayoutParams windowLayoutParams, WindowManager windowManager, View windowView) { + mWindowLayoutParams = windowLayoutParams; + mWindowManager = windowManager; + mWindowView = windowView; + } + + @Override + public int getX() { + return mWindowLayoutParams.x; + } + + @Override + public int getY() { + return mWindowLayoutParams.y; + } + + @Override + public void updatePosition(int x, int y) { + mWindowLayoutParams.x = x; + mWindowLayoutParams.y = y; + mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams); + } + + @Override + public int getWidth() { + return mWindowView.getWidth(); + } + + @Override + public int getHeight() { + return mWindowView.getHeight(); + } + + @Override + public void updateMeasure(int width, int height) { + mWindowLayoutParams.width = width; + mWindowLayoutParams.height = height; + mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams); + } + + @Override + public int getScreenWidth() { + ensureDisplayMetrics(); + return mDisplayMetrics.widthPixels; + } + + @Override + public int getScreenHeight() { + ensureDisplayMetrics(); + return mDisplayMetrics.heightPixels; + } + + private void ensureDisplayMetrics() { + if (mDisplayMetrics == null) { + mDisplayMetrics = new DisplayMetrics(); + mWindowManager.getDefaultDisplay().getMetrics(mDisplayMetrics); + } + } + } +} \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/gesture/DragGesture.java b/autojs/src/main/java/com/stardust/enhancedfloaty/gesture/DragGesture.java new file mode 100644 index 00000000..99feaf80 --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/gesture/DragGesture.java @@ -0,0 +1,132 @@ +package com.stardust.enhancedfloaty.gesture; + + +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +import androidx.core.view.GestureDetectorCompat; + +import com.stardust.enhancedfloaty.WindowBridge; + +/** + * Created by Stardust on 2017/4/18. + */ + +public class DragGesture extends GestureDetector.SimpleOnGestureListener { + + protected WindowBridge mWindowBridge; + protected View mView; + + private float mKeepToSideHiddenWidthRadio = 0.5f; + private int mInitialX; + private int mInitialY; + private float mInitialTouchX; + private float mInitialTouchY; + private View.OnClickListener mOnClickListener; + private boolean mFlung = false; + private boolean mKeepToSide; + private float mPressedAlpha = 0.7f; + private float mUnpressedAlpha = 1.0f; + + public DragGesture(WindowBridge windowBridge, View view) { + mWindowBridge = windowBridge; + mView = view; + setupView(); + } + + private void setupView() { + final GestureDetectorCompat gestureDetector = new GestureDetectorCompat(mView.getContext(), this); + mView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + gestureDetector.onTouchEvent(event); + if (event.getAction() == MotionEvent.ACTION_UP) { + mView.setAlpha(mUnpressedAlpha); + if (!mFlung && isKeepToSide()) { + keepToSide(); + } + } + return true; + } + }); + } + + public float getPressedAlpha() { + return mPressedAlpha; + } + + public void setPressedAlpha(float pressedAlpha) { + mPressedAlpha = pressedAlpha; + } + + public float getUnpressedAlpha() { + return mUnpressedAlpha; + } + + public void setUnpressedAlpha(float unpressedAlpha) { + mUnpressedAlpha = unpressedAlpha; + } + + public void setKeepToSide(boolean keepToSide) { + mKeepToSide = keepToSide; + } + + public boolean isKeepToSide() { + return mKeepToSide; + } + + public void setKeepToSideHiddenWidthRadio(float keepToSideHiddenWidthRadio) { + mKeepToSideHiddenWidthRadio = keepToSideHiddenWidthRadio; + } + + public float getKeepToSideHiddenWidthRadio() { + return mKeepToSideHiddenWidthRadio; + } + + @Override + public boolean onDown(MotionEvent event) { + mInitialX = mWindowBridge.getX(); + mInitialY = mWindowBridge.getY(); + mInitialTouchX = event.getRawX(); + mInitialTouchY = event.getRawY(); + mFlung = false; + return false; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + mWindowBridge.updatePosition(mInitialX + (int) ((e2.getRawX() - mInitialTouchX)), + mInitialY + (int) ((e2.getRawY() - mInitialTouchY))); + mView.setAlpha(mPressedAlpha); + return false; + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + mFlung = true; + if (mKeepToSide) + keepToSide(); + return false; + } + + public void keepToSide() { + int x = mWindowBridge.getX(); + int hiddenWidth = (int) (mKeepToSideHiddenWidthRadio * mView.getWidth()); + if (x > mWindowBridge.getScreenWidth() / 2) + mWindowBridge.updatePosition(mWindowBridge.getScreenWidth() - mView.getWidth() + hiddenWidth, mWindowBridge.getY()); + else + mWindowBridge.updatePosition(-hiddenWidth, mWindowBridge.getY()); + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + if (mOnClickListener != null) + mOnClickListener.onClick(mView); + return super.onSingleTapConfirmed(e); + } + + public void setOnDraggedViewClickListener(View.OnClickListener onClickListener) { + mOnClickListener = onClickListener; + } +} diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/gesture/ResizeGesture.java b/autojs/src/main/java/com/stardust/enhancedfloaty/gesture/ResizeGesture.java new file mode 100644 index 00000000..efc58bca --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/gesture/ResizeGesture.java @@ -0,0 +1,109 @@ +package com.stardust.enhancedfloaty.gesture; + +import android.content.Context; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import com.stardust.enhancedfloaty.WindowBridge; + +/** + * Created by Stardust on 2017/4/18. + */ + +public class ResizeGesture extends GestureDetector.SimpleOnGestureListener { + + public static ResizeGesture enableResize(View resizer, @Nullable View resizableView, WindowBridge windowBridge) { + ResizeGesture resizeGesture = new ResizeGesture(windowBridge, resizer, resizableView); + final GestureDetector detector = new GestureDetector(resizer.getContext(), resizeGesture); + resizer.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + detector.onTouchEvent(event); + return true; + } + }); + return resizeGesture; + } + + public static ResizeGesture enableResize(View resizer, WindowBridge windowBridge) { + return enableResize(resizer, null, windowBridge); + } + + private WindowBridge mWindowBridge; + private float initialTouchX; + private float initialTouchY; + private int mInitialWidth, mInitialHeight; + private View mResizerView; + private int mMinHeight = 200, mMinWidth = 200; + private final int mStatusBarHeight; + private View mResizableView; + + + public ResizeGesture(WindowBridge windowBridge, View resizerView, @Nullable View resizableView) { + mWindowBridge = windowBridge; + mResizerView = resizerView; + mResizableView = resizableView; + mStatusBarHeight = getStatusBarHeight(resizerView.getContext()); + } + + private int getStatusBarHeight(Context context) { + int result = 0; + int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + result = context.getResources().getDimensionPixelSize(resourceId); + } + return result; + } + + public void setMinHeight(int minHeight) { + mMinHeight = minHeight; + } + + public void setMinWidth(int minWidth) { + mMinWidth = minWidth; + } + + @Override + public boolean onDown(MotionEvent event) { + initialTouchX = event.getRawX(); + initialTouchY = event.getRawY(); + mInitialWidth = mResizableView != null ? mResizableView.getWidth() : mWindowBridge.getWidth(); + mInitialHeight = mResizableView != null ? mResizableView.getHeight() : mWindowBridge.getHeight(); + return false; + } + + @Override + public boolean onScroll(MotionEvent e1, final MotionEvent e2, float distanceX, float distanceY) { + int newWidth = mInitialWidth + (int) ((e2.getRawX() - initialTouchX)); + int newHeight = mInitialHeight + (int) ((e2.getRawY() - initialTouchY)); + newWidth = Math.max(mMinWidth, newWidth); + newHeight = Math.max(mMinHeight, newHeight); + newWidth = Math.min(mWindowBridge.getScreenWidth() - getX() - mResizerView.getWidth(), newWidth); + newHeight = Math.min(mWindowBridge.getScreenHeight() - getY() - mResizerView.getHeight() - mStatusBarHeight, newHeight); + updateMeasure(newWidth, newHeight); + return true; + } + + private void updateMeasure(int newWidth, int newHeight) { + if (mResizableView == null) { + mWindowBridge.updateMeasure(newWidth, newHeight); + } else { + ViewGroup.LayoutParams params = mResizableView.getLayoutParams(); + params.width = newWidth; + params.height = newHeight; + mResizableView.setLayoutParams(params); + } + } + + private int getY() { + return mResizableView != null ? (int) mResizableView.getY() : mWindowBridge.getY(); + } + + private int getX() { + return mResizableView != null ? (int) mResizableView.getX() : mWindowBridge.getX(); + } +} \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/util/FloatingWindowPermissionUtil.java b/autojs/src/main/java/com/stardust/enhancedfloaty/util/FloatingWindowPermissionUtil.java new file mode 100644 index 00000000..f4f2f245 --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/util/FloatingWindowPermissionUtil.java @@ -0,0 +1,57 @@ +package com.stardust.enhancedfloaty.util; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; + +/** + * Created by Stardust on 2017/3/10. + */ + +public class FloatingWindowPermissionUtil { + + public static void goToFloatingWindowPermissionSettingIfNeeded(Context context) { + if (!hasFloatingWindowPermission(context)) { + goToFloatingWindowPermissionSetting(context); + } + } + + public static void goToFloatingWindowPermissionSetting(Context context) { + String packageName = context.getPackageName(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + try { + context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, + Uri.parse("package:" + packageName)) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } catch (Exception e) { + goToAppDetailSettings(context, packageName); + } + } else { + goToAppDetailSettings(context, packageName); + } + } + + public static boolean hasFloatingWindowPermission(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return Settings.canDrawOverlays(context); + } + return true; + } + + public static boolean goToAppDetailSettings(Context context, String packageName) { + try { + Intent i = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + i.addCategory(Intent.CATEGORY_DEFAULT); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + i.setData(Uri.parse("package:" + packageName)); + context.startActivity(i); + return true; + } catch (ActivityNotFoundException ignored) { + return false; + } + } + +} diff --git a/autojs/src/main/java/com/stardust/enhancedfloaty/util/WindowTypeCompat.java b/autojs/src/main/java/com/stardust/enhancedfloaty/util/WindowTypeCompat.java new file mode 100644 index 00000000..c8e3eadf --- /dev/null +++ b/autojs/src/main/java/com/stardust/enhancedfloaty/util/WindowTypeCompat.java @@ -0,0 +1,25 @@ +package com.stardust.enhancedfloaty.util; + +import android.os.Build; +import android.view.WindowManager; + +public class WindowTypeCompat { + + + public static int getWindowType() { + return getWindowType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + } + + public static int getPhoneWindowType() { + return getWindowType(WindowManager.LayoutParams.TYPE_PHONE); + } + + public static int getWindowType(int type) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + } else { + return type; + } + } + +} diff --git a/autojs/src/main/java/com/stardust/widget/ViewSupplier.java b/autojs/src/main/java/com/stardust/widget/ViewSupplier.java new file mode 100644 index 00000000..6074e29c --- /dev/null +++ b/autojs/src/main/java/com/stardust/widget/ViewSupplier.java @@ -0,0 +1,20 @@ +package com.stardust.widget; + +import android.content.Context; +import android.view.View; + +import java.io.Serializable; + +/** + * Created by Stardust on 2017/4/18. + *

+ * The interface and its implementations must be serializable. + * Only in this way it can be set to intent extra and be used as service argument. + * So, implementations should not has any non-serializable fields. + */ + + +public interface ViewSupplier extends Serializable { + + View inflateView(Context context); +} diff --git a/autojs/src/main/java/com/stardust/widget/ViewSwitcher.java b/autojs/src/main/java/com/stardust/widget/ViewSwitcher.java new file mode 100644 index 00000000..aa99e07d --- /dev/null +++ b/autojs/src/main/java/com/stardust/widget/ViewSwitcher.java @@ -0,0 +1,63 @@ +package com.stardust.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +/** + * Created by Stardust on 2017/3/11. + */ + +public class ViewSwitcher extends android.widget.ViewSwitcher { + + private View mCurrentView; + + public ViewSwitcher(Context context) { + super(context); + } + + public ViewSwitcher(Context context, View first, View second) { + super(context); + addView(first); + addView(second); + } + + public ViewSwitcher(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public View getCurrentView() { + return mCurrentView; + } + + public int getCurrentViewIndex() { + return mCurrentView == getChildAt(0) ? 0 : 1; + } + + public void showFirst() { + ensureCurrentView(); + if (mCurrentView != getChildAt(0)) { + showPrevious(); + mCurrentView = getChildAt(0); + } + } + + private void ensureCurrentView() { + if (mCurrentView == null) { + mCurrentView = getChildAt(0); + } + } + + public void showSecond() { + ensureCurrentView(); + if (mCurrentView != getChildAt(1)) { + showNext(); + mCurrentView = getChildAt(1); + } + } + + public void setSecondView(View v) { + removeViewAt(1); + addView(v); + } +} diff --git a/autojs/src/main/java/com/taobao/idlefish/AccessibilityService.kt b/autojs/src/main/java/com/taobao/idlefish/AccessibilityService.kt index d60b7a52..c7687e14 100644 --- a/autojs/src/main/java/com/taobao/idlefish/AccessibilityService.kt +++ b/autojs/src/main/java/com/taobao/idlefish/AccessibilityService.kt @@ -4,6 +4,7 @@ import android.accessibilityservice.AccessibilityServiceInfo import android.os.Build import android.view.WindowManager import com.stardust.autojs.core.pref.Pref +import com.stardust.enhancedfloaty.FloatyService import com.stardust.view.accessibility.AccessibilityService class AccessibilityService: AccessibilityService() { @@ -30,6 +31,10 @@ class AccessibilityService: AccessibilityService() { } override fun getWindowManager() : WindowManager { - return windowManager; + return windowManager + } + + override fun refreshFloatyService() { + FloatyService.getInstance()?.refreshAccessWindowManager() } } \ No newline at end of file diff --git a/autojs/src/main/res/layout/ef_expandable_floaty_container.xml b/autojs/src/main/res/layout/ef_expandable_floaty_container.xml new file mode 100644 index 00000000..e2910040 --- /dev/null +++ b/autojs/src/main/res/layout/ef_expandable_floaty_container.xml @@ -0,0 +1,6 @@ + + + diff --git a/autojs/src/main/res/layout/ef_floaty_container.xml b/autojs/src/main/res/layout/ef_floaty_container.xml new file mode 100644 index 00000000..de41fd84 --- /dev/null +++ b/autojs/src/main/res/layout/ef_floaty_container.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.kt b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.kt index 1dd42252..bc88bf67 100644 --- a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.kt +++ b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.kt @@ -100,6 +100,7 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ Log.v(TAG, "onDestroy: $instance") instance = null mEventExecutor?.shutdownNow() + refreshFloatyService() super.onDestroy() } @@ -107,6 +108,7 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ override fun onServiceConnected() { Log.v(TAG, "onServiceConnected: " + serviceInfo.toString()) instance = this + refreshFloatyService() super.onServiceConnected() LOCK.lock() ENABLED.signalAll() @@ -119,6 +121,13 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ return mFastRootInActiveWindow } + /** + * 刷新悬浮窗的windowManager + */ + open fun refreshFloatyService() { + // do refresh on sub class + } + open fun getWindowManager() : WindowManager? { return null; } diff --git a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityServiceUtils.kt b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityServiceUtils.kt index aa3685b6..6231e897 100644 --- a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityServiceUtils.kt +++ b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityServiceUtils.kt @@ -7,8 +7,6 @@ import android.content.Intent import android.provider.Settings import android.text.TextUtils -import java.util.Locale - /** * Created by Stardust on 2017/1/26.