Use jackson instead, default enable minify on debug.Version compare fix
This commit is contained in:
parent
7fd7e00511
commit
b4e8917f8d
|
@ -18,8 +18,13 @@ android {
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled true
|
||||||
shrinkResources false
|
shrinkResources true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
minifyEnabled true
|
||||||
|
shrinkResources true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,11 +58,15 @@ dependencies {
|
||||||
implementation group: 'com.google.guava', name: 'guava', version: '28.2-android'
|
implementation group: 'com.google.guava', name: 'guava', version: '28.2-android'
|
||||||
// https://mvnrepository.com/artifact/org.zeroturnaround/zt-zip
|
// https://mvnrepository.com/artifact/org.zeroturnaround/zt-zip
|
||||||
implementation group: 'org.zeroturnaround', name: 'zt-zip', version: '1.14'
|
implementation group: 'org.zeroturnaround', name: 'zt-zip', version: '1.14'
|
||||||
// https://mvnrepository.com/artifact/com.google.code.gson/gson
|
|
||||||
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
|
|
||||||
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
|
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
|
||||||
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.9'
|
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.9'
|
||||||
|
// https://mvnrepository.com/artifact/commons-io/commons-io
|
||||||
|
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
|
||||||
implementation 'com.lzy.net:okgo:3.0.4'
|
implementation 'com.lzy.net:okgo:3.0.4'
|
||||||
|
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
|
||||||
|
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.10.3'
|
||||||
|
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.10.3'
|
||||||
|
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.10.3'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
# If you keep the line number information, uncomment this to
|
# If you keep the line number information, uncomment this to
|
||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
-keepnames class com.path.to.your.ParcelableArg
|
#-keepnames class com.path.to.your.ParcelableArg
|
||||||
-keepnames class com.path.to.your.SerializableArg
|
#-keepnames class com.path.to.your.SerializableArg
|
||||||
-keepnames class com.path.to.your.EnumArg
|
#-keepnames class com.path.to.your.EnumArg
|
||||||
|
|
||||||
-dontwarn javax.lang.model.element.Modifier
|
-dontwarn javax.lang.model.element.Modifier
|
||||||
|
|
||||||
|
@ -118,34 +118,15 @@
|
||||||
static *** getCurrentEnvironment (...);
|
static *** getCurrentEnvironment (...);
|
||||||
}
|
}
|
||||||
|
|
||||||
##---------------Begin: proguard configuration for Gson ----------
|
# For Jackson
|
||||||
# Gson uses generic type information stored in a class file when working with fields. Proguard
|
|
||||||
# removes such information by default, so configure it to keep all of it.
|
|
||||||
-keepattributes Signature
|
-keepattributes Signature
|
||||||
|
|
||||||
# For using GSON @Expose annotation
|
|
||||||
-keepattributes *Annotation*
|
-keepattributes *Annotation*
|
||||||
|
-keep class sun.misc.Unsafe { *; }
|
||||||
|
-dontwarn org.codehaus.jackson.**
|
||||||
|
-dontwarn com.fasterxml.jackson.databind.**
|
||||||
|
-keep class org.codehaus.jackson.** { *;}
|
||||||
|
-keep class com.fasterxml.jackson.** { *; }
|
||||||
|
|
||||||
# Gson specific classes
|
|
||||||
-dontwarn sun.misc.**
|
|
||||||
#-keep class com.google.gson.stream.** { *; }
|
|
||||||
|
|
||||||
# Application classes that will be serialized/deserialized over Gson
|
|
||||||
-keep class com.google.gson.examples.android.model.** { <fields>; }
|
|
||||||
|
|
||||||
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
|
|
||||||
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
|
|
||||||
-keep class * implements com.google.gson.TypeAdapter
|
|
||||||
-keep class * implements com.google.gson.TypeAdapterFactory
|
|
||||||
-keep class * implements com.google.gson.JsonSerializer
|
|
||||||
-keep class * implements com.google.gson.JsonDeserializer
|
|
||||||
|
|
||||||
# Prevent R8 from leaving Data object members always null
|
|
||||||
-keepclassmembers,allowobfuscation class * {
|
|
||||||
@com.google.gson.annotations.SerializedName <fields>;
|
|
||||||
}
|
|
||||||
|
|
||||||
##---------------End: proguard configuration for Gson ----------
|
|
||||||
#okhttp
|
#okhttp
|
||||||
-dontwarn okhttp3.**
|
-dontwarn okhttp3.**
|
||||||
-keep class okhttp3.**{*;}
|
-keep class okhttp3.**{*;}
|
||||||
|
|
|
@ -13,4 +13,7 @@ public class ModManifestEntry {
|
||||||
private String Description;
|
private String Description;
|
||||||
private Set<ModManifestEntry> Dependencies;
|
private Set<ModManifestEntry> Dependencies;
|
||||||
private ModManifestEntry ContentPackFor;
|
private ModManifestEntry ContentPackFor;
|
||||||
|
|
||||||
|
private String MinimumVersion;
|
||||||
|
private Boolean IsRequired;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import com.zane.smapiinstaller.BuildConfig;
|
import com.zane.smapiinstaller.BuildConfig;
|
||||||
import com.zane.smapiinstaller.R;
|
import com.zane.smapiinstaller.R;
|
||||||
import com.zane.smapiinstaller.constant.Constants;
|
import com.zane.smapiinstaller.constant.Constants;
|
||||||
|
@ -59,8 +59,7 @@ public class ApkPatcher {
|
||||||
|
|
||||||
public String extract() {
|
public String extract() {
|
||||||
PackageManager packageManager = context.getPackageManager();
|
PackageManager packageManager = context.getPackageManager();
|
||||||
List<String> packageNames = FileUtils.getAssetJson(context, "package_names.json", new TypeToken<List<String>>() {
|
List<String> packageNames = FileUtils.getAssetJson(context, "package_names.json", new TypeReference<List<String>>() { });
|
||||||
}.getType());
|
|
||||||
if (packageNames == null) {
|
if (packageNames == null) {
|
||||||
errorMessage.set(context.getString(R.string.error_game_not_found));
|
errorMessage.set(context.getString(R.string.error_game_not_found));
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -10,10 +10,10 @@ import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import com.zane.smapiinstaller.R;
|
import com.zane.smapiinstaller.R;
|
||||||
import com.zane.smapiinstaller.entity.ApkFilesManifest;
|
import com.zane.smapiinstaller.entity.ApkFilesManifest;
|
||||||
import com.zane.smapiinstaller.entity.ManifestEntry;
|
import com.zane.smapiinstaller.entity.ManifestEntry;
|
||||||
|
@ -131,8 +131,7 @@ public class CommonLogic {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean unpackSmapiFiles(Context context, String apkPath, boolean checkMod) {
|
public static boolean unpackSmapiFiles(Context context, String apkPath, boolean checkMod) {
|
||||||
List<ManifestEntry> manifestEntries = com.zane.smapiinstaller.utils.FileUtils.getAssetJson(context, "smapi_files_manifest.json", new TypeToken<List<ManifestEntry>>() {
|
List<ManifestEntry> manifestEntries = com.zane.smapiinstaller.utils.FileUtils.getAssetJson(context, "smapi_files_manifest.json", new TypeReference<List<ManifestEntry>>() { });
|
||||||
}.getType());
|
|
||||||
if (manifestEntries == null)
|
if (manifestEntries == null)
|
||||||
return false;
|
return false;
|
||||||
File basePath = new File(Environment.getExternalStorageDirectory() + "/StardewValley/");
|
File basePath = new File(Environment.getExternalStorageDirectory() + "/StardewValley/");
|
||||||
|
|
|
@ -2,13 +2,13 @@ package com.zane.smapiinstaller.logic;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.lzy.okgo.OkGo;
|
import com.lzy.okgo.OkGo;
|
||||||
import com.lzy.okgo.callback.StringCallback;
|
import com.lzy.okgo.callback.StringCallback;
|
||||||
import com.lzy.okgo.model.Response;
|
import com.lzy.okgo.model.Response;
|
||||||
import com.zane.smapiinstaller.constant.Constants;
|
import com.zane.smapiinstaller.constant.Constants;
|
||||||
import com.zane.smapiinstaller.entity.DownloadableContentList;
|
import com.zane.smapiinstaller.entity.DownloadableContentList;
|
||||||
import com.zane.smapiinstaller.utils.FileUtils;
|
import com.zane.smapiinstaller.utils.FileUtils;
|
||||||
|
import com.zane.smapiinstaller.utils.JSONUtil;
|
||||||
|
|
||||||
public class DownloadabeContentManager {
|
public class DownloadabeContentManager {
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ public class DownloadabeContentManager {
|
||||||
OkGo.<String>get(Constants.DLC_LIST_UPDATE_URL).execute(new StringCallback(){
|
OkGo.<String>get(Constants.DLC_LIST_UPDATE_URL).execute(new StringCallback(){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Response<String> response) {
|
public void onSuccess(Response<String> response) {
|
||||||
DownloadableContentList content = new Gson().fromJson(response.body(), DownloadableContentList.class);
|
DownloadableContentList content = JSONUtil.fromJson(response.body(), DownloadableContentList.class);
|
||||||
if(downloadableContentList.getVersion() < content.getVersion()) {
|
if(content != null && downloadableContentList.getVersion() < content.getVersion()) {
|
||||||
FileUtils.writeAssetJson(root.getContext(), "downloadable_content_list.json", content);
|
FileUtils.writeAssetJson(root.getContext(), "downloadable_content_list.json", content);
|
||||||
downloadableContentList = content;
|
downloadableContentList = content;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.DialogAction;
|
import com.afollestad.materialdialogs.DialogAction;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
@ -14,7 +15,6 @@ import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
import com.google.common.collect.Queues;
|
import com.google.common.collect.Queues;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import com.zane.smapiinstaller.R;
|
import com.zane.smapiinstaller.R;
|
||||||
import com.zane.smapiinstaller.constant.Constants;
|
import com.zane.smapiinstaller.constant.Constants;
|
||||||
import com.zane.smapiinstaller.entity.ModManifestEntry;
|
import com.zane.smapiinstaller.entity.ModManifestEntry;
|
||||||
|
@ -51,8 +51,7 @@ public class ModAssetsManager {
|
||||||
boolean foundManifest = false;
|
boolean foundManifest = false;
|
||||||
for (File file : currentFile.listFiles(File::isFile)) {
|
for (File file : currentFile.listFiles(File::isFile)) {
|
||||||
if (StringUtils.equalsIgnoreCase(file.getName(), "manifest.json")) {
|
if (StringUtils.equalsIgnoreCase(file.getName(), "manifest.json")) {
|
||||||
ModManifestEntry manifest = FileUtils.getFileJson(file, new TypeToken<ModManifestEntry>() {
|
ModManifestEntry manifest = FileUtils.getFileJson(file, ModManifestEntry.class);
|
||||||
}.getType());
|
|
||||||
foundManifest = true;
|
foundManifest = true;
|
||||||
if (manifest != null) {
|
if (manifest != null) {
|
||||||
manifest.setAssetPath(file.getParentFile().getAbsolutePath());
|
manifest.setAssetPath(file.getParentFile().getAbsolutePath());
|
||||||
|
@ -81,8 +80,7 @@ public class ModAssetsManager {
|
||||||
boolean foundManifest = false;
|
boolean foundManifest = false;
|
||||||
for (File file : currentFile.listFiles(File::isFile)) {
|
for (File file : currentFile.listFiles(File::isFile)) {
|
||||||
if (StringUtils.equalsIgnoreCase(file.getName(), "manifest.json")) {
|
if (StringUtils.equalsIgnoreCase(file.getName(), "manifest.json")) {
|
||||||
ModManifestEntry manifest = FileUtils.getFileJson(file, new TypeToken<ModManifestEntry>() {
|
ModManifestEntry manifest = FileUtils.getFileJson(file, ModManifestEntry.class);
|
||||||
}.getType());
|
|
||||||
foundManifest = true;
|
foundManifest = true;
|
||||||
if (manifest != null) {
|
if (manifest != null) {
|
||||||
manifest.setAssetPath(file.getParentFile().getAbsolutePath());
|
manifest.setAssetPath(file.getParentFile().getAbsolutePath());
|
||||||
|
@ -101,8 +99,7 @@ public class ModAssetsManager {
|
||||||
|
|
||||||
public boolean installDefaultMods() {
|
public boolean installDefaultMods() {
|
||||||
Activity context = CommonLogic.getActivityFromView(root);
|
Activity context = CommonLogic.getActivityFromView(root);
|
||||||
List<ModManifestEntry> modManifestEntries = FileUtils.getAssetJson(context, "mods_manifest.json", new TypeToken<List<ModManifestEntry>>() {
|
List<ModManifestEntry> modManifestEntries = FileUtils.getAssetJson(context, "mods_manifest.json", new TypeReference<List<ModManifestEntry>>() { });
|
||||||
}.getType());
|
|
||||||
if (modManifestEntries == null)
|
if (modManifestEntries == null)
|
||||||
return false;
|
return false;
|
||||||
File modFolder = new File(Environment.getExternalStorageDirectory(), Constants.MOD_PATH);
|
File modFolder = new File(Environment.getExternalStorageDirectory(), Constants.MOD_PATH);
|
||||||
|
@ -179,6 +176,9 @@ public class ModAssetsManager {
|
||||||
Iterable<String> dependencyErrors = Iterables.filter(Iterables.transform(installedModMap.values(), mod -> {
|
Iterable<String> dependencyErrors = Iterables.filter(Iterables.transform(installedModMap.values(), mod -> {
|
||||||
if (mod.getDependencies() != null) {
|
if (mod.getDependencies() != null) {
|
||||||
ArrayList<ModManifestEntry> unsatisfiedDependencies = Lists.newArrayList(Iterables.filter(mod.getDependencies(), dependency -> {
|
ArrayList<ModManifestEntry> unsatisfiedDependencies = Lists.newArrayList(Iterables.filter(mod.getDependencies(), dependency -> {
|
||||||
|
if(dependency.getIsRequired() != null && !dependency.getIsRequired()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ImmutableList<ModManifestEntry> entries = installedModMap.get(dependency.getUniqueID());
|
ImmutableList<ModManifestEntry> entries = installedModMap.get(dependency.getUniqueID());
|
||||||
if (entries.size() != 1)
|
if (entries.size() != 1)
|
||||||
return true;
|
return true;
|
||||||
|
@ -186,10 +186,10 @@ public class ModAssetsManager {
|
||||||
if (StringUtils.isBlank(version)) {
|
if (StringUtils.isBlank(version)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (StringUtils.isBlank(dependency.getVersion())) {
|
if (StringUtils.isBlank(dependency.getMinimumVersion())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (VersionUtil.compareVersion(version, dependency.getVersion()) < 0) {
|
if (VersionUtil.compareVersion(version, dependency.getMinimumVersion()) < 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -219,16 +219,19 @@ public class ModAssetsManager {
|
||||||
Iterable<String> dependencyErrors = Iterables.filter(Iterables.transform(installedModMap.values(), mod -> {
|
Iterable<String> dependencyErrors = Iterables.filter(Iterables.transform(installedModMap.values(), mod -> {
|
||||||
ModManifestEntry dependency = mod.getContentPackFor();
|
ModManifestEntry dependency = mod.getContentPackFor();
|
||||||
if (dependency != null) {
|
if (dependency != null) {
|
||||||
|
if(dependency.getIsRequired() != null && !dependency.getIsRequired()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
ImmutableList<ModManifestEntry> entries = installedModMap.get(dependency.getUniqueID());
|
ImmutableList<ModManifestEntry> entries = installedModMap.get(dependency.getUniqueID());
|
||||||
if (entries.size() != 1)
|
if (entries.size() != 1)
|
||||||
return root.getContext().getString(R.string.error_depends_on_mod, mod.getUniqueID(), dependency.getUniqueID());
|
return root.getContext().getString(R.string.error_depends_on_mod, mod.getUniqueID(), dependency.getUniqueID());
|
||||||
String version = entries.get(0).getVersion();
|
String version = entries.get(0).getVersion();
|
||||||
if (!StringUtils.isBlank(version)) {
|
if (!StringUtils.isBlank(version)) {
|
||||||
if (StringUtils.isBlank(dependency.getVersion())) {
|
if (StringUtils.isBlank(dependency.getMinimumVersion())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (VersionUtil.compareVersion(version, dependency.getVersion()) < 0) {
|
if (VersionUtil.compareVersion(version, dependency.getMinimumVersion()) < 0) {
|
||||||
return root.getContext().getString(R.string.error_depends_on_mod, mod.getUniqueID(), dependency.getUniqueID());
|
return root.getContext().getString(R.string.error_depends_on_mod_version, mod.getUniqueID(), dependency.getUniqueID(), dependency.getMinimumVersion());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -7,10 +7,10 @@ import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.zane.smapiinstaller.R;
|
import com.zane.smapiinstaller.R;
|
||||||
import com.zane.smapiinstaller.logic.CommonLogic;
|
import com.zane.smapiinstaller.logic.CommonLogic;
|
||||||
import com.zane.smapiinstaller.utils.FileUtils;
|
import com.zane.smapiinstaller.utils.FileUtils;
|
||||||
|
import com.zane.smapiinstaller.utils.JSONUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
@ -54,7 +54,7 @@ public class ConfigEditFragment extends Fragment {
|
||||||
}
|
}
|
||||||
@OnClick(R.id.button_config_save) void onConfigSave() {
|
@OnClick(R.id.button_config_save) void onConfigSave() {
|
||||||
try {
|
try {
|
||||||
new Gson().fromJson(editText.getText().toString(), Object.class);
|
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());
|
||||||
|
|
|
@ -2,13 +2,14 @@ package com.zane.smapiinstaller.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.common.io.CharStreams;
|
import com.google.common.io.CharStreams;
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
|
|
||||||
|
import org.apache.commons.io.input.BOMInputStream;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -36,18 +37,16 @@ public class FileUtils {
|
||||||
public static InputStream getLocalAsset(Context context, String filename) throws IOException {
|
public static InputStream getLocalAsset(Context context, String filename) throws IOException {
|
||||||
File file = new File(context.getFilesDir(), filename);
|
File file = new File(context.getFilesDir(), filename);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
return new FileInputStream(file);
|
return new BOMInputStream(new FileInputStream(file));
|
||||||
}
|
}
|
||||||
return context.getAssets().open(filename);
|
return context.getAssets().open(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T getFileJson(File file, Type type) {
|
public static <T> T getFileJson(File file, TypeReference<T> type) {
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = new FileInputStream(file);
|
InputStream inputStream = new FileInputStream(file);
|
||||||
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
|
try (InputStreamReader reader = new InputStreamReader(new BOMInputStream(inputStream), StandardCharsets.UTF_8)) {
|
||||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
return JSONUtil.fromJson(CharStreams.toString(reader), type);
|
||||||
gsonBuilder.setLenient();
|
|
||||||
return gsonBuilder.create().fromJson(CharStreams.toString(reader), type);
|
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
|
@ -57,10 +56,8 @@ public class FileUtils {
|
||||||
public static <T> T getFileJson(File file, Class<T> tClass) {
|
public static <T> T getFileJson(File file, Class<T> tClass) {
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = new FileInputStream(file);
|
InputStream inputStream = new FileInputStream(file);
|
||||||
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
|
try (InputStreamReader reader = new InputStreamReader(new BOMInputStream(inputStream), StandardCharsets.UTF_8)) {
|
||||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
return JSONUtil.fromJson(CharStreams.toString(reader), tClass);
|
||||||
gsonBuilder.setLenient();
|
|
||||||
return gsonBuilder.create().fromJson(CharStreams.toString(reader), tClass);
|
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
|
@ -73,7 +70,7 @@ public class 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(new Gson().toJson(content));
|
writer.write(JSONUtil.toJson(content));
|
||||||
} finally {
|
} finally {
|
||||||
org.zeroturnaround.zip.commons.FileUtils.moveFile(file, new File(context.getFilesDir(), filename));
|
org.zeroturnaround.zip.commons.FileUtils.moveFile(file, new File(context.getFilesDir(), filename));
|
||||||
}
|
}
|
||||||
|
@ -85,18 +82,18 @@ public class 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 new Gson().fromJson(CharStreams.toString(reader), tClass);
|
return JSONUtil.fromJson(CharStreams.toString(reader), tClass);
|
||||||
}
|
}
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T getAssetJson(Context context, String filename, Type type) {
|
public static <T> T getAssetJson(Context context, String filename, TypeReference<T> type) {
|
||||||
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 new Gson().fromJson(CharStreams.toString(reader), type);
|
return JSONUtil.fromJson(CharStreams.toString(reader), type);
|
||||||
}
|
}
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.zane.smapiinstaller.utils;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.json.JsonReadFeature;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
public class JSONUtil {
|
||||||
|
private static final ObjectMapper mapper = new ObjectMapper();
|
||||||
|
static {
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
|
||||||
|
mapper.configure(JsonReadFeature.ALLOW_TRAILING_COMMA.mappedFeature(), true);
|
||||||
|
mapper.configure(JsonReadFeature.ALLOW_MISSING_VALUES.mappedFeature(), true);
|
||||||
|
mapper.configure(JsonReadFeature.ALLOW_JAVA_COMMENTS.mappedFeature(), true);
|
||||||
|
}
|
||||||
|
public static String toJson(Object object) throws Exception {
|
||||||
|
return mapper.writeValueAsString(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void checkJson(String jsonString) throws JsonProcessingException {
|
||||||
|
mapper.readValue(jsonString, Object.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T fromJson(String jsonString, Class<T> cls) {
|
||||||
|
try {
|
||||||
|
return mapper.readValue(jsonString, cls);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
Log.e("JSON", "Deserialize error", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T fromJson(String jsonString, TypeReference<T> type) {
|
||||||
|
try {
|
||||||
|
return mapper.readValue(jsonString, type);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
Log.e("JSON", "Deserialize error", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,22 +4,41 @@ import com.google.common.base.CharMatcher;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class VersionUtil {
|
public class VersionUtil {
|
||||||
private static int parseVersionSection(String version) {
|
private static int compareVersionSection(String sectionA, String sectionB) {
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(version);
|
return Integer.compare(Integer.parseInt(sectionA), Integer.parseInt(sectionB));
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
List<String> list = Splitter.on("-").splitToList(version);
|
List<String> listA = Splitter.on("-").splitToList(sectionA);
|
||||||
switch (list.get(0).toLowerCase()) {
|
List<String> listB = Splitter.on("-").splitToList(sectionB);
|
||||||
case "alpha":
|
int i;
|
||||||
return -2;
|
for (i = 0; i < listA.size() && i < listB.size(); i++) {
|
||||||
case "beta":
|
Integer intA = null;
|
||||||
|
Integer intB = null;
|
||||||
|
try {
|
||||||
|
intA = Integer.parseInt(listA.get(i));
|
||||||
|
return Integer.compare(intA, Integer.parseInt(listB.get(i)));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
intB = Integer.parseInt(listB.get(i));
|
||||||
|
} catch (Exception ignored2) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(StringUtils.equals(listA.get(i), listB.get(i)))
|
||||||
|
continue;
|
||||||
|
if(intA != null && intB == null)
|
||||||
|
return 1;
|
||||||
|
else if(intA == null)
|
||||||
return -1;
|
return -1;
|
||||||
|
return listA.get(i).compareTo(listB.get(i));
|
||||||
}
|
}
|
||||||
return 0;
|
return Integer.compare(listA.size(), listB.size());
|
||||||
}
|
}
|
||||||
private static boolean isZero(List<String> versionSections) {
|
private static boolean isZero(List<String> versionSections) {
|
||||||
return !Iterables.filter(versionSections, version -> {
|
return !Iterables.filter(versionSections, version -> {
|
||||||
|
@ -44,10 +63,16 @@ public class VersionUtil {
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int compare = Integer.compare(parseVersionSection(versionSectionsA.get(i)), parseVersionSection(versionSectionsB.get(i)));
|
int compare = compareVersionSection(versionSectionsA.get(i), versionSectionsB.get(i));
|
||||||
if(compare != 0)
|
if(compare != 0)
|
||||||
return compare;
|
return compare;
|
||||||
}
|
}
|
||||||
|
if(versionSectionsA.size() < versionSectionsB.size()) {
|
||||||
|
if(isZero(versionSectionsB.subList(versionSectionsA.size(), versionSectionsB.size()))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,4 +53,5 @@
|
||||||
<string name="downloading">正在下載: %d KB / %d KB</string>
|
<string name="downloading">正在下載: %d KB / %d KB</string>
|
||||||
<string name="menu_about">關於</string>
|
<string name="menu_about">關於</string>
|
||||||
<string name="android_version_confirm">你的系統版本過老,可能會導致0Harmony無效,建議升級到安卓6及以上版本</string>
|
<string name="android_version_confirm">你的系統版本過老,可能會導致0Harmony無效,建議升級到安卓6及以上版本</string>
|
||||||
|
<string name="error_depends_on_mod_version" >The %s is depends on %s %s version or later, please update it first</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -53,4 +53,5 @@
|
||||||
<string name="downloading">正在下載: %d KB / %d KB</string>
|
<string name="downloading">正在下載: %d KB / %d KB</string>
|
||||||
<string name="menu_about">關於</string>
|
<string name="menu_about">關於</string>
|
||||||
<string name="android_version_confirm">你的系統版本過老,可能會導致0Harmony無效,建議升級到安卓6及以上版本</string>
|
<string name="android_version_confirm">你的系統版本過老,可能會導致0Harmony無效,建議升級到安卓6及以上版本</string>
|
||||||
|
<string name="error_depends_on_mod_version" >The %s is depends on %s %s version or later, please update it first</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -53,4 +53,5 @@
|
||||||
<string name="downloading">正在下载: %d KB / %d KB</string>
|
<string name="downloading">正在下载: %d KB / %d KB</string>
|
||||||
<string name="menu_about">关于</string>
|
<string name="menu_about">关于</string>
|
||||||
<string name="android_version_confirm">你的系统版本过老,可能会导致0Harmony无效,建议升级到安卓6及以上版本</string>
|
<string name="android_version_confirm">你的系统版本过老,可能会导致0Harmony无效,建议升级到安卓6及以上版本</string>
|
||||||
|
<string name="error_depends_on_mod_version" >%s依赖%s %s版本,请先更新它</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -56,4 +56,5 @@
|
||||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||||
<string name="menu_about">About</string>
|
<string name="menu_about">About</string>
|
||||||
<string name="android_version_confirm">You device system version is too old for MonoMod, this may leads to crash of 0Harmony framework, update to Android M or later if possible</string>
|
<string name="android_version_confirm">You device system version is too old for MonoMod, this may leads to crash of 0Harmony framework, update to Android M or later if possible</string>
|
||||||
|
<string name="error_depends_on_mod_version">The %s is depends on %s %s version or later, please update it first</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue