Add v9.0: Auto-update system with Gitea integration
- Implement UpdateManager to check Gitea releases for new versions - Add update dialogs with mandatory/optional update support - Integrate DownloadManager for APK downloads - Add FileProvider configuration for app installation - Support update-manifest.json for version control enforcement - Add comprehensive update strings and error handling - Include gradlew executable permissions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
package com.streamplayer;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
@@ -35,6 +38,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
private final List<EventItem> cachedEvents = new ArrayList<>();
|
||||
private List<SectionEntry> sections;
|
||||
private SectionEntry currentSection;
|
||||
private UpdateManager updateManager;
|
||||
private AlertDialog updateDialog;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -60,6 +65,45 @@ public class MainActivity extends AppCompatActivity {
|
||||
sectionList.setAdapter(sectionAdapter);
|
||||
|
||||
selectSection(0);
|
||||
|
||||
updateManager = new UpdateManager(this);
|
||||
updateManager.checkForUpdates(new UpdateManager.UpdateCallback() {
|
||||
@Override
|
||||
public void onUpdateAvailable(UpdateManager.UpdateInfo info) {
|
||||
handleUpdateInfo(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpToDate() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String message) {
|
||||
Toast.makeText(MainActivity.this,
|
||||
getString(R.string.update_error_checking, message),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (updateManager != null) {
|
||||
updateManager.resumePendingInstall(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (updateDialog != null && updateDialog.isShowing()) {
|
||||
updateDialog.dismiss();
|
||||
}
|
||||
if (updateManager != null) {
|
||||
updateManager.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void selectSection(int index) {
|
||||
@@ -151,6 +195,87 @@ public class MainActivity extends AppCompatActivity {
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void handleUpdateInfo(UpdateManager.UpdateInfo info) {
|
||||
if (info == null) {
|
||||
return;
|
||||
}
|
||||
boolean forceUpdate = info.isMandatory(BuildConfig.VERSION_CODE);
|
||||
showUpdateDialog(info, forceUpdate);
|
||||
}
|
||||
|
||||
private void showUpdateDialog(UpdateManager.UpdateInfo info, boolean mandatory) {
|
||||
if (isFinishing()) {
|
||||
return;
|
||||
}
|
||||
if (updateDialog != null && updateDialog.isShowing()) {
|
||||
updateDialog.dismiss();
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this)
|
||||
.setTitle(mandatory ? R.string.update_required_title : R.string.update_available_title)
|
||||
.setMessage(buildUpdateMessage(info))
|
||||
.setPositiveButton(R.string.update_action_download,
|
||||
(dialog, which) -> updateManager.downloadUpdate(MainActivity.this, info))
|
||||
.setNeutralButton(R.string.update_action_view_release,
|
||||
(dialog, which) -> openReleasePage(info));
|
||||
if (mandatory) {
|
||||
builder.setCancelable(false);
|
||||
builder.setNegativeButton(R.string.update_action_close_app,
|
||||
(dialog, which) -> finish());
|
||||
} else {
|
||||
builder.setNegativeButton(R.string.update_action_later, null);
|
||||
}
|
||||
updateDialog = builder.show();
|
||||
}
|
||||
|
||||
private CharSequence buildUpdateMessage(UpdateManager.UpdateInfo info) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(getString(R.string.update_current_version,
|
||||
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
|
||||
builder.append('\n');
|
||||
builder.append(getString(R.string.update_latest_version,
|
||||
info.versionName, info.versionCode));
|
||||
if (info.minSupportedVersionCode > 0) {
|
||||
builder.append('\n').append(getString(R.string.update_min_supported,
|
||||
info.minSupportedVersionCode));
|
||||
}
|
||||
String size = info.formatSize(this);
|
||||
if (!size.isEmpty()) {
|
||||
builder.append('\n').append(getString(R.string.update_download_size, size));
|
||||
}
|
||||
if (info.downloadCount > 0) {
|
||||
builder.append('\n').append(getString(R.string.update_downloads,
|
||||
info.downloadCount));
|
||||
}
|
||||
if (!info.releaseNotes.isEmpty()) {
|
||||
builder.append("\n\n");
|
||||
builder.append(getString(R.string.update_release_notes_title));
|
||||
builder.append('\n');
|
||||
builder.append(info.getReleaseNotesPreview());
|
||||
}
|
||||
if (!info.isMandatory(BuildConfig.VERSION_CODE)) {
|
||||
builder.append("\n\n");
|
||||
builder.append(getString(R.string.update_optional_hint));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void openReleasePage(UpdateManager.UpdateInfo info) {
|
||||
String url = info.releasePageUrl;
|
||||
if (url == null || url.isEmpty()) {
|
||||
url = info.downloadUrl;
|
||||
}
|
||||
if (url == null || url.isEmpty()) {
|
||||
Toast.makeText(this, R.string.update_error_missing_url, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
try {
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, R.string.update_error_open_release, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private int getSpanCount() {
|
||||
return getResources().getInteger(R.integer.channel_grid_span);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user