diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bf2d2ff6d..fcfe2031f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -144,6 +144,18 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/fr/neamar/kiss/forwarder/ExperienceTweaks.java b/app/src/main/java/fr/neamar/kiss/forwarder/ExperienceTweaks.java
index 7f7b16bab..7bef5756b 100644
--- a/app/src/main/java/fr/neamar/kiss/forwarder/ExperienceTweaks.java
+++ b/app/src/main/java/fr/neamar/kiss/forwarder/ExperienceTweaks.java
@@ -1,7 +1,12 @@
package fr.neamar.kiss.forwarder;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.SuppressLint;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.Handler;
import android.provider.Settings;
@@ -9,16 +14,19 @@
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityManager;
import android.widget.ImageView;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.List;
import fr.neamar.kiss.MainActivity;
import fr.neamar.kiss.R;
import fr.neamar.kiss.searcher.HistorySearcher;
import fr.neamar.kiss.searcher.NullSearcher;
import fr.neamar.kiss.searcher.Searcher;
+import fr.neamar.kiss.utils.LockAccessibilityService;
// Deals with any settings in the "User Experience" setting sub-screen
class ExperienceTweaks extends Forwarder {
@@ -46,6 +54,7 @@ class ExperienceTweaks extends Forwarder {
private View mainEmptyView;
private final GestureDetector gd;
+ @SuppressLint("SourceLockedOrientationActivity")
ExperienceTweaks(final MainActivity mainActivity) {
super(mainActivity);
@@ -63,14 +72,43 @@ class ExperienceTweaks extends Forwarder {
gd = new GestureDetector(mainActivity, new GestureDetector.SimpleOnGestureListener() {
@Override
- public boolean onSingleTapUp(MotionEvent e) {
- if(prefs.getBoolean("history-onclick", false)) {
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ if (prefs.getBoolean("history-onclick", false)) {
doAction("display-history");
}
return super.onSingleTapConfirmed(e);
}
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
+ return super.onDoubleTap(e);
+ }
+
+ if (isAccessibilityServiceEnabled(mainActivity)) {
+ Intent intent = new Intent(LockAccessibilityService.ACTION_LOCK, null, mainActivity, LockAccessibilityService.class);
+ mainActivity.startService(intent);
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
+ builder.setMessage(R.string.enable_double_tap_to_lock);
+
+ builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
+ Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mainActivity.startActivity(intent);
+ });
+
+ builder.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
+ dialog.dismiss();
+ });
+
+ AlertDialog alert = builder.create();
+ alert.show();
+ }
+ return super.onDoubleTap(e);
+ }
+
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float directionY = e2.getY() - e1.getY();
@@ -95,7 +133,7 @@ private void doAction(String action) {
mainActivity.showKeyboard();
break;
case "display-apps":
- if(mainActivity.isViewingSearchResults()) {
+ if (mainActivity.isViewingSearchResults()) {
mainActivity.displayKissBar(true);
}
break;
@@ -160,7 +198,7 @@ void onResume() {
}
}
- void onTouch(View view, MotionEvent event) {
+ void onTouch(MotionEvent event) {
// Forward touch events to the gesture detector
gd.onTouchEvent(event);
}
@@ -225,7 +263,7 @@ private void adjustInputType() {
@SuppressWarnings("CatchAndPrintStackTrace")
private void displayNotificationDrawer() {
@SuppressLint("WrongConstant") Object sbservice = mainActivity.getSystemService("statusbar");
- Class> statusbarManager = null;
+ Class> statusbarManager;
try {
statusbarManager = Class.forName("android.app.StatusBarManager");
Method showStatusBar;
@@ -277,4 +315,25 @@ private boolean isKeyboardOnStartEnabled() {
private boolean isSuggestionsEnabled() {
return prefs.getBoolean("enable-suggestions-keyboard", false);
}
+
+ /**
+ * Are we allowed to run our AccessibilityService?
+ */
+ private boolean isAccessibilityServiceEnabled(Context context) {
+ AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ if (am == null) {
+ return false;
+ }
+
+ List enabledServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+
+
+ for (AccessibilityServiceInfo enabledService : enabledServices) {
+ ServiceInfo enabledServiceInfo = enabledService.getResolveInfo().serviceInfo;
+ if (enabledServiceInfo.packageName.equals(context.getPackageName()) && enabledServiceInfo.name.equals(LockAccessibilityService.class.getName()))
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/app/src/main/java/fr/neamar/kiss/forwarder/ForwarderManager.java b/app/src/main/java/fr/neamar/kiss/forwarder/ForwarderManager.java
index f3d9393cd..831306155 100644
--- a/app/src/main/java/fr/neamar/kiss/forwarder/ForwarderManager.java
+++ b/app/src/main/java/fr/neamar/kiss/forwarder/ForwarderManager.java
@@ -82,7 +82,7 @@ public void onCreateContextMenu(ContextMenu menu) {
}
public boolean onTouch(View view, MotionEvent event) {
- experienceTweaks.onTouch(view, event); // always return false anyway
+ experienceTweaks.onTouch(event);
return liveWallpaperForwarder.onTouch(view, event);
}
diff --git a/app/src/main/java/fr/neamar/kiss/utils/LockAccessibilityService.java b/app/src/main/java/fr/neamar/kiss/utils/LockAccessibilityService.java
new file mode 100644
index 000000000..e2223fb10
--- /dev/null
+++ b/app/src/main/java/fr/neamar/kiss/utils/LockAccessibilityService.java
@@ -0,0 +1,31 @@
+package fr.neamar.kiss.utils;
+
+import android.accessibilityservice.AccessibilityService;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Build;
+import android.view.accessibility.AccessibilityEvent;
+
+public class LockAccessibilityService extends AccessibilityService {
+ public static String ACTION_LOCK = "fr.neamar.kiss.LOCK";
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+
+ }
+
+ @Override
+ public void onInterrupt() {
+
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (ACTION_LOCK.equals(intent.getAction())) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ performGlobalAction(AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
+ }
+ }
+ return Service.START_STICKY;
+ }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 64ab32f52..b875589a5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -228,6 +228,8 @@
Enlarge
Move up
Move down
+ Lock screen from KISS Launcher
Action on swipe up
Action on swipe down
+ To enable double-tap to lock, you\'ll need to grant additional permissions: enable KISS in the following screen.
diff --git a/app/src/main/res/xml/lock_accessibility_service_config.xml b/app/src/main/res/xml/lock_accessibility_service_config.xml
new file mode 100644
index 000000000..a787aa5fe
--- /dev/null
+++ b/app/src/main/res/xml/lock_accessibility_service_config.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file