11package org .microg .tools .updater ;
22
3+ import android .app .Activity ;
34import android .content .Context ;
45import android .content .Intent ;
56import android .net .Uri ;
67import android .os .Handler ;
78import android .os .Looper ;
9+ import android .util .Log ;
810import android .view .View ;
911import android .view .ViewGroup ;
1012
1517
1618import org .json .JSONException ;
1719import org .json .JSONObject ;
20+ import org .microg .tools .ui .BuildConfig ;
1821import org .microg .tools .ui .R ;
1922
2023import java .io .IOException ;
2730
2831public class UpdateChecker {
2932
33+ private static final String TAG = "UpdateChecker" ;
3034 private static final String GITHUB_API_URL = "https://api.github.com/repos/MorpheApp/MicroG-RE/releases/latest" ;
3135 private static final String GITHUB_RELEASE_LINK = "https://github.com/MorpheApp/MicroG-RE/releases/latest" ;
3236
37+ private static final OkHttpClient client = new OkHttpClient .Builder ().retryOnConnectionFailure (true ).build ();
38+
3339 private final WeakReference <Context > contextRef ;
34- private final OkHttpClient client ;
40+ private final Handler mainHandler = new Handler ( Looper . getMainLooper ()) ;
3541
3642 public UpdateChecker (Context context ) {
3743 this .contextRef = new WeakReference <>(context );
38- this .client = new OkHttpClient .Builder ().retryOnConnectionFailure (true ).build ();
3944 }
4045
4146 public void checkForUpdates (View view , Runnable onComplete ) {
42- CompletableFuture .supplyAsync (this ::fetchLatestVersion ).thenAccept (latestVersion -> runOnMainThread (() -> {
47+ CompletableFuture .supplyAsync (this ::fetchLatestVersion ).thenAccept (latestVersion -> mainHandler . post (() -> {
4348 handleLatestVersion (latestVersion , view );
44- onComplete .run ();
49+ if ( onComplete != null ) onComplete .run ();
4550 })).exceptionally (throwable -> {
46- runOnMainThread (() -> {
51+ mainHandler . post (() -> {
4752 handleError (throwable , view );
48- onComplete .run ();
53+ if ( onComplete != null ) onComplete .run ();
4954 });
5055 return null ;
5156 });
5257 }
5358
5459 private String fetchLatestVersion () {
55- Request request = new Request .Builder ().url (GITHUB_API_URL ).build ();
60+ Request request = new Request .Builder ().url (GITHUB_API_URL ).header ("User-Agent" , "MicroG-RE-Updater" ).build ();
61+
5662 try (Response response = client .newCall (request ).execute ()) {
5763 if (response .isSuccessful ()) {
5864 return parseLatestVersion (response .body ().string ());
@@ -67,35 +73,60 @@ private String fetchLatestVersion() {
6773 private String parseLatestVersion (String jsonData ) {
6874 try {
6975 JSONObject jsonObject = new JSONObject (jsonData );
70- return jsonObject .optString ("tag_name" , "" );
76+ return jsonObject .optString ("tag_name" , "" ). replace ( "v" , "" ). trim () ;
7177 } catch (JSONException e ) {
7278 throw new RuntimeException ("Error processing JSON" , e );
7379 }
7480 }
7581
7682 private void handleLatestVersion (String latestVersion , View view ) {
7783 Context context = contextRef .get ();
78- if (context == null || view == null ) return ;
84+ if (context == null || view == null || latestVersion .isEmpty ()) return ;
85+
86+
87+ if (context instanceof Activity && ((Activity ) context ).isFinishing ()) return ;
7988
80- String appVersion = context . getString ( R . string . github_tag_version );
89+ String appVersion = BuildConfig . APP_VERSION_NAME . replace ( "v" , "" ). trim ( );
8190
82- if (appVersion . compareTo ( latestVersion ) < 0 ) {
83- showSnackbarWithAction (view , context .getString (R .string .update_available ), context .getString (R .string .download_button ), v -> openGitHubReleaseLink (context ));
91+ if (isVersionNewer ( appVersion , latestVersion )) {
92+ showSnackbarWithAction (view , context .getString (R .string .update_available ) + " (" + latestVersion + ")" , context .getString (R .string .download_button ), v -> openGitHubReleaseLink (context ));
8493 } else {
8594 showSnackbar (view , context .getString (R .string .no_update_available ));
8695 }
8796 }
8897
98+ private boolean isVersionNewer (String current , String latest ) {
99+ try {
100+ String [] currParts = current .split ("\\ ." );
101+ String [] latParts = latest .split ("\\ ." );
102+ int length = Math .max (currParts .length , latParts .length );
103+
104+ for (int i = 0 ; i < length ; i ++) {
105+ int currV = i < currParts .length ? Integer .parseInt (currParts [i ].replaceAll ("[^0-9]" , "" )) : 0 ;
106+ int latV = i < latParts .length ? Integer .parseInt (latParts [i ].replaceAll ("[^0-9]" , "" )) : 0 ;
107+
108+ if (latV > currV ) return true ;
109+ if (currV > latV ) return false ;
110+ }
111+ } catch (Exception e ) {
112+ Log .e (TAG , "Error comparing versions" , e );
113+ return latest .compareTo (current ) > 0 ;
114+ }
115+ return false ;
116+ }
117+
89118 private void handleError (Throwable throwable , View view ) {
90119 Context context = contextRef .get ();
91120 if (context == null || view == null ) return ;
92121
93- String errorMessage = throwable .getMessage () != null && throwable .getMessage ().toLowerCase ().contains ("connection" ) ? context .getString (R .string .error_connection ) + " " + throwable .getMessage () : context .getString (R .string .error_others ) + " " + throwable .getMessage ();
94- showSnackbar (view , errorMessage );
122+ String message = throwable .getCause () != null ? throwable .getCause ().getMessage () : throwable .getMessage ();
123+ String errorText = (message != null && message .contains ("connection" )) ? context .getString (R .string .error_connection ) : context .getString (R .string .error_others );
124+
125+ showSnackbar (view , errorText );
95126 }
96127
97128 private void showSnackbar (View view , String message ) {
98- Snackbar snackbar = Snackbar .make (view , message , Snackbar .LENGTH_LONG );
129+ Snackbar snackbar = Snackbar .make (view , message , Snackbar .LENGTH_SHORT );
99130 configureSnackbar (snackbar );
100131 snackbar .show ();
101132 }
@@ -110,18 +141,19 @@ private void configureSnackbar(Snackbar snackbar) {
110141 ViewCompat .setOnApplyWindowInsetsListener (snackbar .getView (), (v , insets ) -> {
111142 int bottomPadding = insets .getInsets (WindowInsetsCompat .Type .systemBars ()).bottom ;
112143 ViewGroup .MarginLayoutParams params = (ViewGroup .MarginLayoutParams ) v .getLayoutParams ();
113- params .bottomMargin = bottomPadding ;
144+ params .bottomMargin = bottomPadding + 20 ;
114145 v .setLayoutParams (params );
115146 return insets ;
116147 });
117148 }
118149
119150 private void openGitHubReleaseLink (Context context ) {
120- Intent intent = new Intent (Intent .ACTION_VIEW , Uri .parse (GITHUB_RELEASE_LINK ));
121- context .startActivity (intent );
122- }
123-
124- private void runOnMainThread (Runnable action ) {
125- new Handler (Looper .getMainLooper ()).post (action );
151+ try {
152+ Intent intent = new Intent (Intent .ACTION_VIEW , Uri .parse (GITHUB_RELEASE_LINK ));
153+ intent .addFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
154+ context .startActivity (intent );
155+ } catch (Exception e ) {
156+ Log .e (TAG , "Error opening release link" , e );
157+ }
126158 }
127159}
0 commit comments