Skip to content

Commit f9014a4

Browse files
committed
improve apk
1 parent 812dfc0 commit f9014a4

File tree

1 file changed

+46
-22
lines changed

1 file changed

+46
-22
lines changed

android/src/main/java/cn/reactnative/modules/update/DownloadTask.java

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.util.Iterator;
3030
import java.util.zip.ZipEntry;
3131
import java.util.HashMap;
32+
import java.util.regex.Matcher;
33+
import java.util.regex.Pattern;
3234

3335
import okio.BufferedSink;
3436
import okio.BufferedSource;
@@ -285,7 +287,16 @@ private void doFullPatch(DownloadTaskParams param) throws IOException {
285287
}
286288
}
287289

288-
private String findDrawableFallback(String originalToPath, HashMap<String, String> copiesMap, HashMap<String, ZipEntry> availableEntries) {
290+
// Pattern to strip -vN version qualifiers from resource directory paths
291+
// e.g., "res/drawable-xxhdpi-v4/img.png" → "res/drawable-xxhdpi/img.png"
292+
private static final Pattern VERSION_QUALIFIER_PATTERN =
293+
Pattern.compile("-v\\d+(?=/)");
294+
295+
private String normalizeResPath(String path) {
296+
return VERSION_QUALIFIER_PATTERN.matcher(path).replaceAll("");
297+
}
298+
299+
private String findDrawableFallback(String originalToPath, HashMap<String, String> copiesMap, HashMap<String, ZipEntry> availableEntries, HashMap<String, String> normalizedEntryMap) {
289300
// 检查是否是 drawable 路径
290301
if (!originalToPath.contains("drawable")) {
291302
return null;
@@ -309,13 +320,22 @@ private String findDrawableFallback(String originalToPath, HashMap<String, Strin
309320
// 检查这个 key 是否在 copies 映射中
310321
if (copiesMap.containsKey(fallbackToPath)) {
311322
String fallbackFromPath = copiesMap.get(fallbackToPath);
312-
// 检查对应的 value 路径是否在 APK 中存在
323+
// 检查对应的 value 路径是否在 APK 中存在(精确匹配)
313324
if (availableEntries.containsKey(fallbackFromPath)) {
314325
if (UpdateContext.DEBUG) {
315326
Log.d("react-native-update", "Found fallback for " + originalToPath + ": " + fallbackToPath + " -> " + fallbackFromPath);
316327
}
317328
return fallbackFromPath;
318329
}
330+
// 尝试版本限定符无关匹配(APK ↔ AAB 兼容)
331+
String normalizedFallback = normalizeResPath(fallbackFromPath);
332+
String actualEntry = normalizedEntryMap.get(normalizedFallback);
333+
if (actualEntry != null) {
334+
if (UpdateContext.DEBUG) {
335+
Log.d("react-native-update", "Found normalized fallback for " + originalToPath + ": " + fallbackToPath + " -> " + actualEntry);
336+
}
337+
return actualEntry;
338+
}
319339
}
320340
}
321341

@@ -369,6 +389,14 @@ private void copyFromResource(HashMap<String, ArrayList<File> > resToCopy, HashM
369389
}
370390
}
371391

392+
// 构建规范化路径映射,用于 APK ↔ AAB 版本限定符无关匹配
393+
// 例如 "res/drawable-xxhdpi-v4/img.png" → "res/drawable-xxhdpi/img.png"
394+
HashMap<String, String> normalizedEntryMap = new HashMap<>();
395+
for (String entryName : availableEntries.keySet()) {
396+
String normalized = normalizeResPath(entryName);
397+
normalizedEntryMap.putIfAbsent(normalized, entryName);
398+
}
399+
372400
// 使用基础 APK 的 ZipFile 作为主要操作对象
373401
SafeZipFile zipFile = zipFileMap.get(context.getPackageResourcePath());
374402

@@ -387,7 +415,21 @@ private void copyFromResource(HashMap<String, ArrayList<File> > resToCopy, HashM
387415
ZipEntry ze = availableEntries.get(fromPath);
388416
String actualSourcePath = fromPath;
389417

390-
// 如果文件不存在,尝试 fallback
418+
// 如果精确匹配找不到,尝试版本限定符无关匹配(APK ↔ AAB 兼容)
419+
// 例如 __diff.json 中的 "res/drawable-xxhdpi-v4/img.png" 匹配设备上的 "res/drawable-xxhdpi/img.png"
420+
if (ze == null) {
421+
String normalizedFrom = normalizeResPath(fromPath);
422+
String actualEntry = normalizedEntryMap.get(normalizedFrom);
423+
if (actualEntry != null) {
424+
ze = availableEntries.get(actualEntry);
425+
actualSourcePath = actualEntry;
426+
if (UpdateContext.DEBUG) {
427+
Log.d("react-native-update", "Normalized match: " + fromPath + " -> " + actualEntry);
428+
}
429+
}
430+
}
431+
432+
// 如果仍然找不到,尝试 drawable 密度降级 fallback
391433
if (ze == null) {
392434
if (UpdateContext.DEBUG) {
393435
Log.d("react-native-update", "File not found in APK: " + fromPath + ", trying fallback");
@@ -405,28 +447,10 @@ private void copyFromResource(HashMap<String, ArrayList<File> > resToCopy, HashM
405447
if (UpdateContext.DEBUG) {
406448
Log.d("react-native-update", "Found toPath: " + toPath + " for fromPath: " + fromPath);
407449
}
408-
String fallbackFromPath = findDrawableFallback(toPath, copiesMap, availableEntries);
450+
String fallbackFromPath = findDrawableFallback(toPath, copiesMap, availableEntries, normalizedEntryMap);
409451
if (fallbackFromPath != null) {
410452
ze = availableEntries.get(fallbackFromPath);
411453
actualSourcePath = fallbackFromPath;
412-
// 确保 fallback 路径也在 entryToZipFileMap 中
413-
if (!entryToZipFileMap.containsKey(fallbackFromPath)) {
414-
// 查找包含该 fallback 路径的 ZipFile
415-
for (String apkPath : apkPaths) {
416-
SafeZipFile testZipFile = zipFileMap.get(apkPath);
417-
if (testZipFile != null) {
418-
try {
419-
ZipEntry testEntry = testZipFile.getEntry(fallbackFromPath);
420-
if (testEntry != null) {
421-
entryToZipFileMap.put(fallbackFromPath, testZipFile);
422-
break;
423-
}
424-
} catch (Exception e) {
425-
// 继续查找
426-
}
427-
}
428-
}
429-
}
430454
if (UpdateContext.DEBUG) {
431455
Log.w("react-native-update", "Using fallback: " + fallbackFromPath + " for " + fromPath);
432456
}

0 commit comments

Comments
 (0)