1.Compatibility fix, add save load error validate logic

2.Layout adjust
3.Minor fix
4.Disabled MonoMod for Android K and L by default
This commit is contained in:
ZaneYork 2020-04-26 11:43:53 +08:00
parent 91818a3f25
commit 303f754ee6
34 changed files with 108 additions and 132 deletions

View File

@ -12,8 +12,8 @@ android {
applicationId "com.zane.smapiinstaller" applicationId "com.zane.smapiinstaller"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 28 targetSdkVersion 28
versionCode 36 versionCode 37
versionName "1.4.5" versionName "1.4.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true

View File

@ -1,5 +1,5 @@
{ {
"version": 13, "version": 14,
"contents": [ "contents": [
{ {
"type": "COMPAT", "type": "COMPAT",
@ -13,9 +13,9 @@
"type": "COMPAT", "type": "COMPAT",
"name": "SMAPI for Galaxy Store", "name": "SMAPI for Galaxy Store",
"assetPath": "compat/samsung_138/", "assetPath": "compat/samsung_138/",
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.4.1.6", "description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.4.1.7",
"url": "http://zaneyork.cn/download/compat/smapi_samsung_138_8.zip", "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_9.zip",
"hash": "9def0e6f711c46e50cd962d10aa0ccf6014026a7cc544be42922ac9b49172a38" "hash": "be1908c4e456526e25e41536dff50888143eb3fa1b24ca17499d51f72c456f66"
}, },
{ {
"type": "LOCALE", "type": "LOCALE",

View File

@ -1,5 +1,5 @@
{ {
"version": 13, "version": 14,
"contents": [ "contents": [
{ {
"type": "COMPAT", "type": "COMPAT",
@ -13,9 +13,9 @@
"type": "COMPAT", "type": "COMPAT",
"name": "SMAPI for Galaxy Store", "name": "SMAPI for Galaxy Store",
"assetPath": "compat/samsung_138/", "assetPath": "compat/samsung_138/",
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.4.1.6", "description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.4.1.7",
"url": "http://zaneyork.cn/download/compat/smapi_samsung_138_8.zip", "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_9.zip",
"hash": "9def0e6f711c46e50cd962d10aa0ccf6014026a7cc544be42922ac9b49172a38" "hash": "be1908c4e456526e25e41536dff50888143eb3fa1b24ca17499d51f72c456f66"
}, },
{ {
"type": "LOCALE", "type": "LOCALE",

View File

@ -1,5 +1,5 @@
{ {
"version": 13, "version": 14,
"contents": [ "contents": [
{ {
"type": "COMPAT", "type": "COMPAT",
@ -13,9 +13,9 @@
"type": "COMPAT", "type": "COMPAT",
"name": "SMAPI三星商店兼容包", "name": "SMAPI三星商店兼容包",
"assetPath": "compat/samsung_138/", "assetPath": "compat/samsung_138/",
"description": "SMAPI三星商店兼容包 适用版本1.4.4.138至今, SMAPI 3.4.1.6", "description": "SMAPI三星商店兼容包 适用版本1.4.4.138至今, SMAPI 3.4.1.7",
"url": "http://zaneyork.cn/download/compat/smapi_samsung_138_8.zip", "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_9.zip",
"hash": "9def0e6f711c46e50cd962d10aa0ccf6014026a7cc544be42922ac9b49172a38" "hash": "be1908c4e456526e25e41536dff50888143eb3fa1b24ca17499d51f72c456f66"
}, },
{ {
"type": "LOCALE", "type": "LOCALE",

View File

@ -1,3 +1,6 @@
{ {
"warn.invalid-content-removed": "Invalid content was removed to prevent a crash (see the SMAPI console for info)." "warn.invalid-content-removed": "Invalid content was removed to prevent a crash (see the SMAPI console for info).",
"warn.save-broken": "Load save failed, your save file may be broken.You can swap to previous day's save, or restore save files manually with save backups.Backup provided by SMAPI was located at StardewValley/smapi-internal/save-backups",
"btn.swap": "Swap",
"btn.back": "Back"
} }

View File

@ -1,3 +1,6 @@
{ {
"warn.invalid-content-removed": "非法内容已移除以防游戏闪退查看SMAPI控制台获得更多信息" "warn.invalid-content-removed": "非法内容已移除以防游戏闪退查看SMAPI控制台获得更多信息",
"warn.save-broken": "无法加载该存档,存档可能已损坏.你可以切换到前一日的存档,或者手动恢复到备份的存档.SMAPI提供的备份文件位于: StardewValley/smapi-internal/save-backups",
"btn.swap": "切换",
"btn.back": "返回"
} }

View File

@ -31,7 +31,7 @@ import com.zane.smapiinstaller.logic.ConfigManager;
import com.zane.smapiinstaller.logic.GameLauncher; import com.zane.smapiinstaller.logic.GameLauncher;
import com.zane.smapiinstaller.logic.ModAssetsManager; import com.zane.smapiinstaller.logic.ModAssetsManager;
import com.zane.smapiinstaller.utils.DialogUtils; import com.zane.smapiinstaller.utils.DialogUtils;
import com.zane.smapiinstaller.utils.JSONUtil; import com.zane.smapiinstaller.utils.JsonUtil;
import com.zane.smapiinstaller.utils.JsonCallback; import com.zane.smapiinstaller.utils.JsonCallback;
import com.zane.smapiinstaller.utils.TranslateUtil; import com.zane.smapiinstaller.utils.TranslateUtil;
@ -343,7 +343,7 @@ public class MainActivity extends AppCompatActivity {
} }
try { try {
NavController controller = Navigation.findNavController(this, R.id.nav_host_fragment); NavController controller = Navigation.findNavController(this, R.id.nav_host_fragment);
controller.navigate(MobileNavigationDirections.actionNavAnyToModUpdateFragment(JSONUtil.toJson(list))); controller.navigate(MobileNavigationDirections.actionNavAnyToModUpdateFragment(JsonUtil.toJson(list)));
} catch (Exception e) { } catch (Exception e) {
Crashes.trackError(e); Crashes.trackError(e);
} }

View File

@ -63,7 +63,7 @@ public class Constants {
/** /**
* SMAPI版本 * SMAPI版本
*/ */
public static final String SMAPI_VERSION = "3.4.1.6"; public static final String SMAPI_VERSION = "3.4.1.7";
/** /**
* 平台 * 平台

View File

@ -1,6 +1,7 @@
package com.zane.smapiinstaller.entity; package com.zane.smapiinstaller.entity;
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data; import lombok.Data;
@ -12,6 +13,8 @@ import lombok.Data;
@Data @Data
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility= JsonAutoDetect.Visibility.NONE) @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility= JsonAutoDetect.Visibility.NONE)
public class FrameworkConfig { public class FrameworkConfig {
@JsonIgnore
private transient boolean initial;
/** /**
* 详细日志 * 详细日志
*/ */

View File

@ -22,6 +22,7 @@ public class ConfigManager {
} }
if(config == null) { if(config == null) {
config = new FrameworkConfig(); config = new FrameworkConfig();
config.setInitial(true);
} }
} }

View File

@ -25,7 +25,7 @@ import com.zane.smapiinstaller.dto.ModUpdateCheckResponseDto;
import com.zane.smapiinstaller.entity.ModManifestEntry; import com.zane.smapiinstaller.entity.ModManifestEntry;
import com.zane.smapiinstaller.utils.DialogUtils; import com.zane.smapiinstaller.utils.DialogUtils;
import com.zane.smapiinstaller.utils.FileUtils; import com.zane.smapiinstaller.utils.FileUtils;
import com.zane.smapiinstaller.utils.JSONUtil; import com.zane.smapiinstaller.utils.JsonUtil;
import com.zane.smapiinstaller.utils.JsonCallback; import com.zane.smapiinstaller.utils.JsonCallback;
import com.zane.smapiinstaller.utils.VersionUtil; import com.zane.smapiinstaller.utils.VersionUtil;
@ -319,7 +319,7 @@ public class ModAssetsManager {
try { try {
ModUpdateCheckRequestDto requestDto = new ModUpdateCheckRequestDto(list, new ModUpdateCheckRequestDto.SemanticVersion(gamePackageInfo.versionName)); ModUpdateCheckRequestDto requestDto = new ModUpdateCheckRequestDto(list, new ModUpdateCheckRequestDto.SemanticVersion(gamePackageInfo.versionName));
OkGo.<List<ModUpdateCheckResponseDto>>post(Constants.UPDATE_CHECK_SERVICE_URL) OkGo.<List<ModUpdateCheckResponseDto>>post(Constants.UPDATE_CHECK_SERVICE_URL)
.upJson(JSONUtil.toJson(requestDto)) .upJson(JsonUtil.toJson(requestDto))
.execute(new JsonCallback<List<ModUpdateCheckResponseDto>>(new TypeReference<List<ModUpdateCheckResponseDto>>() { .execute(new JsonCallback<List<ModUpdateCheckResponseDto>>(new TypeReference<List<ModUpdateCheckResponseDto>>() {
}) { }) {
@Override @Override

View File

@ -1,5 +0,0 @@
package com.zane.smapiinstaller.logic;
public class SaveValidator {
}

View File

@ -8,7 +8,7 @@ import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Response; import com.lzy.okgo.model.Response;
import com.zane.smapiinstaller.entity.UpdatableList; import com.zane.smapiinstaller.entity.UpdatableList;
import com.zane.smapiinstaller.utils.FileUtils; import com.zane.smapiinstaller.utils.FileUtils;
import com.zane.smapiinstaller.utils.JSONUtil; import com.zane.smapiinstaller.utils.JsonUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -60,7 +60,7 @@ public class UpdatableListManager<T extends UpdatableList> implements Listenable
@Override @Override
public void onSuccess(Response<String> response) { public void onSuccess(Response<String> response) {
UpdatableList content = JSONUtil.fromJson(response.body(), tClass); UpdatableList content = JsonUtil.fromJson(response.body(), tClass);
if(content != null && updatableList.getVersion() < content.getVersion()) { if(content != null && updatableList.getVersion() < content.getVersion()) {
FileUtils.writeAssetJson(root.getContext(), finalFilename, content); FileUtils.writeAssetJson(root.getContext(), finalFilename, content);
updatableList = content; updatableList = content;

View File

@ -50,22 +50,22 @@ public class AboutFragment extends Fragment {
CommonLogic.openInPlayStore(this.getActivity()); CommonLogic.openInPlayStore(this.getActivity());
} }
private void openPlayStore(String url) { @OnClick(R.id.button_qq_group_1)
Intent intent = new Intent("android.intent.action.VIEW"); void joinQQ() {
intent.setData(Uri.parse(url));
intent.setPackage("com.android.vending");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
CommonLogic.doOnNonNull(this.getActivity(), (activity) -> activity.startActivity(intent));
}
@OnClick({R.id.button_qq_group_1, R.id.button_qq_group_2})
void joinQQ(Button which) {
String baseUrl = "mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D"; String baseUrl = "mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D";
if (which.getId() == R.id.button_qq_group_1) { DialogUtils.showListItemsDialog(imgHeart, R.string.button_qq_group_text, R.array.qq_group_list, (dialog, position) -> {
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "AAflCLHiWw1haM1obu_f-CpGsETxXc6b")); switch (position){
} else { case 0:
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "kshK7BavcS2jXZ6exDvezc18ksLB8YsM")); CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "AAflCLHiWw1haM1obu_f-CpGsETxXc6b"));
} break;
case 1:
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "kshK7BavcS2jXZ6exDvezc18ksLB8YsM"));
break;
default:
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "zqsWYGBuAxPx0n9RI_ONs-7NA1Mm48QY"));
break;
}
});
} }
@OnClick(R.id.button_donation) @OnClick(R.id.button_donation)

View File

@ -17,7 +17,7 @@ import com.zane.smapiinstaller.constant.DialogAction;
import com.zane.smapiinstaller.logic.CommonLogic; import com.zane.smapiinstaller.logic.CommonLogic;
import com.zane.smapiinstaller.utils.DialogUtils; import com.zane.smapiinstaller.utils.DialogUtils;
import com.zane.smapiinstaller.utils.FileUtils; import com.zane.smapiinstaller.utils.FileUtils;
import com.zane.smapiinstaller.utils.JSONUtil; import com.zane.smapiinstaller.utils.JsonUtil;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -96,7 +96,7 @@ public class ConfigEditFragment extends Fragment {
@OnClick(R.id.button_config_save) @OnClick(R.id.button_config_save)
void onConfigSave() { void onConfigSave() {
try { try {
JSONUtil.checkJson(editText.getText().toString()); JsonUtil.checkJson(editText.getText().toString());
FileOutputStream outputStream = new FileOutputStream(configPath); FileOutputStream outputStream = new FileOutputStream(configPath);
try (OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream)) { try (OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream)) {
outputStreamWriter.write(editText.getText().toString()); outputStreamWriter.write(editText.getText().toString());

View File

@ -39,6 +39,7 @@ import butterknife.OnClick;
/** /**
* {@link RecyclerView.Adapter} that can display a {@link DownloadableContent} * {@link RecyclerView.Adapter} that can display a {@link DownloadableContent}
*
* @author Zane * @author Zane
*/ */
public class DownloadableContentAdapter extends RecyclerView.Adapter<DownloadableContentAdapter.ViewHolder> { public class DownloadableContentAdapter extends RecyclerView.Adapter<DownloadableContentAdapter.ViewHolder> {
@ -193,14 +194,18 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter<Downloadabl
} }
private void unpackLogic(Context context, File downloadedFile, ModManifestEntry finalModManifestEntry) { private void unpackLogic(Context context, File downloadedFile, ModManifestEntry finalModManifestEntry) {
if (StringUtils.equals(downloadableContent.getType(), DownloadableContentTypes.LOCALE)) { try {
if (finalModManifestEntry != null) { if (StringUtils.equals(downloadableContent.getType(), DownloadableContentTypes.LOCALE)) {
ZipUtil.unpack(downloadedFile, new File(finalModManifestEntry.getAssetPath())); if (finalModManifestEntry != null) {
ZipUtil.unpack(downloadedFile, new File(finalModManifestEntry.getAssetPath()));
}
} else {
ZipUtil.unpack(downloadedFile, new File(context.getFilesDir(), downloadableContent.getAssetPath()));
} }
} else { DialogUtils.showAlertDialog(itemView, R.string.info, R.string.download_unpack_success);
ZipUtil.unpack(downloadedFile, new File(context.getFilesDir(), downloadableContent.getAssetPath())); } catch (Exception e) {
DialogUtils.showAlertDialog(itemView, R.string.error, e.getLocalizedMessage());
} }
DialogUtils.showAlertDialog(itemView, R.string.info, R.string.download_unpack_success);
} }
} }
} }

View File

@ -7,6 +7,7 @@ import android.os.Environment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import com.google.common.io.Files; import com.google.common.io.Files;
@ -17,6 +18,7 @@ import com.zane.smapiinstaller.constant.Constants;
import com.zane.smapiinstaller.constant.DialogAction; import com.zane.smapiinstaller.constant.DialogAction;
import com.zane.smapiinstaller.logic.ApkPatcher; import com.zane.smapiinstaller.logic.ApkPatcher;
import com.zane.smapiinstaller.logic.CommonLogic; import com.zane.smapiinstaller.logic.CommonLogic;
import com.zane.smapiinstaller.logic.ConfigManager;
import com.zane.smapiinstaller.logic.ModAssetsManager; import com.zane.smapiinstaller.logic.ModAssetsManager;
import com.zane.smapiinstaller.utils.DialogUtils; import com.zane.smapiinstaller.utils.DialogUtils;
@ -47,6 +49,9 @@ public class InstallFragment extends Fragment {
private View root; private View root;
@BindView(R.id.button_install)
Button installButton;
@BindView(R.id.text_latest_running) @BindView(R.id.text_latest_running)
TextView textLatestRunning; TextView textLatestRunning;
@ -98,6 +103,14 @@ public class InstallFragment extends Fragment {
dialog = dialogHolder.get(); dialog = dialogHolder.get();
} while (dialog == null); } while (dialog == null);
ApkPatcher patcher = new ApkPatcher(context); ApkPatcher patcher = new ApkPatcher(context);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
ConfigManager configManager = new ConfigManager();
if(configManager.getConfig().isInitial()) {
configManager.getConfig().setInitial(false);
configManager.getConfig().setDisableMonoMod(true);
configManager.flushConfig();
}
}
ProgressDialog finalDialog = dialog; ProgressDialog finalDialog = dialog;
patcher.registerProgressListener((progress) -> DialogUtils.setProgressDialogState(root, finalDialog, null, progress)); patcher.registerProgressListener((progress) -> DialogUtils.setProgressDialogState(root, finalDialog, null, progress));
DialogUtils.setProgressDialogState(root, dialog, R.string.extracting_package, null); DialogUtils.setProgressDialogState(root, dialog, R.string.extracting_package, null);
@ -120,7 +133,7 @@ public class InstallFragment extends Fragment {
if (target == R.string.menu_download) { if (target == R.string.menu_download) {
DialogUtils.showConfirmDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game)), R.string.menu_download, R.string.cancel, (d, which) -> { DialogUtils.showConfirmDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game)), R.string.menu_download, R.string.cancel, (d, which) -> {
if (which == DialogAction.POSITIVE) { if (which == DialogAction.POSITIVE) {
NavController controller = Navigation.findNavController(root); NavController controller = Navigation.findNavController(installButton);
controller.navigate(InstallFragmentDirections.actionNavInstallToNavDownload()); controller.navigate(InstallFragmentDirections.actionNavInstallToNavDownload());
} }
}); });

View File

@ -10,7 +10,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.zane.smapiinstaller.R; import com.zane.smapiinstaller.R;
import com.zane.smapiinstaller.dto.ModUpdateCheckResponseDto; import com.zane.smapiinstaller.dto.ModUpdateCheckResponseDto;
import com.zane.smapiinstaller.logic.CommonLogic; import com.zane.smapiinstaller.logic.CommonLogic;
import com.zane.smapiinstaller.utils.JSONUtil; import com.zane.smapiinstaller.utils.JsonUtil;
import java.util.List; import java.util.List;
@ -45,7 +45,7 @@ public class ModUpdateFragment extends Fragment {
CommonLogic.doOnNonNull(this.getArguments(), arguments -> { CommonLogic.doOnNonNull(this.getArguments(), arguments -> {
String updateInfoListJson = ModUpdateFragmentArgs.fromBundle(arguments).getUpdateInfoListJson(); String updateInfoListJson = ModUpdateFragmentArgs.fromBundle(arguments).getUpdateInfoListJson();
List<ModUpdateCheckResponseDto> updateInfos = JSONUtil.fromJson(updateInfoListJson, new TypeReference<List<ModUpdateCheckResponseDto>>() { List<ModUpdateCheckResponseDto> updateInfos = JsonUtil.fromJson(updateInfoListJson, new TypeReference<List<ModUpdateCheckResponseDto>>() {
}); });
ModUpdateAdapter adapter = new ModUpdateAdapter(updateInfos); ModUpdateAdapter adapter = new ModUpdateAdapter(updateInfos);
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);

View File

@ -92,7 +92,7 @@ public class FileUtils extends org.zeroturnaround.zip.commons.FileUtils {
try { try {
InputStream inputStream = new FileInputStream(file); InputStream inputStream = new FileInputStream(file);
try (InputStreamReader reader = new InputStreamReader(new BOMInputStream(inputStream), StandardCharsets.UTF_8)) { try (InputStreamReader reader = new InputStreamReader(new BOMInputStream(inputStream), StandardCharsets.UTF_8)) {
return JSONUtil.fromJson(CharStreams.toString(reader), type); return JsonUtil.fromJson(CharStreams.toString(reader), type);
} }
} catch (Exception ignored) { } catch (Exception ignored) {
} }
@ -110,7 +110,7 @@ public class FileUtils extends org.zeroturnaround.zip.commons.FileUtils {
try { try {
InputStream inputStream = new FileInputStream(file); InputStream inputStream = new FileInputStream(file);
try (InputStreamReader reader = new InputStreamReader(new BOMInputStream(inputStream), StandardCharsets.UTF_8)) { try (InputStreamReader reader = new InputStreamReader(new BOMInputStream(inputStream), StandardCharsets.UTF_8)) {
return JSONUtil.fromJson(CharStreams.toString(reader), tClass); return JsonUtil.fromJson(CharStreams.toString(reader), tClass);
} }
} catch (Exception ignored) { } catch (Exception ignored) {
} }
@ -129,7 +129,7 @@ public class FileUtils extends org.zeroturnaround.zip.commons.FileUtils {
File file = new File(context.getFilesDir(), tmpFilename); File file = new File(context.getFilesDir(), tmpFilename);
FileOutputStream outputStream = new FileOutputStream(file); FileOutputStream outputStream = new FileOutputStream(file);
try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) { try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) {
writer.write(JSONUtil.toJson(content)); writer.write(JsonUtil.toJson(content));
} finally { } finally {
File distFile = new File(context.getFilesDir(), filename); File distFile = new File(context.getFilesDir(), filename);
if(distFile.exists()) { if(distFile.exists()) {
@ -156,7 +156,7 @@ public class FileUtils extends org.zeroturnaround.zip.commons.FileUtils {
File fileTmp = new File(file.getParent(), tmpFilename); File fileTmp = new File(file.getParent(), tmpFilename);
FileOutputStream outputStream = new FileOutputStream(fileTmp); FileOutputStream outputStream = new FileOutputStream(fileTmp);
try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) { try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) {
writer.write(JSONUtil.toJson(content)); writer.write(JsonUtil.toJson(content));
} finally { } finally {
if(file.exists()) { if(file.exists()) {
org.zeroturnaround.zip.commons.FileUtils.forceDelete(file); org.zeroturnaround.zip.commons.FileUtils.forceDelete(file);
@ -179,7 +179,7 @@ public class FileUtils extends org.zeroturnaround.zip.commons.FileUtils {
try { try {
InputStream inputStream = getLocalAsset(context, filename); InputStream inputStream = getLocalAsset(context, filename);
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
return JSONUtil.fromJson(CharStreams.toString(reader), tClass); return JsonUtil.fromJson(CharStreams.toString(reader), tClass);
} }
} catch (IOException ignored) { } catch (IOException ignored) {
} }
@ -190,7 +190,7 @@ public class FileUtils extends org.zeroturnaround.zip.commons.FileUtils {
try { try {
InputStream inputStream = getLocaledLocalAsset(context, filename); InputStream inputStream = getLocaledLocalAsset(context, filename);
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
return JSONUtil.fromJson(CharStreams.toString(reader), tClass); return JsonUtil.fromJson(CharStreams.toString(reader), tClass);
} }
} catch (IOException ignored) { } catch (IOException ignored) {
} }
@ -209,7 +209,7 @@ public class FileUtils extends org.zeroturnaround.zip.commons.FileUtils {
try { try {
InputStream inputStream = getLocalAsset(context, filename); InputStream inputStream = getLocalAsset(context, filename);
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
return JSONUtil.fromJson(CharStreams.toString(reader), type); return JsonUtil.fromJson(CharStreams.toString(reader), type);
} }
} catch (IOException ignored) { } catch (IOException ignored) {
} }

View File

@ -41,10 +41,10 @@ public abstract class JsonCallback<T> extends AbsCallback<T> {
} }
T data = null; T data = null;
if (type != null) { if (type != null) {
data = JSONUtil.fromJson(body.string(), type); data = JsonUtil.fromJson(body.string(), type);
} }
if (clazz != null) { if (clazz != null) {
data = JSONUtil.fromJson(body.string(), clazz); data = JsonUtil.fromJson(body.string(), clazz);
} }
return data; return data;
} }

View File

@ -12,7 +12,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
* JSON工具类 * JSON工具类
* @author Zane * @author Zane
*/ */
public class JSONUtil { public class JsonUtil {
private static final ObjectMapper MAPPER = new ObjectMapper(); private static final ObjectMapper MAPPER = new ObjectMapper();
static { static {
// 允许未定义的属性 // 允许未定义的属性

View File

@ -54,7 +54,7 @@ public class TranslateUtil {
OkGo.<String>get(String.format(Constants.TRANSLATE_SERVICE_URL_YOUDAO, queryText)).execute(new StringCallback() { OkGo.<String>get(String.format(Constants.TRANSLATE_SERVICE_URL_YOUDAO, queryText)).execute(new StringCallback() {
@Override @Override
public void onSuccess(Response<String> response) { public void onSuccess(Response<String> response) {
YouDaoTranslationDto translationDto = JSONUtil.fromJson(response.body(), YouDaoTranslationDto.class); YouDaoTranslationDto translationDto = JsonUtil.fromJson(response.body(), YouDaoTranslationDto.class);
if (translationDto != null && translationDto.getErrorCode() == 0) { if (translationDto != null && translationDto.getErrorCode() == 0) {
List<List<YouDaoTranslationDto.Entry>> lists = translationDto.getTranslateResult(); List<List<YouDaoTranslationDto.Entry>> lists = translationDto.getTranslateResult();
List<TranslationResult> translations = new ArrayList<>(lists.size()); List<TranslationResult> translations = new ArrayList<>(lists.size());
@ -83,7 +83,7 @@ public class TranslateUtil {
OkGo.<String>get(String.format(Constants.TRANSLATE_SERVICE_URL_GOOGLE, locale, queryText)).execute(new StringCallback() { OkGo.<String>get(String.format(Constants.TRANSLATE_SERVICE_URL_GOOGLE, locale, queryText)).execute(new StringCallback() {
@Override @Override
public void onSuccess(Response<String> response) { public void onSuccess(Response<String> response) {
GoogleTranslationDto translationDto = JSONUtil.fromJson(response.body(), GoogleTranslationDto.class); GoogleTranslationDto translationDto = JsonUtil.fromJson(response.body(), GoogleTranslationDto.class);
if(translationDto != null) { if(translationDto != null) {
List<String> sourceText = Splitter.on("%0A").splitToList(queryText); List<String> sourceText = Splitter.on("%0A").splitToList(queryText);
List<TranslationResult> translations = new ArrayList<>(sourceText.size()); List<TranslationResult> translations = new ArrayList<>(sourceText.size());

View File

@ -18,7 +18,7 @@ public class KeyStoreFileManager {
static { static {
// Add the bouncycastle version of the BC provider so that the implementation classes returned from the keystore // Add the bouncycastle version of the BC provider so that the implementation classes returned from the keystore
// are all from the spongycastle libs. // are all from the bouncycastle libs.
Security.addProvider(SECURITY_PROVIDER); Security.addProvider(SECURITY_PROVIDER);
} }

View File

@ -33,59 +33,7 @@
style="@style/Widget.AppCompat.Button.Borderless" style="@style/Widget.AppCompat.Button.Borderless"
android:gravity="center" android:gravity="center"
android:textSize="24sp" android:textSize="24sp"
android:text="@string/button_qq_group_1_text" /> android:text="@string/button_qq_group_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/img_qq_2"
android:layout_width="40dp"
android:layout_height="40dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/tencentqq"
android:contentDescription="@string/icon_desc" />
<Button
android:id="@+id/button_qq_group_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/img_qq_2"
app:layout_constraintEnd_toEndOf="parent"
style="@style/Widget.AppCompat.Button.Borderless"
android:gravity="center"
android:textSize="24sp"
android:text="@string/button_qq_group_2_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/img_tieba"
android:layout_width="40dp"
android:layout_height="40dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/global"
android:contentDescription="@string/icon_desc" />
<Button
android:id="@+id/button_tieba"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/img_tieba"
app:layout_constraintEnd_toEndOf="parent"
style="@style/Widget.AppCompat.Button.Borderless"
android:gravity="center"
android:textSize="24sp"
android:text="@string/button_tieba_sdvandroid" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout

View File

@ -61,7 +61,7 @@
<string name="settings_verbose_logging">Registro detallado</string> <string name="settings_verbose_logging">Registro detallado</string>
<string name="signing_package">Firmando paquete deinstalación</string> <string name="signing_package">Firmando paquete deinstalación</string>
<string name="smapi_game_name">SMAPI Stardew Valley</string> <string name="smapi_game_name">SMAPI Stardew Valley</string>
<string name="smapi_version">Versión SMAPI: 3.4.1.6</string> <string name="smapi_version">Versión SMAPI: 3.4.1.7</string>
<string name="text_install_tip1">Nota: Requiere la versión del juego 1.4.5.138 o superior</string> <string name="text_install_tip1">Nota: Requiere la versión del juego 1.4.5.138 o superior</string>
<string name="text_install_tip2">El cuerpo del juego debe instalarse durante la actualización o instalación</string> <string name="text_install_tip2">El cuerpo del juego debe instalarse durante la actualización o instalación</string>
<string name="unpacking_smapi_files">Desempacando</string> <string name="unpacking_smapi_files">Desempacando</string>

View File

@ -61,7 +61,7 @@
<string name="settings_verbose_logging">Journalisation détaillée</string> <string name="settings_verbose_logging">Journalisation détaillée</string>
<string name="signing_package">Signature</string> <string name="signing_package">Signature</string>
<string name="smapi_game_name">SMAPI Stardew Valley</string> <string name="smapi_game_name">SMAPI Stardew Valley</string>
<string name="smapi_version">Version SMAPI: 3.4.1.6</string> <string name="smapi_version">Version SMAPI: 3.4.1.7</string>
<string name="text_install_tip1">Remarques: La version du jeu 1.4.5.138 ou ultérieure est requise.</string> <string name="text_install_tip1">Remarques: La version du jeu 1.4.5.138 ou ultérieure est requise.</string>
<string name="text_install_tip2">Le jeu de base est requis lors de la mise à jour / installation.</string> <string name="text_install_tip2">Le jeu de base est requis lors de la mise à jour / installation.</string>
<string name="unpacking_smapi_files">Déballage</string> <string name="unpacking_smapi_files">Déballage</string>

View File

@ -61,7 +61,7 @@
<string name="settings_verbose_logging">Catatan Terperinci</string> <string name="settings_verbose_logging">Catatan Terperinci</string>
<string name="signing_package">Menandatangani</string> <string name="signing_package">Menandatangani</string>
<string name="smapi_game_name">SMAPI Stardew Valley</string> <string name="smapi_game_name">SMAPI Stardew Valley</string>
<string name="smapi_version">Versi SMAPI: 3.4.1.6</string> <string name="smapi_version">Versi SMAPI: 3.4.1.7</string>
<string name="text_install_tip1">Catatan: Dibutuhkan Stardew Valley versi 1.4.5.138 atau yang lebih baru.</string> <string name="text_install_tip1">Catatan: Dibutuhkan Stardew Valley versi 1.4.5.138 atau yang lebih baru.</string>
<string name="text_install_tip2">Permainan dasar diperlukan saat memperbarui/menginstal.</string> <string name="text_install_tip2">Permainan dasar diperlukan saat memperbarui/menginstal.</string>
<string name="unpacking_smapi_files">Membongkar</string> <string name="unpacking_smapi_files">Membongkar</string>

View File

@ -61,7 +61,7 @@
<string name="settings_verbose_logging">자세한 로그</string> <string name="settings_verbose_logging">자세한 로그</string>
<string name="signing_package">설치 패키지 서명</string> <string name="signing_package">설치 패키지 서명</string>
<string name="smapi_game_name">SMAPI Stardew Valley</string> <string name="smapi_game_name">SMAPI Stardew Valley</string>
<string name="smapi_version">SMAPI버전: 3.4.1.6</string> <string name="smapi_version">SMAPI버전: 3.4.1.7</string>
<string name="text_install_tip1">참고 : 게임 버전 1.4.5.138 이상이 필요합니다</string> <string name="text_install_tip1">참고 : 게임 버전 1.4.5.138 이상이 필요합니다</string>
<string name="text_install_tip2">업데이트 또는 설치 중에 게임 본체를 설치해야합니다</string> <string name="text_install_tip2">업데이트 또는 설치 중에 게임 본체를 설치해야합니다</string>
<string name="unpacking_smapi_files">포장 풀기</string> <string name="unpacking_smapi_files">포장 풀기</string>

View File

@ -61,7 +61,7 @@
<string name="settings_verbose_logging">Log detalhado</string> <string name="settings_verbose_logging">Log detalhado</string>
<string name="signing_package">Assinatura</string> <string name="signing_package">Assinatura</string>
<string name="smapi_game_name">SMAPI Stardew Valley</string> <string name="smapi_game_name">SMAPI Stardew Valley</string>
<string name="smapi_version">Versão SMAPI: 3.4.1.6</string> <string name="smapi_version">Versão SMAPI: 3.4.1.7</string>
<string name="text_install_tip1">Notas: É necessária a versão do jogo 1.4.5.138 ou posterior.</string> <string name="text_install_tip1">Notas: É necessária a versão do jogo 1.4.5.138 ou posterior.</string>
<string name="text_install_tip2">O jogo base é necessário ao atualizar / instalar.</string> <string name="text_install_tip2">O jogo base é necessário ao atualizar / instalar.</string>
<string name="unpacking_smapi_files">Desembalar</string> <string name="unpacking_smapi_files">Desembalar</string>

View File

@ -61,7 +61,7 @@
<string name="settings_verbose_logging">การบันทึกอย่างละเอียด</string> <string name="settings_verbose_logging">การบันทึกอย่างละเอียด</string>
<string name="signing_package">การลงชื่อ</string> <string name="signing_package">การลงชื่อ</string>
<string name="smapi_game_name">SMAPI Stardew Valley</string> <string name="smapi_game_name">SMAPI Stardew Valley</string>
<string name="smapi_version">เวอร์ชั่น SMAPI: 3.4.1.6</string> <string name="smapi_version">เวอร์ชั่น SMAPI: 3.4.1.7</string>
<string name="text_install_tip1">หมายเหตุ: จำเป็นต้องใช้เวอร์ชั่นเกม 1.4.5.138 หรือใหม่กว่า</string> <string name="text_install_tip1">หมายเหตุ: จำเป็นต้องใช้เวอร์ชั่นเกม 1.4.5.138 หรือใหม่กว่า</string>
<string name="text_install_tip2">จำเป็นต้องมีเกมพื้นฐานเมื่อทำการอัพเดต / ติดตั้ง</string> <string name="text_install_tip2">จำเป็นต้องมีเกมพื้นฐานเมื่อทำการอัพเดต / ติดตั้ง</string>
<string name="unpacking_smapi_files">แกะกล่อง</string> <string name="unpacking_smapi_files">แกะกล่อง</string>

View File

@ -60,7 +60,7 @@
<string name="settings_verbose_logging">詳細日誌</string> <string name="settings_verbose_logging">詳細日誌</string>
<string name="signing_package">正在簽名安裝包</string> <string name="signing_package">正在簽名安裝包</string>
<string name="smapi_game_name">SMAPI 星露谷物語</string> <string name="smapi_game_name">SMAPI 星露谷物語</string>
<string name="smapi_version">SMAPI版本: 3.4.1.6</string> <string name="smapi_version">SMAPI版本: 3.4.1.7</string>
<string name="text_install_tip1">注意:需要 1.4.5.138 以上遊戲版本</string> <string name="text_install_tip1">注意:需要 1.4.5.138 以上遊戲版本</string>
<string name="text_install_tip2">更新或安裝期間需要安裝遊戲</string> <string name="text_install_tip2">更新或安裝期間需要安裝遊戲</string>
<string name="unpacking_smapi_files">正在解包</string> <string name="unpacking_smapi_files">正在解包</string>
@ -72,7 +72,7 @@
<string name="parser">格式化</string> <string name="parser">格式化</string>
<string name="mod_version_update_checking">正在檢查 MOD 更新</string> <string name="mod_version_update_checking">正在檢查 MOD 更新</string>
<string name="smapi_version_runing">最近執行:%s</string> <string name="smapi_version_runing">最近執行:%s</string>
<string name="button_tieba_sdvandroid">貼吧:星露谷安卓</string>
<string name="settings_disable_mono_mod">停用 MonoMod</string> <string name="settings_disable_mono_mod">停用 MonoMod</string>
<string name="settings_set_max_log_size">最大日誌檔案大小</string> <string name="settings_set_max_log_size">最大日誌檔案大小</string>
<string name="button_qq_group_text">QQ群</string>
</resources> </resources>

View File

@ -60,7 +60,7 @@
<string name="settings_verbose_logging">详细日志</string> <string name="settings_verbose_logging">详细日志</string>
<string name="signing_package">正在签名安装包</string> <string name="signing_package">正在签名安装包</string>
<string name="smapi_game_name">SMAPI星露谷物语</string> <string name="smapi_game_name">SMAPI星露谷物语</string>
<string name="smapi_version">SMAPI版本: 3.4.1.6</string> <string name="smapi_version">SMAPI版本: 3.4.1.7</string>
<string name="text_install_tip1">注意需要不低于1.4.5.138版本的游戏本体</string> <string name="text_install_tip1">注意需要不低于1.4.5.138版本的游戏本体</string>
<string name="text_install_tip2">更新或安装期间需要安装游戏本体</string> <string name="text_install_tip2">更新或安装期间需要安装游戏本体</string>
<string name="unpacking_smapi_files">正在解包</string> <string name="unpacking_smapi_files">正在解包</string>
@ -72,7 +72,7 @@
<string name="parser">格式化</string> <string name="parser">格式化</string>
<string name="mod_version_update_checking">正在检查MOD更新</string> <string name="mod_version_update_checking">正在检查MOD更新</string>
<string name="smapi_version_runing">最近运行: %s</string> <string name="smapi_version_runing">最近运行: %s</string>
<string name="button_tieba_sdvandroid">贴吧: 星露谷安卓</string>
<string name="settings_disable_mono_mod">禁用MonoMod</string> <string name="settings_disable_mono_mod">禁用MonoMod</string>
<string name="settings_set_max_log_size">最大日志大小</string> <string name="settings_set_max_log_size">最大日志大小</string>
<string name="button_qq_group_text">QQ群</string>
</resources> </resources>

View File

@ -30,4 +30,9 @@
<item>by Date(asc)</item> <item>by Date(asc)</item>
<item>by Date(desc)</item> <item>by Date(desc)</item>
</string-array> </string-array>
<string-array name="qq_group_list">
<item>860453392</item>
<item>1078428449</item>
<item>980882763</item>
</string-array>
</resources> </resources>

View File

@ -60,7 +60,7 @@
<string name="settings_verbose_logging">Verbose Logging</string> <string name="settings_verbose_logging">Verbose Logging</string>
<string name="signing_package">Signing</string> <string name="signing_package">Signing</string>
<string name="smapi_game_name">SMAPI Stardew Valley</string> <string name="smapi_game_name">SMAPI Stardew Valley</string>
<string name="smapi_version">SMAPI Version: 3.4.1.6</string> <string name="smapi_version">SMAPI Version: 3.4.1.7</string>
<string name="text_install_tip1">Notes: Game version 1.4.5.138 or later is required.</string> <string name="text_install_tip1">Notes: Game version 1.4.5.138 or later is required.</string>
<string name="text_install_tip2">The base game is required when updating/installing.</string> <string name="text_install_tip2">The base game is required when updating/installing.</string>
<string name="unpacking_smapi_files">Unpacking</string> <string name="unpacking_smapi_files">Unpacking</string>
@ -76,7 +76,7 @@
<string name="parser">Parser</string> <string name="parser">Parser</string>
<string name="mod_version_update_checking">Checking for mod updates</string> <string name="mod_version_update_checking">Checking for mod updates</string>
<string name="smapi_version_runing">Latest running: %s</string> <string name="smapi_version_runing">Latest running: %s</string>
<string name="button_tieba_sdvandroid">Tieba: SDV Android</string>
<string name="settings_disable_mono_mod">Disable MonoMod</string> <string name="settings_disable_mono_mod">Disable MonoMod</string>
<string name="settings_set_max_log_size">Max Log Size</string> <string name="settings_set_max_log_size">Max Log Size</string>
<string name="button_qq_group_text">QQ Group</string>
</resources> </resources>