diff --git a/CHANGELOG.md b/CHANGELOG.md
index f41e8d4d67..40db86abda 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+## [4.0.2](https://github.com/sds100/KeyMapper/releases/tag/v4.0.2)
+
+#### 04 February 2026
+
+## Added
+
+- Added Chinese Simplified translations.
+
+## Removed
+
+- [#1973](https://github.com/keymapperorg/KeyMapper/issues/1973) [#2006](https://github.com/keymapperorg/KeyMapper/issues/2006) Removed language switching feature due to crash with no solution.
+
## [4.0.1](https://github.com/sds100/KeyMapper/releases/tag/v4.0.1)
#### 01 February 2026
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index a0083b73db..7d234f10e3 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -91,10 +91,6 @@ android {
}
}
- androidResources {
- generateLocaleConfig = true
- }
-
buildFeatures {
dataBinding = true
aidl = true
diff --git a/app/src/main/res/resources.properties b/app/src/main/res/resources.properties
deleted file mode 100644
index d5a3ddc92a..0000000000
--- a/app/src/main/res/resources.properties
+++ /dev/null
@@ -1 +0,0 @@
-unqualifiedResLocale=en-US
\ No newline at end of file
diff --git a/app/version.properties b/app/version.properties
index a40000211d..cd9ef648b2 100644
--- a/app/version.properties
+++ b/app/version.properties
@@ -1,2 +1,2 @@
-VERSION_NAME=4.0.1
-VERSION_CODE=241
+VERSION_NAME=4.0.2
+VERSION_CODE=242
diff --git a/base/src/main/AndroidManifest.xml b/base/src/main/AndroidManifest.xml
index 7b945089d6..faddfc687d 100644
--- a/base/src/main/AndroidManifest.xml
+++ b/base/src/main/AndroidManifest.xml
@@ -5,7 +5,7 @@
-
+
-
-
-
-
\ No newline at end of file
diff --git a/base/src/main/java/io/github/sds100/keymapper/base/BaseMainActivity.kt b/base/src/main/java/io/github/sds100/keymapper/base/BaseMainActivity.kt
index b8b86e3a43..b726317db1 100644
--- a/base/src/main/java/io/github/sds100/keymapper/base/BaseMainActivity.kt
+++ b/base/src/main/java/io/github/sds100/keymapper/base/BaseMainActivity.kt
@@ -29,7 +29,6 @@ import io.github.sds100.keymapper.base.input.InputEventDetectionSource
import io.github.sds100.keymapper.base.input.InputEventHubImpl
import io.github.sds100.keymapper.base.keymaps.ConfigKeyMapStateImpl
import io.github.sds100.keymapper.base.onboarding.OnboardingUseCase
-import io.github.sds100.keymapper.base.settings.AppLocaleAdapterImpl
import io.github.sds100.keymapper.base.system.accessibility.AccessibilityServiceAdapterImpl
import io.github.sds100.keymapper.base.system.permissions.RequestPermissionDelegate
import io.github.sds100.keymapper.base.utils.navigation.NavigationProvider
@@ -105,9 +104,6 @@ abstract class BaseMainActivity : AppCompatActivity() {
@Inject
lateinit var configKeyMapState: ConfigKeyMapStateImpl
- @Inject
- lateinit var appLocaleAdapter: AppLocaleAdapterImpl
-
private lateinit var requestPermissionDelegate: RequestPermissionDelegate
private val currentNightMode: Int
@@ -205,7 +201,6 @@ abstract class BaseMainActivity : AppCompatActivity() {
systemBridgeSetupController.invalidateSettings()
networkAdapter.invalidateState()
onboardingUseCase.handledMigrateScreenOffKeyMapsNotification()
- appLocaleAdapter.invalidate()
}
override fun onSaveInstanceState(outState: Bundle) {
diff --git a/base/src/main/java/io/github/sds100/keymapper/base/BaseSingletonHiltModule.kt b/base/src/main/java/io/github/sds100/keymapper/base/BaseSingletonHiltModule.kt
index ad7fb1ee08..435a7e3265 100644
--- a/base/src/main/java/io/github/sds100/keymapper/base/BaseSingletonHiltModule.kt
+++ b/base/src/main/java/io/github/sds100/keymapper/base/BaseSingletonHiltModule.kt
@@ -30,8 +30,6 @@ import io.github.sds100.keymapper.base.onboarding.OnboardingUseCase
import io.github.sds100.keymapper.base.onboarding.OnboardingUseCaseImpl
import io.github.sds100.keymapper.base.onboarding.SetupAccessibilityServiceDelegate
import io.github.sds100.keymapper.base.onboarding.SetupAccessibilityServiceDelegateImpl
-import io.github.sds100.keymapper.base.settings.AppLocaleAdapter
-import io.github.sds100.keymapper.base.settings.AppLocaleAdapterImpl
import io.github.sds100.keymapper.base.system.accessibility.AccessibilityServiceAdapterImpl
import io.github.sds100.keymapper.base.system.accessibility.ControlAccessibilityServiceUseCase
import io.github.sds100.keymapper.base.system.accessibility.ControlAccessibilityServiceUseCaseImpl
@@ -210,8 +208,4 @@ abstract class BaseSingletonHiltModule {
@Binds
@Singleton
abstract fun bindClock(impl: ClockImpl): Clock
-
- @Binds
- @Singleton
- abstract fun bindAppLocaleAdapter(impl: AppLocaleAdapterImpl): AppLocaleAdapter
}
diff --git a/base/src/main/java/io/github/sds100/keymapper/base/expertmode/ExpertModeScreen.kt b/base/src/main/java/io/github/sds100/keymapper/base/expertmode/ExpertModeScreen.kt
index 5bd52a8319..bf25890a53 100644
--- a/base/src/main/java/io/github/sds100/keymapper/base/expertmode/ExpertModeScreen.kt
+++ b/base/src/main/java/io/github/sds100/keymapper/base/expertmode/ExpertModeScreen.kt
@@ -516,7 +516,7 @@ private fun IncompatibleUsbModeCard(modifier: Modifier = Modifier) {
SettingsUtils.launchSettingsScreen(
ctx,
Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS,
- fragmentArg = "default_usb_configuration",
+ "default_usb_configuration",
)
},
)
diff --git a/base/src/main/java/io/github/sds100/keymapper/base/settings/AppLocaleAdapter.kt b/base/src/main/java/io/github/sds100/keymapper/base/settings/AppLocaleAdapter.kt
deleted file mode 100644
index ccb95a58e9..0000000000
--- a/base/src/main/java/io/github/sds100/keymapper/base/settings/AppLocaleAdapter.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-package io.github.sds100.keymapper.base.settings
-
-import android.content.Context
-import android.os.Build
-import android.provider.Settings
-import androidx.annotation.RequiresApi
-import androidx.appcompat.app.AppCompatDelegate
-import androidx.core.net.toUri
-import androidx.core.os.LocaleListCompat
-import dagger.hilt.android.qualifiers.ApplicationContext
-import io.github.sds100.keymapper.base.R
-import io.github.sds100.keymapper.common.utils.SettingsUtils
-import javax.inject.Inject
-import javax.inject.Singleton
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-
-@Singleton
-class AppLocaleAdapterImpl @Inject constructor(
- @param:ApplicationContext private val ctx: Context,
-) : AppLocaleAdapter {
-
- private val _currentLocaleDisplayName = MutableStateFlow(getLocaleDisplayName())
- override val currentLocaleDisplayName: StateFlow =
- _currentLocaleDisplayName.asStateFlow()
-
- fun invalidate() {
- _currentLocaleDisplayName.value = getLocaleDisplayName()
- }
-
- private fun getLocaleDisplayName(): String? {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
- return null
- }
-
- val locales = AppCompatDelegate.getApplicationLocales()
- return if (locales.isEmpty) {
- ctx.getString(R.string.language_system_default)
- } else {
- locales.get(0)?.displayName
- }
- }
-
- override fun launchAppLocaleSettingsScreen(): Boolean {
- return SettingsUtils.launchSettingsScreen(
- ctx,
- Settings.ACTION_APP_LOCALE_SETTINGS,
- uri = "package:${ctx.packageName}".toUri(),
- )
- }
-
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- override fun getSupportedLocales(): List {
- return buildList {
- val localeList = AppCompatDelegate.getApplicationLocales()
- for (i in 0 until localeList.size()) {
- val locale = localeList.get(i) ?: continue
-
- add(AppLocaleOption(locale.toLanguageTag(), locale.displayName))
- }
- }
- }
-
- override fun getCurrentLocale(): String? {
- val locales = AppCompatDelegate.getApplicationLocales()
- return if (locales.isEmpty) {
- null
- } else {
- locales.toLanguageTags()
- }
- }
-
- override fun setLocale(localeTag: String?) {
- val localeList = if (localeTag.isNullOrEmpty()) {
- LocaleListCompat.getEmptyLocaleList()
- } else {
- LocaleListCompat.forLanguageTags(localeTag)
- }
- AppCompatDelegate.setApplicationLocales(localeList)
- }
-}
-
-/**
- * Represents a locale option for the language picker.
- * @param tag The locale tag (e.g., "en", "pt") or null for system default.
- * @param displayName The display name shown to users.
- */
-data class AppLocaleOption(val tag: String?, val displayName: String)
-
-/**
- * Adapter to manage app locale settings using AndroidX AppCompatDelegate.
- * This integrates with Android 13+ per-app language preferences and provides
- * backward compatibility for older Android versions.
- */
-interface AppLocaleAdapter {
- /**
- * The display name of the current locale, or null if not supported (Android < 13).
- */
- val currentLocaleDisplayName: StateFlow
-
- fun launchAppLocaleSettingsScreen(): Boolean
-
- /**
- * Get list of supported locales by parsing the locales_config.xml file.
- * Returns a list of AppLocaleOption with locale tag and display name.
- */
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- fun getSupportedLocales(): List
-
- /**
- * Get the currently selected locale tag, or null if using system default.
- */
- fun getCurrentLocale(): String?
-
- /**
- * Set the app locale.
- * @param localeTag The locale tag (e.g., "en", "pt", "tr") or null for system default.
- */
- fun setLocale(localeTag: String?)
-}
diff --git a/base/src/main/java/io/github/sds100/keymapper/base/settings/ConfigSettingsUseCase.kt b/base/src/main/java/io/github/sds100/keymapper/base/settings/ConfigSettingsUseCase.kt
index 306571de8c..d4305fd7a7 100644
--- a/base/src/main/java/io/github/sds100/keymapper/base/settings/ConfigSettingsUseCase.kt
+++ b/base/src/main/java/io/github/sds100/keymapper/base/settings/ConfigSettingsUseCase.kt
@@ -1,14 +1,10 @@
package io.github.sds100.keymapper.base.settings
-import android.os.Build
-import androidx.annotation.RequiresApi
import androidx.datastore.preferences.core.Preferences
-import dagger.hilt.android.scopes.ViewModelScoped
import io.github.sds100.keymapper.base.actions.sound.SoundFileInfo
import io.github.sds100.keymapper.base.actions.sound.SoundsManager
import io.github.sds100.keymapper.base.system.inputmethod.KeyMapperImeHelper
import io.github.sds100.keymapper.base.system.inputmethod.SwitchImeInterface
-import io.github.sds100.keymapper.base.utils.ui.ResourceProvider
import io.github.sds100.keymapper.common.BuildConfigProvider
import io.github.sds100.keymapper.common.utils.InputDeviceInfo
import io.github.sds100.keymapper.common.utils.KMResult
@@ -34,7 +30,6 @@ import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map
-@ViewModelScoped
class ConfigSettingsUseCaseImpl @Inject constructor(
private val preferences: PreferenceRepository,
private val permissionAdapter: PermissionAdapter,
@@ -47,8 +42,6 @@ class ConfigSettingsUseCaseImpl @Inject constructor(
private val devicesAdapter: DevicesAdapter,
private val buildConfigProvider: BuildConfigProvider,
private val notificationAdapter: NotificationAdapter,
- private val appLocaleAdapter: AppLocaleAdapter,
- private val resourceProvider: ResourceProvider,
) : ConfigSettingsUseCase {
private val imeHelper by lazy {
@@ -201,20 +194,6 @@ class ConfigSettingsUseCaseImpl @Inject constructor(
override fun openNotificationChannelSettings(channelId: String) {
notificationAdapter.openChannelSettings(channelId)
}
-
- override val currentLocaleDisplayName: StateFlow =
- appLocaleAdapter.currentLocaleDisplayName
-
- override fun launchAppLocaleSettingsScreen(): Boolean =
- appLocaleAdapter.launchAppLocaleSettingsScreen()
-
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- override fun getSupportedLocales(): List =
- appLocaleAdapter.getSupportedLocales()
-
- override fun setLocale(localeTag: String?) {
- appLocaleAdapter.setLocale(localeTag)
- }
}
interface ConfigSettingsUseCase {
@@ -260,13 +239,4 @@ interface ConfigSettingsUseCase {
val connectedInputDevices: StateFlow>>
fun resetAllSettings()
-
- // Locale settings (Android 13+ only)
- val currentLocaleDisplayName: StateFlow
- fun launchAppLocaleSettingsScreen(): Boolean
-
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- fun getSupportedLocales(): List
-
- fun setLocale(localeTag: String?)
}
diff --git a/base/src/main/java/io/github/sds100/keymapper/base/settings/SettingsScreen.kt b/base/src/main/java/io/github/sds100/keymapper/base/settings/SettingsScreen.kt
index 625475e0b9..9cbcb0ed7a 100644
--- a/base/src/main/java/io/github/sds100/keymapper/base/settings/SettingsScreen.kt
+++ b/base/src/main/java/io/github/sds100/keymapper/base/settings/SettingsScreen.kt
@@ -24,7 +24,6 @@ import androidx.compose.material.icons.outlined.Android
import androidx.compose.material.icons.outlined.BugReport
import androidx.compose.material.icons.outlined.FindInPage
import androidx.compose.material.icons.outlined.Gamepad
-import androidx.compose.material.icons.outlined.Language
import androidx.compose.material.icons.outlined.OfflineBolt
import androidx.compose.material.icons.rounded.Code
import androidx.compose.material.icons.rounded.Construction
@@ -79,12 +78,10 @@ import kotlinx.coroutines.launch
private val isExpertModeSupported = Build.VERSION.SDK_INT >= Constants.SYSTEM_BRIDGE_MIN_API
private val isAutoSwitchImeSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
-private val isLanguageSettingsSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
@Composable
fun SettingsScreen(modifier: Modifier = Modifier, viewModel: SettingsViewModel) {
val state by viewModel.mainScreenState.collectAsStateWithLifecycle()
- val currentLocaleDisplayName by viewModel.currentLocaleDisplayName.collectAsStateWithLifecycle()
val snackbarHostState = SnackbarHostState()
var showAutomaticBackupDialog by remember { mutableStateOf(false) }
val context = LocalContext.current
@@ -149,8 +146,6 @@ fun SettingsScreen(modifier: Modifier = Modifier, viewModel: SettingsViewModel)
) {
Content(
state = state,
- currentLocaleDisplayName = currentLocaleDisplayName ?: "",
- onLanguageClick = viewModel::onLanguageClick,
onThemeSelected = viewModel::onThemeSelected,
onPauseResumeNotificationClick = viewModel::onPauseResumeNotificationClick,
onDefaultOptionsClick = viewModel::onDefaultOptionsClick,
@@ -246,8 +241,6 @@ private fun SettingsScreen(
private fun Content(
modifier: Modifier = Modifier,
state: MainSettingsState,
- currentLocaleDisplayName: String = "",
- onLanguageClick: () -> Unit = { },
onThemeSelected: (Theme) -> Unit = { },
onPauseResumeNotificationClick: () -> Unit = { },
onDefaultOptionsClick: () -> Unit = { },
@@ -294,21 +287,6 @@ private fun Content(
onStateSelected = onThemeSelected,
)
- OptionPageButton(
- title = stringResource(R.string.title_pref_language),
- text = if (isLanguageSettingsSupported) {
- currentLocaleDisplayName
- } else {
- stringResource(
- R.string.error_sdk_version_too_low,
- BuildUtils.getSdkVersionName(Build.VERSION_CODES.TIRAMISU),
- )
- },
- icon = Icons.Outlined.Language,
- onClick = onLanguageClick,
- enabled = isLanguageSettingsSupported,
- )
-
OptionPageButton(
title = stringResource(R.string.title_pref_show_toggle_keymaps_notification),
text = stringResource(R.string.summary_pref_show_toggle_keymaps_notification),
@@ -494,7 +472,6 @@ private fun Preview() {
SettingsScreen(modifier = Modifier.fillMaxSize(), onBackClick = {}) {
Content(
state = MainSettingsState(),
- currentLocaleDisplayName = "System default",
)
}
}
diff --git a/base/src/main/java/io/github/sds100/keymapper/base/settings/SettingsViewModel.kt b/base/src/main/java/io/github/sds100/keymapper/base/settings/SettingsViewModel.kt
index 74896e05a7..7628eb1edc 100644
--- a/base/src/main/java/io/github/sds100/keymapper/base/settings/SettingsViewModel.kt
+++ b/base/src/main/java/io/github/sds100/keymapper/base/settings/SettingsViewModel.kt
@@ -110,17 +110,6 @@ class SettingsViewModel @Inject constructor(
)
}.stateIn(viewModelScope, SharingStarted.Lazily, AutomaticChangeImeSettingsState())
- /**
- * The display name of the currently selected locale, or null if not supported (Android < 13).
- */
- val currentLocaleDisplayName: StateFlow = useCase.currentLocaleDisplayName
-
- fun onLanguageClick() {
- viewModelScope.launch {
- useCase.launchAppLocaleSettingsScreen()
- }
- }
-
fun setAutomaticBackupLocation(uri: String) = useCase.setAutomaticBackupLocation(uri)
fun disableAutomaticBackup() = useCase.disableAutomaticBackup()
@@ -178,6 +167,10 @@ class SettingsViewModel @Inject constructor(
}
}
+ fun onRequestRootClick() {
+ useCase.requestRootPermission()
+ }
+
fun onExpertModeClick() {
viewModelScope.launch {
navigate("expert_mode_settings", NavDestination.ExpertMode)
diff --git a/base/src/main/java/io/github/sds100/keymapper/base/trigger/TriggerSetupBottomSheet.kt b/base/src/main/java/io/github/sds100/keymapper/base/trigger/TriggerSetupBottomSheet.kt
index c00cb0f19b..1131d4f5a1 100644
--- a/base/src/main/java/io/github/sds100/keymapper/base/trigger/TriggerSetupBottomSheet.kt
+++ b/base/src/main/java/io/github/sds100/keymapper/base/trigger/TriggerSetupBottomSheet.kt
@@ -42,6 +42,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
@@ -64,6 +65,7 @@ import io.github.sds100.keymapper.base.utils.ui.compose.icons.IndeterminateQuest
import io.github.sds100.keymapper.base.utils.ui.compose.icons.KeyMapperIcons
import io.github.sds100.keymapper.base.utils.ui.compose.icons.ModeOffOn
import io.github.sds100.keymapper.base.utils.ui.compose.icons.SportsEsports
+import io.github.sds100.keymapper.base.utils.ui.compose.openUriSafe
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@@ -553,12 +555,13 @@ private fun NotDetectedSetupBottomSheet(
)
val uriHandler = LocalUriHandler.current
+ val ctx = LocalContext.current
val helpUrl = stringResource(R.string.url_discord_server_invite)
Button(
modifier = Modifier.align(Alignment.CenterHorizontally),
onClick = {
- uriHandler.openUri(helpUrl)
+ uriHandler.openUriSafe(ctx, helpUrl)
},
colors = ButtonDefaults.buttonColors(
containerColor = LocalCustomColorsPalette.current.discord,
diff --git a/base/src/main/res/values-zh-rCN/strings.xml b/base/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..80e29f3c39
--- /dev/null
+++ b/base/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,1585 @@
+
+
+ 释放你的按键潜能!
+ Key Mapper需要无障碍权限,以便检测并更改您在本应用之外的操作。必须授予无障碍权限才能创建和测试触发器,并使按键映射生效。
+ 已选择
+ 启用
+ ¯\\_(ツ)_/¯\n\n这里什么都没有!
+ 需要ROOT权限
+ 无操作
+ 无触发器
+ 未知设备名称
+ 打开
+ 关闭
+ 跟随系统
+ 此设备
+ 任何设备
+ 默认
+ 启用无障碍服务
+ 重启无障碍服务
+ 分享
+ 这里什么都没有!
+ Key Mapper 未检测到任何交互。请尝试显示更多元素。
+ 停止重复当…
+ 触发器被松开
+ 触发器被再次按下
+ 次数达到上限
+ 触发器被松开
+ 触发器被再次按下
+ 显示隐藏的应用
+ 修饰键
+ 重要提示!!!只有当屏幕旋转方向与截图一致时,这些坐标才是准确的。执行此动作会取消当前屏幕上正在进行的所有触控或手势。\n\n如果你不确定如何获取坐标,可以先截一张图,然后直接在截图上点击目标所在的位置。
+ 注意:使用“缩小”时,X 和 Y 代表结束坐标;使用“放大”时,X 和 Y 代表起始坐标。
+ 点击操作以修复!
+ 点击条件以修复!
+ 执行动作
+ 长按直到触发器…
+ 没有设备
+ ¯\\_(ツ)_/¯\n\n无扩展!
+ 完成按键事件配置
+ 完成坐标选择
+ Key Mapper 日志
+ 最新更新
+ 您可以选择系统铃声,也可以选择自定义音频文件。\n\n自定义音频文件将被复制到 Key Mapper 的私有数据文件夹中。这意味着即使原始文件被移动或删除,您的操作仍可正常触发。此外,该文件也会包含在按键映射备份的压缩包内,您可以在设置中删除已保存的音频文件
+ 找不到任何已配对的设备。蓝牙开启了吗?
+ 点击一个按键映射作为快捷键使用。
+ 创建按键映射快捷键
+ 已启用
+ 已禁用
+ 重置
+ 启用设备管理员后,如果要 Key Mapper,您必须先停用它。
+ 等待 %sms
+ 启动活动: %s
+ 启动服务: %s
+ 发送广播: %s
+ 按键映射id
+ 需要权限以在 ”免打扰” 模式下运行!
+ 此触发器在响铃或通话时失效!
+ 当您的手机响铃或处于通话中时,安卓系统会限制辅助功能服务检测音量键的操作,但输入法服务仍可检测。因此,若要使此触发器生效,请您使用键映射器输入法。
+ 由于 Android 的限制,需要多指才能执行手势
+ 由于 Android 的限制,手势持续时间不能过长。
+ 若要使 DPAD 触发器生效,您必须使用键映射器输入法!
+ 专家模式在当前安卓版本中不可用
+ 专家模式未启用!
+ 需要连接触发器设备!
+ 迁移此屏幕关闭触发器
+ 关闭电池优化
+ 你的按键映射已暂停!
+ 取消暂停
+ 需要开启无障碍服务才能使你的按键映射正常工作!
+ 您的手机在后台关闭了 Key Mapper,或者它崩溃了!
+ 无障碍服务已启用!你的按键映射将会工作。
+ 额外日志已开启!如果您没有在解决问题,请关闭它。
+ 关闭
+ 开启通知以获得更好的屏幕消息、更多操作和服务更新。
+ 关于
+
+ 打开 %s
+ 输入 \'%s\'
+ 输入 %s%s
+ 输入 %s%s 来自 %s
+ 打开 %s
+ 点击屏幕 (%d, %d)
+ 点击屏幕 (%s)
+ 用 %d 根手指从 (%d,%d) 划至 (%d,%d),动作耗时 %d 毫秒
+ 以 %d 根手指从 (%d,%d) 划至 (%d,%d),动作耗时 %d 毫秒 (%s)
+ 用 %d 根手指在 (%d,%d) 处进行 %s操作,缩放 %d 像素,动作耗时 %d 毫秒
+ 用 %d 根手指在 (%d,%d) 处进行 %s操作,缩放 %d 像素,耗时 %d 毫秒 (%s)
+ 呼叫 %s
+ 播放音效:%s
+ 播放未知声音
+
+
+ 选项:
+ 操作:
+ 触发器:
+ 条件:
+ 上滑
+ 下滑
+ 左滑
+ 右滑
+ 扩展
+
+
+ 起点 X
+ 起点 Y
+ 终点 X
+ 终点 Y
+ 缩放距离 (px)
+ 缩放类型
+ 缩小
+ 放大
+ 键码
+ 来自设备
+ 快捷方式名称
+ 坐标描述 (可选)
+ 要输入的文本
+ 要打开的URL
+ 要拨打的电话号码
+ 需要发送短信的电话号码
+ 需要发送的短信
+ 操作
+ 类别
+ 数据
+ 包名
+ 分类
+ 名称
+ 值 (%s)
+ Key Mapper 描述(必需)
+ 标志
+ 音效文件描述
+ WiFi 网络名
+
+
+ 同时按下
+ 按顺序按下
+ 和
+ 或
+ 短按
+ 长按
+ 双击
+ 短整形
+ 长
+ 双精度浮点数
+ 真
+ 假
+ 活动
+ 服务
+ 广播接收器
+
+
+ 触发器和操作
+ 条件等
+ 触发器
+ 动作
+ 条件
+ 选项
+
+
+
+
+ 选择 %s
+ 备份成功!
+ 备份失败!
+ 还原成功!
+ 还原失败!
+ 自动备份成功!
+ 自动备份失败!
+ 屏幕截图完成
+ 屏幕截图分辨率与该设备的分辨率不匹配!
+ 复制按键映射 UUID 到剪贴板
+ 你已经触发了一个按键映射
+ 日志已复制
+ 您没有保存任何声音文件!
+ Key Mapper 可以使用 Shizuku 授予自身 WRITE_SECURE_SETTINGS 权限
+ Key Mapper 可以使用 Root 授予自身 WRITE_SECURE_SETTINGS 权限
+ 麦克风已静音
+ 麦克风已解除静音
+
+
+ 序列触发超时
+ 长按延迟
+ 双击超时
+ 重复延迟
+ 重复限制
+ 每重复…
+ 振动时长
+ 次数
+ 每次重复多少次
+ 下个操作之前的延迟
+ 按住时长
+ 滑动持续时间 (ms)
+ 手指数量
+ 使用屏幕截图设置坐标
+ 开始
+ 结束
+ 缩放持续时间 (ms)
+ 手指数量
+
+
+ %s 处于前台状态
+ %s 不处于前台状态
+ %s 正在播放媒体
+ %s 没有播放媒体
+ %s 已连接
+ %s 已断开连接
+ 屏幕开启
+ 屏幕关闭
+ 手电筒已关闭
+ 手电筒已打开
+ 前置手电筒已关闭
+ 前置手电筒已打开
+ 和
+ 或
+ 前台应用
+ 非前台应用
+ 蓝牙设备已连接
+ 蓝牙设备已断开连接
+ 屏幕开启
+ 屏幕关闭
+ 纵向(0°)
+ 横向(90°)
+ 纵向(180°)
+ 横向(270°)
+ 纵向(任何)
+ 横向(任何)
+ 屏幕方向
+ 设备物理朝向
+ 物理朝向:纵向
+ 物理朝向:横向
+ 物理:纵向(倒置)
+ 物理:横向(反向)
+ 应用正在播放媒体
+ 应用没有播放媒体
+ 正在播放媒体
+ 没有正在播放的媒体
+ 手电筒已打开
+ 手电筒已关闭
+ WiFi 已打开
+ WiFi 已关闭
+ 连接到 WiFi 网络
+ 与 WiFi 网络断开
+ 留空则系统将自动匹配任意 Wi-Fi 网络
+ 已连接到 %s WiFi
+ 与 WiFi “%s” 断开连接
+ 已连接到任意 WiFi
+ 未连接到任何 Wi-Fi
+ 输入法已选择
+ 已选择 %s
+ 没有选择输入法
+ %s 没有被选择
+ 已显示键盘
+ 已显示屏幕键盘
+ 已隐藏键盘
+ 已隐藏屏幕键盘
+ 设备已锁定
+ 设备已解锁
+ 正在显示锁屏界面
+ 未显示锁屏界面
+ 正在通话
+ 未在通话
+ 设备正在响铃
+ 正在充电
+ 未在充电
+ 折叠轴关闭
+ 折叠轴开启
+ 折叠轴已被关闭
+ 折叠轴已被开启
+ 纵向(0°)
+ 横向(90°)
+ 纵向(180°)
+ 横向(270°)
+ 时间
+ 时间介于 %s 和 %s
+ 时间约束
+ 开始时间
+ 编辑开始时间
+ 结束时间
+ 编辑结束时间
+
+
+ 长按
+ 双击
+
+
+
+
+
+
+ 停止 “终止应用”
+ 遵循 dontkillmyapp.com 上的精彩指南,该指南向您展示如何关闭手机上所有的应用程序终止“功能”。
+
+ \n\n阅读完指南后,您需要切换下一个并重新启动无障碍服务。
+ 打开指南
+ 重启无障碍服务
+ 必须重新启动无障碍服务。 关闭它,然后再打开。
+ 报告BUG
+ 通过点击 “创建报告” 选择保存错误报告的位置。 下一页将告诉您如何将其发送给开发人员。
+ 创建报告
+ 分享报告
+ 有2种方法可以向开发人员分享错误报告。要么加入 Discord 服务器,要么创建一个 GitHub issue。确保将错误报告附加到您的消息中!
+ Discord
+ GitHub
+
+
+ 设置
+ 关于
+ 搜索
+ 帮助
+ 报告问题
+ 显示输入法选择器
+ 保存
+ 还原
+ 备份所有内容
+ 点击以暂停
+ 点击以恢复
+ 分享
+ 切换短消息
+ 复制
+ 清除
+
+
+ 添加操作
+ 点击录制触发器
+ 使用专家模式录制
+ 开启专家模式
+ 新增功能!
+ 已完成
+ 修复
+ 请按下按键
+ 添加条件
+ 选择键码
+ 添加额外的
+ 创建启动器快捷方式
+ 手动创建快捷方式
+ 系统指令指南
+ 帮助
+ 选择屏幕截图(可选)
+ 选择活动
+ 设置标记
+ 无限制
+ 选择音效文件
+ 选择系统铃声
+ 编辑操作
+ 覆盖操作
+
+
+ 需要Root权限!
+ 无法找到无障碍服务设置页面
+ 未保存的更改
+ 您有未保存的更改。如果放弃它们,你的编辑将丢失。
+ 请在您的root管理应用(如Magisk)中,为Key Mapper授予root权限。
+ 授予 WRITE_SECURE_SETTINGS 权限
+ 需要使用专家模式授予此权限
+ 您的设备似乎没有无障碍服务设置页面,可以设置专家模式,或者运行 ADB 命令 \"adb shell pm grant io.github.sds100.keymapper android.permission.WRITE_SECURE_SETTINGS\"以修复此项。
+ 请按列表顺序依次按住按键
+ 输入此触发器有时间限制,您可以在“选项”标签页中修改此超时时间
+ 此触发器的使用方法
+ 序列触发器
+ 在屏幕关闭时触发映射
+ 由于该触发键未通过“专家模式”录入,在屏幕熄灭时无法被检测到,请使用“专家模式”重新录入触发键,以实现息屏重映射
+ Android 不允许应用获取已连接(未配对)的蓝牙设备列表。它们只有在连接和和断开连接时才能被应用检测到。因此,如果在无障碍服务启动前,蓝牙设备已经连接到了您的设备,您将必须重新连接它,为了让这个应用知道它已经连接了。
+ 自动备份
+ 要更改位置或关闭自动备份吗?
+ 如果您使用数字密码(PIN)或图案来解锁设备,则无需担心。但如果您设置了混合密码锁屏,在使用 Key Mapper 输入法时将“无法”解锁手机,因为它没有交互界面(GUI)。您可以授予 Key Mapper WRITE_SECURE_SETTINGS 权限,以便其显示通知来切换键盘,点击屏幕底部的问号图标可查看操作指南
+ 选择一个动作需要的输入法。您可以稍候在主屏幕的底部菜单,点击 “选择操作键盘” 来更改此项。
+ 未连接外部设备。
+ 禁用电池优化
+ 您必须阅读此全部,否则您将来会沮丧!\n\n点击“部分修复”可能 防止 Android 在后台停止应用程序。\n\n这还不够。 您的 OEM 厂商 (例如 MIUI 或 Samsung Experience) 可能具有其他应用程序终止功能,因此您必须按照 dontkillmyapp.com 上的在线指南为 Key Mapper 关闭它们。
+ 通过打开和关闭重新启动无障碍服务,以便您可以测试该操作。
+ Key Mapper已终止
+ Key Mapper 曾尝试在后台运行,但被系统终止。\n这通常是因为您开启了电池或内存优化。\n\n要解决此问题,您可以尝试参考在线指南。完成设置后,您还应重新启动服务
+ 继续
+ 忽略
+ 错误报告生成失败
+ 修复错误
+ 您没有安装可以为 Key Mapper 创建文件的文件应用程序。 请安装文件管理器。
+ 您没有安装可以为 Key Mapper 选择文件的文件应用程序。 请安装文件管理器。
+ 需要启用无障碍服务
+ @string/accessibility_service_explanation
+ 您可能需要允许“受限制的设置”
+ 点击查看操作说明
+ 授予 “勿扰” 权限
+ 您将被带到设备的设置页面,以管理哪些应用程序可以修改 “请勿打扰” 状态。此功能在某些设备上可能不存在,因此如果您在列表中未看到“键映射器”,请点击 “不再显示”。
+ 排序方式
+ 拖动手柄可调整优先级。最上面的项目是最重要的。您还可以轻点任何项目来颠倒其排序顺序。
+ 例如:要主要按升序排列的操作及其触发器按降序排列的键映射,请将“操作”移到第一位,将“触发器”移到第二位。
+ 拖动 %1$s 的滑块
+ 显示示例
+ 启用通知
+ 某些操作和选项需要此权限才能运行。您还可以在有关于应用程序的重要信息时收到通知。
+ 迁移此屏幕关闭触发器
+ 很抱歉造成不便,我们推出了一项名为“专家模式”的*免费*功能,用来取代原有的的熄屏映射选项。该功能更加可靠,且支持了电源键映射。\n\n由于其工作原理不同,您需要使用专家模式重新录制此触发器。
+ 继续
+ 授予 READ_LOGS 权限
+ 您需要拥有 root 权限或已开启专家模式才能使其生效。系统在授予此权限时会关闭应用,您需要自行重新打开应用,并尝试再次分享 logcat 日志
+ 已完成
+ 结束进程
+ 使用专家模式
+ 更改
+ 部分修复
+ 确定
+ 重新启动
+ 不再显示
+ 应用
+ 放弃更改
+ 保存
+ 已了解
+ 开启
+ 继续
+ 关闭
+ 取消
+ 不再显示
+ 继续编辑
+ 不用了
+ 隐藏
+ 在线指南
+ 设置
+ 文档
+ 更改日志
+ 修复
+
+
+ 暂停/恢复按键映射
+ 键盘已隐藏警告
+ 切换键映射器输入法
+ 新功能
+ 自定义通知
+ 运行中
+ 点击以打开 Key Mapper。
+ 暂停
+ 已暂停
+ 点击以打开 Key Mapper。
+ 恢复
+ 忽略
+ 重新启动
+ 无障碍服务已禁用
+ 点击以启动无障碍服务。
+ 需要重新启动无障碍服务!
+ 无障碍服务崩溃了! 您的手机可能正在积极杀死它! 点击以重新启动无障碍服务。
+
+ 停止服务
+ 键盘已隐藏!
+ 点击 “显示键盘” 再次显示键盘。
+ 切换键映射器输入法
+ 点击“切换”可以在键映射器输入法与其他输入法之间切换
+ 切换
+ 熄屏按键映射需要注意!
+ 很抱歉造成不便,但您需要重新录制您的熄屏按键映射
+
+
+ 默认长按延时
+ 检测到按钮长按需要多长时间。默认值为 500ms。可被按键映射选项覆盖。
+ 默认双击是从
+ 检测到按钮双击需要多快。默认值为 300ms。可被按键映射选项覆盖。
+ 如果按键映射启用了震动,将震动多长时间。默认值为 200ms。可被按键映射选项覆盖。
+ 默认振动时长
+ 需要按住触发器多长时间才能开始重复操作。 默认为 400 毫秒。 可以在键映射的选项中被覆盖。
+ 重复前的默认延迟
+ 每次重复动作之间的延迟。默认值为 50ms。可被按键映射选项覆盖。
+ 重复之前的默认延迟
+ 允许 “序列触发器” 完成的时间。默认值为 1000ms。可被按键映射选项覆盖。
+ 顺序触发器的默认超时限制
+ 重置
+ 使所有按键映射振动
+ 每次触发按键映射时
+ 显示暂停/恢复通知
+ 开启或关闭按键映射
+ 更改自动备份位置
+ 开启自动备份
+ 在修改按键映射后进行备份
+ 当设备(如键盘)连接/断开连接时自动更改屏幕键盘
+ 连接指定设备时,您的系统将自动切换至键映射器输入法;断开连接后,系统将自动切回您的常用键盘
+ 当开始输入文本时自动更改屏幕键盘
+ 当您打开键盘时,您的系统将自动选择上次使用的普通屏幕键盘;一旦键盘停止使用,系统将自动切回键映射器输入法
+ 屏幕消息
+ 自动更改键盘时显示提示
+ 请求root权限
+ 如果您的设备已获取 root 权限,此操作将触发 Magisk 或其他 root 管理应用的权限申请弹窗
+ 选择主题
+ 亮色和暗色主题可用
+ 点击通知即可在键映射器输入法与常用键盘之间进行切换
+ 切换键映射器输入法通知
+ 切换按键映射时自动更改键盘
+ 恢复按键映射时自动选择键映射器输入法,暂停时则自动选择系统默认键盘
+ 隐藏主屏幕提醒
+ 隐藏主屏幕顶部的提醒
+ 显示设备ID
+ 区分同名设备
+ 启用附加日志
+ 记录更详细的日志
+ 查看键映射器日志
+ 遇到问题时将此错误信息分享给开发者
+ 分享 Logcat 日志
+ 分享完整系统日志
+ 分享 Logcat 日志失败
+ 反馈问题
+ 删除音效文件
+ 删除可用于声音操作的声音文件。
+ 授权
+ 已授权
+ 1. 未安装 Shizuku!点击下载 Shizuku。
+ 1. Shizuku 已安装。
+ 2. Shizuku 未启动!点击打开 Shizuku 应用程序,然后阅读说明,了解如何启动它。
+ 2. Shizuku 已启动。
+ 3. Key Mapper 未获取 Shizuku 的权限。点击以授予此权限。
+ 3. Key Mapper 会自动使用 Shizuku。点击查看哪些 Key Mapper 功能使用 Shizuku。
+ 更改默认选项
+ 适用于触发器与动作
+ 重置所有
+ 危险!
+ 确定要将应用中的所有设置重置为默认值吗?您现有的按键映射不会受到影响,功能介绍和警告弹窗将重新显示
+ 是,重置
+ 重置所有
+ 自定义体验
+ 按键映射
+ 数据管理
+ 高级用户选项
+ 调试
+ 通知
+
+
+ Root 设置
+ 这些选项只适用于 root 设备!如果您不知道 root 是什么或您的设备是否 root,他们无效时请不要留下不好的评论。:)
+ 请求 WRITE_SECURE_SETTINGS 权限
+ 这些选项只有在 Key Mapper 拥有 WRITE_SECURE_SETTINGS 权限时才会启用。单击下面的按钮了解如何授予权限。
+ 自动切换键盘
+ 在必要时切换并在结束后切回
+ 选择设备
+ 选择可触发自动键盘切换的设备
+ 日志记录
+ 这可能会增加按键映射的延迟,因此只有在您尝试调试程序,或被开发人员要求时才打开。
+ 使用专家模式
+ 高级按键事件检测及更多功能
+ 亮色
+ 暗色
+ 系统
+ 语言
+ 选择应用语言
+ 跟随系统
+
+
+ 显示音量对话框
+ 振动
+ 显示屏幕消息
+ 长按时再次震动
+ 重复
+ %dx
+ %d ms 之后
+ 每 %d ms
+ 直到再次按下
+ 直到释放
+ 重复
+ 按住
+ 保持直到再次按下
+ 不要重映射
+ 允许其他应用通过 Intent 或快捷方式控制此按键映射
+ 复制按键映射 id
+ ⌨
+
+
+ 无障碍
+ 闹钟
+ DTMF
+ 音乐
+ 通知
+ 铃声
+ 系统
+ 语音通话
+ 普通
+ 振动
+ 静音
+ 前
+ 后
+ 提醒
+ 优先级
+ 无
+
+
+ 暂停按键映射
+ 恢复按键映射
+ 已暂停
+ 运行中
+ 服务已禁用
+ Key Mapper 无障碍服务已禁用
+ 切换键映射器输入法
+
+
+ Ctrl
+ 左 Ctrl
+ 右 Ctrl
+ Alt
+ 左 Alt
+ 右 Alt
+ Shift
+ 左 Shift
+ 右 Shift
+ Meta
+ 左 Meta
+ 右 Meta
+ Sym
+ Func
+ Caps Lock
+ Num Lock
+ Scroll Lock
+
+
+ 您需要使用键映射器输入法才能执行此动作!
+ 包名为 %s 的应用未安装!
+ 应用 %s 已禁用!
+ 您需要授予 Key Mapper 修改系统设置的权限。
+ 这需要 root 权限!
+ 此操作需要相机权限!
+ 需要 Android %s 或更新版本
+ 需要 Android %s 或更老版本
+ 此设备没有相机。
+ 此设备不支持 NFC。
+ 此设备没有指纹传感器。
+ 此设备不支持 WiFi。
+ 此设备不支持蓝牙。
+ 此设备不支持设备协议执行。
+ 此设备没有相机闪光灯。
+ 您的设备无法使用电话功能,请检查是否已插入 SIM 卡
+ 找不到键盘设置页面!
+ Key Mapper 需要设置为设备管理员!
+ Key Mapper 没有使用该快捷方式的权限
+ 应用需要权限才能更改“勿扰”状态!
+ 此动作需要权限以读取手机状态!
+ 无法找到WRITE_SETTINGS权限页面!
+ 打开此应用快捷方式时出错
+ 无法找到 “勿扰” 访问权限设置!
+ Key Mapper需要WRITE_SECURE_SETTINGS权限。
+ 没有拨号应用
+ 没有应用可以发送此短信
+ 相机正在使用中!
+ 相机已断开连接!
+ 相机已禁用!
+ 相机出错!
+ 正在使用最大数量的相机!
+ 无前置闪光灯
+ 无后置闪光灯
+ 手电筒不支持可变亮度
+ 无障碍服务需要启用!
+ 无障碍需要重启!
+ 您的启动器不支持快捷方式。
+ 需要启用键映射器输入法!
+ 找不到 %s 输入法
+ 输入法选择器无法显示!
+ 寻找授权节点失败!
+ 全局动作 %s 执行失败!
+ 此操作需要配置
+ 找不到电池优化设置,如果该设置项存在,请手动将其打开
+ 找不到额外 (%s) !
+ 不能有重复的条件!
+ 不能为空!
+ 找不到设备!
+ 空的 SON 文件!
+ 文件访问被拒绝!%s
+ 未知 IO 错误!
+ 已取消
+ 无效的数字!
+ 必须至少为 %s!
+ 最多只能是 %s!
+ 电池优化已开启!请将其关闭,否则可能会导致 Key Mapper 停止运行
+ 已拒绝通知访问权限!
+ 无效!
+ 拒绝了开始通话的权限!
+ 发送短信权限已被拒绝!
+ 发送短信失败,请检查号码是否正确
+ 无法发送短信,请关闭飞行模式
+ 无移动网络服务,无法发送短信
+ 超出短信发送限制,请稍后再试
+ 网络已拒绝发送此短信
+ 设备存储空间不足,无法发送短信
+ 短信格式无效
+ 网络错误,无法发送短信
+ 紧急通话期间无法发送短信
+ 未检测到 SIM 卡,无法发送短信
+ 你需要更新 Key Mapper 到最新版本才能使用此备份。
+ 未安装语音助理!
+ 权限不足
+ 您没有安装任何屏幕键盘!
+ 无应用正在播放媒体!
+ 源文件未找到!%s
+ 目标文件未找到!%s
+ 手势输入失败!
+ 修改系统设置失败 %s!
+ 需要打开%s!
+ 切换输入法失败!
+ 启用输入法失败!
+ 此设备无相机应用!
+ 此设备无助理!
+ 您的设备没有设置!
+ 任何应用程序都无法打开该网址!
+ 不是一个文件夹!%s
+ 此项不属于文件!%s
+ 找不到路径!%s
+ 无法找到声音文件!
+ 无法获取存储权限!
+ 目标和源文件不可同名!
+ 目标中无剩余空间!%s
+ Shizuku 未授权!
+ Shizuku 未启动!
+ 文件未命名!
+ 无效文件。必须是从 Key Mapper 导出的 zip 文件。
+ 必须授权 Key Mapper 查看配对蓝牙设备的权限。
+ URL 格式错误。您是否忘记了 http://?
+ 拒绝了读取精确位置的权限!
+ 拒绝了开始和结束通话的权限!
+ 拒绝了查看配对蓝牙设备的权限!
+ 拒绝了显示通知的权限!
+ 读取日志权限已被拒绝!
+ 必须是 2 或以上!
+ 必须是 %d 或以下!
+ 必须大于 0!
+ 必须大于 0!
+ 必须大于 0!
+ 必须大于 0!
+ 必须是 %d 或以下!
+ 未找到 UI 元素!
+ 命令在 %1$d 秒后超时
+ 需要启用专家模式
+ 已达到发送频率限制,每秒只能发送一次短信
+ 该应用不支持此功能
+
+
+ 切换 WiFi
+ 启用 WiFi
+ 禁用 WiFi
+ 切换蓝牙
+ 启用蓝牙
+ 禁用蓝牙
+ 调高音量
+ 调低音量
+ 静音
+ 切换静音
+ 取消静音
+ 静音麦克风
+ 将麦克风接触静音
+ 切换麦克风静音
+ 显示音量对话框
+ 增加流
+ 增加 %s 流
+ 减少流
+ 减少 %s 流
+ 循环切换响铃模式(正常、振动、静音)
+ 循环切换响铃模式(正常、振动、静音)
+ 更改铃声模式
+ 更改为 %s 模式
+ 切换勿扰模式
+ 切换允许 %s 打扰的勿扰模式
+ 启用勿扰模式
+ 启用允许 %s 打扰的勿扰模式
+ 禁用勿扰模式
+ 启用自动旋转
+ 禁用自动旋转
+ 切换自动旋转
+ 纵向模式
+ 横向模式
+ 切换方向
+ 循环旋转
+ 循环旋转 %s
+ 切换移动数据
+ 启用移动数据
+ 禁用移动数据
+ 切换热点
+ 开启热点
+ 关闭热点
+ 切换自动亮度
+ 禁用自动亮度
+ 启用自动亮度
+ 调高显示亮度
+ 调低显示亮度
+ 切换夜值
+ 启用夜值
+ 禁用夜值
+ 下拉通知栏
+ 切换通知栏
+ 展开快速设置
+ 切换快速设置抽屉
+ 折叠状态栏
+ 暂停媒体播放
+ 暂停应用的媒体播放
+ 暂停 %s 的媒体
+ 恢复媒体播放
+ 恢复应用的媒体播放
+ 恢复 %s 的媒体
+ 播放/暂停媒体播放
+ 播放/暂停应用的媒体播放
+ 播放/暂停 %s 的媒体
+ 下一曲
+ 应用的下一曲目
+ %s 的下一曲
+ 上一曲
+ 应用的上一曲目
+ %s 的上一曲
+ 快进
+ 应用的快进
+ 快进 %s
+ 快退
+ 应用的快退
+ 快退 %s
+ 停止媒体
+ 停止一个应用的媒体
+ 停止 %s 的媒体
+ 步进媒体
+ 步进一个应用的媒体
+ 步进 %s 的媒体
+ 步退媒体
+ 步进一个应用的媒体
+ 步进 %s 的媒体
+ 返回
+ 主屏幕
+ 打开最近任务
+ 打开菜单
+ 切换分屏
+ 转到上一个应用程序 (双击最近任务)
+ 切换闪光灯
+ 启用手电筒
+ 禁用手电筒
+ 切换手电筒
+ 切换手电筒 (%s)
+ 启用手电筒
+ 启用手电筒 (%s)
+ 禁用闪光灯
+ 更改手电筒亮度
+ 调亮手电筒 %s
+ 调暗手电筒 %s
+ 切换前置手电筒
+ 切换前置手电筒 (%s)
+ 启用前置手电筒
+ 启用前置手电筒 (%s)
+ 禁用前置手电筒
+ 改变前置手电筒亮度
+ 调亮手电筒 %s
+ 调暗手电筒 %s
+ 启用NFC
+ 禁用NFC
+ 切换NFC
+ 屏幕截图
+ 启动语音助手
+ 启动设备助手
+ 打开相机
+ 锁定设备
+ 安全锁定设备
+ 您将只能使用您的 PIN 重新解锁。指纹扫描仪和面部解锁将被禁用。这是我发现的在 Android Pie 9.0 之前锁定无 root 设备的唯一可靠方法。
+ 睡眠/唤醒设备
+ 什么也不做
+ 移动鼠标
+ 移动到上个字
+ 移动到下个字
+ 移动到上个词
+ 移动到下个词
+ 移到上行
+ 移到下行
+ 移到段落开头
+ 移到段落结尾
+ 移到页面开头
+ 移到页面结尾
+ 切换键盘
+ 这个动作只有在你点击了键盘应该显示的输入字段时才能起作用。
+ 显示键盘
+ 隐藏键盘
+ 显示键盘选择器
+ 切换键盘
+ 切换到 %s
+ 剪切
+ 复制
+ 粘贴
+ 在光标处选择单词
+ 打开设置
+ 显示电源菜单
+ 切换飞行模式
+ 启用飞行模式
+ 禁用飞行模式
+ 启动应用
+ 部分设备要求 Key Mapper 在后台启动应用前获得权限。请点击 “阅读更多” 以查看我们网站上的操作指引。
+ 阅读更多
+ 忽略
+ 警告!
+ 启动应用快捷方式
+ 输入键码
+ 输入按键事件
+ 点击屏幕
+ 滑动屏幕
+ 缩放屏幕
+ 输入文本
+ 打开 URL
+ 发送系统指令
+ 开始呼叫
+ 应答呼叫
+ 结束呼叫
+ 发送短信
+ 向%s发送短信“%s”
+ 新建短信
+ 撰写信息:向%s发送短信“%s”
+ 修改设置:%1$s = %2$s
+ 系统
+ 安全设置
+ 全局设置
+ 修改设置
+ 播放声音
+ 忽略多数最近的通知
+ 清除所有通知
+ 创建通知
+ 显示通知:%1$s
+ 通知标题
+ 请输入通知标题
+ 标题不能为空
+ 通知内容
+ 输入通知内容
+ 内容不能为空
+ 自动忽略通知
+ 在此时间后自动取消
+ %d 秒
+ 测试
+ 正在测试按键中……
+ 通知已成功显示
+ 设备控制屏幕
+ HTTP 请求
+ HTTP 方法
+ 描述
+ 不能为空!
+ URL
+ 不能为空!
+ URL 格式错误。您是否忘记了 http://?
+ 请求体 (可选)
+ 授权请求头(可选)
+ 必要时您必须在开头添加 \'Bearer\'
+ Shell 命令
+ Shell 脚本动作
+ 脚本
+ 脚本不能为空!
+ 请勿输入“adb shell”!
+ 以 Root 权限运行
+ 标准模式
+ Root 模式
+ ADB 模式
+ 执行模式
+ ADB 模式不支持流式输出
+ 设置专家模式
+ 设置专家模式 (不支持)
+ 配置
+ 输出
+ 暂无输出,点击“测试”以运行命令。
+ 测试
+ 输出
+ 正在运行……
+ 运行成功
+ 运行失败
+ 退出代码:%1$d
+ 以 Root 权限执行:%s
+ 以 ADB 模式执行:%s
+ 执行:%s
+ 与应用界面元素交互
+ Key Mapper 可以检测并与菜单、标签、按钮和复选框等应用程序内容进行交互。您需要录下自己与应用程序交互的过程,以便 Key Mapper 知道您想做什么。要做什么。
+ 开始录制
+ 停止录制 (剩余 %s 分钟)
+
+ - 检测到 %d 内容
+
+ 选择要交互的应用
+ 再次录制
+ 选择应用元素
+ 选择您希望按键映射与之交互的元素。
+ 找不到您需要的内容?
+ 并非所有应用都兼容。对于不兼容的应用,您可以尝试使用 “点击屏幕” 操作。
+ 可能的交互
+ 选择您想要与 UI 元素交互的方式。
+ 过滤交互类型
+ 显示其他元素
+ 任何网络
+ 点击
+ 点击并按住
+ 聚焦
+ 向前滚动
+ 向后滚动
+ 展开
+ 折叠
+ 未知的: %d
+ 交互详情
+ 描述
+ 应用
+ 文本/内容描述
+ 类名
+ 工具提示/提示
+ 查看资源 ID
+ 唯一 ID
+ 交互类型
+ 强制停止应用
+ 关闭并从最近任务中清除应用
+ 修改设置
+ 键名
+ 键值
+ 设置的键名不能为空
+ 设置的键值不能为空
+ 注意:仅修改设置值可能不足以使更改生效,某些设置需要额外的操作或广播才能被系统处理
+ 测试
+ 设置修改成功
+ 授权
+ 选择设置项
+ 没有找到设置
+ 选择已有设置项
+
+
+ 导航
+ 音量
+ 媒体
+ 键盘
+ 应用
+ 输入
+ 手电筒
+ 连接
+ 接口
+ 手机
+ 显示
+ 通知
+ 特殊
+
+
+ 应用
+ 媒体
+ 蓝牙
+ 显示
+ 手电筒
+ WiFi
+ 键盘
+ 锁定状态
+ 手机
+ 电源
+ 设备
+ 时间
+
+
+ 布尔值
+ 布尔数组
+ 整数
+ 整数组
+ 字符串
+ 字符串数组
+ 长整型
+ 长整型数组
+ 字节
+ 字节数组
+ 双精度浮点数
+ 双精度浮点数数组
+ 字符
+ 字符数组
+ 单精度浮点数
+ 单精度浮点数数组
+ 短整形
+ 短整形数组
+ 只能为 \"true\" 或 \"false\"
+ 逗号分隔 “true” 和 “false” 列表。例如 true,false,true
+ 一个Java编程语言中的有效整数。
+ 一个逗号分隔Java编程语言中的有效整数列表。例如 100,399
+ 一个逗号分隔列表。例如 类别1,类别2
+ 任何文本。
+ 一个逗号分隔字符串列表。例如 字符串1,字符串2
+ 一个Java编程语言中有效的长整形。
+ 一个逗号分隔Java编程语言中有效的长整形列表。例如 10230223234234234,3990834234429
+ 一个Java编程语言中的有效字节。
+ 一个逗号分隔Java编程语言中有效字节的列表。例如 123,3
+ Java编程语言中有效的双精度浮点数。
+ 一个逗号分隔Java编程语言中有效的双精度浮点数列表。例如 1.0,3.234
+ Java编程语言中的有效字符。例如 \'a\'和\'b\'
+ 一个逗号分隔Java编程语言的有效字符列表。例如 a,b,c
+ 一个Java编程语言中的有效单精度浮点数。例如 3.145
+ 一个逗号分隔Java编程语言的单精度浮点数的有效的列表,例如 1241.123
+ 一个Java编程语言中的有效短整形。例如2342
+ 一个逗号分隔Java编程语言的有效短整形列表。例如 3242,12354
+ 一个意图的标记最好是位图。这些标记的改变即意图的操作。如果一个活动的意图没有标记,Key Mapper 将默认使用 FLAG_ACTIVITY_NEW_TASK,更多信息请点击 “文档” 查看安卓开发文档.
+
+
+ GitHub
+ 网站
+ 翻译
+ %s 版本
+ 评价
+ 更新日志
+ Discord
+ 琐事
+ 许可协议
+ 此应用的开源许可
+ 隐私政策
+ 正如隐私政策所说我们不会收集任何私人信息
+ 我们的团队
+ 开发人员
+ 用户体验设计师
+ 译者(波兰语)
+ 译者(捷克语)
+ 译者(西班牙语)
+
+
+ 支持键映射器❤️
+ 选择插件以升级您的体验
+ 您的支持让键映射器更进一步!
+ "悬浮按钮功能是个重大改进"
+ Google Play 用户评论
+ 悬浮按钮功能简直是神来之笔!
+ 我一直很喜欢悬浮按钮这个功能
+ 加入悬浮按钮真是个明智之举
+ 它已成为我手机使用体验中不可或缺的一部分
+ 一次付费,永久解锁
+ 观看视频
+ 立即购买 (%s)
+ 更多信息
+ 屏幕悬浮按钮
+ 设备按键不够用?键映射器可以在任何应用、游戏或锁屏界面上,即刻创建快捷方式与宏命令!
+ 在游戏中使用
+ 在锁屏界面使用
+ 侧键与助手触发器
+ 侧键暂时空闲?可以将助手按键或设备的侧键快捷方式重新映射为您想要的任何功能!
+ 关闭屏幕
+ Bixby
+ Gemini
+
+ Key Mapper: 侧键
+ 任何助手
+ 侧边键/电源按钮
+ 语音助手
+ 您必须购买侧键触发器功能
+ 您必须购买悬浮按钮功能
+ 按钮已删除
+ 悬浮按钮
+ 无法验证购买。您有互联网连接吗?
+
+ 解锁 (%s)
+ 使用
+ 加载中…
+ 已购买!
+ 重试获取价格
+ 已取消支付
+ 这是一个需要从 Google Play 购买并下载的 Key Mapper 才能使用的付费功能。
+ 遇到网络错误。您有互联网连接吗?
+ 产品未找到。
+ Google Play 遇到错误。
+ 我们正在等待 Google Play 确认您的购买是否成功。请于银行卡扣款成功后,重新打开 Key\u00A0Mapper 应用。
+ 无效的购买。
+ 待付款
+ 出错了 😕
+ 重试
+ 联系开发者
+ 您必须购买侧键触发功能!请点击按键映射,然后前往商店购买
+ 您必须购买悬浮按钮功能!请点击按键映射,然后前往商店购买
+ 感谢您对本应用的支持!
+ 购买成功!作为键映射器的付费用户,您将获得优先支持以帮助您使用本应用。现在商店中已增加一个联系开发者的按钮
+ 高级触发器属于付费功能,但您下载的键映射器开源版本 (FOSS) 不包含此闭源模块或 Google Play 结算功能,请从 Google Play 下载键映射器以使用该功能。
+ 下载 Play 版本
+
+ 按钮未被检测到?
+ 您可以使用 Key Mapper GUI Keyboard 应用程序来替代无障碍服务以录制触发器。
+ 设置完成!点击“完成”并重新录制您的触发器。若仍无效,则说明该按键受 Android 系统限制无法重映射 🫤
+
+ 点击
+ 以显示/隐藏这个菜单
+ 您可以将按钮放置在任何应用中,甚至是锁定屏幕上。
+ 忽略
+ 帮助
+ 切换布局
+ 添加按钮
+ 返回
+ 隐藏按钮
+ 显示按钮
+ 删除
+ 配置
+ 使用触发器
+ 删除
+ 按钮文字(可选)(提示:使用表情符号)
+ 按钮大小:
+ 边框不透明度:
+ 背景不透明度:
+ 取消
+ 已完成
+ 显示在通知面板上方
+ 显示在键盘上方
+ 锁定位置
+ 悬浮按钮
+ 悬浮按钮可以显示在您需要的应用程序之上。它们就像实体按钮一样工作,并且您可以随心所欲地放置、美化、映射它们。
+ 悬浮按钮 %s (%s)
+ 悬浮按钮(无文字)(%s)
+ 已删除悬浮按钮
+ 更好的大写锁定键兼容性
+ 专家模式能为大写锁定重映射提供更好的兼容性,请点击“使用专家模式”并重新录制按键
+ 使用专家模式
+ 息屏映射?
+ 开启专家模式后,任何触发器都可以在息屏时免费使用!您需要重新录制按键
+ 使用专家模式
+ 应用固定警告
+ 将返回键用作触发器可能会与应用固定功能冲突,导致解锁系统时出现黑屏,重启设备即可修复此问题
+ 键盘图标
+ ⌨ 符号表示受 Android 系统限制,您必须使用键映射器输入法才能使此触发器生效
+ 铃声模式动作
+ 建议在执行铃声模式动作时使用专家模式,以避免与“请勿打扰”设置冲突
+ 使用专家模式
+ 仅限特定应用使用?
+ 在“约束”选项卡中添加约束条件
+ 选择一个布局
+ 返回
+ 帮助
+ 需要帮助吗?
+ 创建按钮
+ 选择按钮
+ 退出
+ 您需要先创建一个悬浮按钮,才能将其用作触发器。
+ 您需要选择一个浮动按钮用作触发器。
+ 配置按钮
+ 编辑布局
+ 需要 Android 11 或更高版本。
+
+ 触发器
+ 动作
+ 排除
+ 选项
+ 按键映射
+ 悬浮按钮
+ 新建按键映射
+ 新布局
+ 点击一个按键映射来配置它。\n长按以获取更多选项。
+ 创建一个按键映射!\n\n按键映射是一条规则,用来告诉您的设备在按下某个按钮时该执行什么操作
+ 没有足够的按钮?
+ 您自己来制作!
+ 悬浮按钮可以显示在您需要的应用程序之上。它们就像实体按钮一样工作,并且您可以随心所欲地放置、美化、映射它们。
+ 隐藏此页面
+ 感谢您对 Key\u00A0Mapper\u00A0❤️ 的支持!
+ 创建您的第一个布局!
+ 布局功能可助您将悬浮按钮分组管理,但不会影响按钮的显示状态。任何布局中的按钮均可同时显示在屏幕上。
+ 修改布局 %s 名称
+ 删除布局 %s
+ 悬浮按钮
+ 没有按钮
+ 编辑按钮
+ 添加按钮
+ 更改布局名称
+ 保存
+ 名称不能为空!
+ 名称不能重复!
+ 删除 %s
+ 确定要删除此悬浮按钮布局吗?
+ 是的,删除
+ 取消
+ 隐藏悬浮布局
+ 在创建触发器时,您可以在“商店”按钮中找到悬浮按钮
+ 悬浮按钮
+ 菜单
+ 排序
+ 更多
+ 帮助
+ 全选
+ 取消全选
+ 停止选择
+ 上一组
+ 已暂停
+
+ - %d 条警告
+
+ 运行中
+ 设置
+ 删除群组
+ 关于
+ 导出全部
+ 导入
+ 选择键盘
+ 导入中…
+ 导入成功!
+ 导出中…
+ 导出失败: %s
+ 加载文件…
+ 导入成功!
+ 导入中…
+ 错误
+ 打开应用
+
+ - 导入 %d 个键映射
+
+ 您想替换所有现有的按键映射,还是将它们附加到列表中?
+ 取消
+ 忽略
+ 追加
+ 替换
+ 复制
+ 删除
+ 导出
+ 已启用
+ 已禁用
+ 混合
+ 移动到分组
+
+ - 删除 %d 键映射
+
+ 确定要删除这些按键映射吗?
+ 是的,删除
+ 取消
+ 保存到文件
+ 新建分组
+ 新建子分组
+ 查看全部
+ 隐藏
+ 约束条件分组
+ 新建约束条件
+ 删除约束条件分组
+ 当前分组
+
+ 移除
+ 编辑
+ 触发键选项
+ 设备
+ 助手类型
+ 指纹手势类型
+ 点击类型
+ 使用悬浮按钮
+ 使用指纹手势
+ 使用侧键触发器
+ 悬浮按钮
+ 侧键触发器
+ 指纹手势
+ 悬浮按钮: %s
+ 悬浮按钮(无文字)
+ 上划指纹识别器
+ 下划指纹识别器
+ 左划指纹识别器
+ 右划指纹识别器
+ 按键代码 %d
+ 扫描码 %d
+ 扫描码
+ 可以通过“按键代码”或“扫描码”来识别按键,扫描码比按键代码更具唯一性,但您的触发器可能无法在其他设备上运行,我们建议使用按键代码
+ 未知按键代码
+ 使用按键代码 %d
+ 使用扫描码 %d
+ 未保存扫描码
+ 使用专家模式
+ 添加更多
+
+ 移除
+ 编辑
+ 测试
+ 添加操作以设置按键映射触发后应执行的操作。
+ 最近使用的动作
+ 动作选项
+ 重置
+ 默认:%s
+ 选择一个动作
+ 搜索…
+ 这里什么都没有!
+ 删除动作
+ 确定删除此操作?
+ 是的,删除
+ 取消
+ 触发按键映射时运行这些操作:
+ 选择侧边
+ 亮度
+ 最小
+ 一半
+ 最大
+ 测试
+ 需要 Android 13 及以上。
+ 此设备不允许您更改亮度。
+ 亮度更改
+ 音量通道
+ 默认(系统控制)
+ 选项
+ 不支持
+ 不支持
+
+ 如果您希望按键映射仅在某些情况下工作,请添加约束。
+ 最近使用的约束
+ 移除
+ 删除限制条件
+ 确定删除此限制条件?
+ 确定删除
+ 取消
+ 逻辑模式
+ 选择一个条件
+ 只有在以下情况下,此按键映射才会运行:
+
+ 未命名分组
+ 编辑分组名称
+ 保存分组名称
+ 名称不能重复!
+ 主页
+ 删除分组
+ 删除分组 %s
+ 确定要删除此分组吗?该组及其子组中的所有按键映射也将被删除!
+ 确定删除
+ 取消
+
+ - 继承限制条件 +%d
+
+
+ 专业模式
+ 配置
+ 重要提示!
+ 使用专家模式(Expert Mode)重新映射按键具有一定的危险性,如果映射不当,可能会导致按键失效。\n\n如果您操作失误,可能需要强制重启设备,方法通常是长按电源键和音量键 30 秒——请查阅您的设备手册或通过网络搜索了解具体操作方法
+ %d……
+ 我已知悉
+ 已了解
+ 设置
+ 已检测到 Root 权限
+ 通过授予键映射器Root 权限,您可以跳过设置过程,这还能让键映射器自动开启专家模式,无需等待 WiFi 连接
+ 开启专家模式
+ 已检测到 Shizuku
+ 通过授予键映射器 Shizuku 权限,您可以跳过设置过程
+ 启动 Shizuku
+ 请求权限
+ 开启专家模式
+ 通过键映射器进行设置
+ 继续
+ (需 Android 11 或更高版本)
+ 为所有按键映射启用专家模式
+ 键映射器将使用 ADB Shell 进行重新映射
+ 在您确认警告信息之前,这些设置不可用
+ 专家模式服务正在运行
+ 终止服务
+ 通过 ADB 手动启动专家模式
+ 建议优先使用上方列出的其他方法。在执行此命令之前,您必须先执行 “adb shell”
+ 获取命令
+ 重试
+ 获取命令失败,请重试
+ 系统桥接启动命令
+ 将命令复制到剪贴板
+ 自启动与保持后台运行
+ 每当您重启设备或应用意外退出时,专家模式都会自动启动
+ 无论是在设备开机还是程序意外退出时,“专家模式”都会自动启动,不过这需要获取 WRITE_SECURE_SETTINGS 权限
+ 按键事件动作
+ 选择按键事件动作的执行方式
+ 紧急提示
+ 如果您的电源键失效,请长按电源键 10 秒后松开,即可关闭专家模式
+ 设置向导
+ 进程第 %d 步(共 %d 步)
+ 使用交互式设置助手
+ 自动配置设置项
+ 请先开启无障碍服务
+ 观看教程
+ 开始服务
+ 前往设置
+ 开始服务
+ 启用无障碍服务
+ 键映射器需要使用此服务协助完成设置,这同时也是实现常规按键映射所必需的一步
+ 开启开发者选项
+ Key Mapper 需要使用 Android 调试桥 (ADB),因此您需要开启开发者选项
+ 连接至 Wi-Fi 网络
+ 开启 ADB 需要 Wi-Fi 环境(无需联网)\n\n如果没有 Wi-Fi,可以连接其他手机的热点
+ 开启无线调试
+ Key Mapper 需要通过“无线调试”来启动其重映射及输入服务
+ 配对无线调试
+ Key Mapper 需要先完成“无线调试”配对,才能启动其重映射及输入服务
+ 开始服务
+ Key Mapper 需要连接 ADB 网桥才能启动服务
+ 允许通知
+ Key Mapper 需要获取通知权限,以便在设置过程中出现问题时及时提醒您
+ 授予权限
+ USB 配置不兼容
+ 您必须将默认 USB 配置设置为“不进行数据传输”,以防止“专家模式”在每次锁屏时被强行关闭
+ “USB 调试(安全设置)”已禁用
+ 您需要在“开发者选项”中开启“USB 调试(安全设置)”,专家模式才能正常工作,这通常是小米等设备的必要操作
+ 打开开发者选项
+ 设置专家模式助手
+ 专家模式正在运行
+ 您现在可以在熄屏状态下重映射按键,并使用更多功能
+ 完成专家模式配置
+ 开启开发者选项
+ 连续点击手机系统设置中的版本号五次以开启开发者模式
+ 自动配对
+ 正在搜索配对码和端口……
+ 未找到搜索配对码和端口
+ 点击“使用配对码配对”按钮,并在此处输入该配对码
+ 输入配对码
+ 点击“使用配对码配对设备”
+ 开启专家模式失败
+ 点击以重新设置。如果反复失败,请尝试使用 ADB 配对并重启手机
+ 正在自动开启专家模式
+ 正在使用 Root 权限
+ 正在使用 Shizuku
+ 正在使用无线 ADB
+ 专家模式已开启
+ 祝你映射愉快!❤️
+ 配对失败
+ 提交配对码时,请将配对码弹窗保持在屏幕上
+ 输入配对码
+ 专家模式有什么用?
+ 📲 您可以映射更多按键,例如电源键。\n⌨️ 在使用“按键代码 (Key Code)”动作时,可配合任何屏幕键盘使用。 \n⭐️ 解锁并使用更多高级动作。
+ 显示专家模式信息
+ 忽略
+ 专家模式意外停止
+ 正在自动重启……
+ 由于距离上次自动启动不到 5 分钟,将不再自动重启,如果您没有手动强杀服务,请向开发者报告此问题
+ 开启专家模式失败
+ 您的手机必须连接到 Wi-Fi 网络
+
+ 发现
+ 您想映射什么?
+ 设备按键
+ 外设与游戏
+ 悬浮按钮
+ 音量
+ 助手快捷键
+ 电源键
+ 指纹手势
+ 键盘
+ 鼠标
+ 手柄
+ 其他
+ 自定义
+ 刘海区域(刘海屏或水滴屏)
+ 锁屏
+ 提升您的使用体验
+ 悬浮按钮可在任何应用、游戏或锁定屏幕上作为即时快捷方式使用,您的支持是键映射器持续开发的动力 ❤️
+ 查看演示
+ 忽略
+ 只需 %s 即可解锁
+
+
+ 音量键
+ 键盘
+ 电源键
+ 助手触发器
+ 助手触发器扩展
+ 鼠标按键
+ 手柄按键
+ 其他按键
+ 指纹手势
+ 未检测到触发键
+ 点击添加触发键
+ 未满足要求
+ 获取帮助
+ 无法映射此按键
+ 无法使用此功能
+ 您或许可以映射此按键
+ 您或许可以映射此设备
+ 您的设备可能支持此功能
+ 您可以映射此按键
+ 您可以映射此设备
+ 您的设备支持此功能
+ 在熄屏状态下映射按键
+ 在熄屏状态下映射按键
+ 选项
+ 前置要求
+ 如果您的按键仍无法被检测到,请加入我们的 Discord 服务器并告知我们,我们将尽力帮助您完成按键映射
+ 如果您的按键仍无法被检测到,请加入我们的 Discord 服务器并告知我们,我们将尽力帮助您完成按键映射
+ 详情说明
+ 无障碍服务
+ 启用
+ 运行中
+ 已购买
+ 专业模式
+ 免费启用
+ 运行中
+ 此 Android 版本暂不可用
+ 如果您的设备助手是通过硬件按键触发的,或许可以通过“专家模式”免费对其进行重映射,请尝试在触发器页面选择“其他”,并按照说明进行操作
+ 此触发器需要进行一些设置,具体步骤因设备而异,请...
+ 查看操作指南
+ 阅读说明
+ 选择触发器类型
+ 如果您的设备助手是通过电源键触发的,或许可以直接对助手进行重映射,这意味着您无需使用“专家模式”。请尝试在触发器页面选择“助手”,并按照说明进行操作
+ 方向键
+ 其他常规按键
+ 映射方向键时,您将无法使用常规的屏幕键盘
+ 键映射器输入法
+ 启用
+ 选择
+ 运行中
+
+
+ 修复按键事件动作
+ 使用此动作还需要额外的步骤,请选择您想要使用的方法:
+ 键映射器输入法
+ 无屏幕键盘
+ 可以随时使用常规的屏幕键盘
+ 与应用和游戏有更好的兼容性
+ 启用键映射器输入法
+ 使用键映射器输入法
+ 打字时自动切换到常规屏幕键盘
+ 您可以随时在“设置”中更改此项
+ 设置
+ 选项
+ 测试短信
+ 成功发送短信
+ 发送短信可能会产生运营商费用或漫游费用,Key Mapper 开发者不承担任何相关费用
+ 描述
+ 指令超时
+
+ 你喜欢悬浮按钮功能吗?
+ 我们很想知道您的想法!请考虑在 Google Play 上留下评价,以帮助其他人发现此功能。❤️
+ 忽略
+ 写入 evdev 事件失败
+
diff --git a/base/src/main/res/values/strings.xml b/base/src/main/res/values/strings.xml
index 310a1c2da6..1144fc4bc3 100644
--- a/base/src/main/res/values/strings.xml
+++ b/base/src/main/res/values/strings.xml
@@ -692,11 +692,6 @@
Light
Dark
System
-
- Language
- Choose the app language
- System default
-
diff --git a/common/src/main/java/io/github/sds100/keymapper/common/utils/SettingsUtils.kt b/common/src/main/java/io/github/sds100/keymapper/common/utils/SettingsUtils.kt
index 3dfd55b876..c38e7e074f 100644
--- a/common/src/main/java/io/github/sds100/keymapper/common/utils/SettingsUtils.kt
+++ b/common/src/main/java/io/github/sds100/keymapper/common/utils/SettingsUtils.kt
@@ -27,11 +27,8 @@ object SettingsUtils {
return try {
when (T::class) {
Int::class -> Settings.System.getInt(contentResolver, name) as T?
-
String::class -> Settings.System.getString(contentResolver, name) as T?
-
Float::class -> Settings.System.getFloat(contentResolver, name) as T?
-
Long::class -> Settings.System.getLong(contentResolver, name) as T?
else -> {
@@ -52,11 +49,8 @@ object SettingsUtils {
return try {
when (T::class) {
Int::class -> Settings.Secure.getInt(contentResolver, name) as T?
-
String::class -> Settings.Secure.getString(contentResolver, name) as T?
-
Float::class -> Settings.Secure.getFloat(contentResolver, name) as T?
-
Long::class -> Settings.Secure.getLong(contentResolver, name) as T?
else -> {
@@ -77,11 +71,8 @@ object SettingsUtils {
return try {
when (T::class) {
Int::class -> Settings.Global.getInt(contentResolver, name) as T?
-
String::class -> Settings.Global.getString(contentResolver, name) as T?
-
Float::class -> Settings.Global.getFloat(contentResolver, name) as T?
-
Long::class -> Settings.Global.getLong(contentResolver, name) as T?
else -> {
@@ -102,11 +93,8 @@ object SettingsUtils {
return when (T::class) {
Int::class -> Settings.System.putInt(contentResolver, name, value as Int)
-
String::class -> Settings.System.putString(contentResolver, name, value as String)
-
Float::class -> Settings.System.putFloat(contentResolver, name, value as Float)
-
Long::class -> Settings.System.putLong(contentResolver, name, value as Long)
else -> {
@@ -124,11 +112,8 @@ object SettingsUtils {
return when (T::class) {
Int::class -> Settings.Secure.putInt(contentResolver, name, value as Int)
-
String::class -> Settings.Secure.putString(contentResolver, name, value as String)
-
Float::class -> Settings.Secure.putFloat(contentResolver, name, value as Float)
-
Long::class -> Settings.Secure.putLong(contentResolver, name, value as Long)
else -> {
@@ -146,11 +131,8 @@ object SettingsUtils {
return when (T::class) {
Int::class -> Settings.Global.putInt(contentResolver, name, value as Int)
-
String::class -> Settings.Global.putString(contentResolver, name, value as String)
-
Float::class -> Settings.Global.putFloat(contentResolver, name, value as Float)
-
Long::class -> Settings.Global.putLong(contentResolver, name, value as Long)
else -> {
@@ -159,13 +141,8 @@ object SettingsUtils {
}
}
- fun launchSettingsScreen(
- ctx: Context,
- action: String,
- uri: Uri? = null,
- fragmentArg: String? = null,
- ): Boolean {
- val intent = Intent(action, uri).apply {
+ fun launchSettingsScreen(ctx: Context, action: String, fragmentArg: String? = null) {
+ val intent = Intent(action).apply {
if (fragmentArg != null) {
val fragmentArgKey = ":settings:fragment_args_key"
val showFragmentArgsKey = ":settings:show_fragment_args"
@@ -184,10 +161,8 @@ object SettingsUtils {
try {
ctx.startActivity(intent)
- return true
} catch (e: ActivityNotFoundException) {
Timber.e("Failed to start Settings activity: $e")
- return false
}
}
diff --git a/evdev/src/main/rust/evdev_manager/Cargo.lock b/evdev/src/main/rust/evdev_manager/Cargo.lock
index efe3500145..adc4a9d3c6 100644
--- a/evdev/src/main/rust/evdev_manager/Cargo.lock
+++ b/evdev/src/main/rust/evdev_manager/Cargo.lock
@@ -28,9 +28,9 @@ checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
name = "bytes"
-version = "1.11.0"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cc"
diff --git a/sysbridge/src/main/java/io/github/sds100/keymapper/sysbridge/service/SystemBridgeSetupController.kt b/sysbridge/src/main/java/io/github/sds100/keymapper/sysbridge/service/SystemBridgeSetupController.kt
index 545e46f2a6..cc6f0b247f 100644
--- a/sysbridge/src/main/java/io/github/sds100/keymapper/sysbridge/service/SystemBridgeSetupController.kt
+++ b/sysbridge/src/main/java/io/github/sds100/keymapper/sysbridge/service/SystemBridgeSetupController.kt
@@ -264,7 +264,7 @@ class SystemBridgeSetupControllerImpl @Inject constructor(
SettingsUtils.launchSettingsScreen(
ctx,
Settings.ACTION_DEVICE_INFO_SETTINGS,
- fragmentArg = "build_number",
+ "build_number",
)
coroutineScope.launch {
@@ -359,7 +359,7 @@ class SystemBridgeSetupControllerImpl @Inject constructor(
SettingsUtils.launchSettingsScreen(
ctx,
Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS,
- fragmentArg = "toggle_adb_wireless",
+ "toggle_adb_wireless",
)
}