diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 78bf9e5..8eb05e8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -15,6 +15,9 @@
+
+
+
-
+
+
+
+
+
+
+
diff --git a/app/src/main/java/io/github/sankalp/lunox/LauncherActivity.java b/app/src/main/java/io/github/sankalp/lunox/LauncherActivity.java
index 8312105..fdf8ce1 100644
--- a/app/src/main/java/io/github/sankalp/lunox/LauncherActivity.java
+++ b/app/src/main/java/io/github/sankalp/lunox/LauncherActivity.java
@@ -82,6 +82,7 @@ import java.util.Map;
import io.github.sankalp.lunox.dialogs.AppSettingsPopup;
import io.github.sankalp.lunox.dialogs.ColorSizeDialog;
+import io.github.sankalp.lunox.dialogs.DoubleTapLockDialog;
import io.github.sankalp.lunox.dialogs.FrozenAppsDialogs;
import io.github.sankalp.lunox.dialogs.GlobalColorSizeDialog;
import io.github.sankalp.lunox.dialogs.GlobalSettingsDialog;
@@ -94,6 +95,7 @@ import io.github.sankalp.lunox.model.Shortcut;
import io.github.sankalp.lunox.utils.CrashUtils;
import io.github.sankalp.lunox.utils.DbUtils;
+import io.github.sankalp.lunox.utils.AccessibilityUtils;
import io.github.sankalp.lunox.utils.Gestures;
import io.github.sankalp.lunox.utils.NotificationPanelManager;
import io.github.sankalp.lunox.utils.ShortcutUtils;
@@ -140,7 +142,8 @@ import static io.github.sankalp.lunox.utils.Constants.SORT_BY_UPDATE_TIME;
@SuppressLint("NonConstantResourceId")
public class LauncherActivity extends Activity implements View.OnClickListener,
View.OnLongClickListener,
- Gestures.OnSwipeListener {
+ Gestures.OnSwipeListener,
+ Gestures.OnDoubleTapListener {
//region Field declarations
@@ -283,7 +286,7 @@ public class LauncherActivity extends Activity implements View.OnClickListener,
//set padding ..
mHomeLayout.setPadding(DbUtils.getPaddingLeft(), DbUtils.getPaddingTop(), DbUtils.getPaddingRight(), DbUtils.getPaddingBottom());
- detector = new Gestures(this, this);
+ detector = new Gestures(this, this, this);
// Initialize long press detector for empty areas
longPressDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@@ -1211,6 +1214,27 @@ public class LauncherActivity extends Activity implements View.OnClickListener,
}
}
+ @Override
+ public void onDoubleTap(MotionEvent e) {
+ // Check if double tap to lock is enabled
+ if (!DbUtils.isDoubleTapToLockEnabled()) {
+ return;
+ }
+
+ // Check if the double tap is on an empty area (not on an app)
+ View touchedView = findViewAt(e.getX(), e.getY());
+ if (!(touchedView instanceof AppTextView)) {
+ // Attempt to lock screen using accessibility service
+ boolean success = AccessibilityUtils.requestLockScreen(this);
+ if (!success) {
+ // Show message if accessibility service is not enabled
+ if (!AccessibilityUtils.isAccessibilityServiceEnabled(this)) {
+ showAccessibilityServiceDialog();
+ }
+ }
+ }
+ }
+
@@ -1322,5 +1346,33 @@ public class LauncherActivity extends Activity implements View.OnClickListener,
permissionDialog.show();
}
+ /**
+ * Show dialog to enable accessibility service for double tap to lock
+ */
+ private void showAccessibilityServiceDialog() {
+ Context ctx;
+ if (DbUtils.getTheme() == R.style.Wallpaper)
+ ctx = new ContextThemeWrapper(this, R.style.AppTheme);
+ else
+ ctx = new ContextThemeWrapper(this, DbUtils.getTheme());
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
+ builder.setTitle("Enable Accessibility Service");
+ builder.setMessage("To use double tap to lock screen, please enable the Lunox Accessibility Service in Settings.");
+ builder.setPositiveButton("Open Settings", (dialog, which) -> {
+ AccessibilityUtils.openAccessibilitySettings(this);
+ });
+ builder.setNegativeButton("Cancel", null);
+ builder.show();
+ }
+
+ /**
+ * Show detailed double tap to lock dialog
+ */
+ private void showDoubleTapLockDialog() {
+ dialogs = new DoubleTapLockDialog(this, this);
+ dialogs.show();
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/io/github/sankalp/lunox/dialogs/DoubleTapLockDialog.java b/app/src/main/java/io/github/sankalp/lunox/dialogs/DoubleTapLockDialog.java
new file mode 100644
index 0000000..a4e9443
--- /dev/null
+++ b/app/src/main/java/io/github/sankalp/lunox/dialogs/DoubleTapLockDialog.java
@@ -0,0 +1,151 @@
+/*
+ * Lunox Launcher
+ * Copyright (C) 2024 Sankalp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package io.github.sankalp.lunox.dialogs;
+
+import android.app.Dialog;
+import android.content.Context;
+
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.widget.TextView;
+
+import io.github.sankalp.lunox.LauncherActivity;
+import io.github.sankalp.lunox.R;
+import io.github.sankalp.lunox.utils.AccessibilityUtils;
+import io.github.sankalp.lunox.utils.DbUtils;
+
+/**
+ * Dialog for configuring double tap to lock screen functionality
+ */
+public class DoubleTapLockDialog extends Dialog implements View.OnClickListener {
+
+ private final LauncherActivity launcherActivity;
+ private final Context context;
+ private TextView enableButton;
+ private TextView closeButton;
+ private TextView mainDescription;
+ private TextView additionalInfo;
+
+ public DoubleTapLockDialog(Context context, LauncherActivity launcherActivity) {
+ super(context);
+ this.context = context;
+ this.launcherActivity = launcherActivity;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.dialog_double_tap_lock);
+
+ // Make background transparent for rounded corners
+ if (getWindow() != null) {
+ getWindow().setBackgroundDrawableResource(android.R.color.transparent);
+ }
+
+ // Initialize views
+ enableButton = findViewById(R.id.btn_enable);
+ closeButton = findViewById(R.id.btn_close);
+ mainDescription = findViewById(R.id.tv_main_description);
+ additionalInfo = findViewById(R.id.tv_additional_info);
+
+ // Set click listeners
+ enableButton.setOnClickListener(this);
+ closeButton.setOnClickListener(this);
+
+ // Update content based on current state
+ updateDialogContent();
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ if (hasFocus) {
+ // Refresh dialog content when user returns from settings
+ updateDialogContent();
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ int id = view.getId();
+
+ if (id == R.id.btn_enable) {
+ handleEnableButton();
+ } else if (id == R.id.btn_close) {
+ dismiss();
+ }
+ }
+
+ private void handleEnableButton() {
+ boolean isCurrentlyEnabled = DbUtils.isDoubleTapToLockEnabled();
+
+ if (isCurrentlyEnabled) {
+ // Disable the feature
+ DbUtils.setDoubleTapToLock(false);
+ updateDialogContent();
+ dismiss();
+ } else {
+ // Check if accessibility service is enabled before enabling the feature
+ if (AccessibilityUtils.isAccessibilityServiceEnabled(context)) {
+ // Service is enabled, so we can enable the feature
+ DbUtils.setDoubleTapToLock(true);
+ updateDialogContent();
+ dismiss();
+ } else {
+ // Service is not enabled, open accessibility settings but don't enable the feature yet
+ AccessibilityUtils.openAccessibilitySettings(context);
+ // Keep the dialog open so user can try again after enabling the service
+ updateDialogContent();
+ }
+ }
+ }
+
+ private void updateDialogContent() {
+ boolean isEnabled = DbUtils.isDoubleTapToLockEnabled();
+ boolean isServiceEnabled = AccessibilityUtils.isAccessibilityServiceEnabled(context);
+
+ // Update button text based on current state
+ if (isEnabled) {
+ enableButton.setText("Disable");
+ } else if (isServiceEnabled) {
+ enableButton.setText("Enable");
+ } else {
+ enableButton.setText("Open Settings");
+ }
+
+ // Update description based on current state
+ if (isEnabled && isServiceEnabled) {
+ mainDescription.setText("Double tap to lock is currently enabled and working. You can disable it below if you no longer want this feature.");
+ additionalInfo.setText("The accessibility service is active and allows you to lock your screen by double tapping on empty areas of the launcher.");
+ } else if (isEnabled && !isServiceEnabled) {
+ mainDescription.setText("Double tap to lock is enabled but the accessibility service is not active. Please enable Lunox's accessibility service in your device's settings.");
+ additionalInfo.setText("The accessibility service is required for the double tap to lock feature to work. It only locks your screen and does not collect any data.");
+ } else if (!isEnabled && isServiceEnabled) {
+ mainDescription.setText("The accessibility service is enabled. You can now enable double tap to lock to quickly lock your screen by double tapping on empty areas.");
+ additionalInfo.setText("This feature will use the accessibility service to lock your screen when you double tap on empty areas of the launcher.");
+ } else {
+ mainDescription.setText("To enable double tap to lock, you first need to enable Lunox's accessibility service in your device's settings.");
+ additionalInfo.setText("The accessibility service is required for this feature to work. It only locks your screen and does not collect or share any data. Click Enable to open the settings.");
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/io/github/sankalp/lunox/dialogs/GlobalSettingsDialog.java b/app/src/main/java/io/github/sankalp/lunox/dialogs/GlobalSettingsDialog.java
index 373337d..9128356 100644
--- a/app/src/main/java/io/github/sankalp/lunox/dialogs/GlobalSettingsDialog.java
+++ b/app/src/main/java/io/github/sankalp/lunox/dialogs/GlobalSettingsDialog.java
@@ -18,6 +18,7 @@
package io.github.sankalp.lunox.dialogs;
+import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
@@ -38,7 +39,9 @@ import java.util.Locale;
import io.github.sankalp.lunox.BuildConfig;
import io.github.sankalp.lunox.LauncherActivity;
import io.github.sankalp.lunox.R;
+import io.github.sankalp.lunox.dialogs.DoubleTapLockDialog;
import io.github.sankalp.lunox.model.Apps;
+import io.github.sankalp.lunox.utils.AccessibilityUtils;
import io.github.sankalp.lunox.utils.Constants;
import io.github.sankalp.lunox.utils.DbUtils;
import io.github.sankalp.lunox.utils.Utils;
@@ -57,6 +60,7 @@ public class GlobalSettingsDialog extends Dialog implements View.OnClickListener
private final LauncherActivity launcherActivity;
private final Context context;
private TextView freezeSize;
+ private TextView doubleTapLockButton;
public GlobalSettingsDialog(Context context, LauncherActivity launcherActivity) {
super(context);
@@ -102,6 +106,10 @@ public class GlobalSettingsDialog extends Dialog implements View.OnClickListener
findViewById(R.id.settings_frozen_apps).setOnClickListener(this);
findViewById(R.id.settings_hidden_apps).setOnClickListener(this);
+ // Double tap to lock setting
+ doubleTapLockButton = findViewById(R.id.settings_double_tap_lock);
+ doubleTapLockButton.setOnClickListener(this);
+
//reflect the DB value
if (DbUtils.isSizeFrozen()) {
@@ -109,6 +117,9 @@ public class GlobalSettingsDialog extends Dialog implements View.OnClickListener
} else
freezeSize.setText(R.string.freeze_apps_size);
+ // Set double tap to lock button text
+ updateDoubleTapLockButtonText();
+
}
@Override
@@ -145,6 +156,8 @@ public class GlobalSettingsDialog extends Dialog implements View.OnClickListener
cancel();
} else if (id == R.id.settings_restart_launcher) {
launcherActivity.recreate();
+ } else if (id == R.id.settings_double_tap_lock) {
+ toggleDoubleTapToLock();
}
}
@@ -278,6 +291,48 @@ public class GlobalSettingsDialog extends Dialog implements View.OnClickListener
}
+ private void toggleDoubleTapToLock() {
+ boolean currentState = DbUtils.isDoubleTapToLockEnabled();
+
+ if (currentState) {
+ // If currently enabled, just disable it directly
+ DbUtils.setDoubleTapToLock(false);
+ updateDoubleTapLockButtonText();
+ } else {
+ // If currently disabled, show the detailed dialog to explain and enable the feature
+ DoubleTapLockDialog doubleTapDialog = new DoubleTapLockDialog(context, launcherActivity);
+ doubleTapDialog.show();
+
+ // Update button text when dialog is dismissed
+ doubleTapDialog.setOnDismissListener(dialog -> updateDoubleTapLockButtonText());
+ }
+ }
+
+ private void updateDoubleTapLockButtonText() {
+ if (DbUtils.isDoubleTapToLockEnabled()) {
+ doubleTapLockButton.setText(R.string.double_tap_to_lock_enabled);
+ } else {
+ doubleTapLockButton.setText(R.string.double_tap_to_lock_disabled);
+ }
+ }
+
+ private void showAccessibilityServiceDialog() {
+ Context ctx;
+ if (DbUtils.getTheme() == R.style.Wallpaper)
+ ctx = new ContextThemeWrapper(getContext(), R.style.AppTheme);
+ else
+ ctx = new ContextThemeWrapper(getContext(), DbUtils.getTheme());
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
+ builder.setTitle("Enable Accessibility Service");
+ builder.setMessage("To use double tap to lock screen, please enable the Lunox Accessibility Service in Settings.");
+ builder.setPositiveButton("Open Settings", (dialog, which) -> {
+ AccessibilityUtils.openAccessibilitySettings(context);
+ });
+ builder.setNegativeButton("Cancel", null);
+ builder.show();
+ }
+
private void backup() {
cancel();
Intent intentBackupFiles;
diff --git a/app/src/main/java/io/github/sankalp/lunox/services/LockScreenAccessibilityService.java b/app/src/main/java/io/github/sankalp/lunox/services/LockScreenAccessibilityService.java
new file mode 100644
index 0000000..5008ff6
--- /dev/null
+++ b/app/src/main/java/io/github/sankalp/lunox/services/LockScreenAccessibilityService.java
@@ -0,0 +1,130 @@
+/*
+ * Lunox Launcher
+ * Copyright (C) 2024 Sankalp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package io.github.sankalp.lunox.services;
+
+import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.GestureDescription;
+import android.content.Intent;
+import android.graphics.Path;
+import android.os.Build;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * Accessibility service for lock screen functionality
+ * This service can perform global actions like simulating power key press
+ */
+public class LockScreenAccessibilityService extends AccessibilityService {
+
+ private static final String TAG = "LockScreenAccessibilityService";
+ private static LockScreenAccessibilityService instance;
+
+ public static final String ACTION_LOCK_SCREEN = "io.github.sankalp.lunox.ACTION_LOCK_SCREEN";
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ instance = this;
+ Log.d(TAG, "Accessibility service created");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ instance = null;
+ Log.d(TAG, "Accessibility service destroyed");
+ }
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+ // We don't need to handle accessibility events for this use case
+ }
+
+ @Override
+ public void onInterrupt() {
+ Log.d(TAG, "Accessibility service interrupted");
+ }
+
+ @Override
+ protected boolean onKeyEvent(KeyEvent event) {
+ return super.onKeyEvent(event);
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent != null && ACTION_LOCK_SCREEN.equals(intent.getAction())) {
+ lockScreen();
+ }
+ return START_NOT_STICKY;
+ }
+
+ /**
+ * Lock the screen using accessibility service global action
+ */
+ public void lockScreen() {
+ try {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ // Android 9+ supports GLOBAL_ACTION_LOCK_SCREEN
+ boolean success = performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN);
+ Log.d(TAG, "Lock screen action performed: " + success);
+ if (!success) {
+ // Fallback to power button simulation
+ simulatePowerButton();
+ }
+ } else {
+ // For older versions, simulate power button press
+ simulatePowerButton();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to lock screen", e);
+ }
+ }
+
+ /**
+ * Simulate power button press using accessibility service
+ */
+ private void simulatePowerButton() {
+ try {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ // Use gesture simulation to simulate power button
+ // This is a workaround since we can't directly simulate hardware keys
+ // We'll use the global action for power dialog which can lock the screen
+ boolean success = performGlobalAction(GLOBAL_ACTION_POWER_DIALOG);
+ Log.d(TAG, "Power dialog action performed: " + success);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to simulate power button", e);
+ }
+ }
+
+ /**
+ * Get the current instance of the accessibility service
+ */
+ public static LockScreenAccessibilityService getInstance() {
+ return instance;
+ }
+
+ /**
+ * Check if the accessibility service is running
+ */
+ public static boolean isServiceRunning() {
+ return instance != null;
+ }
+}
diff --git a/app/src/main/java/io/github/sankalp/lunox/utils/AccessibilityUtils.java b/app/src/main/java/io/github/sankalp/lunox/utils/AccessibilityUtils.java
new file mode 100644
index 0000000..fcaa98f
--- /dev/null
+++ b/app/src/main/java/io/github/sankalp/lunox/utils/AccessibilityUtils.java
@@ -0,0 +1,109 @@
+/*
+ * Lunox Launcher
+ * Copyright (C) 2024 Sankalp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package io.github.sankalp.lunox.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.accessibility.AccessibilityManager;
+
+import io.github.sankalp.lunox.services.LockScreenAccessibilityService;
+
+/**
+ * Utility class for accessibility service operations
+ */
+public class AccessibilityUtils {
+
+ private static final String TAG = "AccessibilityUtils";
+
+ /**
+ * Check if our accessibility service is enabled
+ */
+ public static boolean isAccessibilityServiceEnabled(Context context) {
+ AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ if (am == null) {
+ return false;
+ }
+
+ // Check if accessibility is enabled and our service is in the enabled services list
+ String enabledServices = Settings.Secure.getString(
+ context.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
+ );
+
+ if (enabledServices == null || enabledServices.isEmpty()) {
+ return false;
+ }
+
+ String packageName = context.getPackageName();
+ String serviceName = LockScreenAccessibilityService.class.getName();
+ String fullServiceName = packageName + "/" + serviceName;
+
+ // Check if our service is in the enabled services list
+ return enabledServices.contains(fullServiceName);
+ }
+
+ /**
+ * Open accessibility settings to enable our service
+ */
+ public static void openAccessibilitySettings(Context context) {
+ try {
+ Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to open accessibility settings", e);
+ }
+ }
+
+ /**
+ * Request lock screen action through accessibility service
+ */
+ public static boolean requestLockScreen(Context context) {
+ if (!isAccessibilityServiceEnabled(context)) {
+ Log.w(TAG, "Accessibility service not enabled");
+ return false;
+ }
+
+ LockScreenAccessibilityService service = LockScreenAccessibilityService.getInstance();
+ if (service != null) {
+ service.lockScreen();
+ return true;
+ } else {
+ // Try to start the service with intent
+ try {
+ Intent intent = new Intent(context, LockScreenAccessibilityService.class);
+ intent.setAction(LockScreenAccessibilityService.ACTION_LOCK_SCREEN);
+ context.startService(intent);
+ return true;
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to start accessibility service", e);
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Check if accessibility service is running
+ */
+ public static boolean isServiceRunning() {
+ return LockScreenAccessibilityService.isServiceRunning();
+ }
+}
diff --git a/app/src/main/java/io/github/sankalp/lunox/utils/DbUtils.java b/app/src/main/java/io/github/sankalp/lunox/utils/DbUtils.java
index 78d82ad..33f9b2c 100644
--- a/app/src/main/java/io/github/sankalp/lunox/utils/DbUtils.java
+++ b/app/src/main/java/io/github/sankalp/lunox/utils/DbUtils.java
@@ -62,6 +62,7 @@ public class DbUtils {
private static final String APPS_COLORS_DEFAULT = "apps_color_default";
private static final String APPS_SORTS_TYPE = "apps_sorts_types";
private static final String PERMISSION_DIALOG_SHOWN = "permission_dialog_shown";
+ private static final String DOUBLE_TAP_TO_LOCK = "double_tap_to_lock";
public static void init(Context context) {
@@ -392,6 +393,20 @@ public class DbUtils {
SpUtils.getInstance().putBoolean(PERMISSION_DIALOG_SHOWN, shown);
}
+ /**
+ * Check if double tap to lock is enabled
+ */
+ public static boolean isDoubleTapToLockEnabled() {
+ return SpUtils.getInstance().getBoolean(DOUBLE_TAP_TO_LOCK, false);
+ }
+
+ /**
+ * Set double tap to lock preference
+ */
+ public static void setDoubleTapToLock(boolean enabled) {
+ SpUtils.getInstance().putBoolean(DOUBLE_TAP_TO_LOCK, enabled);
+ }
+
// a simple ciphered counter: "opening counter" is a private thing
// rest is on device security
private static String codeCount(int count) {
diff --git a/app/src/main/java/io/github/sankalp/lunox/utils/Gestures.java b/app/src/main/java/io/github/sankalp/lunox/utils/Gestures.java
index dfcba81..1571f80 100644
--- a/app/src/main/java/io/github/sankalp/lunox/utils/Gestures.java
+++ b/app/src/main/java/io/github/sankalp/lunox/utils/Gestures.java
@@ -30,12 +30,20 @@ public class Gestures extends GestureDetector.SimpleOnGestureListener {
private final GestureDetector detector;
private final OnSwipeListener listener;
+ private final OnDoubleTapListener doubleTapListener;
public Gestures(Activity context,
OnSwipeListener onSwipeListener) {
+ this(context, onSwipeListener, null);
+ }
+
+ public Gestures(Activity context,
+ OnSwipeListener onSwipeListener,
+ OnDoubleTapListener onDoubleTapListener) {
this.detector = new GestureDetector(context, this);
this.listener = onSwipeListener;
+ this.doubleTapListener = onDoubleTapListener;
}
public void onTouchEvent(MotionEvent event) {
@@ -73,8 +81,14 @@ public class Gestures extends GestureDetector.SimpleOnGestureListener {
return consumed;
}
-
-
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (doubleTapListener != null) {
+ doubleTapListener.onDoubleTap(e);
+ return true;
+ }
+ return super.onDoubleTap(e);
+ }
public enum Direction {
SWIPE_UP, SWIPE_DOWN, SWIPE_LEFT, SWIPE_RIGHT
@@ -84,4 +98,8 @@ public class Gestures extends GestureDetector.SimpleOnGestureListener {
void onSwipe(Direction direction);
}
+ public interface OnDoubleTapListener {
+ void onDoubleTap(MotionEvent e);
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/dialog_background.xml b/app/src/main/res/drawable/dialog_background.xml
new file mode 100644
index 0000000..5f337f2
--- /dev/null
+++ b/app/src/main/res/drawable/dialog_background.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_double_tap_lock.xml b/app/src/main/res/layout/dialog_double_tap_lock.xml
new file mode 100644
index 0000000..b31e273
--- /dev/null
+++ b/app/src/main/res/layout/dialog_double_tap_lock.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_global_settings.xml b/app/src/main/res/layout/dialog_global_settings.xml
index 92c95bb..60d5042 100644
--- a/app/src/main/res/layout/dialog_global_settings.xml
+++ b/app/src/main/res/layout/dialog_global_settings.xml
@@ -208,6 +208,23 @@
android:background="#DEDEDE"
android:foregroundGravity="center_vertical|center_horizontal" />
+
+
+
+
From ColorSniffer App
Size for this entry
+
+
+ Double Tap Lock
+ Double Tap Lock:On
+ Double Tap Lock:Off
+
+
+ Lunox Accessibility Service for lock screen functionality. This service allows double tap to lock the screen.
\ No newline at end of file
diff --git a/app/src/main/res/xml/accessibility_service_config.xml b/app/src/main/res/xml/accessibility_service_config.xml
new file mode 100644
index 0000000..c54b847
--- /dev/null
+++ b/app/src/main/res/xml/accessibility_service_config.xml
@@ -0,0 +1,11 @@
+
+