diff --git a/app/src/main/java/com/auto/autoclicker/AutoClickService.java b/app/src/main/java/com/auto/autoclicker/AutoClickService.java index 7a9d97c..131c5b4 100644 --- a/app/src/main/java/com/auto/autoclicker/AutoClickService.java +++ b/app/src/main/java/com/auto/autoclicker/AutoClickService.java @@ -151,10 +151,8 @@ public class AutoClickService extends AccessibilityService { } private void flashTouchFeedback() { - FloatingViewManager manager = FloatingViewManager.getInstance(); - if (manager != null) { - manager.flashTouchPoint(); - } + Intent intent = new Intent("com.auto.autoclicker.FLASH_TOUCH_POINT"); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } @Override diff --git a/app/src/main/java/com/auto/autoclicker/FloatingViewManager.java b/app/src/main/java/com/auto/autoclicker/FloatingViewManager.java index 25ab103..4b36d9d 100644 --- a/app/src/main/java/com/auto/autoclicker/FloatingViewManager.java +++ b/app/src/main/java/com/auto/autoclicker/FloatingViewManager.java @@ -3,9 +3,10 @@ package com.auto.autoclicker; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.graphics.Color; +import android.content.IntentFilter; import android.graphics.PixelFormat; import android.graphics.Point; import android.os.Build; @@ -18,12 +19,14 @@ import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; -import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import com.auto.autoclicker.util.PrefUtils; import com.auto.autoclicker.util.ScreenUtils; import com.auto.autoclicker.util.ViewUtils; @@ -31,8 +34,6 @@ public class FloatingViewManager { private static final String TAG = "FloatingViewManager"; private static final long DEBOUNCE_INTERVAL = 500; - private static FloatingViewManager instance; - private final Context context; private final WindowManager windowManager; private View touchPointView; @@ -46,22 +47,17 @@ public class FloatingViewManager { private long lastToggleTime = 0; private final int screenWidth; private final int screenHeight; - private final AutoClickService service = AutoClickService.getInstance(); public FloatingViewManager(Context context) { this.context = context; - instance = this; this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Point screenSize = ScreenUtils.getScreenSize(context); this.screenWidth = screenSize.x; this.screenHeight = screenSize.y; + registerBroadcast(context); logDebug("屏幕尺寸: " + screenWidth + "x" + screenHeight); } - public static FloatingViewManager getInstance() { - return instance; - } - public void showFloatingViews() throws SecurityException { if (!Settings.canDrawOverlays(context)) { throw new SecurityException("需要悬浮窗权限"); @@ -146,7 +142,7 @@ public class FloatingViewManager { @SuppressLint("ClickableViewAccessibility") private void initializeControlBarView() { - controlBarView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.control_bar, null); + controlBarView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.single_control_bar, null); controlBarParams = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, @@ -194,6 +190,8 @@ public class FloatingViewManager { play.setOnClickListener(v -> { if (!isDebounced()) return; + AutoClickService service = AutoClickService.getInstance(); + if (service == null) { Log.e(TAG, "AutoClickService 未初始化"); Toast.makeText(context, "请在设置中启用无障碍服务", Toast.LENGTH_LONG).show(); @@ -221,9 +219,26 @@ public class FloatingViewManager { }); close.setOnClickListener(v -> { - service.stopClicking(); + AutoClickService service = AutoClickService.getInstance(); + + if (service != null) { + service.stopClicking(); + } else { + logDebug("AutoClickService 未初始化"); + Toast.makeText(context, "请启用无障碍服务", Toast.LENGTH_SHORT).show(); + } + touchPointView.setBackgroundResource(R.drawable.un_touch_point); removeFloatingViews(); + + context.stopService(new Intent(context, ForegroundService.class)); + + PrefUtils.setFloatingShown(context, false); + + Intent intent = new Intent("com.auto.autoclicker.FLOATING_WINDOW_STATE_CHANGED"); + intent.putExtra("isShown", false); + LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + }); setting.setOnClickListener(v -> showInputDialog()); @@ -276,7 +291,6 @@ public class FloatingViewManager { AlertDialog dialog = builder.create(); - // 设置弹窗的类型,允许在悬浮窗中显示输入框 if (!(context instanceof Activity)) { if (dialog.getWindow() != null) { dialog.getWindow().setType( @@ -314,6 +328,17 @@ public class FloatingViewManager { .start(); } + private void registerBroadcast(Context context) { + LocalBroadcastManager.getInstance(context).registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if ("com.auto.autoclicker.FLASH_TOUCH_POINT".equals(intent.getAction())) { + flashTouchPoint(); + } + } + }, new IntentFilter("com.auto.autoclicker.FLASH_TOUCH_POINT")); + } + private boolean isDebounced() { long currentTime = System.currentTimeMillis(); if (currentTime - lastToggleTime < DEBOUNCE_INTERVAL) { diff --git a/app/src/main/java/com/auto/autoclicker/MainActivity.java b/app/src/main/java/com/auto/autoclicker/MainActivity.java index 3d8bf91..0723a45 100644 --- a/app/src/main/java/com/auto/autoclicker/MainActivity.java +++ b/app/src/main/java/com/auto/autoclicker/MainActivity.java @@ -1,28 +1,42 @@ package com.auto.autoclicker; import android.app.ActivityManager; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.PowerManager; import android.provider.Settings; +import android.util.Log; import android.widget.Toast; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.auto.autoclicker.databinding.ActivityMainBinding; - +import com.auto.autoclicker.util.PrefUtils; public class MainActivity extends AppCompatActivity { + private static final String TAG = "MainActivity"; private ActivityMainBinding binding; private ActivityResultLauncher permissionLauncher; - private boolean isFloatingShown = false; private long lastClickTime = 0; private static final long DEBOUNCE_INTERVAL = 500; + private boolean isFloatingShown; + private static final String ACTION_FLOATING_STATE_CHANGED = "com.auto.autoclicker.FLOATING_WINDOW_STATE_CHANGED"; + + private final BroadcastReceiver floatingReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + isFloatingShown = intent.getBooleanExtra("isShown", false); + updateButtonText(); + } + }; @Override protected void onCreate(Bundle savedInstanceState) { @@ -31,7 +45,13 @@ public class MainActivity extends AppCompatActivity { binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - binding.startButton.setOnClickListener(v -> toggleFloatingWindow()); + isFloatingShown = PrefUtils.isFloatingShown(this); + updateButtonText(); + + LocalBroadcastManager.getInstance(this).registerReceiver( + floatingReceiver, new IntentFilter(ACTION_FLOATING_STATE_CHANGED)); + + binding.singleButton.setOnClickListener(v -> onToggleFloatingWindowClicked()); permissionLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> checkPermissions()); @@ -77,7 +97,7 @@ public class MainActivity extends AppCompatActivity { } } - binding.startButton.setEnabled(allPermissionsGranted); + binding.singleButton.setEnabled(allPermissionsGranted); updateButtonText(); } @@ -114,9 +134,10 @@ public class MainActivity extends AppCompatActivity { return false; } - private void toggleFloatingWindow() { + public void onToggleFloatingWindowClicked() { long currentTime = System.currentTimeMillis(); if (currentTime - lastClickTime < DEBOUNCE_INTERVAL) { + Toast.makeText(this, "点击太频繁", Toast.LENGTH_LONG).show(); return; } lastClickTime = currentTime; @@ -127,7 +148,12 @@ public class MainActivity extends AppCompatActivity { return; } - if (!isFloatingShown) { + if (isFloatingShown) { + stopService(new Intent(this, ForegroundService.class)); + AutoClickService.getInstance().stopClicking(); + isFloatingShown = false; + logDebug("悬浮窗已经隐藏"); + } else { Intent serviceIntent = new Intent(this, ForegroundService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(serviceIntent); @@ -135,18 +161,31 @@ public class MainActivity extends AppCompatActivity { startService(serviceIntent); } isFloatingShown = true; - Toast.makeText(this, "悬浮窗已显示", Toast.LENGTH_SHORT).show(); - } else { - AutoClickService service = AutoClickService.getInstance(); - stopService(new Intent(this, ForegroundService.class)); - service.stopClicking(); - isFloatingShown = false; - Toast.makeText(this, "悬浮窗已隐藏", Toast.LENGTH_SHORT).show(); + logDebug("悬浮窗已经显示"); } + + PrefUtils.setFloatingShown(this, isFloatingShown); + broadcastFloatingState(isFloatingShown); updateButtonText(); } + private void broadcastFloatingState(boolean isShown) { + Intent intent = new Intent(ACTION_FLOATING_STATE_CHANGED); + intent.putExtra("isShown", isShown); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + private void updateButtonText() { - binding.startButton.setText(isFloatingShown ? R.string.hide_floating_window : R.string.show_floating_window); + binding.singleButton.setText(isFloatingShown ? "隐藏悬浮窗" : "显示悬浮窗"); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + LocalBroadcastManager.getInstance(this).unregisterReceiver(floatingReceiver); + } + + private void logDebug(String message) { + Log.d(TAG, message); } } \ No newline at end of file diff --git a/app/src/main/java/com/auto/autoclicker/util/PrefUtils.java b/app/src/main/java/com/auto/autoclicker/util/PrefUtils.java new file mode 100644 index 0000000..6401cb4 --- /dev/null +++ b/app/src/main/java/com/auto/autoclicker/util/PrefUtils.java @@ -0,0 +1,18 @@ +package com.auto.autoclicker.util; + +import android.content.Context; + +public class PrefUtils { + private static final String PREF_NAME = "app_prefs"; + private static final String KEY_FLOATING_SHOWN = "floating_window_shown"; + + public static void setFloatingShown(Context context, boolean shown) { + context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) + .edit().putBoolean(KEY_FLOATING_SHOWN, shown).apply(); + } + + public static boolean isFloatingShown(Context context) { + return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) + .getBoolean(KEY_FLOATING_SHOWN, false); + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b2e5c31..e4378bb 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,8 +4,18 @@ android:layout_width="match_parent" android:layout_height="match_parent"> -