Skip to content

Commit 0aa2c6c

Browse files
committed
extend AutomaticAdvancedSettingsExpander by ExpandablePreference
1 parent 0be61fd commit 0aa2c6c

12 files changed

Lines changed: 221 additions & 50 deletions

File tree

AutomaticAdvancedSettingsExpander/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
# Automatic Advanced Settings Expander
22

3-
This Xposed module automatically expands the advanced settings in the Settings app by hooking setInitialExpandedChildrenCount in PreferenceGroup.
3+
This Xposed module automatically expands the advanced settings in the Settings app by hooking PreferenceGroup and ExpandablePreference.
44
I hate to always expand them myself every time.
55

66
Should work on all Android versions where the Settings app uses one of
77

88
- androidx.preference.PreferenceGroup
99
- android.preference.PreferenceGroup
1010
- android.support.v7.preference.PreferenceGroup
11+
- com.android.settingslib.widget.ExpandablePreference
1112

1213
Please report where it stops working so that I can edit the minSdkVersion or add missing classes.
1314

14-
This is an xposed module [part of the LSPosed Module Repo](https://github.com/Xposed-Modules-Repo/de.binarynoise.automaticadvancedsettingsexpander) or
15+
This is an Xposed module [part of the LSPosed Module Repo](https://github.com/Xposed-Modules-Repo/de.binarynoise.automaticadvancedsettingsexpander) or
1516
in the LSPosed App.
1617

1718
| `before` | `after ` |

AutomaticAdvancedSettingsExpander/build.gradle.kts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ android {
88

99
defaultConfig {
1010
minSdk = 16
11-
targetSdk = 33
11+
targetSdk = 36
12+
13+
buildConfigField("String", "SHARED_PREFERENCES_NAME", "\"automatic_advanced_settings_expander\"")
14+
}
15+
16+
buildFeatures {
17+
buildConfig = true
1218
}
1319

1420
signingConfigs {
@@ -17,3 +23,9 @@ android {
1723
}
1824
}
1925
}
26+
27+
dependencies {
28+
implementation(projects.logger)
29+
// implementation(libs.androidx.fragment.ktx)
30+
implementation(libs.androidx.preference.ktx)
31+
}

AutomaticAdvancedSettingsExpander/src/main/AndroidManifest.xml

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

5-
<application android:label="Automatic Advanced Settings Expander">
5+
<application
6+
android:label="Automatic Advanced Settings Expander"
7+
android:theme="@style/AppTheme"
8+
>
69
<meta-data
710
android:name="xposedmodule"
811
android:value="true"
@@ -13,12 +16,25 @@
1316
/>
1417
<meta-data
1518
android:name="xposedminversion"
16-
android:value="53"
19+
android:value="93"
1720
/>
1821
<meta-data
1922
android:name="xposedscope"
2023
android:resource="@array/scope"
2124
/>
25+
26+
<activity
27+
android:name=".SettingsActivity"
28+
android:exported="true"
29+
>
30+
<intent-filter>
31+
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
32+
<action android:name="android.intent.action.MAIN" />
33+
34+
<category android:name="android.intent.category.DEFAULT" />
35+
<category android:name="de.robv.android.xposed.category.MODULE_SETTINGS" />
36+
</intent-filter>
37+
</activity>
2238
</application>
2339

2440
</manifest>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
de.binarynoise.automaticadvancedsettingsexpander.Hook
1+
de.binarynoise.AutomaticAdvancedSettingsExpander.ExpandablePreferenceHook
2+
de.binarynoise.AutomaticAdvancedSettingsExpander.PreferenceGroupChildrenHook
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package de.binarynoise.AutomaticAdvancedSettingsExpander
2+
3+
import android.content.Context
4+
import android.os.Build
5+
import android.util.AttributeSet
6+
import de.robv.android.xposed.IXposedHookLoadPackage
7+
import de.robv.android.xposed.XC_MethodHook
8+
import de.robv.android.xposed.XposedHelpers
9+
import de.robv.android.xposed.callbacks.XC_LoadPackage
10+
11+
class ExpandablePreferenceHook : IXposedHookLoadPackage {
12+
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
13+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.BAKLAVA) return
14+
15+
val ExpandablePreferenceClass = XposedHelpers.findClass("com.android.settingslib.widget.ExpandablePreference", lpparam.classLoader)
16+
XposedHelpers.findAndHookConstructor(
17+
ExpandablePreferenceClass, Context::class.java, AttributeSet::class.java, Int::class.java, Int::class.java,
18+
object : XC_MethodHook() {
19+
override fun afterHookedMethod(param: MethodHookParam) {
20+
XposedHelpers.setBooleanField(param.thisObject, "isExpanded", true)
21+
}
22+
},
23+
)
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package de.binarynoise.AutomaticAdvancedSettingsExpander
2+
3+
import de.binarynoise.logger.Logger.log
4+
import de.robv.android.xposed.IXposedHookLoadPackage
5+
import de.robv.android.xposed.XposedHelpers
6+
import de.robv.android.xposed.callbacks.XC_LoadPackage
7+
import de.robv.android.xposed.XC_MethodHook as MethodHook
8+
9+
10+
class PreferenceGroupChildrenHook : IXposedHookLoadPackage {
11+
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
12+
val packages = arrayOf(
13+
"androidx.preference",
14+
"android.preference",
15+
"android.support.v7.preference",
16+
)
17+
18+
val classes = arrayOf("PreferenceGroup")
19+
20+
val hook = object : MethodHook() {
21+
override fun beforeHookedMethod(param: MethodHookParam) {
22+
log("expandedCount would have been set to ${param.args[0]}, but setting to Int.MAX_VALUE instead")
23+
param.args[0] = Int.MAX_VALUE
24+
}
25+
}
26+
27+
packages.forEach { pkg ->
28+
classes.forEach { cls ->
29+
try {
30+
XposedHelpers.findAndHookMethod("$pkg.$cls", lpparam.classLoader, "setInitialExpandedChildrenCount", Int::class.java, hook)
31+
log("Hooked $pkg.$cls")
32+
} catch (_: NoSuchMethodError) {
33+
} catch (_: NoSuchMethodException) {
34+
} catch (_: XposedHelpers.ClassNotFoundError) {
35+
} catch (_: ClassNotFoundException) {
36+
} catch (e: Exception) {
37+
log("failed to hook", e)
38+
}
39+
}
40+
}
41+
}
42+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package de.binarynoise.AutomaticAdvancedSettingsExpander
2+
3+
import kotlin.contracts.ExperimentalContracts
4+
import kotlin.contracts.InvocationKind
5+
import kotlin.contracts.contract
6+
import android.os.Build
7+
import android.os.Bundle
8+
import androidx.fragment.app.FragmentActivity
9+
import androidx.preference.Preference
10+
import androidx.preference.PreferenceFragmentCompat
11+
import androidx.preference.PreferenceGroup
12+
import androidx.preference.SwitchPreference
13+
import androidx.preference.children
14+
import de.binarynoise.AutomaticAdvancedSettingsExpander.BuildConfig.SHARED_PREFERENCES_NAME
15+
16+
class SettingsActivity : FragmentActivity() {
17+
override fun onCreate(savedInstanceState: Bundle?) {
18+
super.onCreate(savedInstanceState)
19+
setContentView(R.layout.settings_activity)
20+
if (savedInstanceState == null) {
21+
supportFragmentManager.beginTransaction().replace(R.id.settings, SettingsFragment()).commit()
22+
}
23+
actionBar?.setDisplayHomeAsUpEnabled(true)
24+
}
25+
26+
override fun onNavigateUp(): Boolean {
27+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
28+
finishAndRemoveTask()
29+
}
30+
return true
31+
}
32+
33+
class SettingsFragment : PreferenceFragmentCompat() {
34+
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
35+
preferenceManager.sharedPreferencesName = SHARED_PREFERENCES_NAME
36+
preferenceManager.sharedPreferencesMode = MODE_WORLD_READABLE
37+
38+
val ctx = preferenceManager.context
39+
preferenceScreen = preferenceManager.createPreferenceScreen(ctx)
40+
preferenceScreen.apply {
41+
addPreference(SwitchPreference(ctx)) {
42+
key = "PreferenceGroupChildrenHook"
43+
title = "Automatically show all children in PreferenceGroups"
44+
setDefaultValue(true)
45+
summary = "Found quite often in the Settings on older Androids"
46+
}
47+
48+
addPreference(SwitchPreference(ctx)) {
49+
key = "ExpandablePreferenceHook"
50+
title = "Automatically expand ExpandablePreferences"
51+
val canUse = Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA
52+
setDefaultValue(canUse)
53+
isEnabled = canUse
54+
summary = "Found in newer Androids (16+) in the Notification Settings"
55+
}
56+
57+
setIconSpaceReservedRecursive(false)
58+
}
59+
}
60+
61+
62+
@OptIn(ExperimentalContracts::class)
63+
inline fun <T : Preference> PreferenceGroup.addPreference(preference: T, setup: T.() -> Unit) {
64+
contract {
65+
callsInPlace(setup, InvocationKind.EXACTLY_ONCE)
66+
}
67+
68+
val isPreferenceGroup = preference is PreferenceGroup
69+
70+
if (isPreferenceGroup) {
71+
// PreferenceGroup needs to be added to the tree before other preferences can be added to it
72+
addPreference(preference)
73+
}
74+
75+
preference.apply(setup)
76+
77+
if (!isPreferenceGroup) {
78+
// normal preferences need the setup applied before being added to the tree
79+
addPreference(preference)
80+
}
81+
}
82+
83+
private fun Preference.setIconSpaceReservedRecursive(iconSpaceReserved: Boolean = false) {
84+
this.isIconSpaceReserved = iconSpaceReserved
85+
if (this is PreferenceGroup) this.children.forEach { it.setIconSpaceReservedRecursive(iconSpaceReserved) }
86+
}
87+
}
88+
}

AutomaticAdvancedSettingsExpander/src/main/java/de/binarynoise/automaticadvancedsettingsexpander/Hook.kt

Lines changed: 0 additions & 44 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout
3+
xmlns:android="http://schemas.android.com/apk/res/android"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent"
6+
style="@style/AppTheme.Edge2EdgeFix"
7+
>
8+
9+
<FrameLayout
10+
android:id="@+id/settings"
11+
android:layout_width="match_parent"
12+
android:layout_height="match_parent"
13+
/>
14+
</LinearLayout>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
4+
<style name="AppTheme"
5+
parent="android:Theme.DeviceDefault.Settings" />
6+
</resources>

0 commit comments

Comments
 (0)