package com.stardust.scriptdroid.external.floatingwindow.menu; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.IBinder; import android.support.annotation.Nullable; import android.view.ContextThemeWrapper; import android.view.View; import android.view.WindowManager; import android.widget.Toast; import com.stardust.hover.HoverMenuBuilder; import com.stardust.hover.SimpleHoverMenuTransitionListener; import com.stardust.hover.WindowHoverMenu; import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.external.floatingwindow.FloatingWindowManger; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutBoundsView; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView; import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.theme.ThemeColorManagerCompat; import com.stardust.util.MessageEvent; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import io.mattcarroll.hover.HoverMenu; import io.mattcarroll.hover.defaulthovermenu.window.WindowViewController; /** * Created by Stardust on 2017/3/11. */ public class HoverMenuService extends Service { public static class ServiceStateChangedEvent { ServiceStateChangedEvent(boolean state) { this.state = state; } public boolean state; } public static final String MESSAGE_SHOW_AND_EXPAND_MENU = "MESSAGE_SHOW_AND_EXPAND_MENU"; public static final String MESSAGE_SHOW_LAYOUT_HIERARCHY = "MESSAGE_SHOW_LAYOUT_HIERARCHY"; public static final String MESSAGE_SHOW_LAYOUT_BOUNDS = "MESSAGE_SHOW_LAYOUT_BOUNDS"; public static final String MESSAGE_COLLAPSE_MENU = "MESSAGE_COLLAPSE_MENU"; public static final String MESSAGE_MENU_COLLAPSING = "MESSAGE_MENU_COLLAPSING"; public static final String MESSAGE_MENU_EXPANDING = "MESSAGE_MENU_EXPANDING"; public static final String MESSAGE_MENU_EXIT = "MESSAGE_MENU_EXIT"; private static boolean sIsRunning; private static EventBus eventBus = new EventBus(); public static void startService(Context context) { context.startService(new Intent(context, HoverMenuService.class)); setIsRunning(true); } public static boolean isServiceRunning() { return sIsRunning; } private static void setIsRunning(boolean isRunning) { sIsRunning = isRunning; eventBus.post(new ServiceStateChangedEvent(sIsRunning)); } public static void postEvent(MessageEvent event) { eventBus.post(event); } public static EventBus getEventBus() { return eventBus; } private static final String TAG = "HoverMenuService"; private static final String PREF_FILE = "hover_menu"; private static final String PREF_HOVER_MENU_VISUAL_STATE = "hover_menu_visual_state"; private SharedPreferences mPrefs; private WindowViewController mWindowViewController; private FloatingLayoutHierarchyView mFloatingLayoutHierarchyView; private FloatingLayoutBoundsView mFloatingLayoutBoundsView; private WindowHoverMenu mWindowHoverMenu; private HoverMenu.OnExitListener mWindowHoverMenuMenuExitListener = new HoverMenu.OnExitListener() { @Override public void onExitByUserRequest() { eventBus.post(new MessageEvent(MESSAGE_MENU_EXIT)); savePreferredLocation(); mWindowHoverMenu.hide(); stopSelf(); } }; @Override public void onCreate() { super.onCreate(); eventBus.register(this); mPrefs = getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); tryInitViews(); } private void tryInitViews() { try { initViews(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show(); FloatingWindowManger.goToFloatingWindowPermissionSetting(); } } private void initViews() { mFloatingLayoutHierarchyView = new FloatingLayoutHierarchyView(this); mFloatingLayoutBoundsView = new FloatingLayoutBoundsView(this); initWindowMenu(); mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true, mFloatingLayoutHierarchyView); mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true, mFloatingLayoutBoundsView); } private void initWindowMenu() { mWindowHoverMenu = (WindowHoverMenu) new HoverMenuBuilder(new ContextThemeWrapper(this, R.style.AppTheme)) .displayWithinWindow() .useAdapter(new HoverMenuAdapter(this)) .restoreVisualState(loadPreferredLocation()) .build(); mWindowHoverMenu.getHoverMenuView().setContentBackgroundColor(ThemeColorManagerCompat.getColorPrimary()); mWindowHoverMenu.addOnExitListener(mWindowHoverMenuMenuExitListener); mWindowViewController = mWindowHoverMenu.getWindowViewController(); mWindowHoverMenu.setHoverMenuTransitionListener(new SimpleHoverMenuTransitionListener() { @Override public void onExpanding() { eventBus.post(new MessageEvent(MESSAGE_MENU_EXPANDING)); captureCurrentWindow(); } @Override public void onCollapsing() { AutoJs.getInstance().getLayoutInspector().clearCapture(); eventBus.post(new MessageEvent(MESSAGE_MENU_COLLAPSING)); } }); } private void captureCurrentWindow() { AutoJs.getInstance().getLayoutInspector().captureCurrentWindow(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (mWindowHoverMenu == null) tryInitViews(); if (mWindowHoverMenu != null) mWindowHoverMenu.show(); AccessibilityServiceTool.enableAccessibilityServiceByRootIfNeeded(); return START_STICKY; } @Override public void onDestroy() { if (mWindowHoverMenu != null) mWindowHoverMenu.hide(); if (eventBus.isRegistered(this)) eventBus.unregister(this); setIsRunning(false); mWindowViewController.removeView(mFloatingLayoutBoundsView); mWindowViewController.removeView(mFloatingLayoutHierarchyView); } private void savePreferredLocation() { String memento = mWindowHoverMenu.getVisualState(); mPrefs.edit().putString(PREF_HOVER_MENU_VISUAL_STATE, memento).apply(); } private String loadPreferredLocation() { return mPrefs.getString(PREF_HOVER_MENU_VISUAL_STATE, null); } @Subscribe public void onMessageEvent(MessageEvent event) { switch (event.message) { case MESSAGE_SHOW_AND_EXPAND_MENU: showAndExpandMenu(); break; case MESSAGE_SHOW_LAYOUT_HIERARCHY: showLayoutHierarchy(); break; case MESSAGE_SHOW_LAYOUT_BOUNDS: showLayoutBounds(); break; case MESSAGE_COLLAPSE_MENU: mWindowHoverMenu.collapseMenu(); break; } } private void showLayoutBounds() { mFloatingLayoutBoundsView.setRootNode(AutoJs.getInstance().getLayoutInspector().getCapture()); mWindowHoverMenu.getHoverMenuView().setVisibility(View.GONE); showView(mFloatingLayoutBoundsView); } public void showLayoutHierarchy() { mFloatingLayoutHierarchyView.setRootNode(AutoJs.getInstance().getLayoutInspector().getCapture()); mWindowHoverMenu.getHoverMenuView().setVisibility(View.GONE); showView(mFloatingLayoutHierarchyView); } public void showAndExpandMenu() { showView(mWindowHoverMenu.getHoverMenuView()); } private void showView(View view) { view.setVisibility(View.VISIBLE); mWindowViewController.makeTouchable(view); } }