1.Traditional Chinese translation
2.Download progress bar
This commit is contained in:
parent
e04aa786c6
commit
cc21df5126
|
@ -9,8 +9,8 @@ android {
|
|||
applicationId "com.zane.smapiinstaller"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
versionCode 4
|
||||
versionName "1.1.1"
|
||||
versionCode 5
|
||||
versionName "1.1.2"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
"version": 1,
|
||||
"version": 2,
|
||||
"contents": [
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI for 1.4.5.137",
|
||||
"assetPath": "compat/137/",
|
||||
"description": "SMAPI compat package for game 1.4.4.128 - 1.4.5.137",
|
||||
"url": "http://dl.zaneyork.cn/compat/smapi_137.zip",
|
||||
"url": "http://zaneyork.cn/download/compat/smapi_137.zip",
|
||||
"hash": "bd16e8e4cb52d636e24c6a2d2309b66a60e492d2b97c1b8f6a519c04ac42ebdc"
|
||||
},
|
||||
{
|
||||
"type": "LOCALE",
|
||||
"name": "中文汉化v2.4",
|
||||
"description": "简体中文语言包,感谢Wabi-Sabi提供",
|
||||
"url": "http://dl.zaneyork.cn/locale/locale_pack_zh_2.4.zip",
|
||||
"url": "http://zaneyork.cn/download/locale/locale_pack_zh_2.4.zip",
|
||||
"hash": "59be19240160de61046f05619f3e448d180137e0989feb537e392a014588615f"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import pxb.android.axml.AxmlReader;
|
||||
import pxb.android.axml.AxmlVisitor;
|
||||
|
@ -59,7 +60,7 @@ public class CommonLogic {
|
|||
|
||||
public static InputStream getLocalAsset(Context context, String filename) throws IOException {
|
||||
File file = new File(context.getFilesDir(), filename);
|
||||
if(file.exists()){
|
||||
if (file.exists()) {
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
return context.getAssets().open(filename);
|
||||
|
@ -94,8 +95,7 @@ public class CommonLogic {
|
|||
FileOutputStream outputStream = new FileOutputStream(file);
|
||||
try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) {
|
||||
writer.write(new Gson().toJson(content));
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
FileUtils.moveFile(file, new File(context.getFilesDir(), filename));
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
|
@ -136,8 +136,8 @@ public class CommonLogic {
|
|||
|
||||
public static void setProgressDialogState(View view, MaterialDialog dialog, int message, int progress) {
|
||||
Activity activity = getActivityFromView(view);
|
||||
if(activity != null && !activity.isFinishing() && !dialog.isCancelled()) {
|
||||
activity.runOnUiThread(()->{
|
||||
if (activity != null && !activity.isFinishing() && !dialog.isCancelled()) {
|
||||
activity.runOnUiThread(() -> {
|
||||
dialog.incrementProgress(progress - dialog.getCurrentProgress());
|
||||
dialog.setContent(message);
|
||||
});
|
||||
|
@ -159,62 +159,80 @@ public class CommonLogic {
|
|||
|
||||
public static void showAlertDialog(View view, int title, String message) {
|
||||
Activity activity = getActivityFromView(view);
|
||||
if(activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(()-> new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.ok).show());
|
||||
if (activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(() -> new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.ok).show());
|
||||
}
|
||||
}
|
||||
|
||||
public static void showAlertDialog(View view, int title, int message) {
|
||||
Activity activity = getActivityFromView(view);
|
||||
if(activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(()-> new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.ok).show());
|
||||
if (activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(() -> new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.ok).show());
|
||||
}
|
||||
}
|
||||
|
||||
public static void showConfirmDialog(View view, int title, int message, MaterialDialog.SingleButtonCallback callback) {
|
||||
Activity activity = getActivityFromView(view);
|
||||
if(activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(()-> new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.confirm).negativeText(R.string.cancel).onAny(callback).show());
|
||||
if (activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(() -> new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.confirm).negativeText(R.string.cancel).onAny(callback).show());
|
||||
}
|
||||
}
|
||||
|
||||
public static void showConfirmDialog(View view, int title, String message, MaterialDialog.SingleButtonCallback callback) {
|
||||
Activity activity = getActivityFromView(view);
|
||||
if(activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(()-> new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.confirm).negativeText(R.string.cancel).onAny(callback).show());
|
||||
if (activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(() -> new MaterialDialog.Builder(activity).title(title).content(message).positiveText(R.string.confirm).negativeText(R.string.cancel).onAny(callback).show());
|
||||
}
|
||||
}
|
||||
|
||||
public static AtomicReference<MaterialDialog> showProgressDialog(View view, int title, String message) {
|
||||
Activity activity = getActivityFromView(view);
|
||||
AtomicReference<MaterialDialog> reference = new AtomicReference<>();
|
||||
if (activity != null && !activity.isFinishing()) {
|
||||
activity.runOnUiThread(() -> {
|
||||
MaterialDialog dialog = new MaterialDialog.Builder(activity)
|
||||
.title(title)
|
||||
.content(message)
|
||||
.progress(false, 100, true)
|
||||
.cancelable(false)
|
||||
.show();
|
||||
reference.set(dialog);
|
||||
});
|
||||
}
|
||||
return reference;
|
||||
}
|
||||
|
||||
public static List<ApkFilesManifest> findAllApkFileManifest(Context context) {
|
||||
ApkFilesManifest apkFilesManifest = CommonLogic.getAssetJson(context, "apk_files_manifest.json", ApkFilesManifest.class);
|
||||
ArrayList<ApkFilesManifest> apkFilesManifests = Lists.newArrayList(apkFilesManifest);
|
||||
File compatFolder = new File(context.getFilesDir(), "compat");
|
||||
if(compatFolder.exists()) {
|
||||
if (compatFolder.exists()) {
|
||||
for (File directory : compatFolder.listFiles(File::isDirectory)) {
|
||||
File manifestFile = new File(directory, "apk_files_manifest.json");
|
||||
if(manifestFile.exists()) {
|
||||
if (manifestFile.exists()) {
|
||||
ApkFilesManifest manifest = getFileJson(manifestFile, ApkFilesManifest.class);
|
||||
if(manifest != null) {
|
||||
if (manifest != null) {
|
||||
apkFilesManifests.add(manifest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(apkFilesManifests, (a, b)-> Long.compare(b.getMinBuildCode(), a.getMinBuildCode()));
|
||||
Collections.sort(apkFilesManifests, (a, b) -> Long.compare(b.getMinBuildCode(), a.getMinBuildCode()));
|
||||
return apkFilesManifests;
|
||||
}
|
||||
|
||||
public static boolean unpackSmapiFiles(Context context, String apkPath, boolean checkMod) {
|
||||
List<ManifestEntry> manifestEntries = CommonLogic.getAssetJson(context, "smapi_files_manifest.json", new TypeToken<List<ManifestEntry>>() {
|
||||
}.getType());
|
||||
if(manifestEntries == null)
|
||||
if (manifestEntries == null)
|
||||
return false;
|
||||
File basePath = new File(Environment.getExternalStorageDirectory() + "/StardewValley/");
|
||||
if(!basePath.exists()) {
|
||||
if(!basePath.mkdir()) {
|
||||
if (!basePath.exists()) {
|
||||
if (!basePath.mkdir()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
File noMedia = new File(basePath,".nomedia");
|
||||
File noMedia = new File(basePath, ".nomedia");
|
||||
if (!noMedia.exists()) {
|
||||
try {
|
||||
noMedia.createNewFile();
|
||||
|
@ -225,7 +243,7 @@ public class CommonLogic {
|
|||
File targetFile = new File(basePath, entry.getTargetPath());
|
||||
switch (entry.getOrigin()) {
|
||||
case 0:
|
||||
if(!checkMod || !targetFile.exists()) {
|
||||
if (!checkMod || !targetFile.exists()) {
|
||||
try (InputStream inputStream = context.getAssets().open(entry.getAssetPath())) {
|
||||
if (!targetFile.getParentFile().exists()) {
|
||||
if (!targetFile.getParentFile().mkdirs()) {
|
||||
|
@ -241,7 +259,7 @@ public class CommonLogic {
|
|||
}
|
||||
break;
|
||||
case 1:
|
||||
if(!checkMod || !targetFile.exists()) {
|
||||
if (!checkMod || !targetFile.exists()) {
|
||||
ZipUtil.unpackEntry(new File(apkPath), entry.getAssetPath(), targetFile);
|
||||
}
|
||||
break;
|
||||
|
@ -275,7 +293,7 @@ public class CommonLogic {
|
|||
}
|
||||
|
||||
public static String getFileHash(Context context, String filename) {
|
||||
try(InputStream inputStream = getLocalAsset(context, filename)){
|
||||
try (InputStream inputStream = getLocalAsset(context, filename)) {
|
||||
return Hashing.sha256().hashBytes(ByteStreams.toByteArray(inputStream)).toString();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
@ -283,7 +301,7 @@ public class CommonLogic {
|
|||
}
|
||||
|
||||
public static String getFileHash(File file) {
|
||||
try(InputStream inputStream = new FileInputStream(file)){
|
||||
try (InputStream inputStream = new FileInputStream(file)) {
|
||||
return Hashing.sha256().hashBytes(ByteStreams.toByteArray(inputStream)).toString();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package com.zane.smapiinstaller.ui.about;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.zane.smapiinstaller.R;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
* Use the {@link AboutFragment#newInstance} factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
public class AboutFragment extends Fragment {
|
||||
// TODO: Rename parameter arguments, choose names that match
|
||||
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
||||
private static final String ARG_PARAM1 = "param1";
|
||||
private static final String ARG_PARAM2 = "param2";
|
||||
|
||||
// TODO: Rename and change types of parameters
|
||||
private String mParam1;
|
||||
private String mParam2;
|
||||
|
||||
public AboutFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @param param1 Parameter 1.
|
||||
* @param param2 Parameter 2.
|
||||
* @return A new instance of fragment AboutFragment.
|
||||
*/
|
||||
// TODO: Rename and change types and number of parameters
|
||||
public static AboutFragment newInstance(String param1, String param2) {
|
||||
AboutFragment fragment = new AboutFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_PARAM1, param1);
|
||||
args.putString(ARG_PARAM2, param2);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_about, container, false);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import com.afollestad.materialdialogs.DialogAction;
|
|||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.lzy.okgo.OkGo;
|
||||
import com.lzy.okgo.callback.FileCallback;
|
||||
import com.lzy.okgo.model.Progress;
|
||||
import com.lzy.okgo.model.Response;
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.entity.DownloadableContent;
|
||||
|
@ -31,6 +32,8 @@ import org.zeroturnaround.zip.commons.FileUtils;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* {@link RecyclerView.Adapter} that can display a {@link DownloadableContent}
|
||||
|
@ -71,6 +74,7 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter<Downloadabl
|
|||
Button buttonRemove;
|
||||
@BindView(R.id.button_download_content)
|
||||
Button buttonDownload;
|
||||
private AtomicBoolean downloading = new AtomicBoolean(false);
|
||||
|
||||
public DownloadableContent downloadableContent;
|
||||
|
||||
|
@ -134,16 +138,40 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter<Downloadabl
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (downloading.get())
|
||||
return;
|
||||
downloading.set(true);
|
||||
ModManifestEntry finalModManifestEntry = modManifestEntry;
|
||||
AtomicReference<MaterialDialog> dialogRef = CommonLogic.showProgressDialog(itemView, R.string.progress, "");
|
||||
OkGo.<File>get(downloadableContent.getUrl()).execute(new FileCallback(file.getParentFile().getAbsolutePath(), file.getName()) {
|
||||
@Override
|
||||
public void onError(Response<File> response) {
|
||||
super.onError(response);
|
||||
MaterialDialog dialog = dialogRef.get();
|
||||
if (dialog != null && !dialog.isCancelled()) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
downloading.set(false);
|
||||
CommonLogic.showAlertDialog(itemView, R.string.error, R.string.error_failed_to_download);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadProgress(Progress progress) {
|
||||
super.downloadProgress(progress);
|
||||
MaterialDialog dialog = dialogRef.get();
|
||||
if (dialog != null && !dialog.isCancelled()) {
|
||||
dialog.setContent(R.string.downloading, progress.currentSize / 1024, progress.totalSize / 1024);
|
||||
dialog.setProgress((int) (progress.currentSize / progress.totalSize));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Response<File> response) {
|
||||
MaterialDialog dialog = dialogRef.get();
|
||||
if (dialog != null && !dialog.isCancelled()) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
downloading.set(false);
|
||||
File downloadedFile = response.body();
|
||||
String hash = CommonLogic.getFileHash(downloadedFile);
|
||||
if (!StringUtils.equalsIgnoreCase(hash, downloadableContent.getHash())) {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@drawable/horizontal_divider"
|
||||
android:showDividers="middle"
|
||||
tools:context=".ui.about.AboutFragment">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/test_message" />
|
||||
|
||||
</LinearLayout>
|
|
@ -20,5 +20,9 @@
|
|||
android:id="@+id/nav_help"
|
||||
android:icon="@android:drawable/ic_menu_help"
|
||||
android:title="@string/menu_help" />
|
||||
<item
|
||||
android:id="@+id/nav_about"
|
||||
android:icon="@android:drawable/ic_dialog_info"
|
||||
android:title="@string/menu_about" />
|
||||
</group>
|
||||
</menu>
|
||||
|
|
|
@ -44,4 +44,9 @@
|
|||
android:name="com.zane.smapiinstaller.ui.download.DownloadableContentFragment"
|
||||
android:label="@string/menu_download"
|
||||
tools:layout="@layout/fragment_download_content_list" />
|
||||
<fragment
|
||||
android:id="@+id/nav_about"
|
||||
android:name="com.zane.smapiinstaller.ui.about.AboutFragment"
|
||||
android:label="@string/menu_about"
|
||||
tools:layout="@layout/fragment_about" />
|
||||
</navigation>
|
|
@ -49,4 +49,7 @@
|
|||
<string name="locale_pack">語言包</string>
|
||||
<string name="info">提示</string>
|
||||
<string name="download_unpack_success">已完成下載安裝</string>
|
||||
<string name="progress">進度</string>
|
||||
<string name="downloading">正在下載: %d KB / %d KB</string>
|
||||
<string name="menu_about">關於</string>
|
||||
</resources>
|
||||
|
|
|
@ -49,4 +49,7 @@
|
|||
<string name="locale_pack">語言包</string>
|
||||
<string name="info">提示</string>
|
||||
<string name="download_unpack_success">已完成下載安裝</string>
|
||||
<string name="progress">進度</string>
|
||||
<string name="downloading">正在下載: %d KB / %d KB</string>
|
||||
<string name="menu_about">關於</string>
|
||||
</resources>
|
||||
|
|
|
@ -49,4 +49,7 @@
|
|||
<string name="locale_pack">语言包</string>
|
||||
<string name="info">提示</string>
|
||||
<string name="download_unpack_success">已完成下载安装</string>
|
||||
<string name="progress">进度</string>
|
||||
<string name="downloading">正在下载: %d KB / %d KB</string>
|
||||
<string name="menu_about">关于</string>
|
||||
</resources>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<string name="button_compat">Compat</string>
|
||||
<string name="button_nexus">Nexus</string>
|
||||
<string name="button_release">Release</string>
|
||||
<string name="test_message">Still at test stage now, not release yet.</string>
|
||||
<string name="test_message">Still at test stage now.</string>
|
||||
<string name="button_logs">Logs</string>
|
||||
<string name="smapi_game_name">SMAPI Stardew Valley</string>
|
||||
<string name="error_failed_to_create_file">Failed to create target file : %s</string>
|
||||
|
@ -49,4 +49,10 @@
|
|||
<string name="locale_pack">Locale Pack</string>
|
||||
<string name="info">Info</string>
|
||||
<string name="download_unpack_success">Download and unpack success</string>
|
||||
<string name="progress">Progress</string>
|
||||
<string name="downloading">Downloading: %d KB / %d KB</string>
|
||||
|
||||
<!-- TODO: Remove or change this placeholder text -->
|
||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||
<string name="menu_about">About</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue