Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit dc9ded2

Browse files
committed
1. Improve compatibility
2. Fix install logic
1 parent a23388e commit dc9ded2

File tree

24 files changed

+182
-29
lines changed

24 files changed

+182
-29
lines changed

.idea/misc.xml

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ android {
1212
minSdkVersion 21
1313
//noinspection ExpiredTargetSdkVersion
1414
targetSdkVersion 30
15-
versionCode 76
16-
versionName "3.18.3.2"
15+
versionCode 77
16+
versionName "3.18.3.3"
1717

1818
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1919
multiDexEnabled true
1.5 KB
Binary file not shown.

app/src/main/assets/mods_manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
{
88
"assetPath":"mods/console-commands.zip",
9-
"Name": "Console Commands",
9+
"Name": "ConsoleCommands",
1010
"UniqueID": "SMAPI.ConsoleCommands"
1111
}
1212
]
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package androidx.documentfile.provider;
2+
3+
import android.content.ContentResolver;
4+
import android.content.Context;
5+
import android.database.Cursor;
6+
import android.net.Uri;
7+
import android.provider.DocumentsContract;
8+
import android.text.TextUtils;
9+
import android.util.Log;
10+
11+
12+
import java.util.ArrayList;
13+
import java.util.List;
14+
15+
public class DocumentUtils {
16+
public interface IFileFilter {
17+
boolean accept(String name);
18+
}
19+
private static TreeDocumentFile findFile(Context context, TreeDocumentFile file, String name) {
20+
final ContentResolver resolver = context.getContentResolver();
21+
final Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(file.getUri(), DocumentsContract.getDocumentId(file.getUri()));
22+
Cursor c = null;
23+
try {
24+
c = resolver.query(childrenUri, new String[] {DocumentsContract.Document.COLUMN_DOCUMENT_ID, DocumentsContract.Document.COLUMN_DISPLAY_NAME}, null, null, null);
25+
while (c.moveToNext()) {
26+
final String documentName = c.getString(1);
27+
if (TextUtils.equals(name, documentName)) {
28+
final String documentId = c.getString(0);
29+
final Uri documentUri = DocumentsContract.buildDocumentUriUsingTree(file.getUri(), documentId);
30+
return new TreeDocumentFile(file, context, documentUri);
31+
}
32+
}
33+
} catch (Exception e) {
34+
Log.w("DocumentUtils", "Failed query: " + e);
35+
} finally {
36+
if (c != null) {
37+
c.close();
38+
}
39+
}
40+
return null;
41+
}
42+
public static DocumentFile findFile(Context context, DocumentFile documentFile, String name) {
43+
if (documentFile instanceof TreeDocumentFile)
44+
return findFile(context, (TreeDocumentFile)documentFile, name);
45+
return documentFile.findFile(name);
46+
}
47+
private static List<DocumentFile> filterFiles(Context context, TreeDocumentFile file, IFileFilter filter) {
48+
ContentResolver resolver = context.getContentResolver();
49+
Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(file.getUri(), DocumentsContract.getDocumentId(file.getUri()));
50+
List<DocumentFile> filtered = new ArrayList<>();
51+
Cursor c = null;
52+
try {
53+
c = resolver.query(childrenUri, new String[] {DocumentsContract.Document.COLUMN_DOCUMENT_ID, DocumentsContract.Document.COLUMN_DISPLAY_NAME}, null, null, null);
54+
while (c.moveToNext()) {
55+
String documentName = c.getString(1);
56+
String documentId = c.getString(0);
57+
Uri documentUri = DocumentsContract.buildDocumentUriUsingTree(file.getUri(), documentId);
58+
TreeDocumentFile child = new TreeDocumentFile(file, context, documentUri);
59+
if (child.isDirectory())
60+
filtered.addAll(filterFiles(context, child, filter));
61+
else if (filter.accept(documentName))
62+
filtered.add(child);
63+
}
64+
} catch (Exception e) {
65+
Log.w("DocumentUtils", "Failed query: " + e);
66+
} finally {
67+
if (c != null) {
68+
c.close();
69+
}
70+
}
71+
return filtered;
72+
}
73+
public static List<DocumentFile> filterFiles(Context context, DocumentFile documentFile, IFileFilter filter) {
74+
if (documentFile instanceof TreeDocumentFile)
75+
return filterFiles(context, (TreeDocumentFile)documentFile, filter);
76+
List<DocumentFile> filtered = new ArrayList<>();
77+
DocumentFile[] files = documentFile.listFiles();
78+
if (files != null) {
79+
for (DocumentFile file : files) {
80+
if (filter.accept(file.getName()))
81+
filtered.add(file);
82+
}
83+
}
84+
return filtered;
85+
}
86+
}

app/src/main/java/com/zane/smapiinstaller/logic/ApkPatcher.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ public Tuple2<String, String[]> extract(int advancedStage) {
173173
* 将指定APK文件重新打包,添加SMAPI,修改AndroidManifest.xml,同时验证版本是否正确
174174
*
175175
* @param apkPath APK文件路径
176-
* @param second
177176
* @param targetFile 目标文件
178177
* @param isAdvanced 是否高级模式
179178
* @return 是否成功打包

app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import androidx.annotation.RequiresApi;
2424
import androidx.documentfile.provider.DocumentFile;
25+
import androidx.documentfile.provider.DocumentUtils;
2526

2627
import com.afollestad.materialdialogs.MaterialDialog;
2728
import com.fasterxml.jackson.core.type.TypeReference;
@@ -275,27 +276,25 @@ public static boolean unpackSmapiFiles(Activity context, String apkPath, boolean
275276
if (CommonLogic.checkDataRootPermission(context)) {
276277
Uri targetDirUri = pathToTreeUri(Constants.TARGET_DATA_FILE_URI);
277278
DocumentFile documentFile = DocumentFile.fromTreeUri(context, targetDirUri);
278-
for (DocumentFile file : documentFile.listFiles()) {
279-
if (file.getName().equals("files")) {
280-
copyDocument(context, new File(basePath, "smapi-internal"), file);
281-
copyDocument(context, new File(basePath, "Mods"), file);
282-
}
279+
DocumentFile filesDoc = DocumentUtils.findFile(context, documentFile, "files");
280+
if(filesDoc != null) {
281+
copyDocument(context, new File(basePath, "smapi-internal"), filesDoc);
283282
}
284283
}
285284
return true;
286285
}
287286

288-
private static void copyDocument(Activity context, File src, DocumentFile dest) {
287+
public static void copyDocument(Activity context, File src, DocumentFile dest) {
289288
if (src.isDirectory()) {
290-
DocumentFile documentFile = dest.findFile(src.getName());
289+
DocumentFile documentFile = DocumentUtils.findFile(context, dest, src.getName());
291290
if (documentFile == null) {
292291
documentFile = dest.createDirectory(src.getName());
293292
}
294293
for (File file : src.listFiles()) {
295294
copyDocument(context, file, documentFile);
296295
}
297296
} else {
298-
DocumentFile documentFile = dest.findFile(src.getName());
297+
DocumentFile documentFile = DocumentUtils.findFile(context, dest, src.getName());
299298
if (documentFile == null) {
300299
documentFile = dest.createFile("application/x-binary", src.getName());
301300
}
@@ -512,7 +511,7 @@ public static void openPermissionSetting(Activity activity) {
512511
}
513512
}
514513

515-
public static boolean checkDataRootPermission(Activity context) {
514+
public static boolean checkDataRootPermission(Context context) {
516515
File pathFrom = new File(FileUtils.getStadewValleyBasePath(), "Android/data/" + Constants.TARGET_PACKAGE_NAME + "/files/");
517516
if (!pathFrom.exists()) {
518517
return false;

app/src/main/java/com/zane/smapiinstaller/logic/ModAssetsManager.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.app.Activity;
44
import android.content.pm.PackageInfo;
5+
import android.net.Uri;
56
import android.util.Log;
67
import android.view.View;
78
import android.widget.Toast;
@@ -45,6 +46,8 @@
4546
import java.util.function.Predicate;
4647
import java.util.stream.Collectors;
4748

49+
import androidx.documentfile.provider.DocumentFile;
50+
import androidx.documentfile.provider.DocumentUtils;
4851
import androidx.navigation.NavController;
4952
import androidx.navigation.Navigation;
5053

@@ -169,6 +172,7 @@ public boolean installDefaultMods() {
169172
}
170173
File modFolder = new File(FileUtils.getStadewValleyBasePath(), Constants.MOD_PATH);
171174
ImmutableListMultimap<String, ModManifestEntry> installedModMap = Multimaps.index(findAllInstalledMods(), ModManifestEntry::getUniqueID);
175+
List<File> unpackedMods = new ArrayList<>();
172176
for (ModManifestEntry mod : modManifestEntries) {
173177
if (installedModMap.containsKey(mod.getUniqueID())) {
174178
ImmutableList<ModManifestEntry> installedMods = installedModMap.get(mod.getUniqueID());
@@ -202,7 +206,9 @@ public boolean installDefaultMods() {
202206
}
203207
if (installedMods.size() > 0) {
204208
try {
205-
ZipUtil.unpack(context.getAssets().open(mod.getAssetPath()), new File(installedMods.get(0).getAssetPath()), (name) -> StringUtils.removeStart(name, mod.getName() + "/"));
209+
File targetFile = new File(installedMods.get(0).getAssetPath());
210+
ZipUtil.unpack(context.getAssets().open(mod.getAssetPath()), targetFile, (name) -> StringUtils.removeStart(name, mod.getName() + "/"));
211+
unpackedMods.add(targetFile);
206212
} catch (IOException e) {
207213
Log.e(TAG, "Install Mod Error", e);
208214
}
@@ -211,10 +217,25 @@ public boolean installDefaultMods() {
211217
}
212218
try {
213219
ZipUtil.unpack(context.getAssets().open(mod.getAssetPath()), modFolder);
220+
unpackedMods.add(new File(modFolder, mod.getName()));
214221
} catch (IOException e) {
215222
Log.e(TAG, "Install Mod Error", e);
216223
}
217224
}
225+
if (CommonLogic.checkDataRootPermission(context)) {
226+
Uri targetDirUri = CommonLogic.pathToTreeUri(Constants.TARGET_DATA_FILE_URI);
227+
DocumentFile documentFile = DocumentFile.fromTreeUri(context, targetDirUri);
228+
if(documentFile != null) {
229+
DocumentFile filesDoc = DocumentUtils.findFile(context, documentFile, "files");
230+
DocumentFile modsDoc = DocumentUtils.findFile(context, filesDoc, "Mods");
231+
if (modsDoc == null) {
232+
modsDoc = filesDoc.createDirectory("Mods");
233+
}
234+
for (File mod : unpackedMods) {
235+
CommonLogic.copyDocument(context, mod, modsDoc);
236+
}
237+
}
238+
}
218239
return true;
219240
}
220241

app/src/main/java/com/zane/smapiinstaller/ui/about/AboutFragment.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,15 @@ private void joinQQ() {
5959
case 1:
6060
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "kshK7BavcS2jXZ6exDvezc18ksLB8YsM"));
6161
break;
62-
default:
62+
case 2:
6363
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "zqsWYGBuAxPx0n9RI_ONs-7NA1Mm48QY"));
6464
break;
65+
case 3:
66+
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "uYnxVTCGlWuLbeb3XA3mDXoO0tlYhy3J"));
67+
break;
68+
default:
69+
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, "https://s.zaneyork.cn:8443/s/qc"));
70+
break;
6571
}
6672
});
6773
}

app/src/main/java/com/zane/smapiinstaller/ui/install/InstallFragment.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public View onCreateView(@NonNull LayoutInflater inflater,
5757
binding.layoutAdvInstall.setVisibility(View.VISIBLE);
5858
}
5959
try {
60-
String firstLine = Files.asCharSource(new File(FileUtils.getStadewValleyBasePath(), Constants.LOG_PATH), StandardCharsets.UTF_8).readFirstLine();
60+
String firstLine = Files.asCharSource(FileUtils.docOverlayFetch(context, Constants.LOG_PATH), StandardCharsets.UTF_8).readFirstLine();
6161
if (StringUtils.isNoneBlank(firstLine)) {
6262
String versionString = RegExUtils.removePattern(firstLine, "\\[.+\\]\\s+");
6363
versionString = RegExUtils.removePattern(versionString, "\\s+with.+");
@@ -158,7 +158,6 @@ private void installLogic(boolean isAdv) {
158158
return;
159159
}
160160
ModAssetsManager modAssetsManager = new ModAssetsManager(binding.getRoot());
161-
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.unpacking_smapi_files, 6);
162161
modAssetsManager.installDefaultMods();
163162

164163
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.signing_package, null);

app/src/main/java/com/zane/smapiinstaller/utils/FileUtils.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.zane.smapiinstaller.utils;
22

3+
import android.app.Activity;
34
import android.content.Context;
5+
import android.net.Uri;
46
import android.os.Environment;
57
import android.util.Log;
68

9+
import androidx.documentfile.provider.DocumentFile;
10+
import androidx.documentfile.provider.DocumentUtils;
11+
712
import com.fasterxml.jackson.core.type.TypeReference;
813
import com.google.common.collect.Iterables;
914
import com.google.common.collect.Lists;
@@ -12,6 +17,8 @@
1217
import com.google.common.io.CharStreams;
1318
import com.google.common.io.Files;
1419
import com.hjq.language.MultiLanguages;
20+
import com.zane.smapiinstaller.constant.Constants;
21+
import com.zane.smapiinstaller.logic.CommonLogic;
1522

1623
import org.apache.commons.io.input.BOMInputStream;
1724
import org.apache.commons.lang3.StringUtils;
@@ -22,6 +29,7 @@
2229
import java.io.IOException;
2330
import java.io.InputStream;
2431
import java.io.InputStreamReader;
32+
import java.io.OutputStream;
2533
import java.io.OutputStreamWriter;
2634
import java.nio.charset.StandardCharsets;
2735
import java.util.List;
@@ -327,4 +335,34 @@ public static List<String> listAll(String basePath, Predicate<File> filter) {
327335
File::getAbsolutePath)
328336
);
329337
}
338+
339+
public static File docOverlayFetch(Context context, String relativePath) {
340+
relativePath = relativePath.replace("StardewValley/", "");
341+
if (CommonLogic.checkDataRootPermission(context)) {
342+
Uri targetDirUri = CommonLogic.pathToTreeUri(Constants.TARGET_DATA_FILE_URI);
343+
DocumentFile documentFile = DocumentFile.fromTreeUri(context, targetDirUri);
344+
DocumentFile filesDoc = DocumentUtils.findFile(context, documentFile, "files");
345+
if(filesDoc != null) {
346+
String[] split = relativePath.split("/");
347+
DocumentFile currentDoc = filesDoc;
348+
for (String path : split) {
349+
currentDoc = DocumentUtils.findFile(context, currentDoc, path);
350+
if(currentDoc == null) {
351+
break;
352+
}
353+
}
354+
if(currentDoc != null && currentDoc.isFile()) {
355+
try (InputStream inputStream = context.getContentResolver().openInputStream(currentDoc.getUri())) {
356+
File tempFile = File.createTempFile(currentDoc.getName(), null);
357+
tempFile.deleteOnExit();
358+
FileUtils.copy(inputStream, tempFile);
359+
return tempFile;
360+
} catch (IOException e) {
361+
throw new RuntimeException(e);
362+
}
363+
}
364+
}
365+
}
366+
return new File(FileUtils.getStadewValleyBasePath(), relativePath);
367+
}
330368
}

app/src/main/res/values-es/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<string name="settings_verbose_logging">Registro detallado</string>
6262
<string name="signing_package">Firmando paquete deinstalación</string>
6363
<string name="smapi_game_name">SMAPI Stardew Valley</string>
64-
<string name="smapi_version">Versión SMAPI: 3.18.3.2</string>
64+
<string name="smapi_version">Versión SMAPI: 3.18.3.3</string>
6565
<string name="text_install_tip1">Nota: Requiere la versión del juego 1.5.6.39 o superior</string>
6666
<string name="text_install_tip2">El cuerpo del juego debe instalarse durante la actualización o instalación</string>
6767
<string name="unpacking_smapi_files">Desempacando</string>

app/src/main/res/values-fr/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<string name="settings_verbose_logging">Journalisation détaillée</string>
6262
<string name="signing_package">Signature</string>
6363
<string name="smapi_game_name">SMAPI Stardew Valley</string>
64-
<string name="smapi_version">Version SMAPI: 3.18.3.2</string>
64+
<string name="smapi_version">Version SMAPI: 3.18.3.3</string>
6565
<string name="text_install_tip1">Remarques: La version du jeu 1.5.6.39 ou ultérieure est requise.</string>
6666
<string name="text_install_tip2">Le jeu de base est requis lors de la mise à jour / installation.</string>
6767
<string name="unpacking_smapi_files">Déballage</string>

app/src/main/res/values-in/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<string name="settings_verbose_logging">Catatan Terperinci</string>
6262
<string name="signing_package">Menandatangani</string>
6363
<string name="smapi_game_name">SMAPI Stardew Valley</string>
64-
<string name="smapi_version">Versi SMAPI: 3.18.3.2</string>
64+
<string name="smapi_version">Versi SMAPI: 3.18.3.3</string>
6565
<string name="text_install_tip1">Catatan: Dibutuhkan Stardew Valley versi 1.5.6.39 atau yang lebih baru.</string>
6666
<string name="text_install_tip2">Permainan dasar diperlukan saat memperbarui/menginstal.</string>
6767
<string name="unpacking_smapi_files">Membongkar</string>

app/src/main/res/values-ko-rKR/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<string name="settings_verbose_logging">자세한 로그</string>
6262
<string name="signing_package">설치 패키지 서명</string>
6363
<string name="smapi_game_name">SMAPI Stardew Valley</string>
64-
<string name="smapi_version">SMAPI버전: 3.18.3.2</string>
64+
<string name="smapi_version">SMAPI버전: 3.18.3.3</string>
6565
<string name="text_install_tip1">참고 : 게임 버전 1.5.6.39 이상이 필요합니다</string>
6666
<string name="text_install_tip2">업데이트 또는 설치 중에 게임 본체를 설치해야합니다</string>
6767
<string name="unpacking_smapi_files">포장 풀기</string>

app/src/main/res/values-pt/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<string name="settings_verbose_logging">Log detalhado</string>
6262
<string name="signing_package">Assinatura</string>
6363
<string name="smapi_game_name">SMAPI Stardew Valley</string>
64-
<string name="smapi_version">Versão SMAPI: 3.18.3.2</string>
64+
<string name="smapi_version">Versão SMAPI: 3.18.3.3</string>
6565
<string name="text_install_tip1">Notas: É necessária a versão do jogo 1.5.6.39 ou posterior.</string>
6666
<string name="text_install_tip2">O jogo base é necessário ao atualizar / instalar.</string>
6767
<string name="unpacking_smapi_files">Desembalar</string>

app/src/main/res/values-th/arrays.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,7 @@
3535
<item>860453392</item>
3636
<item>1078428449</item>
3737
<item>980882763</item>
38+
<item>1156021254</item>
39+
<item>QQ频道</item>
3840
</string-array>
3941
</resources>

app/src/main/res/values-th/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<string name="settings_verbose_logging">บันทึกอย่างละเอียด</string>
6262
<string name="signing_package">กำลังลงทะเบียนแอป</string>
6363
<string name="smapi_game_name">SMAPI Stardew Valley</string>
64-
<string name="smapi_version">เวอร์ชั่น SMAPI: 3.18.3.2</string>
64+
<string name="smapi_version">เวอร์ชั่น SMAPI: 3.18.3.3</string>
6565
<string name="text_install_tip1">หมายเหตุ: ต้องการเกมเวอร์ชั่น 1.5.6.39 หรือใหม่กว่า</string>
6666
<string name="text_install_tip2">ต้องการเกมหลักเมื่อทำการอัปเดต / ติดตั้ง</string>
6767
<string name="unpacking_smapi_files">กำลังแกะกล่อง</string>

0 commit comments

Comments
 (0)