Skip to content

Commit c27097f

Browse files
Implement disable screenshot sounds
1 parent e5d1632 commit c27097f

File tree

13 files changed

+172
-5
lines changed

13 files changed

+172
-5
lines changed

DisableSounds/build.gradle.kts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,12 @@ android {
1111
targetSdk = 36
1212
}
1313
}
14+
15+
dependencies {
16+
// fragment-ktx is included as transitive dependency through preference-ktx
17+
// the transitive dependency is a lower version though, which allows minSdk 17,
18+
// while explicit mention with the latest version forced minSdk 21
19+
//implementation(libs.androidx.fragment.ktx)
20+
implementation(libs.androidx.preference.ktx)
21+
implementation(libs.kotlinx.coroutines.guava)
22+
}

DisableSounds/src/main/AndroidManifest.xml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,31 @@
22
<manifest
33
xmlns:android="http://schemas.android.com/apk/res/android">
44

5-
<application android:label="DisableSounds">
5+
<application android:label="@string/app_name">
6+
<activity
7+
android:name=".SettingsActivity"
8+
android:exported="true"
9+
android:excludeFromRecents="true"
10+
android:label="@string/title_activity_settings"
11+
android:theme="@style/AppTheme"
12+
>
13+
<intent-filter>
14+
<action android:name="android.intent.action.MAIN" />
15+
<category android:name="de.robv.android.xposed.category.MODULE_SETTINGS" />
16+
</intent-filter>
17+
</activity>
18+
619
<meta-data
720
android:name="xposedmodule"
821
android:value="true"
922
/>
1023
<meta-data
1124
android:name="xposeddescription"
12-
android:value="Disable various system sounds"
25+
android:value="@string/description"
1326
/>
1427
<meta-data
1528
android:name="xposedminversion"
16-
android:value="53"
29+
android:value="93"
1730
/>
1831
<meta-data
1932
android:name="xposedscope"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
com.programminghoch10.DisableSounds.DisableForcedCameraSoundHook
2+
com.programminghoch10.DisableSounds.DisableScreenshotSoundHook

DisableSounds/src/main/java/com/programminghoch10/DisableSounds/DisableForcedCameraSoundHook.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.programminghoch10.DisableSounds
33
import android.content.res.XResources
44
import android.media.MediaActionSound
55
import android.os.Build
6-
import android.util.Log
76
import de.robv.android.xposed.IXposedHookLoadPackage
87
import de.robv.android.xposed.IXposedHookZygoteInit
98
import de.robv.android.xposed.XC_MethodReplacement
@@ -12,7 +11,6 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage
1211

1312
class DisableForcedCameraSoundHook : IXposedHookLoadPackage, IXposedHookZygoteInit {
1413
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
15-
Log.d(TAG, "handleLoadPackage: loaded ${this::class.java.simpleName} with package ${lpparam.packageName}")
1614
if (lpparam.packageName == "android") {
1715
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
1816
val AudioServiceClass = XposedHelpers.findClass("com.android.server.audio.AudioService", lpparam.classLoader)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.programminghoch10.DisableSounds
2+
3+
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import android.media.MediaActionSound
6+
import android.os.Build
7+
import com.google.common.util.concurrent.Futures
8+
import de.robv.android.xposed.IXposedHookLoadPackage
9+
import de.robv.android.xposed.XC_MethodHook
10+
import de.robv.android.xposed.XC_MethodReplacement
11+
import de.robv.android.xposed.XSharedPreferences
12+
import de.robv.android.xposed.XposedHelpers
13+
import de.robv.android.xposed.callbacks.XC_LoadPackage
14+
15+
class DisableScreenshotSoundHook : IXposedHookLoadPackage {
16+
@SuppressLint("ObsoleteSdkInt")
17+
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
18+
if (lpparam.packageName != "com.android.systemui") return
19+
val sharedPreferences = XSharedPreferences(BuildConfig.APPLICATION_ID, SHARED_PREFERENCES_NAME)
20+
if (!sharedPreferences.getBoolean("screenshot", false)) return
21+
22+
when {
23+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> XposedHelpers.findAndHookMethod(
24+
"com.android.systemui.screenshot.ScreenshotSoundControllerImpl",
25+
lpparam.classLoader,
26+
"playScreenshotSoundAsync",
27+
XC_MethodReplacement.DO_NOTHING,
28+
)
29+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ->
30+
// TODO: check if inlined by r8 on 33
31+
XposedHelpers.findAndHookMethod(
32+
"com.android.systemui.screenshot.ScreenshotController",
33+
lpparam.classLoader,
34+
"playCameraSound",
35+
XC_MethodReplacement.DO_NOTHING,
36+
)
37+
38+
}
39+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
40+
val ScreenshotControllerClass = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
41+
XposedHelpers.findClass("com.android.systemui.screenshot.ScreenshotController", lpparam.classLoader)
42+
} else {
43+
XposedHelpers.findClass("com.android.systemui.screenshot.GlobalScreenshot", lpparam.classLoader)
44+
}
45+
46+
var replacementDummy: Any = MediaActionSoundDummy()
47+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) replacementDummy =
48+
Futures.immediateFuture(replacementDummy)
49+
50+
XposedHelpers.findAndHookConstructor(
51+
ScreenshotControllerClass, Context::class.java, object : XC_MethodHook() {
52+
override fun afterHookedMethod(param: MethodHookParam) {
53+
XposedHelpers.setObjectField(
54+
param.thisObject, "mCameraSound", replacementDummy
55+
)
56+
}
57+
})
58+
}
59+
}
60+
61+
class MediaActionSoundDummy : MediaActionSound() {
62+
override fun load(soundName: Int) {}
63+
override fun play(soundName: Int) {}
64+
override fun release() {}
65+
}
66+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.programminghoch10.DisableSounds
2+
3+
import android.annotation.SuppressLint
4+
import android.os.Bundle
5+
import androidx.fragment.app.FragmentActivity
6+
import androidx.preference.PreferenceFragmentCompat
7+
8+
val SHARED_PREFERENCES_NAME = "disable_sounds"
9+
10+
class SettingsActivity : FragmentActivity() {
11+
override fun onCreate(savedInstanceState: Bundle?) {
12+
super.onCreate(savedInstanceState)
13+
setContentView(R.layout.settings_activity)
14+
if (savedInstanceState == null) {
15+
supportFragmentManager.beginTransaction().replace(R.id.settings, SettingsFragment()).commit()
16+
}
17+
actionBar?.setDisplayHomeAsUpEnabled(true)
18+
}
19+
20+
override fun onNavigateUp(): Boolean {
21+
finish()
22+
return true
23+
}
24+
25+
class SettingsFragment : PreferenceFragmentCompat() {
26+
@SuppressLint("WorldReadableFiles")
27+
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
28+
preferenceManager.sharedPreferencesName = SHARED_PREFERENCES_NAME
29+
preferenceManager.sharedPreferencesMode = MODE_WORLD_READABLE
30+
setPreferencesFromResource(R.xml.root_preferences, rootKey)
31+
}
32+
}
33+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<LinearLayout
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:layout_width="match_parent"
4+
android:layout_height="match_parent"
5+
android:theme="@style/AppTheme.Edge2EdgeFix"
6+
>
7+
8+
<FrameLayout
9+
android:id="@+id/settings"
10+
android:layout_width="match_parent"
11+
android:layout_height="match_parent"
12+
/>
13+
</LinearLayout>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
4+
<style name="AppTheme" parent="@android:style/Theme.DeviceDefault.Settings" />
5+
</resources>

DisableSounds/src/main/res/values/arrays.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<resources>
33
<string-array name="scope">
44
<item>android</item>
5+
<item>com.android.systemui</item>
56
<item>org.lineageos.aperture</item>
67
</string-array>
78
</resources>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="title_activity_settings">DisableSounds Configuration</string>
4+
<string name="app_name">DisableSounds</string>
5+
<string name="description">Disable various system sounds</string>
6+
<string name="disable_screenshot_sound_title">Disable screenshot sound</string>
7+
<string name="disable_screenshot_sound_description">@null</string>
8+
</resources>

0 commit comments

Comments
 (0)