1. Fix music issue of Android 11

2. Update to 3.7.6.1
This commit is contained in:
ZaneYork 2021-02-05 16:39:50 +08:00
parent 3569afb695
commit 3763f7757f
16 changed files with 103 additions and 39 deletions

View File

@ -12,8 +12,8 @@ android {
applicationId "com.zane.smapiinstaller" applicationId "com.zane.smapiinstaller"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 30 targetSdkVersion 30
versionCode 70 versionCode 71
versionName "3.7.6.8" versionName "3.7.6.9"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
@ -70,6 +70,7 @@ dependencies {
implementation "androidx.navigation:navigation-ui:2.3.1" implementation "androidx.navigation:navigation-ui:2.3.1"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.webkit:webkit:1.3.0' implementation 'androidx.webkit:webkit:1.3.0'
implementation "androidx.documentfile:documentfile:1.0.1"
// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.65.01' implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.65.01'
implementation 'com.afollestad.material-dialogs:core:3.3.0' implementation 'com.afollestad.material-dialogs:core:3.3.0'

View File

@ -1,9 +1,11 @@
package com.zane.smapiinstaller; package com.zane.smapiinstaller;
import android.Manifest; import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
@ -67,6 +69,20 @@ public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding; private ActivityMainBinding binding;
private void requestPermissions() { private void requestPermissions() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
boolean haveInstallPermission = this.getPackageManager().canRequestPackageInstalls();
if (!haveInstallPermission) {
DialogUtils.showConfirmDialog(MainActivity.instance, R.string.confirm, R.string.request_unknown_source_permission, ((dialog, dialogAction) -> {
if (dialogAction == DialogAction.POSITIVE) {
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.setData(Uri.parse("package:" + this.getPackageName()));
ActivityResultHandler.registerListener(ActivityResultHandler.REQUEST_CODE_APP_INSTALL, (resultCode, data) -> this.requestPermissions());
MainActivity.instance.startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_APP_INSTALL);
}
}));
return;
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// 先判断有没有权限 // 先判断有没有权限
if (!Environment.isExternalStorageManager()) { if (!Environment.isExternalStorageManager()) {
@ -79,7 +95,13 @@ public class MainActivity extends AppCompatActivity {
requestPermissions(); requestPermissions();
} }
}); });
startActivityForResult(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION), ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION); try {
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:" + this.getPackageName()));
startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION);
} catch (ActivityNotFoundException ignored){
startActivityForResult(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION), ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION);
}
} else { } else {
this.finish(); this.finish();
} }

View File

@ -18,6 +18,10 @@ public class Constants {
* 配置文件路径 * 配置文件路径
*/ */
public static final String CONFIG_PATH = "StardewValley/smapi-internal/config.user.json"; public static final String CONFIG_PATH = "StardewValley/smapi-internal/config.user.json";
/**
* 原始安装包名
*/
public static final String ORIGIN_PACKAGE_NAME_GOOGLE = "com.chucklefish.stardewvalley";
/** /**
* 安装包目标包名 * 安装包目标包名
*/ */

View File

@ -14,6 +14,7 @@ import com.android.apksig.ApkSigner;
import com.android.apksig.ApkVerifier; import com.android.apksig.ApkVerifier;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.google.common.base.Ticker;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.zane.smapiinstaller.BuildConfig; import com.zane.smapiinstaller.BuildConfig;
@ -80,7 +81,12 @@ public class ApkPatcher {
private final List<Consumer<Integer>> progressListener = new ArrayList<>(); private final List<Consumer<Integer>> progressListener = new ArrayList<>();
private final Stopwatch stopwatch = Stopwatch.createUnstarted(); private final Stopwatch stopwatch = Stopwatch.createUnstarted(new Ticker() {
@Override
public long read() {
return android.os.SystemClock.elapsedRealtimeNanos();
}
});
public ApkPatcher(Context context) { public ApkPatcher(Context context) {
this.context = context; this.context = context;
@ -165,7 +171,7 @@ public class ApkPatcher {
/** /**
* 将指定APK文件重新打包添加SMAPI修改AndroidManifest.xml同时验证版本是否正确 * 将指定APK文件重新打包添加SMAPI修改AndroidManifest.xml同时验证版本是否正确
* *
* @param apkPath APK文件路径 * @param apkPath APK文件路径
* @param isAdvanced 是否高级模式 * @param isAdvanced 是否高级模式
* @return 是否成功打包 * @return 是否成功打包
*/ */
@ -325,8 +331,8 @@ public class ApkPatcher {
} else { } else {
attr.obj = Constants.PATCHED_APP_NAME; attr.obj = Constants.PATCHED_APP_NAME;
} }
// return Collections.singletonList(new ManifestTagVisitor.AttrArgs(attr.ns, "requestLegacyExternalStorage", -1, NodeVisitor.TYPE_INT_BOOLEAN, true));
} }
// return Collections.singletonList(new ManifestTagVisitor.AttrArgs(attr.ns, "requestLegacyExternalStorage", -1, NodeVisitor.TYPE_INT_BOOLEAN, true));
break; break;
case "authorities": case "authorities":
if (strObj.contains(packageName.get())) { if (strObj.contains(packageName.get())) {
@ -357,11 +363,12 @@ public class ApkPatcher {
Function<ManifestTagVisitor.ChildArgs, List<ManifestTagVisitor.ChildArgs>> childProcessLogic = (child -> { Function<ManifestTagVisitor.ChildArgs, List<ManifestTagVisitor.ChildArgs>> childProcessLogic = (child -> {
if (!permissionAppended.get() && StringUtils.equals(child.name, "uses-permission")) { if (!permissionAppended.get() && StringUtils.equals(child.name, "uses-permission")) {
permissionAppended.set(true); permissionAppended.set(true);
return Collections.singletonList(new ManifestTagVisitor.ChildArgs( return Collections.singletonList(
child.ns, child.name, Collections.singletonList( new ManifestTagVisitor.ChildArgs(child.ns, child.name, Collections.singletonList(
new ManifestTagVisitor.AttrArgs( new ManifestTagVisitor.AttrArgs(
"http://schemas.android.com/apk/res/android", "name", -1, "http://schemas.android.com/apk/res/android", "name", -1,
NodeVisitor.TYPE_STRING, "android.permission.MANAGE_EXTERNAL_STORAGE")))); NodeVisitor.TYPE_STRING, "android.permission.MANAGE_EXTERNAL_STORAGE")))
);
} }
return null; return null;
}); });
@ -453,6 +460,7 @@ public class ApkPatcher {
DialogUtils.showConfirmDialog(MainActivity.instance, R.string.confirm, R.string.request_unknown_source_permission, ((dialog, dialogAction) -> { DialogUtils.showConfirmDialog(MainActivity.instance, R.string.confirm, R.string.request_unknown_source_permission, ((dialog, dialogAction) -> {
if (dialogAction == DialogAction.POSITIVE) { if (dialogAction == DialogAction.POSITIVE) {
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES); Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.setData(Uri.parse("package:" + context.getPackageName()));
ActivityResultHandler.registerListener(ActivityResultHandler.REQUEST_CODE_APP_INSTALL, (resultCode, data) -> this.install(apkPath)); ActivityResultHandler.registerListener(ActivityResultHandler.REQUEST_CODE_APP_INSTALL, (resultCode, data) -> this.install(apkPath));
MainActivity.instance.startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_APP_INSTALL); MainActivity.instance.startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_APP_INSTALL);
} }

View File

@ -26,6 +26,7 @@ import com.lmntrx.android.library.livin.missme.ProgressDialog;
import com.microsoft.appcenter.crashes.Crashes; import com.microsoft.appcenter.crashes.Crashes;
import com.zane.smapiinstaller.MainApplication; import com.zane.smapiinstaller.MainApplication;
import com.zane.smapiinstaller.R; import com.zane.smapiinstaller.R;
import com.zane.smapiinstaller.constant.Constants;
import com.zane.smapiinstaller.constant.DialogAction; import com.zane.smapiinstaller.constant.DialogAction;
import com.zane.smapiinstaller.constant.ManifestPatchConstants; import com.zane.smapiinstaller.constant.ManifestPatchConstants;
import com.zane.smapiinstaller.entity.ApkFilesManifest; import com.zane.smapiinstaller.entity.ApkFilesManifest;
@ -188,7 +189,7 @@ public class CommonLogic {
return apkFilesManifests; return apkFilesManifests;
} }
public static String computePackageName(PackageInfo packageInfo){ public static String computePackageName(PackageInfo packageInfo) {
String packageName = packageInfo.packageName; String packageName = packageInfo.packageName;
if (StringUtils.endsWith(packageInfo.versionName, ManifestPatchConstants.PATTERN_VERSION_AMAZON)) { if (StringUtils.endsWith(packageInfo.versionName, ManifestPatchConstants.PATTERN_VERSION_AMAZON)) {
packageName = ManifestPatchConstants.APP_PACKAGE_NAME + ManifestPatchConstants.PATTERN_VERSION_AMAZON; packageName = ManifestPatchConstants.APP_PACKAGE_NAME + ManifestPatchConstants.PATTERN_VERSION_AMAZON;
@ -199,26 +200,28 @@ public class CommonLogic {
/** /**
* 提取SMAPI环境文件到内部存储对应位置 * 提取SMAPI环境文件到内部存储对应位置
* *
* @param context context * @param context context
* @param apkPath 安装包路径 * @param apkPath 安装包路径
* @param checkMode 是否为校验模式 * @param checkMode 是否为校验模式
* @param packageName 包名 * @param packageName 包名
* @param versionCode 版本号 * @param versionCode 版本号
* @return 操作是否成功 * @return 操作是否成功
*/ */
public static boolean unpackSmapiFiles(Context context, String apkPath, boolean checkMode, String packageName, long versionCode) { public static boolean unpackSmapiFiles(Context context, String apkPath, boolean checkMode, String packageName, long versionCode) {
checkMusic(packageName, checkMode);
List<ApkFilesManifest> apkFilesManifests = CommonLogic.findAllApkFileManifest(context); List<ApkFilesManifest> apkFilesManifests = CommonLogic.findAllApkFileManifest(context);
filterManifest(apkFilesManifests, packageName, versionCode); filterManifest(apkFilesManifests, packageName, versionCode);
List<ManifestEntry> manifestEntries = null; List<ManifestEntry> manifestEntries = null;
ApkFilesManifest apkFilesManifest = null; ApkFilesManifest apkFilesManifest = null;
if(apkFilesManifests.size() > 0) { if (apkFilesManifests.size() > 0) {
apkFilesManifest = apkFilesManifests.get(0); apkFilesManifest = apkFilesManifests.get(0);
String basePath = apkFilesManifest.getBasePath(); String basePath = apkFilesManifest.getBasePath();
if(StringUtils.isNoneBlank(basePath)) { if (StringUtils.isNoneBlank(basePath)) {
manifestEntries = FileUtils.getAssetJson(context, basePath + "smapi_files_manifest.json", new TypeReference<List<ManifestEntry>>() {}); manifestEntries = FileUtils.getAssetJson(context, basePath + "smapi_files_manifest.json", new TypeReference<List<ManifestEntry>>() {
});
} }
} }
if(manifestEntries == null) { if (manifestEntries == null) {
manifestEntries = FileUtils.getAssetJson(context, "smapi_files_manifest.json", new TypeReference<List<ManifestEntry>>() { manifestEntries = FileUtils.getAssetJson(context, "smapi_files_manifest.json", new TypeReference<List<ManifestEntry>>() {
}); });
} }
@ -230,11 +233,10 @@ public class CommonLogic {
if (!basePath.mkdir()) { if (!basePath.mkdir()) {
return false; return false;
} }
} } else {
else { if (!checkMode) {
if(!checkMode) {
File[] oldAssemblies = new File(basePath, "smapi-internal").listFiles((FileFilter) new WildcardFileFilter("*.dll")); File[] oldAssemblies = new File(basePath, "smapi-internal").listFiles((FileFilter) new WildcardFileFilter("*.dll"));
if(oldAssemblies != null) { if (oldAssemblies != null) {
for (File file : oldAssemblies) { for (File file : oldAssemblies) {
FileUtils.deleteQuietly(file); FileUtils.deleteQuietly(file);
} }
@ -264,9 +266,34 @@ public class CommonLogic {
return true; return true;
} }
private static void checkMusic(String packageName, boolean checkMode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && StringUtils.equals(packageName, Constants.ORIGIN_PACKAGE_NAME_GOOGLE)) {
File pathFrom = new File(FileUtils.getStadewValleyBasePath(), "Android/obb/" + packageName);
File pathTo = new File(FileUtils.getStadewValleyBasePath(), "Android/obb/" + Constants.TARGET_PACKAGE_NAME);
if (pathFrom.exists() && pathFrom.isDirectory()) {
if (!pathTo.exists()) {
pathTo.mkdirs();
}
File[] files = pathFrom.listFiles((dir, name) -> name.contains("com.chucklefish.stardewvalley.obb"));
if (files != null) {
for (File file : files) {
try {
File targetFile = new File(pathTo, file.getName());
if (!targetFile.exists() || FileUtils.sizeOf(targetFile) != FileUtils.sizeOf(file)) {
FileUtils.copyFile(file, targetFile);
}
} catch (IOException e) {
Crashes.trackError(e);
}
}
}
}
}
}
private static void unpackFromApk(String apkPath, boolean checkMode, ManifestEntry entry, File targetFile) { private static void unpackFromApk(String apkPath, boolean checkMode, ManifestEntry entry, File targetFile) {
if (!checkMode || !targetFile.exists()) { if (!checkMode || !targetFile.exists()) {
if(entry.isXALZ()){ if (entry.isXALZ()) {
byte[] bytes = ZipUtil.unpackEntry(new File(apkPath), entry.getAssetPath()); byte[] bytes = ZipUtil.unpackEntry(new File(apkPath), entry.getAssetPath());
if (entry.isXALZ()) { if (entry.isXALZ()) {
bytes = ZipUtils.decompressXALZ(bytes); bytes = ZipUtils.decompressXALZ(bytes);
@ -275,22 +302,20 @@ public class CommonLogic {
stream.write(bytes); stream.write(bytes);
} catch (IOException ignore) { } catch (IOException ignore) {
} }
} } else {
else {
ZipUtil.unpackEntry(new File(apkPath), entry.getAssetPath(), targetFile); ZipUtil.unpackEntry(new File(apkPath), entry.getAssetPath(), targetFile);
} }
} }
} }
private static void unpackFromInstaller(Context context, boolean checkMode, ApkFilesManifest apkFilesManifest, File basePath, ManifestEntry entry, File targetFile) { private static void unpackFromInstaller(Context context, boolean checkMode, ApkFilesManifest apkFilesManifest, File basePath, ManifestEntry entry, File targetFile) {
if(entry.isExternal() && apkFilesManifest != null){ if (entry.isExternal() && apkFilesManifest != null) {
byte[] bytes = FileUtils.getAssetBytes(context, apkFilesManifest.getBasePath() + entry.getAssetPath()); byte[] bytes = FileUtils.getAssetBytes(context, apkFilesManifest.getBasePath() + entry.getAssetPath());
try (FileOutputStream outputStream = new FileOutputStream(targetFile)) { try (FileOutputStream outputStream = new FileOutputStream(targetFile)) {
outputStream.write(bytes); outputStream.write(bytes);
} catch (IOException ignored) { } catch (IOException ignored) {
} }
} } else {
else {
if (entry.getTargetPath().endsWith("/") && entry.getAssetPath().contains("*")) { if (entry.getTargetPath().endsWith("/") && entry.getAssetPath().contains("*")) {
String path = StringUtils.substring(entry.getAssetPath(), 0, StringUtils.lastIndexOf(entry.getAssetPath(), "/")); String path = StringUtils.substring(entry.getAssetPath(), 0, StringUtils.lastIndexOf(entry.getAssetPath(), "/"));
String pattern = StringUtils.substringAfterLast(entry.getAssetPath(), "/"); String pattern = StringUtils.substringAfterLast(entry.getAssetPath(), "/");
@ -306,7 +331,7 @@ public class CommonLogic {
} }
} }
public static void filterManifest(List<ApkFilesManifest> manifests, String packageName, long versionCode){ public static void filterManifest(List<ApkFilesManifest> manifests, String packageName, long versionCode) {
Iterables.removeIf(manifests, manifest -> { Iterables.removeIf(manifests, manifest -> {
if (manifest == null) { if (manifest == null) {
return true; return true;
@ -322,6 +347,7 @@ public class CommonLogic {
return manifest.getTargetPackageName() != null && packageName != null && !manifest.getTargetPackageName().contains(packageName); return manifest.getTargetPackageName() != null && packageName != null && !manifest.getTargetPackageName().contains(packageName);
}); });
} }
private static void unpackFile(Context context, boolean checkMode, String assertPath, File targetFile) { private static void unpackFile(Context context, boolean checkMode, String assertPath, File targetFile) {
if (!checkMode || !targetFile.exists()) { if (!checkMode || !targetFile.exists()) {
try (InputStream inputStream = context.getAssets().open(assertPath)) { try (InputStream inputStream = context.getAssets().open(assertPath)) {

View File

@ -35,6 +35,9 @@ public class ZipUtils {
private final static String FILE_HEADER_XALZ = "XALZ"; private final static String FILE_HEADER_XALZ = "XALZ";
public static byte[] decompressXALZ(byte[] bytes) { public static byte[] decompressXALZ(byte[] bytes) {
if (bytes == null) {
return bytes;
}
if (FILE_HEADER_XALZ.equals(new String(ByteUtils.subArray(bytes, 0, 4), StandardCharsets.ISO_8859_1))) { if (FILE_HEADER_XALZ.equals(new String(ByteUtils.subArray(bytes, 0, 4), StandardCharsets.ISO_8859_1))) {
byte[] length = ByteUtils.subArray(bytes, 8, 12); byte[] length = ByteUtils.subArray(bytes, 8, 12);
int len = (length[0] & 0xff) | ((length[1] & 0xff) << 8) | ((length[2] & 0xff) << 16) | ((length[3] & 0xff) << 24); int len = (length[0] & 0xff) | ((length[1] & 0xff) << 8) | ((length[2] & 0xff) << 16) | ((length[3] & 0xff) << 24);

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.7.6</string> <string name="smapi_version">Versión SMAPI: 3.7.6.1</string>
<string name="text_install_tip1">Nota: Requiere la versión del juego 1.4.5.148 o superior</string> <string name="text_install_tip1">Nota: Requiere la versión del juego 1.4.5.148 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.7.6</string> <string name="smapi_version">Version SMAPI: 3.7.6.1</string>
<string name="text_install_tip1">Remarques: La version du jeu 1.4.5.148 ou ultérieure est requise.</string> <string name="text_install_tip1">Remarques: La version du jeu 1.4.5.148 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.7.6</string> <string name="smapi_version">Versi SMAPI: 3.7.6.1</string>
<string name="text_install_tip1">Catatan: Dibutuhkan Stardew Valley versi 1.4.5.148 atau yang lebih baru.</string> <string name="text_install_tip1">Catatan: Dibutuhkan Stardew Valley versi 1.4.5.148 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.7.6</string> <string name="smapi_version">SMAPI버전: 3.7.6.1</string>
<string name="text_install_tip1">참고 : 게임 버전 1.4.5.148 이상이 필요합니다</string> <string name="text_install_tip1">참고 : 게임 버전 1.4.5.148 이상이 필요합니다</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.7.6</string> <string name="smapi_version">Versão SMAPI: 3.7.6.1</string>
<string name="text_install_tip1">Notas: É necessária a versão do jogo 1.4.5.148 ou posterior.</string> <string name="text_install_tip1">Notas: É necessária a versão do jogo 1.4.5.148 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.7.6</string> <string name="smapi_version">เวอร์ชั่น SMAPI: 3.7.6.1</string>
<string name="text_install_tip1">หมายเหตุ: ต้องการเกมเวอร์ชั่น 1.4.5.148 หรือใหม่กว่า</string> <string name="text_install_tip1">หมายเหตุ: ต้องการเกมเวอร์ชั่น 1.4.5.148 หรือใหม่กว่า</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.7.6</string> <string name="smapi_version">SMAPI版本: 3.7.6.1</string>
<string name="text_install_tip1">注意:需要 1.4.5.148 以上遊戲版本</string> <string name="text_install_tip1">注意:需要 1.4.5.148 以上遊戲版本</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.7.6</string> <string name="smapi_version">SMAPI版本: 3.7.6.1</string>
<string name="text_install_tip1">注意需要不低于1.4.5.148版本的游戏本体</string> <string name="text_install_tip1">注意需要不低于1.4.5.148版本的游戏本体</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">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.7.6</string> <string name="smapi_version">SMAPI Version: 3.7.6.1</string>
<string name="text_install_tip1">Notes: Game version 1.4.5.148 or later is required.</string> <string name="text_install_tip1">Notes: Game version 1.4.5.148 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>