mirror of
https://github.com/jrpie/Launcher.git
synced 2025-04-11 14:54:31 +02:00
Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
653d16b269 | |||
5d695ec0ea | |||
b4608ef153 | |||
8e140e2e69 | |||
7fc58fe384 | |||
54409b6312 |
14 changed files with 130 additions and 40 deletions
|
@ -23,8 +23,8 @@ android {
|
|||
minSdkVersion 21
|
||||
targetSdkVersion 35
|
||||
compileSdk 35
|
||||
versionCode 42
|
||||
versionName "0.1.2"
|
||||
versionCode 43
|
||||
versionName "0.1.3"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
<service
|
||||
android:name=".actions.lock.LauncherAccessibilityService"
|
||||
android:exported="true"
|
||||
android:label="@string/accessibility_service_name"
|
||||
android:label="@string/app_name"
|
||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.accessibilityservice.AccessibilityService" />
|
||||
|
@ -97,4 +97,4 @@
|
|||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
|
|
@ -38,6 +38,8 @@ import androidx.core.net.toUri
|
|||
|
||||
const val LOG_TAG = "Launcher"
|
||||
|
||||
const val REQUEST_SET_DEFAULT_HOME = 42
|
||||
|
||||
fun isDefaultHomeScreen(context: Context): Boolean {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
val roleManager = context.getSystemService(RoleManager::class.java)
|
||||
|
@ -59,11 +61,12 @@ fun setDefaultHomeScreen(context: Context, checkDefault: Boolean = false) {
|
|||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
||||
&& context is Activity
|
||||
&& !isDefault // using role manager only works when µLauncher is not already the default.
|
||||
&& checkDefault // using role manager only works when µLauncher is not already the default.
|
||||
) {
|
||||
val roleManager = context.getSystemService(RoleManager::class.java)
|
||||
context.startActivity(
|
||||
roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME)
|
||||
context.startActivityForResult(
|
||||
roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME),
|
||||
REQUEST_SET_DEFAULT_HOME
|
||||
)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ import android.view.KeyEvent
|
|||
import android.widget.Toast
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import de.jrpie.android.launcher.Application
|
||||
import de.jrpie.android.launcher.BuildConfig
|
||||
import de.jrpie.android.launcher.R
|
||||
import de.jrpie.android.launcher.actions.lock.LauncherAccessibilityService
|
||||
import de.jrpie.android.launcher.apps.AppFilter
|
||||
import de.jrpie.android.launcher.apps.hidePrivateSpaceWhenLocked
|
||||
import de.jrpie.android.launcher.apps.isPrivateSpaceSupported
|
||||
|
@ -132,6 +134,14 @@ enum class LauncherAction(
|
|||
R.drawable.baseline_settings_applications_24,
|
||||
::expandSettingsPanel
|
||||
),
|
||||
RECENT_APPS(
|
||||
"recent_apps",
|
||||
R.string.list_other_recent_apps,
|
||||
R.drawable.baseline_apps_24,
|
||||
LauncherAccessibilityService::openRecentApps,
|
||||
false,
|
||||
{ _ -> BuildConfig.USE_ACCESSIBILITY_SERVICE }
|
||||
),
|
||||
LOCK_SCREEN(
|
||||
"lock_screen",
|
||||
R.string.list_other_lock_screen,
|
||||
|
@ -142,7 +152,13 @@ enum class LauncherAction(
|
|||
"toggle_torch",
|
||||
R.string.list_other_torch,
|
||||
R.drawable.baseline_flashlight_on_24,
|
||||
::toggleTorch
|
||||
::toggleTorch,
|
||||
),
|
||||
LAUNCH_OTHER_LAUNCHER(
|
||||
"launcher_other_launcher",
|
||||
R.string.list_other_launch_other_launcher,
|
||||
R.drawable.baseline_home_24,
|
||||
::launchOtherLauncher
|
||||
),
|
||||
NOP("nop", R.string.list_other_nop, R.drawable.baseline_not_interested_24, {});
|
||||
|
||||
|
@ -248,6 +264,15 @@ private fun expandSettingsPanel(context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun launchOtherLauncher(context: Context) {
|
||||
context.startActivity(
|
||||
Intent.createChooser(
|
||||
Intent(Intent.ACTION_MAIN).also { it.addCategory(Intent.CATEGORY_HOME) },
|
||||
context.getString(R.string.list_other_launch_other_launcher)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun openSettings(context: Context) {
|
||||
context.startActivity(Intent(context, SettingsActivity::class.java))
|
||||
}
|
||||
|
|
|
@ -22,26 +22,44 @@ class LauncherAccessibilityService : AccessibilityService() {
|
|||
|
||||
companion object {
|
||||
private const val TAG = "Launcher Accessibility"
|
||||
private const val ACTION_REQUEST_ENABLE = "ACTION_REQUEST_ENABLE"
|
||||
const val ACTION_LOCK_SCREEN = "ACTION_LOCK_SCREEN"
|
||||
const val ACTION_RECENT_APPS = "ACTION_RECENT_APPS"
|
||||
|
||||
fun lockScreen(context: Context) {
|
||||
private fun invoke(context: Context, action: String, failureMessageRes: Int) {
|
||||
try {
|
||||
context.startService(
|
||||
Intent(
|
||||
context,
|
||||
LauncherAccessibilityService::class.java
|
||||
).apply {
|
||||
action = ACTION_LOCK_SCREEN
|
||||
this.action = action
|
||||
})
|
||||
} catch (e: Exception) {
|
||||
} catch (_: Exception) {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.alert_lock_screen_failed),
|
||||
context.getString(failureMessageRes),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
fun lockScreen(context: Context) {
|
||||
if (!isEnabled(context)) {
|
||||
showEnableDialog(context)
|
||||
} else {
|
||||
invoke(context, ACTION_LOCK_SCREEN, R.string.alert_lock_screen_failed)
|
||||
}
|
||||
}
|
||||
|
||||
fun openRecentApps(context: Context) {
|
||||
if (!isEnabled(context)) {
|
||||
showEnableDialog(context)
|
||||
} else {
|
||||
invoke(context, ACTION_RECENT_APPS, R.string.alert_recent_apps_failed)
|
||||
}
|
||||
}
|
||||
|
||||
fun isEnabled(context: Context): Boolean {
|
||||
val enabledServices = Settings.Secure.getString(
|
||||
context.contentResolver,
|
||||
|
@ -58,7 +76,7 @@ class LauncherAccessibilityService : AccessibilityService() {
|
|||
setView(R.layout.dialog_consent_accessibility)
|
||||
setTitle(R.string.dialog_consent_accessibility_title)
|
||||
setPositiveButton(R.string.dialog_consent_accessibility_ok) { _, _ ->
|
||||
lockScreen(context)
|
||||
invoke(context, ACTION_REQUEST_ENABLE, R.string.alert_enable_accessibility_failed)
|
||||
}
|
||||
setNegativeButton(R.string.dialog_cancel) { _, _ -> }
|
||||
}.create().also { it.show() }.apply {
|
||||
|
@ -94,7 +112,9 @@ class LauncherAccessibilityService : AccessibilityService() {
|
|||
}
|
||||
|
||||
when (action) {
|
||||
ACTION_REQUEST_ENABLE -> {} // do nothing
|
||||
ACTION_LOCK_SCREEN -> handleLockScreen()
|
||||
ACTION_RECENT_APPS -> performGlobalAction(GLOBAL_ACTION_RECENTS)
|
||||
}
|
||||
}
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.widget.Button
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import de.jrpie.android.launcher.BuildConfig
|
||||
import de.jrpie.android.launcher.R
|
||||
import de.jrpie.android.launcher.actions.lock.LauncherAccessibilityService
|
||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@ package de.jrpie.android.launcher.ui
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
|
@ -56,22 +56,11 @@ class HomeActivity : UIObject, AppCompatActivity() {
|
|||
super<AppCompatActivity>.onCreate(savedInstanceState)
|
||||
super<UIObject>.onCreate()
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
|
||||
@Suppress("deprecation") // required to support API < 30
|
||||
windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||
|
||||
val width = displayMetrics.widthPixels
|
||||
val height = displayMetrics.heightPixels
|
||||
|
||||
touchGestureDetector = TouchGestureDetector(
|
||||
this,
|
||||
width,
|
||||
height,
|
||||
this, 0, 0,
|
||||
LauncherPreferences.enabled_gestures().edgeSwipeEdgeWidth() / 100f
|
||||
)
|
||||
|
||||
|
||||
touchGestureDetector.updateScreenSize(windowManager)
|
||||
|
||||
// Initialise layout
|
||||
binding = HomeBinding.inflate(layoutInflater)
|
||||
|
@ -103,6 +92,11 @@ class HomeActivity : UIObject, AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
touchGestureDetector.updateScreenSize(windowManager)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super<AppCompatActivity>.onStart()
|
||||
|
||||
|
|
|
@ -5,8 +5,10 @@ import android.graphics.Insets
|
|||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewConfiguration
|
||||
import android.view.WindowManager
|
||||
import androidx.annotation.RequiresApi
|
||||
import de.jrpie.android.launcher.actions.Gesture
|
||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||
|
@ -17,8 +19,8 @@ import kotlin.math.tan
|
|||
|
||||
class TouchGestureDetector(
|
||||
private val context: Context,
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
var width: Int,
|
||||
var height: Int,
|
||||
var edgeWidth: Float
|
||||
) {
|
||||
private val ANGULAR_THRESHOLD = tan(Math.PI / 6)
|
||||
|
@ -319,6 +321,14 @@ class TouchGestureDetector(
|
|||
}
|
||||
}
|
||||
|
||||
fun updateScreenSize(windowManager: WindowManager) {
|
||||
val displayMetrics = DisplayMetrics()
|
||||
@Suppress("deprecation") // required to support API < 30
|
||||
windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||
width = displayMetrics.widthPixels
|
||||
height = displayMetrics.heightPixels
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
fun setSystemGestureInsets(insets: Insets) {
|
||||
systemGestureInsetTop = insets.top
|
||||
|
|
|
@ -109,7 +109,7 @@ class SettingsActivity : AppCompatActivity(), UIObject {
|
|||
}
|
||||
|
||||
private val TAB_TITLES = arrayOf(
|
||||
R.string.settings_tab_app,
|
||||
R.string.settings_tab_actions,
|
||||
R.string.settings_tab_launcher,
|
||||
R.string.settings_tab_meta
|
||||
)
|
||||
|
|
11
app/src/main/res/drawable/baseline_apps_24.xml
Normal file
11
app/src/main/res/drawable/baseline_apps_24.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="?android:textColor"
|
||||
android:pathData="M4,8h4L8,4L4,4v4zM10,20h4v-4h-4v4zM4,20h4v-4L4,16v4zM4,14h4v-4L4,10v4zM10,14h4v-4h-4v4zM16,4v4h4L20,4h-4zM10,8h4L14,4h-4v4zM16,14h4v-4h-4v4zM16,20h4v-4h-4v4z" />
|
||||
|
||||
</vector>
|
11
app/src/main/res/drawable/baseline_home_24.xml
Normal file
11
app/src/main/res/drawable/baseline_home_24.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="?android:textColor"
|
||||
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z" />
|
||||
|
||||
</vector>
|
|
@ -14,7 +14,7 @@
|
|||
-
|
||||
-->
|
||||
<string name="settings_title">Einstellungen</string>
|
||||
<string name="settings_tab_app">Apps</string>
|
||||
<string name="settings_tab_actions">Aktionen</string>
|
||||
<string name="settings_tab_launcher">Launcher</string>
|
||||
<string name="settings_tab_meta">Meta</string>
|
||||
<!--
|
||||
|
@ -54,9 +54,9 @@
|
|||
<string name="settings_gesture_description_down_left_edge">An der linken Kante nach unten wischen</string>
|
||||
<string name="settings_gesture_down_right_edge">Abwärts (rechts)</string>
|
||||
<string name="settings_gesture_description_down_right_edge">An der rechten Kanten nach unten wischen</string>
|
||||
<string name="settings_gesture_vol_up">Lautstärke +</string>
|
||||
<string name="settings_gesture_vol_up">Lauter-Taste</string>
|
||||
<string name="settings_gesture_description_vol_up">Die Taste \"Lauter\" drücken</string>
|
||||
<string name="settings_gesture_vol_down">Lautstärke -</string>
|
||||
<string name="settings_gesture_vol_down">Leiser-Taste</string>
|
||||
<string name="settings_gesture_description_vol_down">Die Taste \"Leiser\" drücken</string>
|
||||
<string name="settings_gesture_double_click">Doppelklick</string>
|
||||
<string name="settings_gesture_description_double_click">In einem leeren Bereich doppelt klicken</string>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
-->
|
||||
<string name="settings_title">Settings</string>
|
||||
|
||||
<string name="settings_tab_app">Apps</string>
|
||||
<string name="settings_tab_actions">Actions</string>
|
||||
<string name="settings_tab_launcher">Launcher</string>
|
||||
<string name="settings_tab_meta">Meta</string>
|
||||
|
||||
|
@ -85,9 +85,9 @@
|
|||
<string name="settings_gesture_swipe_lambda_reverse">Λ (Reverse)</string>
|
||||
<string name="settings_gesture_description_swipe_lambda_reverse">Bottom right -> top mid -> bottom left</string>
|
||||
|
||||
<string name="settings_gesture_vol_up">Volume Up</string>
|
||||
<string name="settings_gesture_vol_up">Volume Up Key</string>
|
||||
<string name="settings_gesture_description_vol_up">Press the volume up button</string>
|
||||
<string name="settings_gesture_vol_down">Volume Down</string>
|
||||
<string name="settings_gesture_vol_down">Volume Down Key</string>
|
||||
<string name="settings_gesture_description_vol_down">Press the volume down button</string>
|
||||
<string name="settings_gesture_double_click">Double Click</string>
|
||||
<string name="settings_gesture_description_double_click">Double click an empty area</string>
|
||||
|
@ -252,9 +252,11 @@
|
|||
<string name="list_other_track_previous">Music: Previous</string>
|
||||
<string name="list_other_track_play_pause">Music: Play / Pause</string>
|
||||
<string name="list_other_expand_notifications_panel">Expand notifications panel</string>
|
||||
<string name="list_other_recent_apps">Recent Apps</string>
|
||||
<string name="list_other_nop">Do nothing</string>
|
||||
<string name="list_other_lock_screen">Lock Screen</string>
|
||||
<string name="list_other_torch">Toggle Torch</string>
|
||||
<string name="list_other_launch_other_launcher">Launch other Home Screen</string>
|
||||
|
||||
<!-- Pin shortcuts -->
|
||||
<string name="pin_shortcut_title">Add Shortcut</string>
|
||||
|
@ -307,6 +309,8 @@
|
|||
<string name="alert_no_torch_found">No camera with torch detected.</string>
|
||||
<string name="alert_torch_access_exception">Error: Can\'t access torch.</string>
|
||||
<string name="alert_lock_screen_failed">Error: Failed to lock screen. (If you just upgraded the app, try to disable and re-enable the accessibility service in phone settings)</string>
|
||||
<string name="alert_recent_apps_failed">Error: Failed to show recent apps. (If you just upgraded the app, try to disable and re-enable the accessibility service in phone settings)</string>
|
||||
<string name="alert_enable_accessibility_failed">Error: Failed to enable the accessibility service.</string>
|
||||
<string name="toast_accessibility_service_not_enabled">μLauncher\'s accessibility service is not enabled. Please enable it in settings</string>
|
||||
<string name="toast_private_space_locked">Private space locked</string>
|
||||
<string name="toast_private_space_unlocked">Private space unlocked</string>
|
||||
|
@ -315,12 +319,17 @@
|
|||
<string name="tooltip_lock_private_space">Lock private space</string>
|
||||
<string name="tooltip_unlock_private_space">Unlock private space</string>
|
||||
<string name="toast_lock_screen_not_supported">Error: Locking the screen using accessibility is not supported on this device. Please use device admin instead.</string>
|
||||
<string name="accessibility_service_name">μLauncher - lock screen</string>
|
||||
<string name="accessibility_service_name">μLauncher</string>
|
||||
<string name="accessibility_service_description">
|
||||
Setting μLauncher as an accessibility service allows it to lock the screen.
|
||||
Setting μLauncher as an accessibility service allows it to lock the screen and open the recent apps menu.
|
||||
Note that excessive permissions are required. You should never grant such permissions lightly to any app.
|
||||
|
||||
μLauncher will use the accessibility service only for locking the screen. You can check the source code to make sure.
|
||||
μLauncher will use the accessibility service only for performing the following actions when requested by the user:
|
||||
|
||||
* lock screen
|
||||
* open recent apps
|
||||
|
||||
μLauncher will never use the accessibility service to collect data. You can check the source code to make sure.
|
||||
|
||||
Note that locking the screen can also be accomplished by granting μLauncher device administrator permissions. However that method doesn\'t work with fingerprint and face unlock.
|
||||
</string>
|
||||
|
@ -365,7 +374,12 @@
|
|||
<string name="dialog_consent_accessibility_other_options">I am aware that other options exist (using device administrator privileges or the power button).</string>
|
||||
<string name="dialog_consent_accessibility_consent">I consent to μLauncher using the accessibility service to provide functionality unrelated to accessibility.</string>
|
||||
<string name="dialog_consent_accessibility_data_collection">I consent to μLauncher not collecting any data.</string>
|
||||
<string name="dialog_consent_accessibility_text"><![CDATA[You are about to activate the accessibility service. This will grant <strong>far-reaching privileges</strong> to μLauncher.<br/>μLauncher will use these privileges <strong>only to lock the screen</strong>. μLauncher <strong>will never collect any data</strong>. In particular, μLauncher does not use the accessibility service to collect any data.]]></string>
|
||||
<string name="dialog_consent_accessibility_text"><![CDATA[You are about to activate the accessibility service. This will grant <strong>far-reaching privileges</strong> to μLauncher.<br/>μLauncher will use these privileges <strong>only</strong> to perform the following actions:
|
||||
<ul>
|
||||
<li>Lock Screen</li>
|
||||
<li>Recent Apps</li>
|
||||
</ul>
|
||||
μLauncher <strong>will never collect any data</strong>. In particular, μLauncher does not use the accessibility service to collect any data.]]></string>
|
||||
<string name="dialog_consent_accessibility_title">Activating the Accessibility Service</string>
|
||||
<string name="dialog_consent_accessibility_ok">Activate Accessibility Service</string>
|
||||
<string name="dialog_cancel">Cancel</string>
|
||||
|
|
1
fastlane/metadata/android/en-US/changelogs/43.txt
Normal file
1
fastlane/metadata/android/en-US/changelogs/43.txt
Normal file
|
@ -0,0 +1 @@
|
|||
* Fixed gesture detection in landscape orientation
|
Loading…
Add table
Reference in a new issue