From 44aff4f30d9b130a003d45bcb33acf2f339e7cba Mon Sep 17 00:00:00 2001 From: gdlbo <41114720+gdlbo@users.noreply.github.com> Date: Sun, 19 Feb 2023 16:49:02 +0300 Subject: [PATCH] refactor code --- .../vtosters/lite/themes/ColorReferences.java | 2 +- .../ru/vtosters/lite/themes/ThemesCore.java | 12 +- .../vtosters/lite/themes/ThemesManager.java | 47 +++--- .../ru/vtosters/lite/themes/VTLResources.java | 48 +++--- .../vtosters/lite/themes/items/VTLColor.java | 1 + .../lite/themes/items/VTLPalette.java | 65 ++++---- .../themes/loaders/AssetManagerHelper.java | 7 +- .../lite/themes/loaders/ResourcesLoader.java | 156 +++++++++--------- .../lite/themes/palettes/PalettesManager.java | 8 +- .../lite/themes/utils/ArscEditor.java | 18 +- .../lite/themes/utils/RecolorUtils.java | 4 +- 11 files changed, 182 insertions(+), 186 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/themes/ColorReferences.java b/app/src/main/java/ru/vtosters/lite/themes/ColorReferences.java index 2348c1f51..6e93451a4 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/ColorReferences.java +++ b/app/src/main/java/ru/vtosters/lite/themes/ColorReferences.java @@ -20,7 +20,7 @@ public class ColorReferences { Color.parseColor("#5c9ce6"), Color.parseColor("#518bcc"), Color.parseColor("#74a2d6") - ); + ); public static List mutedAccentColors = Arrays.asList( Color.parseColor("#663f8ae0"), diff --git a/app/src/main/java/ru/vtosters/lite/themes/ThemesCore.java b/app/src/main/java/ru/vtosters/lite/themes/ThemesCore.java index 5b625aa35..9ddbfa2f7 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/ThemesCore.java +++ b/app/src/main/java/ru/vtosters/lite/themes/ThemesCore.java @@ -4,9 +4,7 @@ import android.annotation.SuppressLint; import android.content.Context; import android.util.SparseBooleanArray; import android.util.SparseIntArray; - import androidx.annotation.IdRes; - import com.vtosters.lite.R; import ru.vtosters.lite.utils.ThemesUtils; @@ -94,7 +92,7 @@ public class ThemesCore { themedColors.put(R.attr.accentColor, accentColor); themedColors.put(R.attr.text_name, accentColor); themedColors.put(R.attr.tabbar_active_icon, accentColor); - + // themedColors.put(com.vtosters.lite.R.attr.header_background, accentColor); // themedColors.put(com.vtosters.lite.R.attr.header_alternate_background, accentColor); // themedColors.put(com.vtosters.lite.R.attr.header_background_before_blur, accentColor); @@ -172,13 +170,13 @@ public class ThemesCore { if (ThemesUtils.isDarkTheme()) { return (themedColors.get(attrID) != 0 && ACCENT_THEME_ONLY_DARK.get(attrID, true) && ( ThemesUtils.isMilkshake() ? - ACCENT_THEME_ONLY_MILK_DARK.get(attrID, true) : - ACCENT_THEME_ONLY_NOMILK_DARK.get(attrID, true))); + ACCENT_THEME_ONLY_MILK_DARK.get(attrID, true) : + ACCENT_THEME_ONLY_NOMILK_DARK.get(attrID, true))); } else { return (themedColors.get(attrID) != 0 && ACCENT_THEME_ONLY_LIGHT.get(attrID, true) && ( ThemesUtils.isMilkshake() ? - ACCENT_THEME_ONLY_MILK_LIGHT.get(attrID, true) : - ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true))); + ACCENT_THEME_ONLY_MILK_LIGHT.get(attrID, true) : + ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true))); } } else { return themedColors.get(attrID) != 0; diff --git a/app/src/main/java/ru/vtosters/lite/themes/ThemesManager.java b/app/src/main/java/ru/vtosters/lite/themes/ThemesManager.java index 8514dc689..b5711f334 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/ThemesManager.java +++ b/app/src/main/java/ru/vtosters/lite/themes/ThemesManager.java @@ -10,7 +10,10 @@ import ru.vtosters.lite.themes.utils.ArscEditor; import ru.vtosters.lite.utils.IOUtils; import ru.vtosters.lite.utils.ThemesUtils; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; @@ -129,24 +132,24 @@ public class ThemesManager { Log.d("ThemesManager", "init paths"); initPaths(app); - if(hasTmpArchive() && !ThemesUtils.isMonetTheme()) { + if (hasTmpArchive() && !ThemesUtils.isMonetTheme()) { ResourcesLoader.init(app); ResourcesLoader.load(app, resTmpZipFile.getAbsolutePath(), assetsZipFile.getAbsolutePath(), false); } - } catch(Exception e) { - Log.e("ThemesManager", e+""); + } catch (Exception e) { + Log.e("ThemesManager", String.valueOf(e)); } } private static void initPaths(Context context) { mainDir = new File(context.getFilesDir(), "VTLThemes"); - if(!mainDir.exists()) mainDir.mkdir(); + if (!mainDir.exists()) mainDir.mkdir(); binDir = new File(mainDir, "bin"); - if(!binDir.exists()) mainDir.mkdir(); + if (!binDir.exists()) mainDir.mkdir(); palettesDir = new File(mainDir, "palettes"); - if(!palettesDir.exists()) palettesDir.mkdir(); + if (!palettesDir.exists()) palettesDir.mkdir(); assetsZipFile = new File(binDir, "assets.zip"); resZipFile = new File(binDir, "res.zip"); @@ -155,32 +158,32 @@ public class ThemesManager { } public static void generateBins(Context context) - throws IOException { - try(final var apk = new ZipFile(context.getApplicationInfo().sourceDir)) { - for(var filename : NAMES) { + throws IOException { + try (final var apk = new ZipFile(context.getApplicationInfo().sourceDir)) { + for (var filename : NAMES) { final var bin = new File(binDir, filename); - if(!bin.exists()) - if(filename.contains(".")) extractFile(apk, filename, bin); + if (!bin.exists()) + if (filename.contains(".")) extractFile(apk, filename, bin); else extractAndCompressDirectory(apk, filename, new File(binDir, filename + ".zip")); } } } private static void extractFile(ZipFile apk, String name, File out) - throws IOException { + throws IOException { final var is = apk.getInputStream(apk.getEntry(name)); - if(!out.exists()) out.getParentFile().mkdirs(); + if (!out.exists()) out.getParentFile().mkdirs(); IOUtils.copy(is, out); } private static void extractAndCompressDirectory(ZipFile apk, String dirName, File out) - throws IOException { + throws IOException { final var zos = new ZipOutputStream(new FileOutputStream(out)); - try(zos) { + try (zos) { final var entries = apk.entries(); - while(entries.hasMoreElements()) { + while (entries.hasMoreElements()) { final var entry = entries.nextElement(); - if(!entry.getName().startsWith(dirName + "/")) continue; + if (!entry.getName().startsWith(dirName + "/")) continue; zos.putNextEntry(new ZipEntry(entry.getName())); @@ -202,12 +205,12 @@ public class ThemesManager { } public static void generateTempResArchive(int accentColor) - throws IOException { + throws IOException { final var resZip = new ZipFile(resZipFile); final var zos = new ZipOutputStream(new FileOutputStream(resTmpZipFile)); - try(zos) { + try (zos) { final var entries = resZip.entries(); - while(entries.hasMoreElements()) { + while (entries.hasMoreElements()) { final var entry = entries.nextElement(); final var is = resZip.getInputStream(entry); @@ -219,7 +222,7 @@ public class ThemesManager { } final var arsc = new BinaryResourceFile(IOUtils.readFully(resourcesArscFile)); - if(!ArscEditor.changeColors(arsc, ACCENT_COLORS, accentColor)) { + if (!ArscEditor.changeColors(arsc, ACCENT_COLORS, accentColor)) { resZip.close(); resTmpZipFile.delete(); throw new IOException("Error while generating res.tmp.res"); diff --git a/app/src/main/java/ru/vtosters/lite/themes/VTLResources.java b/app/src/main/java/ru/vtosters/lite/themes/VTLResources.java index 32ddc7b48..4fa09733f 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/VTLResources.java +++ b/app/src/main/java/ru/vtosters/lite/themes/VTLResources.java @@ -7,21 +7,17 @@ import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; - import androidx.annotation.Nullable; +import ru.vtosters.lite.utils.ThemesUtils; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; -import ru.vtosters.lite.utils.ThemesUtils; - public class VTLResources extends Resources { private static final String TAG = "VTLResources"; - private final Context context; - private static Field typedArrayField; - private static final List attributesToTheme = new ArrayList<>(); + private static Field typedArrayField; static { try { @@ -36,12 +32,28 @@ public class VTLResources extends Resources { attributesToTheme.add(16843173); } + private final Context context; + public VTLResources(Context context, Resources parent) { super(parent.getAssets(), parent.getDisplayMetrics(), parent.getConfiguration()); this.context = context; // Log.d(TAG, "VTLResources: init"); } + private static boolean isAttrThemeable(int attrID) { + return !ThemesUtils.isDarkTheme() && attrID == com.vtosters.lite.R.attr.button_primary_background; + } + + private static int[] getArrayData(TypedArray arr) { + try { + return (int[]) typedArrayField.get(arr); + } catch (IllegalAccessException e) { + Log.e(TAG, "getArrayData: ", e); + e.printStackTrace(); + return new int[0]; + } + } + @Override public TypedArray obtainAttributes(AttributeSet set, int[] attrs) { var typedArray = super.obtainAttributes(set, attrs); @@ -50,13 +62,13 @@ public class VTLResources extends Resources { try { int attrID = attrs[i]; if (attributesToTheme.contains(attrID)) { - int type = data[i*6]; - int cnt = data[(i*6)+1]; + int type = data[i * 6]; + int cnt = data[(i * 6) + 1]; if (type == TypedValue.TYPE_ATTRIBUTE && isAttrThemeable(cnt)) { - data[i*6] = TypedValue.TYPE_INT_COLOR_RGB8; - data[(i*6)+1] = ThemesUtils.getAccentColor(); - data[(i*6)+2] = 0; // clear reference content + data[i * 6] = TypedValue.TYPE_INT_COLOR_RGB8; + data[(i * 6) + 1] = ThemesUtils.getAccentColor(); + data[(i * 6) + 2] = 0; // clear reference content } } } catch (Exception e) { @@ -75,18 +87,4 @@ public class VTLResources extends Resources { } return drawable; } - - private static boolean isAttrThemeable(int attrID) { - return !ThemesUtils.isDarkTheme() && attrID == com.vtosters.lite.R.attr.button_primary_background; - } - - private static int[] getArrayData(TypedArray arr) { - try { - return (int[]) typedArrayField.get(arr); - } catch (IllegalAccessException e) { - Log.e(TAG, "getArrayData: ", e); - e.printStackTrace(); - return new int[0]; - } - } } \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/themes/items/VTLColor.java b/app/src/main/java/ru/vtosters/lite/themes/items/VTLColor.java index 1c086ee17..87854749d 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/items/VTLColor.java +++ b/app/src/main/java/ru/vtosters/lite/themes/items/VTLColor.java @@ -10,6 +10,7 @@ public class VTLColor { this.id = id; this.color = color; } + public VTLColor(String resName, int id, int color) { this.resName = resName; this.id = id; diff --git a/app/src/main/java/ru/vtosters/lite/themes/items/VTLPalette.java b/app/src/main/java/ru/vtosters/lite/themes/items/VTLPalette.java index 19d723329..b7bdb8a1b 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/items/VTLPalette.java +++ b/app/src/main/java/ru/vtosters/lite/themes/items/VTLPalette.java @@ -1,7 +1,6 @@ package ru.vtosters.lite.themes.items; import android.graphics.Color; - import org.json.JSONException; import org.json.JSONObject; @@ -25,38 +24,6 @@ public class VTLPalette { this.colors = colors; } - public VTLPalette setId(String id) { - this.id = id; - return this; - } - - public VTLPalette setName(String name) { - this.name = name; - return this; - } - - public VTLPalette setAuthor(String author) { - this.author = author; - return this; - } - - public VTLPalette setColors(List colors) { - this.colors = colors; - return this; - } - - public VTLPalette setColor(String name, int color) { - this.colors.add(new VTLColor(name, 0, color)); - return this; - } - - public int getColor(String name) { - for (var item : colors) - if (name.equals(item.resName)) - return item.color; - return -1; - } - public static VTLPalette fromJson(JSONObject json) throws JSONException { var palette = new VTLPalette() .setId(json.optString("palette_id")) @@ -91,4 +58,36 @@ public class VTLPalette { .setAuthor(author) .setColors(colors); } + + public VTLPalette setId(String id) { + this.id = id; + return this; + } + + public VTLPalette setName(String name) { + this.name = name; + return this; + } + + public VTLPalette setAuthor(String author) { + this.author = author; + return this; + } + + public VTLPalette setColors(List colors) { + this.colors = colors; + return this; + } + + public VTLPalette setColor(String name, int color) { + this.colors.add(new VTLColor(name, 0, color)); + return this; + } + + public int getColor(String name) { + for (var item : colors) + if (name.equals(item.resName)) + return item.color; + return -1; + } } diff --git a/app/src/main/java/ru/vtosters/lite/themes/loaders/AssetManagerHelper.java b/app/src/main/java/ru/vtosters/lite/themes/loaders/AssetManagerHelper.java index 7ff60dc71..4fb57aada 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/loaders/AssetManagerHelper.java +++ b/app/src/main/java/ru/vtosters/lite/themes/loaders/AssetManagerHelper.java @@ -15,6 +15,7 @@ public class AssetManagerHelper { private final static Method addAssetPathMtd; private final static Method addAssetPathAsSharedLibraryMtd; private final static Method addOverlayPathMtd; + static { try { getAssetPathMtd = ReflectionUtils.findMethod(Class.forName("android.content.res.ApkAssets"), "getAssetPath"); @@ -22,7 +23,7 @@ public class AssetManagerHelper { addAssetPathMtd = AssetManager.class.getMethod("addAssetPath", String.class); addAssetPathAsSharedLibraryMtd = AssetManager.class.getMethod("addAssetPathAsSharedLibrary", String.class); addOverlayPathMtd = AssetManager.class.getMethod("addOverlayPath", String.class); - } catch(ClassNotFoundException | NoSuchMethodException e) { + } catch (ClassNotFoundException | NoSuchMethodException e) { throw new RuntimeException(); } } @@ -31,9 +32,9 @@ public class AssetManagerHelper { throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { Object[] apkAssetsArr = (Object[]) getAssetPathMtd.invoke(assetManager); // By default, base apk is the last element of array if is not, for execution speed, we should iterate array from the end to the beginning - for(int i = apkAssetsArr.length - 1; i >= 0; i--) { + for (int i = apkAssetsArr.length - 1; i >= 0; i--) { final String pathname = (String) getApkAssetsMtd.invoke(apkAssetsArr[i]); - if(pathname.contains(packagename)) return pathname; + if (pathname.contains(packagename)) return pathname; } throw new NullPointerException(); diff --git a/app/src/main/java/ru/vtosters/lite/themes/loaders/ResourcesLoader.java b/app/src/main/java/ru/vtosters/lite/themes/loaders/ResourcesLoader.java index 6a9f9934e..e4c4ec8b6 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/loaders/ResourcesLoader.java +++ b/app/src/main/java/ru/vtosters/lite/themes/loaders/ResourcesLoader.java @@ -13,7 +13,6 @@ import ru.vtosters.lite.utils.ReflectionUtils; import java.io.File; import java.lang.ref.WeakReference; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; @@ -47,22 +46,22 @@ public class ResourcesLoader { Class loadedApkClz; try { loadedApkClz = Class.forName("android.app.LoadedApk"); - } catch(ClassNotFoundException ignored) { + } catch (ClassNotFoundException ignored) { loadedApkClz = Class.forName("android.app.ActivityThread$PackagenInfo"); } resDirFld = ReflectionUtils.findField(loadedApkClz, "mResDir"); packagesFld = ReflectionUtils.findField(activityThreadClz, "mPackages"); - if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) resourcePackagesFld = ReflectionUtils.findField(activityThreadClz, "mResourcePackages"); // fix jianGuo pro has private field 'mAssets' with Resource // try use mResourcesImpl first - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) try { // N moved the mAssets inside an mResourcesImpl field resourcesImplFld = ReflectionUtils.findField(Resources.class, "mResourcesImpl"); - } catch(Throwable ignored) { + } catch (Throwable ignored) { // for safety assetsFld = ReflectionUtils.findField(Resources.class, "mAssets"); } @@ -83,8 +82,8 @@ public class ResourcesLoader { } catch (Throwable ignored) { // Ignored. } - } catch(Throwable e) { - Log.d("WTF", e+""); + } catch (Throwable e) { + Log.d("WTF", String.valueOf(e)); } } @@ -114,18 +113,18 @@ public class ResourcesLoader { final ApplicationInfo appInfo = context.getApplicationInfo(); final Field[] packagesFlds = Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1 - ? new Field[] { packagesFld, resourcePackagesFld } - : new Field[] { packagesFld }; - for(var fld : packagesFlds) { + ? new Field[]{packagesFld, resourcePackagesFld} + : new Field[]{packagesFld}; + for (var fld : packagesFlds) { final var value = fld.get(sCurrentActivityThread); - for(var entry + for (var entry : ((Map>) value).entrySet()) { final var loadedApk = entry.getValue().get(); - if(loadedApk == null) continue; + if (loadedApk == null) continue; final var resDirPath = (String) resDirFld.get(loadedApk); - if(appInfo.sourceDir.equals(resDirPath)) + if (appInfo.sourceDir.equals(resDirPath)) resDirFld.set(loadedApk, resPath); } } @@ -137,16 +136,16 @@ public class ResourcesLoader { sAssetManager = AssetManager.class.newInstance(); // Create a new AssetManager instance and point it to the resources installed under - if(AssetManagerHelper.addAssetPath(sAssetManager, resPath) == 0 - || AssetManagerHelper.addAssetPath(sAssetManager, assetsPath) == 0) + if (AssetManagerHelper.addAssetPath(sAssetManager, resPath) == 0 + || AssetManagerHelper.addAssetPath(sAssetManager, assetsPath) == 0) throw new IllegalStateException("Could not create new AssetManager"); // Add SharedLibraries to AssetManager for resolve system resources not found issue // This influence SharedLibrary Package ID - if(shouldAddSharedLibraryAssets(appInfo)) { - for(var sharedLibrary : appInfo.sharedLibraryFiles) { - if(sharedLibrary.endsWith(".apk")) continue; - if(AssetManagerHelper.addAssetPathAsSharedLibrary(sAssetManager, sharedLibrary) == 0) + if (shouldAddSharedLibraryAssets(appInfo)) { + for (var sharedLibrary : appInfo.sharedLibraryFiles) { + if (sharedLibrary.endsWith(".apk")) continue; + if (AssetManagerHelper.addAssetPathAsSharedLibrary(sAssetManager, sharedLibrary) == 0) throw new IllegalStateException("AssetManager add SharedLibrary Fail"); Log.i("ResourcesLoader", "addAssetPathAsSharedLibrary " + sharedLibrary); } @@ -158,9 +157,9 @@ public class ResourcesLoader { stringBlocksFld.set(sAssetManager, null); ensureStringBlocksMtd.invoke(sAssetManager); } - for(var wr : sResourceReferences) { + for (var wr : sResourceReferences) { final var resources = wr.get(); - if(resources == null) continue; + if (resources == null) continue; // Set the AssetManager of the Resources instance to our brand new one try { @@ -215,6 +214,61 @@ public class ResourcesLoader { } } + private static boolean isPatchedResModifiedAfterLastLoad(String patchedResPath) { + long patchedResModifiedTime; + try { + patchedResModifiedTime = new File(patchedResPath).lastModified(); + } catch (Throwable thr) { + thr.printStackTrace(); + patchedResModifiedTime = 0L; + } + if (patchedResModifiedTime == 0) { + return false; + } + return patchedResModifiedTime != storedPatchedResModifiedTime; + } + + private static void recordCurrentPatchedResModifiedTime(String patchedResPath) { + try { + storedPatchedResModifiedTime = new File(patchedResPath).lastModified(); + } catch (Throwable thr) { + thr.printStackTrace(); + storedPatchedResModifiedTime = 0L; + } + } + + /** + * Why must I do these? + * Resource has mTypedArrayPool field, which just like Message Poll to reduce gc + * MiuiResource change TypedArray to MiuiTypedArray, but it get string block from offset instead of assetManager + */ + private static void clearPreloadTypedArrayIssue(Resources resources) { + // Perform this trick not only in Miui system since we can't predict if any other + // manufacturer would do the same modification to Android. + // if (!isMiuiSystem) { + // return; + // } + Log.w("ResourcesLoader", "try to clear typedArray cache!"); + // Clear typedArray cache. + try { + final Field typedArrayPoolField = ReflectionUtils.findField(Resources.class, "mTypedArrayPool"); + final Object origTypedArrayPool = typedArrayPoolField.get(resources); + final Method acquireMethod = ReflectionUtils.findMethod(origTypedArrayPool, "acquire"); + while (true) { + if (acquireMethod.invoke(origTypedArrayPool) == null) { + break; + } + } + } catch (Throwable ignored) { + Log.e("ResourcesLoader", "clearPreloadTypedArrayIssue failed, ignore error: " + ignored); + } + } + + private static boolean shouldAddSharedLibraryAssets(ApplicationInfo applicationInfo) { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && applicationInfo != null && + applicationInfo.sharedLibraryFiles != null; + } + private static final class ResourceInsuranceHandlerCallback implements Handler.Callback { private static final String LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME = "android.app.servertransaction.LaunchActivityItem"; @@ -240,7 +294,7 @@ public class ResourcesLoader { RELAUNCH_ACTIVITY = fetchMessageId(hClazz, "RELAUNCH_ACTIVITY", 126); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - EXECUTE_TRANSACTION = fetchMessageId(hClazz, "EXECUTE_TRANSACTION ", 159); + EXECUTE_TRANSACTION = fetchMessageId(hClazz, "EXECUTE_TRANSACTION ", 159); } else { EXECUTE_TRANSACTION = -1; } @@ -319,62 +373,4 @@ public class ResourcesLoader { return false; } } - - private static boolean isPatchedResModifiedAfterLastLoad(String patchedResPath) { - long patchedResModifiedTime; - try { - patchedResModifiedTime = new File(patchedResPath).lastModified(); - } catch (Throwable thr) { - thr.printStackTrace(); - patchedResModifiedTime = 0L; - } - if (patchedResModifiedTime == 0) { - return false; - } - if (patchedResModifiedTime == storedPatchedResModifiedTime) { - return false; - } - return true; - } - - private static void recordCurrentPatchedResModifiedTime(String patchedResPath) { - try { - storedPatchedResModifiedTime = new File(patchedResPath).lastModified(); - } catch (Throwable thr) { - thr.printStackTrace(); - storedPatchedResModifiedTime = 0L; - } - } - - /** - * Why must I do these? - * Resource has mTypedArrayPool field, which just like Message Poll to reduce gc - * MiuiResource change TypedArray to MiuiTypedArray, but it get string block from offset instead of assetManager - */ - private static void clearPreloadTypedArrayIssue(Resources resources) { - // Perform this trick not only in Miui system since we can't predict if any other - // manufacturer would do the same modification to Android. - // if (!isMiuiSystem) { - // return; - // } - Log.w("ResourcesLoader", "try to clear typedArray cache!"); - // Clear typedArray cache. - try { - final Field typedArrayPoolField = ReflectionUtils.findField(Resources.class, "mTypedArrayPool"); - final Object origTypedArrayPool = typedArrayPoolField.get(resources); - final Method acquireMethod = ReflectionUtils.findMethod(origTypedArrayPool, "acquire"); - while (true) { - if (acquireMethod.invoke(origTypedArrayPool) == null) { - break; - } - } - } catch (Throwable ignored) { - Log.e("ResourcesLoader", "clearPreloadTypedArrayIssue failed, ignore error: " + ignored); - } - } - - private static boolean shouldAddSharedLibraryAssets(ApplicationInfo applicationInfo) { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && applicationInfo != null && - applicationInfo.sharedLibraryFiles != null; - } } diff --git a/app/src/main/java/ru/vtosters/lite/themes/palettes/PalettesManager.java b/app/src/main/java/ru/vtosters/lite/themes/palettes/PalettesManager.java index fc8666b0e..593e298ec 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/palettes/PalettesManager.java +++ b/app/src/main/java/ru/vtosters/lite/themes/palettes/PalettesManager.java @@ -30,16 +30,16 @@ public class PalettesManager { private final List mPalettes = new ArrayList<>(); + public PalettesManager() { + load(); + } + public static PalettesManager getInstance() { if (sInstance == null) sInstance = new PalettesManager(); return sInstance; } - public PalettesManager() { - load(); - } - public void load() { mPalettes.clear(); if (!PALETTES_DIR.exists()) diff --git a/app/src/main/java/ru/vtosters/lite/themes/utils/ArscEditor.java b/app/src/main/java/ru/vtosters/lite/themes/utils/ArscEditor.java index 26528dc39..c37f8b926 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/utils/ArscEditor.java +++ b/app/src/main/java/ru/vtosters/lite/themes/utils/ArscEditor.java @@ -6,21 +6,21 @@ public class ArscEditor { public static boolean changeColors(BinaryResourceFile arsc, int[] colorIds, int color /*int[] colors*/) { int q = 0; - for(var chunk : arsc.getChunks()) { + for (var chunk : arsc.getChunks()) { final var resourceTableChunk = (ResourceTableChunk) chunk; - for(PackageChunk packageChunk : resourceTableChunk.getPackages()) { - for(TypeSpecChunk typeSpecChunk : packageChunk.getTypeSpecChunks()) { - for(TypeChunk typeChunk : packageChunk.getTypeChunks(typeSpecChunk.getId())) { - if(!"color".equals(typeChunk.getTypeName())) continue; + for (PackageChunk packageChunk : resourceTableChunk.getPackages()) { + for (TypeSpecChunk typeSpecChunk : packageChunk.getTypeSpecChunks()) { + for (TypeChunk typeChunk : packageChunk.getTypeChunks(typeSpecChunk.getId())) { + if (!"color".equals(typeChunk.getTypeName())) continue; - for(var entry : typeChunk.getEntries().entrySet()) { - if(entry.getValue().isComplex()) continue; + for (var entry : typeChunk.getEntries().entrySet()) { + if (entry.getValue().isComplex()) continue; final var id = BinaryResourceIdentifier.create(packageChunk.getId(), typeSpecChunk.getId(), entry.getKey()); - for(int i = 0; i < colorIds.length; ++i) { - if(colorIds[i] != id.resId()) continue; + for (int i = 0; i < colorIds.length; ++i) { + if (colorIds[i] != id.resId()) continue; final var value = entry.getValue(); value.updateValue(new BinaryResourceValue(8, value.value().type(), color /*colors[i]*/)); diff --git a/app/src/main/java/ru/vtosters/lite/themes/utils/RecolorUtils.java b/app/src/main/java/ru/vtosters/lite/themes/utils/RecolorUtils.java index f0236b9d4..d613c7d9a 100644 --- a/app/src/main/java/ru/vtosters/lite/themes/utils/RecolorUtils.java +++ b/app/src/main/java/ru/vtosters/lite/themes/utils/RecolorUtils.java @@ -25,7 +25,7 @@ public class RecolorUtils { return new RecoloredDrawable(res, ThemesUtils.getAccentColor()); } // Get res drawable via id and coloring to accent - public static int recolorHexColor(int i){ + public static int recolorHexColor(int i) { var accented = ColorReferences.isAccentedColor(i); var mutedaccented = ColorReferences.isMutedAccentedColor(i); return (accented || mutedaccented) ? (accented ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : i; @@ -56,7 +56,7 @@ public class RecolorUtils { return themeCSL(csl); } // Recolor ColorStateList - public static ColorStateList themeCSL(ColorStateList csl){ + public static ColorStateList themeCSL(ColorStateList csl) { try { int unsel = csl.getColorForState(new int[]{-android.R.attr.state_selected}, Color.BLACK); int sel = csl.getColorForState(new int[]{android.R.attr.state_selected}, Color.BLACK);