Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## [2.8.2](https://github.com/sds100/KeyMapper/releases/tag/v2.8.2)

## Changes

- #1514, #1454 Improving naming of assistant trigger to also refer to the side key and do not force the user to select Key Mapper as the assistant.

## Bug fixes
- #1461 fix: crash on startup due to getting MotionEvent device
-
## [2.8.1](https://github.com/sds100/KeyMapper/releases/tag/v2.8.1)

#### 18 February 2025
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,14 @@
android:theme="@style/AppTheme.NoActionBar"
tools:ignore="GoogleAppIndexingWarning">

<!-- relinquishTaskIdentity is required because the intent-filter has the
DEFAULT category. If relinquishTaskIdentity is false then when the user resumes the
app from the launcher they are taken back to the SplashActivity, and consequently the
home fragment in MainActivity. -->
<activity
android:name=".SplashActivity"
android:exported="true"
android:relinquishTaskIdentity="true"
android:theme="@style/Theme.App.Starting">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,6 @@ class DisplayKeyMapUseCaseImpl(
errors.add(TriggerError.ASSISTANT_TRIGGER_NOT_PURCHASED)
}

val isKeyMapperDeviceAssistant = permissionAdapter.isGranted(Permission.DEVICE_ASSISTANT)

// Show an error if Key Mapper isn't selected as the device assistant
// and an assistant trigger is used. The error shouldn't be shown
// if the assistant trigger feature is not purchased.
if (containsDeviceAssistantTrigger && isAssistantTriggerPurchased && !isKeyMapperDeviceAssistant) {
errors.add(TriggerError.ASSISTANT_NOT_SELECTED)
}

val containsDpadKey = trigger.keys
.mapNotNull { it as? KeyCodeTriggerKey }
.any { InputEventUtils.isDpadKeyCode(it.keyCode) && it.detectionSource == KeyEventDetectionSource.INPUT_METHOD }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,6 @@ class KeyMapListItemCreator(
error = Error.CantDetectKeyEventsInPhoneCall,
)

TriggerError.ASSISTANT_NOT_SELECTED -> ChipUi.Error(
id = error.toString(),
text = getString(R.string.trigger_error_assistant_activity_not_chosen),
error = Error.PermissionDenied(Permission.DEVICE_ASSISTANT),
)

TriggerError.ASSISTANT_TRIGGER_NOT_PURCHASED -> ChipUi.Error(
id = error.toString(),
text = getString(R.string.trigger_error_assistant_not_purchased),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.sds100.keymapper.mappings.keymaps.detection

import android.view.KeyEvent
import io.github.sds100.keymapper.system.devices.InputDeviceInfo
import io.github.sds100.keymapper.system.inputevents.InputEventUtils
import io.github.sds100.keymapper.system.inputevents.MyKeyEvent
import io.github.sds100.keymapper.system.inputevents.MyMotionEvent
Expand Down Expand Up @@ -62,11 +63,11 @@ class DpadMotionEventTracker {
* @return An array of key events. Empty if no DPAD buttons changed.
*/
fun convertMotionEvent(event: MyMotionEvent): List<MyKeyEvent> {
val oldState = dpadState[event.device.descriptor] ?: 0
val oldState = dpadState[event.device.getDescriptor()] ?: 0
val newState = eventToDpadState(event)
val diff = oldState xor newState

dpadState[event.device.descriptor] = newState
dpadState[event.device.getDescriptor()] = newState

// If no dpad keys changed then return null
if (diff == 0) {
Expand Down Expand Up @@ -114,6 +115,10 @@ class DpadMotionEventTracker {
dpadState.clear()
}

private fun InputDeviceInfo?.getDescriptor(): String {
return this?.descriptor ?: ""
}

private fun eventToDpadState(event: MyMotionEvent): Int {
var state = 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,6 @@ abstract class BaseConfigTriggerViewModel(
text = getString(R.string.trigger_error_cant_detect_in_phone_call),
)

TriggerError.ASSISTANT_NOT_SELECTED -> TextListItem.Error(
id = error.toString(),
text = getString(R.string.trigger_error_assistant_activity_not_chosen),
)

TriggerError.ASSISTANT_TRIGGER_NOT_PURCHASED -> TextListItem.Error(
id = error.toString(),
text = getString(R.string.trigger_error_assistant_not_purchased),
Expand Down Expand Up @@ -521,10 +516,6 @@ abstract class BaseConfigTriggerViewModel(
displayKeyMap.fixError(Error.CantDetectKeyEventsInPhoneCall)
}

TriggerError.ASSISTANT_NOT_SELECTED -> {
displayKeyMap.fixError(Error.PermissionDenied(Permission.DEVICE_ASSISTANT))
}

TriggerError.ASSISTANT_TRIGGER_NOT_PURCHASED -> {
showAdvancedTriggersBottomSheet = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ enum class TriggerError {
SCREEN_OFF_ROOT_DENIED,
CANT_DETECT_IN_PHONE_CALL,

// Key Mapper is not selected as the assistant activity. This is required for assistant
// triggers.
ASSISTANT_NOT_SELECTED,

// This error appears when a key map has an assistant trigger but the user hasn't purchased
// the product.
ASSISTANT_TRIGGER_NOT_PURCHASED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,7 @@ class MyAccessibilityService :
override fun onKeyEvent(event: KeyEvent?): Boolean {
event ?: return false

val device = if (event.device == null) {
null
} else {
InputDeviceUtils.createInputDeviceInfo(event.device)
}
val device = event.device?.let { InputDeviceUtils.createInputDeviceInfo(it) }

if (controller != null) {
return controller!!.onKeyEventFromIme(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import io.github.sds100.keymapper.system.devices.InputDeviceUtils
*/
data class MyMotionEvent(
val metaState: Int,
val device: InputDeviceInfo,
val device: InputDeviceInfo?,
val axisHatX: Float,
val axisHatY: Float,
val isDpad: Boolean,
Expand All @@ -19,7 +19,7 @@ data class MyMotionEvent(
fun fromMotionEvent(event: MotionEvent): MyMotionEvent {
return MyMotionEvent(
metaState = event.metaState,
device = InputDeviceUtils.createInputDeviceInfo(event.device),
device = event.device?.let { InputDeviceUtils.createInputDeviceInfo(it) },
axisHatX = event.getAxisValue(MotionEvent.AXIS_HAT_X),
axisHatY = event.getAxisValue(MotionEvent.AXIS_HAT_Y),
isDpad = InputEventUtils.isDpadDevice(event),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ import io.github.sds100.keymapper.system.apps.PackageManagerAdapter
import io.github.sds100.keymapper.system.root.SuAdapter
import io.github.sds100.keymapper.util.Error
import io.github.sds100.keymapper.util.Result
import io.github.sds100.keymapper.util.Success
import io.github.sds100.keymapper.util.getIdentifier
import io.github.sds100.keymapper.util.onFailure
import io.github.sds100.keymapper.util.onSuccess
import io.github.sds100.keymapper.util.success
import io.github.sds100.keymapper.util.then
import io.github.sds100.keymapper.util.valueIfFailure
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
Expand Down Expand Up @@ -338,11 +335,6 @@ class AndroidPermissionAdapter(
} else {
true
}

Permission.DEVICE_ASSISTANT ->
packageManagerAdapter.getDeviceAssistantPackage()
.then { Success(it == Constants.PACKAGE_NAME) }
.valueIfFailure { false }
}

override fun isGrantedFlow(permission: Permission): Flow<Boolean> = callbackFlow {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ enum class Permission {
ANSWER_PHONE_CALL,
FIND_NEARBY_DEVICES,
POST_NOTIFICATIONS,
DEVICE_ASSISTANT,
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,6 @@ class RequestPermissionDelegate(
Permission.POST_NOTIFICATIONS -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}

Permission.DEVICE_ASSISTANT -> {
try {
Intent(Settings.ACTION_VOICE_INPUT_SETTINGS).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivityForResultLauncher.launch(this)
}
} catch (e: ActivityNotFoundException) {
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ sealed class Error : Result<Nothing>() {
Permission.ANSWER_PHONE_CALL -> R.string.error_answer_end_phone_call_permission_denied
Permission.FIND_NEARBY_DEVICES -> R.string.error_find_nearby_devices_permission_denied
Permission.POST_NOTIFICATIONS -> R.string.error_notifications_permission_denied
Permission.DEVICE_ASSISTANT -> R.string.trigger_error_assistant_activity_not_chosen_short
}

return resourceProvider.getString(resId)
Expand Down
9 changes: 0 additions & 9 deletions app/src/main/res/values-pl/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1057,17 +1057,8 @@
<!-- About -->
<!-- Advanced triggers -->
<string name="assistant_any_trigger_name">Dowolny asystent</string>
<string name="assistant_device_trigger_name">Asystent urządzenia</string>
<string name="assistant_voice_trigger_name">Asystent głosowy</string>
<string name="advanced_triggers_sheet_title">Zaawansowane wyzwalacze</string>
<string name="advanced_triggers_sheet_text">Programista nie wierzy, że reklamy są zrównoważoną lub przyjazną użytkownikowi formą monetyzacji, więc te płatne wyzwalacze pomagają wspierać rozwój ❤️. Otrzymasz również priorytetowe wsparcie.</string>
<string name="assistant_trigger_product_title">Wyzwalacz asystenta</string>
<string name="assistant_trigger_product_description">Czy wiesz, że możesz zmienić przycisk asystenta urządzenia? Zamiast uruchamiać asystenta Google lub Bixby, urządzenie może wykonać niestandardową akcję. Działa nawet, gdy ekran jest wyłączony!</string>
<string name="assistant_trigger_purchase_thank_you_title">Dziękujemy za wsparcie aplikacji! ❤️</string>
<string name="assistant_trigger_purchase_thank_you_message">Zakup zakończył się sukcesem i teraz możesz używać wyzwalaczy asystenta. Jako płatny użytkownik Key Mapper otrzymasz priorytetową pomoc w korzystaniu z aplikacji. Na tej stronie znajduje się teraz przycisk, aby skontaktować się z programistą.</string>
<string name="trigger_error_assistant_activity_not_chosen">Aby ten wyzwalacz działał, musisz ustawić Key Mapper jako domyślną aplikację asystenta cyfrowego.</string>
<string name="trigger_error_assistant_activity_not_chosen_short">Key Mapper musi być domyślnym asystentem.</string>
<string name="trigger_error_assistant_not_purchased">Musisz kupić funkcję wyzwalacza asystenta!</string>
<string name="advanced_triggers_learn_more_button">Dowiedz się więcej</string>
<string name="notification_assistant_trigger_feature_title">Nowy wyzwalacz! Czy wiesz, że możesz zmienić przycisk asystenta?</string>
<string name="notification_assistant_trigger_feature_text">Zamiast uruchamiać Asystenta Google lub Bixby, możesz wykonać wybrane działanie. Kliknij, aby dowiedzieć się więcej.</string>
Expand Down
9 changes: 0 additions & 9 deletions app/src/main/res/values-vi/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1035,17 +1035,8 @@
<!-- About -->
<!-- Advanced triggers -->
<string name="assistant_any_trigger_name">Trợ lý bất kỳ</string>
<string name="assistant_device_trigger_name">Trợ lý thiết bị</string>
<string name="assistant_voice_trigger_name">Trợ lý giọng nói</string>
<string name="advanced_triggers_sheet_title">Trình kích hoạt nâng cao</string>
<string name="advanced_triggers_sheet_text">Nhà phát triển không tin rằng quảng cáo là hình thức kiếm tiền bền vững hoặc thân thiện với người dùng nên những trình kích hoạt trả phí này sẽ giúp hỗ trợ sự phát triển ❤️. Bạn cũng sẽ được ưu tiên hỗ trợ.</string>
<string name="assistant_trigger_product_title">Trình kích hoạt trợ lý</string>
<string name="assistant_trigger_product_description">Bạn có biết bạn có thể ánh xạ lại trợ lý thiết bị của mình không? Thay vì khởi chạy Google Assistant hoặc Bixby, thiết bị của bạn có thể thực hiện hành động mà bạn chọn. Nó hoạt động ngay cả khi màn hình tắt!</string>
<string name="assistant_trigger_purchase_thank_you_title">Cảm ơn bạn đã ủng hộ ứng dụng! ❤️</string>
<string name="assistant_trigger_purchase_thank_you_message">Giao dịch mua hàng của bạn đã thành công và bây giờ bạn có thể sử dụng trình kích hoạt trợ lý. Là người dùng trả phí của Key Mapper, bạn sẽ nhận được hỗ trợ ưu tiên để giúp bạn sử dụng ứng dụng. Hiện tại có một nút trên trang này để liên hệ với nhà phát triển.</string>
<string name="trigger_error_assistant_activity_not_chosen">Bạn phải chọn Key Mapper làm ứng dụng trợ lý kỹ thuật số mặc định để trình kích hoạt này hoạt động.</string>
<string name="trigger_error_assistant_activity_not_chosen_short">Key Mapper phải là trợ lý mặc định.</string>
<string name="trigger_error_assistant_not_purchased">Bạn phải mua tính năng kích hoạt trợ lý!</string>
<string name="advanced_triggers_learn_more_button">Tìm hiểu thêm</string>
<string name="notification_assistant_trigger_feature_title">Kích hoạt mới! Bạn có biết bạn có thể sắp xếp lại trợ lý kỹ thuật số của mình không?</string>
<string name="notification_assistant_trigger_feature_text">Thay vì khởi chạy Google Assistant hoặc Bixby, bạn có thể thực hiện hành động mà mình chọn. Nhấn để tìm hiểu thêm.</string>
Expand Down
17 changes: 8 additions & 9 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1402,18 +1402,17 @@
<!-- About -->

<!-- Advanced triggers -->
<string name="assistant_activity_name">Key Mapper: side key</string>
<string name="assistant_any_trigger_name">Any assistant</string>
<string name="assistant_device_trigger_name">Device assistant</string>
<string name="assistant_device_trigger_name">Side key/power button</string>
<string name="assistant_voice_trigger_name">Voice assistant</string>
<string name="advanced_triggers_sheet_title">Advanced triggers</string>
<string name="advanced_triggers_sheet_text">The developer doesn\'t believe ads are a sustainable or user-friendly form of monetization so these paid triggers help support development ❤️. You will be given priority support as well.</string>
<string name="assistant_trigger_product_title">Assistant trigger</string>
<string name="assistant_trigger_product_description">Did you know you can remap your device assistant? Instead of launching Google Assistant or Bixby, your device can perform an action of your choice. It works even when the screen is off!</string>
<string name="assistant_trigger_purchase_thank_you_title">Thank you for supporting the app! ❤️</string>
<string name="assistant_trigger_purchase_thank_you_message">Your purchase was successful and you can now use the assistant triggers. As a paying user of Key Mapper you will receive priority support to help you use the app. There is now a button on this page to contact the developer.</string>
<string name="trigger_error_assistant_activity_not_chosen">You must select Key Mapper as the default digital assistant app for this trigger to work.</string>
<string name="trigger_error_assistant_activity_not_chosen_short">Key Mapper must be the default assistant.</string>
<string name="trigger_error_assistant_not_purchased">You must purchase the assistant trigger feature!</string>
<string name="advanced_triggers_sheet_text">The developer doesn\'t believe ads are a sustainable or user-friendly form of monetization so these paid triggers help support development\u00A0❤️. You will be given priority support as well.</string>
<string name="assistant_trigger_product_title">Side\u00A0key &amp; Assistant trigger</string>
<string name="assistant_trigger_product_description">Did you know you can remap your side key, power button, or device assistant? Instead of launching the assistant or the power menu, your device can perform an action of your choice. It works even when the screen is off!</string>
<string name="assistant_trigger_purchase_thank_you_title">Thank you for supporting the app\u00A0❤️!</string>
<string name="assistant_trigger_purchase_thank_you_message">Your purchase was successful. As a paying user of Key\u00A0Mapper you will receive priority support to help you use the app. There is now a button on this page to contact the developer.</string>
<string name="trigger_error_assistant_not_purchased">You must purchase the assistant trigger feature.</string>
<string name="advanced_triggers_learn_more_button">Learn more</string>
<string name="notification_assistant_trigger_feature_title">New trigger! Did you know you can remap your digital assistant?</string>
<string name="notification_assistant_trigger_feature_text">Instead of launching Google Assistant or Bixby, you can perform an action of your choice. Tap to learn more.</string>
Expand Down
4 changes: 2 additions & 2 deletions app/version.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
VERSION_NAME=2.8.1
VERSION_CODE=72
VERSION_NAME=2.8.2
VERSION_CODE=73
VERSION_NUM=0