2929import android .content .res .AssetManager ;
3030import android .content .res .Configuration ;
3131import android .content .res .Resources ;
32+ import android .content .res .TypedArray ;
3233import android .content .res .loader .ResourcesLoader ;
3334import android .content .res .loader .ResourcesProvider ;
3435import android .os .Build ;
3536import android .os .Handler ;
3637import android .os .ParcelFileDescriptor ;
3738import android .util .Pair ;
39+ import android .util .TypedValue ;
3840
3941import com .sevtinge .hyperceiler .XposedInit ;
4042import com .sevtinge .hyperceiler .utils .ContextUtils ;
@@ -208,33 +210,52 @@ private void applyHooks() {
208210 switch (method .getName ()) {
209211 case "getInteger" , "getLayout" , "getBoolean" ,
210212 "getDimension" , "getDimensionPixelOffset" ,
211- "getDimensionPixelSize" , "getText" ,
213+ "getDimensionPixelSize" , "getText" , "getFloat" ,
212214 "getIntArray" , "getStringArray" ,
213215 "getTextArray" , "getAnimation" -> {
214216 if (method .getParameterTypes ().length == 1
215217 && method .getParameterTypes ()[0 ].equals (int .class )) {
216- hookResMethod (method .getName (), int .class , hookBefore );
218+ hookResMethod (method .getName (), int .class , hookResBefore );
219+ }
220+ }
221+ case "getColor" -> {
222+ if (method .getParameterTypes ().length == 2 ) {
223+ hookResMethod (method .getName (), int .class , Resources .Theme .class , hookResBefore );
217224 }
218225 }
219226 case "getFraction" -> {
220227 if (method .getParameterTypes ().length == 3 ) {
221- hookResMethod (method .getName (), int .class , int .class , int .class , hookBefore );
228+ hookResMethod (method .getName (), int .class , int .class , int .class , hookResBefore );
222229 }
223230 }
224231 case "getDrawableForDensity" -> {
225232 if (method .getParameterTypes ().length == 3 ) {
226- hookResMethod (method .getName (), int .class , int .class , Resources .Theme .class , hookBefore );
233+ hookResMethod (method .getName (), int .class , int .class , Resources .Theme .class , hookResBefore );
227234 }
228235 }
229236 }
230237 }
238+
239+ Method [] typedMethod = TypedArray .class .getDeclaredMethods ();
240+ for (Method method : typedMethod ) {
241+ switch (method .getName ()) {
242+ case "getColor" -> {
243+ hookTypedMethod (method .getName (), int .class , int .class , hookTypedBefore );
244+ }
245+ }
246+ }
231247 }
232248
233249 private void hookResMethod (String name , Object ... args ) {
234250 XC_MethodHook .Unhook unhook = HookTool .findAndHookMethod (Resources .class , name , args );
235251 unhooks .add (unhook );
236252 }
237253
254+ private void hookTypedMethod (String name , Object ... args ) {
255+ XC_MethodHook .Unhook unhook = HookTool .findAndHookMethod (TypedArray .class , name , args );
256+ unhooks .add (unhook );
257+ }
258+
238259 public void unHookRes () {
239260 if (unhooks .isEmpty ()) {
240261 isInit = false ;
@@ -247,7 +268,27 @@ public void unHookRes() {
247268 isInit = false ;
248269 }
249270
250- private final HookTool .MethodHook hookBefore = new HookTool .MethodHook () {
271+ private final HookTool .MethodHook hookTypedBefore = new HookTool .MethodHook () {
272+ @ Override
273+ protected void before (MethodHookParam param ) {
274+ Resources mResources = (Resources ) XposedHelpers .getObjectField (param .thisObject , "mResources" );
275+ int index = (int ) param .args [0 ];
276+ int [] mData = (int []) XposedHelpers .getObjectField (param .thisObject , "mData" );
277+ int type = mData [index + 0 ];
278+ if (type == TypedValue .TYPE_NULL ) {
279+ return ;
280+ }
281+ int id = mData [index + 3 ];
282+ if (id != 0 ) {
283+ Object value = getTypedArrayReplacement (mResources , id );
284+ if (value != null ) {
285+ param .setResult (value );
286+ }
287+ }
288+ }
289+ };
290+
291+ private final HookTool .MethodHook hookResBefore = new HookTool .MethodHook () {
251292 @ Override
252293 protected void before (MethodHookParam param ) {
253294 Context context ;
@@ -397,4 +438,41 @@ else if ("getDrawableForDensity".equals(method) || "getFraction".equals(method))
397438 }
398439 return null ;
399440 }
441+
442+ private Object getTypedArrayReplacement (Resources resources , int id ) {
443+ if (id != 0 ) {
444+ String pkgName = null ;
445+ String resType = null ;
446+ String resName = null ;
447+ try {
448+ pkgName = resources .getResourcePackageName (id );
449+ resType = resources .getResourceTypeName (id );
450+ resName = resources .getResourceEntryName (id );
451+ } catch (Throwable ignore ) {
452+ }
453+ if (pkgName == null || resType == null || resName == null ) return null ;
454+
455+ try {
456+ String resFullName = pkgName + ":" + resType + "/" + resName ;
457+ String resAnyPkgName = "*:" + resType + "/" + resName ;
458+
459+ Pair <ReplacementType , Object > replacement = null ;
460+ if (replacements .containsKey (resFullName )) {
461+ replacement = replacements .get (resFullName );
462+ } else if (replacements .containsKey (resAnyPkgName )) {
463+ replacement = replacements .get (resAnyPkgName );
464+ }
465+ if (replacement != null ) {
466+ switch (replacement .first ) {
467+ case OBJECT -> {
468+ return replacement .second ;
469+ }
470+ }
471+ }
472+ } catch (Throwable e ) {
473+ XposedLogUtils .logE ("getTypedArrayReplacement" , e );
474+ }
475+ }
476+ return null ;
477+ }
400478}
0 commit comments