check update

This commit is contained in:
Tungstend 2023-07-28 17:06:53 +08:00
parent e839364720
commit ef239f4136
10 changed files with 517 additions and 1 deletions

View File

@ -23,6 +23,7 @@ import com.tungsten.fcl.setting.Profile;
import com.tungsten.fcl.setting.Profiles;
import com.tungsten.fcl.ui.UIManager;
import com.tungsten.fcl.ui.version.Versions;
import com.tungsten.fcl.upgrade.UpdateChecker;
import com.tungsten.fcl.util.AndroidUtils;
import com.tungsten.fcl.util.FXUtils;
import com.tungsten.fcl.util.WeakListenerHolder;
@ -174,6 +175,8 @@ public class MainActivity extends FCLActivity implements FCLMenuView.OnSelectLis
setupAccountDisplay();
setupVersionDisplay();
UpdateChecker.getInstance().checkAuto(this).start();
});
});
}

View File

@ -16,6 +16,7 @@ import android.widget.Toast;
import com.tungsten.fcl.R;
import com.tungsten.fcl.activity.MainActivity;
import com.tungsten.fcl.setting.DownloadProviders;
import com.tungsten.fcl.upgrade.UpdateChecker;
import com.tungsten.fcl.util.AndroidUtils;
import com.tungsten.fcl.util.FXUtils;
import com.tungsten.fcl.util.RequestCodes;
@ -54,6 +55,7 @@ import java.util.logging.Level;
public class LauncherSettingPage extends FCLCommonPage implements View.OnClickListener, AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener {
private FCLSpinner<String> language;
private FCLButton checkUpdate;
private FCLButton clearCache;
private FCLButton exportLog;
private FCLButton theme;
@ -78,6 +80,7 @@ public class LauncherSettingPage extends FCLCommonPage implements View.OnClickLi
public void onCreate() {
super.onCreate();
language = findViewById(R.id.language);
checkUpdate = findViewById(R.id.check_update);
clearCache = findViewById(R.id.clear_cache);
exportLog = findViewById(R.id.export_log);
theme = findViewById(R.id.theme);
@ -94,6 +97,7 @@ public class LauncherSettingPage extends FCLCommonPage implements View.OnClickLi
threads = findViewById(R.id.threads);
threadsText = findViewById(R.id.threads_text);
checkUpdate.setOnClickListener(this);
clearCache.setOnClickListener(this);
exportLog.setOnClickListener(this);
theme.setOnClickListener(this);
@ -175,6 +179,18 @@ public class LauncherSettingPage extends FCLCommonPage implements View.OnClickLi
@Override
public void onClick(View v) {
if (v == checkUpdate && !UpdateChecker.getInstance().isChecking()) {
UpdateChecker.getInstance().checkManually(getContext()).whenComplete(Schedulers.androidUIThread(), e -> {
if (e != null) {
FCLAlertDialog.Builder builder = new FCLAlertDialog.Builder(getContext());
builder.setCancelable(false);
builder.setAlertLevel(FCLAlertDialog.AlertLevel.ALERT);
builder.setMessage(getContext().getString(R.string.update_check_failed) + "\n" + e);
builder.setNegativeButton(getContext().getString(com.tungsten.fcllibrary.R.string.dialog_positive), null);
builder.create().show();
}
}).start();
}
if (v == clearCache) {
FileUtils.cleanDirectoryQuietly(new File(FCLPath.CACHE_DIR).getParentFile());
}

View File

@ -0,0 +1,92 @@
package com.tungsten.fcl.upgrade;
import android.content.Context;
import com.tungsten.fcl.R;
import com.tungsten.fcllibrary.util.LocaleUtils;
import java.util.ArrayList;
public class RemoteVersion {
private final String type;
private final int versionCode;
private final String versionName;
private final String date;
private final ArrayList<Description> description;
private final String url;
public RemoteVersion(String type, int versionCode, String versionName, String date, ArrayList<Description> description, String url) {
this.type = type;
this.versionCode = versionCode;
this.versionName = versionName;
this.date = date;
this.description = description;
this.url = url;
}
public String getType() {
return type;
}
public int getVersionCode() {
return versionCode;
}
public String getVersionName() {
return versionName;
}
public String getDate() {
return date;
}
public ArrayList<Description> getDescription() {
return description;
}
public String getUrl() {
return url;
}
public boolean isBeta() {
return getType().equals("beta");
}
public String getDisplayType(Context context) {
return type.equals("beta") ? context.getString(R.string.update_version_beta) : context.getString(R.string.update_version_release);
}
public String getDisplayDescription(Context context) {
if (description.size() == 0) {
throw new IllegalStateException("No update description list!");
}
for (Description d : description) {
if (d.getLang().equals(LocaleUtils.getLocale(LocaleUtils.getLanguage(context)).toString())) {
return d.getText();
}
}
return description.get(0).getText();
}
public static class Description {
private final String lang;
private final String text;
public Description(String lang, String text) {
this.lang = lang;
this.text = text;
}
public String getLang() {
return lang;
}
public String getText() {
return text;
}
}
}

View File

@ -0,0 +1,106 @@
package com.tungsten.fcl.upgrade;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.widget.Toast;
import com.google.gson.reflect.TypeToken;
import com.tungsten.fcl.R;
import com.tungsten.fclcore.task.Schedulers;
import com.tungsten.fclcore.task.Task;
import com.tungsten.fclcore.util.gson.JsonUtils;
import com.tungsten.fclcore.util.io.NetworkUtils;
import java.util.ArrayList;
public class UpdateChecker {
public static final String UPDATE_CHECK_URL = "https://raw.githubusercontent.com/FCL-Team/FoldCraftLauncher/main/version_map.json";
private static UpdateChecker instance;
public static UpdateChecker getInstance() {
if (instance == null) {
instance = new UpdateChecker();
}
return instance;
}
private boolean isChecking = false;
public boolean isChecking() {
return isChecking;
}
public UpdateChecker() {
}
public Task<?> checkManually(Context context) {
return check(context, true, true);
}
public Task<?> checkAuto(Context context) {
return check(context, false, false);
}
public Task<?> check(Context context, boolean showBeta, boolean showAlert) {
return Task.runAsync(() -> {
isChecking = true;
if (showAlert) {
Schedulers.androidUIThread().execute(() -> Toast.makeText(context, context.getString(R.string.update_checking), Toast.LENGTH_SHORT).show());
}
String res = NetworkUtils.doGet(NetworkUtils.toURL(UPDATE_CHECK_URL));
ArrayList<RemoteVersion> versions = JsonUtils.GSON.fromJson(res, new TypeToken<ArrayList<RemoteVersion>>(){}.getType());
for (RemoteVersion version : versions) {
if (version.getVersionCode() > getCurrentVersionCode(context)) {
if (showBeta || !version.isBeta()) {
if (showBeta || !isIgnore(context, version.getVersionCode())) {
showUpdateDialog(context, version);
}
isChecking = false;
return;
}
}
}
if (showAlert) {
Schedulers.androidUIThread().execute(() -> Toast.makeText(context, context.getString(R.string.update_not_exist), Toast.LENGTH_SHORT).show());
}
isChecking = false;
});
}
private int getCurrentVersionCode(Context context) {
PackageManager pm = context.getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
throw new IllegalStateException("Can't get current version code");
}
}
private void showUpdateDialog(Context context, RemoteVersion version) {
Schedulers.androidUIThread().execute(() -> {
UpdateDialog dialog = new UpdateDialog(context, version);
dialog.show();
});
}
public static boolean isIgnore(Context context, int code) {
SharedPreferences sharedPreferences = context.getSharedPreferences("launcher", Context.MODE_PRIVATE);
return sharedPreferences.getInt("ignore_update", -1) == code;
}
public static void setIgnore(Context context, int code) {
SharedPreferences sharedPreferences = context.getSharedPreferences("launcher", Context.MODE_PRIVATE);
@SuppressLint("CommitPrefEdits") SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("ignore_update", code);
editor.apply();
}
}

View File

@ -0,0 +1,133 @@
package com.tungsten.fcl.upgrade;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.net.Uri;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ScrollView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDialog;
import androidx.core.content.FileProvider;
import com.tungsten.fcl.R;
import com.tungsten.fcl.ui.TaskDialog;
import com.tungsten.fcl.util.TaskCancellationAction;
import com.tungsten.fclauncher.FCLPath;
import com.tungsten.fclcore.task.FileDownloadTask;
import com.tungsten.fclcore.task.Schedulers;
import com.tungsten.fclcore.task.Task;
import com.tungsten.fclcore.task.TaskExecutor;
import com.tungsten.fclcore.util.io.NetworkUtils;
import com.tungsten.fcllibrary.component.dialog.FCLDialog;
import com.tungsten.fcllibrary.component.view.FCLButton;
import com.tungsten.fcllibrary.component.view.FCLLinearLayout;
import com.tungsten.fcllibrary.component.view.FCLTextView;
import com.tungsten.fcllibrary.util.ConvertUtils;
import java.io.File;
public class UpdateDialog extends FCLDialog implements View.OnClickListener {
private final RemoteVersion version;
private View parent;
private ScrollView scrollView;
private FCLLinearLayout layout;
private FCLTextView versionName;
private FCLTextView date;
private FCLTextView type;
private FCLTextView description;
private FCLButton ignore;
private FCLButton positive;
private FCLButton negative;
public UpdateDialog(@NonNull Context context, RemoteVersion version) {
super(context);
this.version = version;
setCancelable(false);
setContentView(R.layout.dialog_update);
init();
}
private void init() {
parent = findViewById(R.id.parent);
scrollView = findViewById(R.id.text_scroll);
layout = findViewById(R.id.layout);
versionName = findViewById(R.id.version);
date = findViewById(R.id.date);
type = findViewById(R.id.type);
description = findViewById(R.id.description);
versionName.setText(String.format(getContext().getString(R.string.update_version), version.getVersionName()));
date.setText(String.format(getContext().getString(R.string.update_date), version.getDate()));
type.setText(String.format(getContext().getString(R.string.update_type), version.getDisplayType(getContext())));
description.setText(String.format(getContext().getString(R.string.update_description), version.getDisplayDescription(getContext())));
ignore = findViewById(R.id.ignore);
positive = findViewById(R.id.positive);
negative = findViewById(R.id.negative);
ignore.setOnClickListener(this);
positive.setOnClickListener(this);
negative.setOnClickListener(this);
checkHeight();
}
private void checkHeight() {
parent.post(() -> layout.post(() -> {
WindowManager wm = getWindow().getWindowManager();
Point point = new Point();
wm.getDefaultDisplay().getSize(point);
int maxHeight = point.y - ConvertUtils.dip2px(getContext(), 30);
if (parent.getMeasuredHeight() < maxHeight) {
ViewGroup.LayoutParams layoutParams = scrollView.getLayoutParams();
layoutParams.height = layout.getMeasuredHeight();
scrollView.setLayoutParams(layoutParams);
getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
} else {
getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT, maxHeight);
}
}));
}
@Override
public void onClick(View v) {
if (v == ignore) {
UpdateChecker.setIgnore(getContext(), version.getVersionCode());
dismiss();
}
if (v == positive) {
TaskDialog dialog = new TaskDialog(getContext(), new TaskCancellationAction(AppCompatDialog::dismiss));
dialog.setTitle(getContext().getString(R.string.update_launcher));
Schedulers.androidUIThread().execute(() -> {
TaskExecutor executor = Task.composeAsync(() -> {
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(version.getUrl()), new File(FCLPath.CACHE_DIR, "FoldCraftLauncher.apk"));
task.setName("FoldCraftLauncher");
return task.whenComplete(Schedulers.androidUIThread(), exception -> {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri apkUri = FileProvider.getUriForFile(getContext(), getContext().getString(com.tungsten.fcllibrary.R.string.file_browser_provider), new File(FCLPath.CACHE_DIR, "FoldCraftLauncher.apk"));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
getContext().startActivity(intent);
});
}).executor();
dialog.setExecutor(executor);
dialog.show();
executor.start();
});
dismiss();
}
if (v == negative) {
dismiss();
}
}
}

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/parent"
android:minWidth="400dp"
android:minHeight="150dp"
android:padding="10dp"
android:orientation="vertical">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:singleLine="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/update_exist"
android:textSize="18sp"
android:layout_gravity="center"/>
<ScrollView
android:id="@+id/text_scroll"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
<com.tungsten.fcllibrary.component.view.FCLLinearLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:id="@+id/version"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:id="@+id/type"
android:layout_weight="1"
android:singleLine="true"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:id="@+id/date"
android:layout_weight="1"
android:singleLine="true"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:layout_marginTop="10dp"
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.tungsten.fcllibrary.component.view.FCLLinearLayout>
</ScrollView>
<androidx.appcompat.widget.LinearLayoutCompat
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.tungsten.fcllibrary.component.view.FCLButton
android:id="@+id/ignore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/update_ignore" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<com.tungsten.fcllibrary.component.view.FCLButton
android:layout_marginStart="10dp"
android:id="@+id/positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/update" />
<com.tungsten.fcllibrary.component.view.FCLButton
android:layout_marginStart="10dp"
android:id="@+id/negative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_negative" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -53,6 +53,44 @@
</androidx.appcompat.widget.LinearLayoutCompat>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/darker_gray"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:minHeight="48dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:auto_text_tint="true"
android:layout_gravity="center"
android:singleLine="true"
android:text="@string/settings_launcher_upgrade"/>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<com.tungsten.fcllibrary.component.view.FCLButton
app:ripple="true"
android:text="@string/settings_launcher_upgrade_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/check_update"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<View
android:layout_width="match_parent"
android:layout_height="1dp"

View File

@ -734,10 +734,17 @@
<string name="style_rocker_corner_radius">摇杆圆角半径</string>
<string name="style_rocker_fill_color">摇杆背景颜色</string>
<string name="update">更新</string>
<string name="update_checking">正在检查更新</string>
<string name="update_check_failed">无法检测更新</string>
<string name="update_date">日期:%s</string>
<string name="update_description">描述:%s</string>
<string name="update_exist">检测到可更新的版本</string>
<string name="update_ignore">忽略此版本</string>
<string name="update_launcher">更新启动器</string>
<string name="update_not_exist">没有可更新的版本</string>
<string name="update_type">类型:%s</string>
<string name="update_version">版本:%s</string>
<string name="update_version_release">正式版</string>
<string name="update_version_beta">测试版</string>

View File

@ -762,10 +762,17 @@
<string name="style_rocker_corner_radius">Rocker Corner Radius</string>
<string name="style_rocker_fill_color">Rocker Fill Color</string>
<string name="update">Update</string>
<string name="update_checking">Checking for Updates</string>
<string name="update_check_failed">Failed to check update</string>
<string name="update_date">Date: %s</string>
<string name="update_description">Description: %s</string>
<string name="update_exist">Updatable version detected</string>
<string name="update_ignore">Ignore this version</string>
<string name="update_launcher">Updating launcher</string>
<string name="update_not_exist">No update available</string>
<string name="update_type">Type: %s</string>
<string name="update_version">Version: %s</string>
<string name="update_version_release">Release</string>
<string name="update_version_beta">Beta</string>

View File

@ -4,7 +4,16 @@
"versionCode": 1,
"versionName": "1.0.0",
"date": "2023.7.28",
"update": "Support all Minecraft versions, download, version management, etc.",
"description": [
{
"lang": "en",
"text": "Support all Minecraft versions, download, version management, etc."
},
{
"lang": "zh_CN",
"text": "支持全版本 Minecraft 启动,及其下载,管理等。"
}
],
"url": ""
}
]