通过settings.db自定义Android系统默认设置:SHOW_IME_WITH_HARD_KEYBOARD 默认物理键盘与软键盘同时使用

本文详细介绍了如何在Android设备上通过修改系统配置文件和数据库操作来默认开启显示输入法的功能。包括在默认配置文件中添加开关,并在数据库加载安全设置时添加新字段。

默认开启“显示输入法”开关


1.先在packages/SettingsProvider/res/values/defaults.xml中增加默认配置

diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 863f702..6770186 100755
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -230,4 +230,6 @@
     <integer name="def_button_lights_off_timeout">1500</integer>
 <!--add by cg for 24 -->
     <string name="def_time_24">24</string>
+    <!--add by cg for Default for Settings.System.SHOW_IME_WITH_HARD_KEYBOARD-->
+    <integer name="def_show_ime_with_hard_keyboard">1</integer>
 </resources>

2.在/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java 中的loadSecureSettings(SQLiteDatabase db)方法中加入新字段的添加代码

chenguo@ubuntu:~/work/RK3229/hmd-rk3229/rk3229_5.1/frameworks/base$ git diff packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvi
index 3c835d6..ab85b04 100755
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2521,6 +2521,10 @@ public class DatabaseHelper extends SQLiteOpenHelper {
 
             loadIntegerSetting(stmt, Settings.Secure.SLEEP_TIMEOUT,
                     R.integer.def_sleep_timeout);
+             //add by cg for Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD
+            loadIntegerSetting(stmt, Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+                    R.integer.def_show_ime_with_hard_keyboard);

         } finally {
             if (stmt != null) stmt.close();
         }
(END)


<think> 我们之前讨论过,使用`ViewConfiguration.setSoundEffectsEnabled(false)`可以禁用应用内的视图交互声音(包括软键盘点击音效),但这仅限于应用内部。而使用`Settings.System.SOUND_EFFECTS_ENABLED`可以全局禁用系统音效,但根据你的反馈,它可能无法屏蔽系统软键盘的点击音效。 实际上,系统软键盘(InputMethodService)的声音效果并不完全受`SOUND_EFFECTS_ENABLED`控制,而是由输入法应用自身控制。因此,要完全屏蔽系统软键盘的点击声音,我们需要采取其他方法。 以下是几种可能的解决方案: 1. **在应用级别禁用声音反馈**:如前所述,使用`ViewConfiguration`或`Window`级别的设置。这对于应用内的输入框有效,但可能无法影响所有系统键盘(因为键盘属于系统UI)。 2. **自定义软键盘**:实现自己的输入法,完全控制键盘行为(包括声音)。 3. **输入法交互**:通过输入法框架(IMF)当前输入法通信,请求其禁用声音(但需要输入法支持)。 4. **全局静音系统音效**:通过`AudioManager`将系统音效流静音,但这会影响所有系统声音。 由于第一种方法我们已经讨论过,这里重点介绍其他方法。 ## 方法1:自定义软键盘(复杂但彻底) 实现一个自定义的输入法,并在其中禁用按键声音。 步骤: 1. 创建自定义输入法服务类 2.键盘布局中禁用声音 3.键盘视图中重写按键方法 示例代码: **AndroidManifest.xml** 声明服务: ```xml <service android:name=".SilentKeyboardService" android:label="@string/silent_keyboard_label" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> <meta-data android:name="android.view.im" android:resource="@xml/method" /> </service> ``` **res/xml/method.xml**: ```xml <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:isDefault="true" android:settingsActivity=".SettingsActivity" /> ``` **SilentKeyboardService.java**: ```java public class SilentKeyboardService extends InputMethodService { @Override public View onCreateInputView() { SilentKeyboardView keyboardView = (SilentKeyboardView) getLayoutInflater().inflate(R.layout.keyboard_view, null); Keyboard keyboard = new Keyboard(this, R.xml.keyboard_layout); keyboardView.setKeyboard(keyboard); return keyboardView; } } ``` **自定义键盘视图 SilentKeyboardView.java**: ```java public class SilentKeyboardView extends KeyboardView { public SilentKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); // 禁用按键声音 setSoundEffectsEnabled(false); } public SilentKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setSoundEffectsEnabled(false); } @Override public void onPress(int primaryCode) { // 重写此方法,不调用super,以避免播放声音 // super.onPress(primaryCode); // 注释掉父类方法 } @Override public void onRelease(int primaryCode) { // 同样,重写释放方法 // super.onRelease(primaryCode); } } ``` 在键盘布局文件(如`res/xml/keyboard_layout.xml`)中定义你的键盘。 ## 方法2:通过AudioManager临时静音系统音效流 这种方法会静音整个系统音效流(STREAM_SYSTEM),包括键盘声音、锁屏声音等。 ```java AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); // 静音系统音效 audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true); // 恢复系统音效 audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false); ``` 注意: - 需要权限:`android.permission.MODIFY_AUDIO_SETTINGS` - 在Android 6.0+,此权限是普通权限,不需要运行时请求。 - 但是,这会静音所有系统声音,可能影响用户体验。 ## 方法3:当前输入法通信(如果输入法支持) 有些输入法提供了扩展API或意图(Intent)来控制声音。但这不是标准方式,因此需要针对特定输入法。 例如,如果当前输入法是Gboard,可以尝试发送广播(但Gboard可能不支持)。 由于缺乏通用性,这种方法并不推荐。 ## 方法4:在输入框获得焦点时禁用声音(最实用) 在应用内,当输入框获得焦点时(即软键盘弹出),我们可以尝试通过以下方式禁用声音: ```java editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { // 当前窗口禁用声音 v.getWindow().getDecorView().setSoundEffectsEnabled(false); } } }); ``` 或者,在Activity中覆盖`dispatchTouchEvent`,确保在触摸事件发生时禁用声音: ```java @Override public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // 每次触摸时都确保禁用声音 getWindow().getDecorView().setSoundEffectsEnabled(false); } return super.dispatchTouchEvent(event); } ``` 这种方法在大多数情况下有效,因为软键盘的按键事件会传递到当前窗口。 ## 总结 1. **自定义键盘**:最彻底,但开发成本高。 2. **全局静音系统音效流**:简单但影响全局。 3. **应用内窗口禁用声音**:推荐,在输入框获得焦点时禁用当前窗口的声音效果。 根据你的需求,选择合适的方法。对于大多数应用,方法4(应用内窗口禁用声音)是最佳选择。 如果遇到特定设备不起作用,可能是由于设备厂商定制了输入法,此时可能需要结合多种方法。 §§相关问题§§: 1. 如何在 Android 中实现自定义输入法(IME)? 2. 如何检测当前正在使用的输入法类型? 3.Android 中如何动态切换输入法? 4. 如何为不同的输入框(EditText)设置不同的输入法? </think># 解决 Settings.System.SOUND_EFFECTS_ENABLED 无法屏蔽软键盘音效的问题 您正确地指出了 `Settings.System.SOUND_EFFECTS_ENABLED` 无法完全屏蔽系统软键盘的点击音效。这是因为系统软键盘的音效由输入法框架(Input Method Framework)独立控制,不受全局系统声音设置的影响。以下是解决这个问题的全面方案: ## 问题原因分析 1. **系统软键盘的特殊性**: - 软键盘由 `InputMethodService` 实现 - 音效控制位于输入法内部实现中 - 不受全局系统音效设置的影响 2. **键盘音效的独立性**: - 每个输入法应用(如 Gboard、Samsung Keyboard)有自己的音效控制 - 系统级别的设置只能影响基本 UI 音效 ## 完整解决方案 ### 方法一:在应用级别禁用键盘音效(推荐) ```java public class KeyboardSoundController { // 禁用当前窗口的键盘音效 public static void disableKeyboardSounds(Activity activity) { // 方法1:禁用整个窗口的声音效果 activity.getWindow().getDecorView().setSoundEffectsEnabled(false); // 方法2:针对 EditText 的特殊处理 View rootView = activity.getWindow().getDecorView(); traverseViews(rootView); } private static void traverseViews(View view) { if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; for (int i = 0; i < group.getChildCount(); i++) { traverseViews(group.getChildAt(i)); } } else if (view instanceof EditText) { disableEditTextSound((EditText) view); } } private static void disableEditTextSound(EditText editText) { // 方法1:禁用点击声音 editText.setSoundEffectsEnabled(false); // 方法2:设置自定义的 OnTouchListener editText.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // 阻止声音反馈 return true; } return false; } }); } } ``` ### 方法二:使用 AudioManager 静音系统音效流 ```java public class AudioUtils { // 静音系统音效 public static void muteSystemSounds(Context context) { AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); // 方法1:设置系统音效流音量为0 audioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, 0, 0); // 方法2:将系统音效流静音 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { audioManager.adjustStreamVolume( AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_MUTE, 0 ); } else { audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true); } } // 恢复系统音效 public static void unmuteSystemSounds(Context context) { AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); // 恢复原始音量设置 int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_SYSTEM); audioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, maxVolume / 2, 0); // 取消静音 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { audioManager.adjustStreamVolume( AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_UNMUTE, 0 ); } else { audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false); } } } ``` **使用示例**: ```java public class MainActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); // 当活动可见时禁用键盘声音 KeyboardSoundController.disableKeyboardSounds(this); AudioUtils.muteSystemSounds(this); } @Override protected void onPause() { super.onPause(); // 当活动不可见时恢复声音 AudioUtils.unmuteSystemSounds(this); } } ``` ### 方法三:自定义输入法(高级方案) ```java public class SilentInputMethodService extends InputMethodService { @Override public View onCreateInputView() { KeyboardView keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard_view, null); Keyboard keyboard = new Keyboard(this, R.xml.qwerty); keyboardView.setKeyboard(keyboard); // 禁用键盘声音 keyboardView.setSoundEffectsEnabled(false); keyboardView.setPreviewEnabled(false); // 同时禁用按键预览 return keyboardView; } @Override public void onPress(int primaryCode) { // 覆盖按键按下事件,不播放声音 } @Override public void onRelease(int primaryCode) { // 覆盖按键释放事件 } } ``` **AndroidManifest.xml 配置**: ```xml <service android:name=".SilentInputMethodService" android:label="@string/silent_keyboard" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> <meta-data android:name="android.view.im" android:resource="@xml/method" /> </service> ``` ### 方法四:特定输入法交互(有限支持) ```java public class KeyboardUtils { // 尝试禁用Gboard的声音(需要Gboard支持) public static void disableGboardSounds(Context context) { try { ContentResolver resolver = context.getContentResolver(); // Gboard设置URI Uri gboardUri = Uri.parse("content://com.google.android.inputmethod.latin.keyboard.settings"); // 设置声音参数为0 ContentValues values = new ContentValues(); values.put("sound_on", 0); values.put("vibrate_on", 0); resolver.update(gboardUri, values, null, null); } catch (Exception e) { // 处理异常 } } // 打开输入法设置 public static void openInputMethodSettings(Context context) { Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (intent.resolveActivity(context.getPackageManager()) != null) { context.startActivity(intent); } else { // 回退到系统设置 context.startActivity(new Intent(Settings.ACTION_SETTINGS)); } } } ``` ## 最佳实践建议 1. **组合使用**: ```java public class SoundManager { public static void disableAllKeyboardSounds(Activity activity) { // 应用级控制 activity.getWindow().getDecorView().setSoundEffectsEnabled(false); // 系统级静音 AudioManager am = (AudioManager) activity.getSystemService(AUDIO_SERVICE); am.setStreamVolume(AudioManager.STREAM_SYSTEM, 0, 0); // 针对特定输入法(如果已知) if (isGboardInstalled(activity)) { KeyboardUtils.disableGboardSounds(activity); } } private static boolean isGboardInstalled(Context context) { // 检查Gboard是否安装 } } ``` 2. **用户选项**: ```java // 在设置中提供选项 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { if ("disable_keyboard_sounds".equals(key)) { boolean disable = prefs.getBoolean(key, false); getWindow().getDecorView().setSoundEffectsEnabled(!disable); } } ``` 3. **兼容性处理**: ```java // 检查设备是否支持声音反馈 public boolean supportsKeyboardSounds() { return !ViewConfiguration.get(this).hasNoSoundEffects(); } // 处理不同Android版本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 使用新的音频管理API } else { // 使用兼容方法 } ``` ## 注意事项 1. **权限要求**: - `AudioManager` 方法需要 `MODIFY_AUDIO_SETTINGS` 权限 - 自定义输入法需要声明 `BIND_INPUT_METHOD` 权限 2. **用户体验**: - 避免完全静音系统声音,除非必要 - 提供用户控制选项 - 在应用退出时恢复原始设置 3. **OEM差异**: - 不同设备厂商可能有不同的输入法实现 - 三星、华为等设备可能需要特殊处理 4. **输入法选择**: ```java // 引导用户使用支持静音的输入法 public void suggestSilentKeyboard() { new AlertDialog.Builder(this) .setTitle("键盘声音问题") .setMessage("建议使用支持静音的输入法") .setPositiveButton("安装静音键盘", (d, w) -> openPlayStore("com.example.silentkeyboard")) .setNeutralButton("打开设置", (d, w) -> KeyboardUtils.openInputMethodSettings(this)) .show(); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值