需求
系统按键音设置后不起作用,需要放开
系统:Android8.1
相关文件查找
布局文件
通过代码搜索“触摸提示音”,找到string对应的名称:“touch_sounds_title”,最后将文件定位到other_sound_settings.xml以及sound_settings.xml
<!-- Touch sounds -->
<SwitchPreference
android:key="touch_sounds"
android:title="@string/touch_sounds_title" />
java文件
通过touch_sounds定位到文件TouchSoundPreferenceController.java
流程
安卓设置中的声音设置页面
通过ARDC开启监测,定位到当前页面内的activity
找到Settings\AndroidManifest.xml
<activity
android:name="Settings$SoundSettingsActivity"
android:label="@string/sound_settings"
android:icon="@drawable/ic_homepage_sound"
android:exported="true"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
<action android:name="com.android.settings.SOUND_SETTINGS" />
<action android:name="android.settings.SOUND_SETTINGS" />
<action android:name="android.settings.ACTION_OTHER_SOUND_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
<intent-filter android:priority="6">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
<meta-data android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.homepage" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.notification.SoundSettings" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/sound_dashboard_summary"/>
</activity>
其中
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.notification.SoundSettings" />
表明点击会跳转至该页面(fragment),也就是SoundSettings页面
里面有各种声音相关的设置,其中TouchSoundPreferenceController就是触摸提示音相关
TouchSoundPreferenceController
\packages\apps\Settings\src\com\android\settings\notification\TouchSoundPreferenceController.java
public TouchSoundPreferenceController(Context context, SettingsPreferenceFragment parent,
Lifecycle lifecycle) {
super(context, parent, lifecycle);
mPreference = new SettingPref(
TYPE_SYSTEM, KEY_TOUCH_SOUNDS, System.SOUND_EFFECTS_ENABLED, DEFAULT_ON) {
@Override
protected boolean setSetting(final Context context, final int value) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
final AudioManager am =
(AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (value != 0) {
am.loadSoundEffects();
} else {
am.unloadSoundEffects();
}
}
});
return super.setSetting(context, value);
}
};
}
先对System属性值赋值
mPreference = new SettingPref(
TYPE_SYSTEM, KEY_TOUCH_SOUNDS, System.SOUND_EFFECTS_ENABLED, DEFAULT_ON){};
PS:使用adb获取按键提示音的状态
adb shell settings get system sound_effects_enabled
监听按键的变化,来选择加载或关闭提示音
am.loadSoundEffects();
am.unloadSoundEffects();
进入framework层,调用系统服务等
framework
framework\base\media\java\android\media\AudioManager.java
public void loadSoundEffects() {
final IAudioService service = getService();//获取AudioService对象
try {
service.loadSoundEffects();//调用AudioService中方法
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private static IAudioService getService()
{
if (sService != null) {
return sService;
}
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);//通过binder调用AudioService
sService = IAudioService.Stub.asInterface(b);
return sService;
}
framework\base\services\core\java\com\android\server\audio\AudioService.java
public boolean loadSoundEffects() {
int attempts = 3;
LoadSoundEffectReply reply = new LoadSoundEffectReply();
synchronized (reply) {
sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
while ((reply.mStatus == 1) && (attempts-- > 0)) {
try {
reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
} catch (InterruptedException e) {
Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
Thread.currentThread().interrupt();
}
}
}
return (reply.mStatus == 0);
}
其中,发送广播
sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
内部处理
private class AudioHandler extend Handler{
...
@Override
public void handleMessage(Message msg){
switch(msg.what){
case MSG_LOAD_SOUND_EFFECTS:
boolean loaded = onLoadSoundEffects();//调用方法,加载音效
if (msg.obj != null) {
LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
synchronized (reply) {
reply.mStatus = loaded ? 0 : -1;
reply.notify();
}
}
break;
}
}
}
同时也就是在这里,我找到了处理播放音效的方法,之前一直对System.SOUND_EFFECTS_ENABLED赋值不起作用,是该处将onPlaySoundEffect方法进行了屏蔽,放开,编译,刷机,成功,而且默认就是开启的
case MSG_PLAY_SOUND_EFFECT:
onPlaySoundEffect(msg.arg1,msg.arg2);
至于为什么会关闭/隐藏该方法,之前合入三方应用的时候提过这个bug,开启之后会与其他应用冲突,所以选择了隐藏,触摸提示音时不走该方法
待定
- 点击后音效播放的加载、实现流程