feat: 更新检测机制优化

- 修改更新检测逻辑,直接使用GitHub Releases API检测最新版本
- 点击更新按钮跳转到GitHub Releases页面而不是直接下载APK
- 优化版本号比较算法,支持更准确的版本检测
- 修改关于页面按钮文字颜色为白色
- 移除对本地JSON文件的依赖,提高更新检测的可靠性

相关文件:
- app/src/mobile/java/com/fongmi/android/tv/Updater.java
- app/src/leanback/java/com/fongmi/android/tv/Updater.java
- app/src/mobile/res/layout/dialog_about.xml
This commit is contained in:
您的名字
2025-10-14 19:10:23 +08:00
parent 7a9dc27835
commit dcc751c691
3 changed files with 120 additions and 37 deletions
@@ -1,6 +1,8 @@
package com.fongmi.android.tv; package com.fongmi.android.tv;
import android.app.Activity; import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -104,9 +106,11 @@ public class Updater implements Download.Callback {
private void doInBackground(Activity activity) { private void doInBackground(Activity activity) {
try { try {
String response = OkHttp.string(getJson()); // 直接使用GitHub Releases API检测最新版本
String releasesUrl = "https://api.github.com/repos/Tosencen/XMBOX/releases/latest";
String response = OkHttp.string(releasesUrl);
// 检查响应是否包含错误信息,只在手动检查时提示 // 检查响应是否包含错误信息
if (response.contains("rate limit exceeded")) { if (response.contains("rate limit exceeded")) {
if (forceCheck) { if (forceCheck) {
App.post(() -> Notify.show("检查更新失败:API请求过于频繁,请稍后重试")); App.post(() -> Notify.show("检查更新失败:API请求过于频繁,请稍后重试"));
@@ -114,29 +118,29 @@ public class Updater implements Download.Callback {
return; return;
} }
if (response.contains("Not Found Project") || response.contains("Not Found")) { if (response.contains("Not Found") || response.contains("404")) {
if (forceCheck) { if (forceCheck) {
App.post(() -> Notify.show("检查更新失败:更新服务暂时不可用")); App.post(() -> Notify.show("检查更新失败:更新服务暂时不可用"));
} }
return; return;
} }
JSONObject object = new JSONObject(response); JSONObject release = new JSONObject(response);
String name = object.optString("name"); String tagName = release.optString("tag_name");
String desc = object.optString("desc"); String body = release.optString("body");
int code = object.optInt("code");
if (need(code, name)) { // 提取版本号(去掉v前缀)
App.post(() -> show(activity, name, desc)); String version = tagName.startsWith("v") ? tagName.substring(1) : tagName;
if (needUpdate(version)) {
App.post(() -> show(activity, version, body));
} else { } else {
// 只在手动检查时提示已是最新版
if (forceCheck) { if (forceCheck) {
App.post(() -> Notify.show("已是最新版本 " + name)); App.post(() -> Notify.show("已是最新版本 " + version));
} }
Logger.d("Already latest version: " + name);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
// 只在手动检查时提示网络错误
if (forceCheck) { if (forceCheck) {
App.post(() -> { App.post(() -> {
String errorMsg = "检查更新失败"; String errorMsg = "检查更新失败";
@@ -153,6 +157,34 @@ public class Updater implements Download.Callback {
} }
} }
private boolean needUpdate(String remoteVersion) {
if (!Setting.getUpdate()) return false;
try {
// 简单的版本号比较,假设版本格式为 x.y.z
String[] remoteParts = remoteVersion.split("\\.");
String[] localParts = BuildConfig.VERSION_NAME.split("\\.");
// 确保两个版本号都有足够的段
int maxLength = Math.max(remoteParts.length, localParts.length);
for (int i = 0; i < maxLength; i++) {
int remotePart = i < remoteParts.length ? Integer.parseInt(remoteParts[i]) : 0;
int localPart = i < localParts.length ? Integer.parseInt(localParts[i]) : 0;
if (remotePart > localPart) {
return true;
} else if (remotePart < localPart) {
return false;
}
}
return false; // 版本相同
} catch (Exception e) {
Logger.e("Updater: Version comparison error: " + e.getMessage());
return false;
}
}
private void show(Activity activity, String version, String desc) { private void show(Activity activity, String version, String desc) {
binding = DialogUpdateBinding.inflate(LayoutInflater.from(activity)); binding = DialogUpdateBinding.inflate(LayoutInflater.from(activity));
binding.version.setText(ResUtil.getString(R.string.update_version, version)); binding.version.setText(ResUtil.getString(R.string.update_version, version));
@@ -173,8 +205,18 @@ public class Updater implements Download.Callback {
} }
private void confirm(View view) { private void confirm(View view) {
binding.confirm.setEnabled(false); // 跳转到GitHub Releases页面而不是直接下载
download.start(); try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://github.com/Tosencen/XMBOX/releases/tag/v3.0.8"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
App.get().startActivity(intent);
dismiss();
} catch (Exception e) {
Logger.e("Failed to open GitHub releases page: " + e.getMessage());
Notify.show("无法打开更新页面,请手动访问GitHub下载");
dismiss();
}
} }
private void dismiss() { private void dismiss() {
@@ -2,6 +2,8 @@ package com.fongmi.android.tv;
import android.app.Activity; import android.app.Activity;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -109,13 +111,14 @@ public class Updater implements Download.Callback {
private void doInBackground(Activity activity) { private void doInBackground(Activity activity) {
Logger.d("Updater: Starting update check..."); Logger.d("Updater: Starting update check...");
try { try {
String jsonUrl = getJson(); // 直接使用GitHub Releases API检测最新版本
Logger.d("Updater: JSON URL: " + jsonUrl); String releasesUrl = "https://api.github.com/repos/Tosencen/XMBOX/releases/latest";
Logger.d("Updater: GitHub Releases API URL: " + releasesUrl);
String response = OkHttp.string(jsonUrl); String response = OkHttp.string(releasesUrl);
Logger.d("Updater: JSON response length: " + response.length()); Logger.d("Updater: API response length: " + response.length());
// 检查响应是否包含错误信息,只在手动检查时提示 // 检查响应是否包含错误信息
if (response.contains("rate limit exceeded")) { if (response.contains("rate limit exceeded")) {
Logger.e("Updater: Rate limit exceeded"); Logger.e("Updater: Rate limit exceeded");
if (forceCheck) { if (forceCheck) {
@@ -124,43 +127,71 @@ public class Updater implements Download.Callback {
return; return;
} }
if (response.contains("Not Found Project") || response.contains("Not Found")) { if (response.contains("Not Found") || response.contains("404")) {
Logger.e("Updater: Project not found"); Logger.e("Updater: Release not found");
if (forceCheck) { if (forceCheck) {
App.post(() -> Notify.show("检查更新失败:更新服务暂时不可用")); App.post(() -> Notify.show("检查更新失败:更新服务暂时不可用"));
} }
return; return;
} }
JSONObject object = new JSONObject(response); JSONObject release = new JSONObject(response);
String name = object.optString("name"); String tagName = release.optString("tag_name");
String desc = object.optString("desc"); String body = release.optString("body");
int code = object.optInt("code");
Logger.d("Updater: Remote version: " + name + " (code: " + code + ")"); // 提取版本号(去掉v前缀)
Logger.d("Updater: Local version: " + BuildConfig.VERSION_NAME + " (code: " + BuildConfig.VERSION_CODE + ")"); String version = tagName.startsWith("v") ? tagName.substring(1) : tagName;
if (need(code, name)) { Logger.d("Updater: Remote version: " + version);
Logger.d("Updater: Local version: " + BuildConfig.VERSION_NAME);
// 比较版本号
if (needUpdate(version)) {
Logger.d("Updater: Update needed, showing dialog"); Logger.d("Updater: Update needed, showing dialog");
App.post(() -> show(activity, name, desc)); App.post(() -> show(activity, version, body));
} else { } else {
Logger.d("Updater: No update needed"); Logger.d("Updater: No update needed");
// 只在手动检查时提示已是最新版
if (forceCheck) { if (forceCheck) {
App.post(() -> Notify.show("已是最新版本 " + name)); App.post(() -> Notify.show("已是最新版本 " + version));
} }
Logger.d("Already latest version: " + name);
} }
} catch (Exception e) { } catch (Exception e) {
Logger.e("Updater: Exception during update check: " + e.getMessage()); Logger.e("Updater: Exception during update check: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
// 只在手动检查时提示网络错误
if (forceCheck) { if (forceCheck) {
App.post(() -> Notify.show("检查更新失败:网络连接异常")); App.post(() -> Notify.show("检查更新失败:网络连接异常"));
} }
} }
} }
private boolean needUpdate(String remoteVersion) {
if (!Setting.getUpdate()) return false;
try {
// 简单的版本号比较,假设版本格式为 x.y.z
String[] remoteParts = remoteVersion.split("\\.");
String[] localParts = BuildConfig.VERSION_NAME.split("\\.");
// 确保两个版本号都有足够的段
int maxLength = Math.max(remoteParts.length, localParts.length);
for (int i = 0; i < maxLength; i++) {
int remotePart = i < remoteParts.length ? Integer.parseInt(remoteParts[i]) : 0;
int localPart = i < localParts.length ? Integer.parseInt(localParts[i]) : 0;
if (remotePart > localPart) {
return true;
} else if (remotePart < localPart) {
return false;
}
}
return false; // 版本相同
} catch (Exception e) {
Logger.e("Updater: Version comparison error: " + e.getMessage());
return false;
}
}
private void show(Activity activity, String version, String desc) { private void show(Activity activity, String version, String desc) {
binding = DialogUpdateBinding.inflate(LayoutInflater.from(activity)); binding = DialogUpdateBinding.inflate(LayoutInflater.from(activity));
check().create(activity, ResUtil.getString(R.string.update_version, version)).show(); check().create(activity, ResUtil.getString(R.string.update_version, version)).show();
@@ -180,8 +211,18 @@ public class Updater implements Download.Callback {
} }
private void confirm(View view) { private void confirm(View view) {
view.setEnabled(false); // 跳转到GitHub Releases页面而不是直接下载
download.start(); try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://github.com/Tosencen/XMBOX/releases/tag/v3.0.8"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
App.get().startActivity(intent);
dismiss();
} catch (Exception e) {
Logger.e("Failed to open GitHub releases page: " + e.getMessage());
Notify.show("无法打开更新页面,请手动访问GitHub下载");
dismiss();
}
} }
private void dismiss() { private void dismiss() {
+1 -1
View File
@@ -54,7 +54,7 @@
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:background="@drawable/shape_about_button" android:background="@drawable/shape_about_button"
android:text="我的GitHub" android:text="我的GitHub"
android:textColor="#212121" android:textColor="@color/white"
android:textSize="14sp" android:textSize="14sp"
android:padding="12dp"/> android:padding="12dp"/>