refactor code
This commit is contained in:
@@ -20,7 +20,7 @@ public class ColorReferences {
|
||||
Color.parseColor("#5c9ce6"),
|
||||
Color.parseColor("#518bcc"),
|
||||
Color.parseColor("#74a2d6")
|
||||
);
|
||||
);
|
||||
|
||||
public static List<Integer> mutedAccentColors = Arrays.asList(
|
||||
Color.parseColor("#663f8ae0"),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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<Integer> 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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<VTLColor> 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<VTLColor> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<String, WeakReference<?>>) 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,16 +30,16 @@ public class PalettesManager {
|
||||
|
||||
private final List<VTLPalette> 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())
|
||||
|
||||
@@ -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]*/));
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user