diff --git a/app/src/main/java/com/github/libretube/SettingsActivity.kt b/app/src/main/java/com/github/libretube/SettingsActivity.kt
index 20a91a1c7..de2eb29d0 100644
--- a/app/src/main/java/com/github/libretube/SettingsActivity.kt
+++ b/app/src/main/java/com/github/libretube/SettingsActivity.kt
@@ -30,6 +30,7 @@ import androidx.preference.PreferenceManager
import com.github.libretube.dialogs.LoginDialog
import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.changeIcon
+import com.github.libretube.util.checkUpdate
import com.github.libretube.util.restartMainActivity
import com.github.libretube.util.updateTheme
import com.google.android.material.color.DynamicColors
@@ -154,6 +155,11 @@ class SettingsActivity :
}
}
super.onCreate(savedInstanceState)
+ try {
+ checkUpdate(childFragmentManager)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
diff --git a/app/src/main/java/com/github/libretube/dialogs/UpdateAvailableDialog.kt b/app/src/main/java/com/github/libretube/dialogs/UpdateAvailableDialog.kt
new file mode 100644
index 000000000..aab997947
--- /dev/null
+++ b/app/src/main/java/com/github/libretube/dialogs/UpdateAvailableDialog.kt
@@ -0,0 +1,32 @@
+package com.github.libretube.dialogs
+
+import android.app.Dialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import androidx.fragment.app.DialogFragment
+import com.github.libretube.R
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+
+class UpdateAvailableDialog(
+ private val versionTag: String,
+ private val updateLink: String
+) : DialogFragment() {
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ return activity?.let {
+ MaterialAlertDialogBuilder(requireContext())
+ .setTitle(context?.getString(R.string.update_available, versionTag))
+ .setMessage(context?.getString(R.string.update_available_text))
+ .setNegativeButton(context?.getString(R.string.cancel)) { _, _ ->
+ dismiss()
+ }
+ .setPositiveButton(context?.getString(R.string.okay)) { _, _ ->
+ val uri = Uri.parse(updateLink)
+ val intent = Intent(Intent.ACTION_VIEW).setData(uri)
+ startActivity(intent)
+ }
+ .show()
+ } ?: throw IllegalStateException("Activity cannot be null")
+ }
+}
diff --git a/app/src/main/java/com/github/libretube/util/UpdateChecker.kt b/app/src/main/java/com/github/libretube/util/UpdateChecker.kt
new file mode 100644
index 000000000..8b7b6f6b0
--- /dev/null
+++ b/app/src/main/java/com/github/libretube/util/UpdateChecker.kt
@@ -0,0 +1,74 @@
+package com.github.libretube.util
+
+import android.util.Log
+import androidx.fragment.app.FragmentManager
+import com.github.libretube.BuildConfig
+import com.github.libretube.dialogs.UpdateAvailableDialog
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.net.URL
+import javax.net.ssl.HttpsURLConnection
+import org.json.JSONArray
+import org.json.JSONObject
+
+fun checkUpdate(childFragmentManager: FragmentManager) {
+ var updateInfo: UpdateInfo? = UpdateInfo("", "")
+ // run http request as thread to make it async
+ val thread = Thread {
+ // otherwise crashes without internet
+ try {
+ updateInfo = getUpdateInfo()
+ } catch (e: Exception) {
+ }
+ }
+ thread.start()
+ // wait for the thread to finish
+ thread.join()
+ // show the UpdateAvailableDialog if there's an update available
+ if (updateInfo?.tagName != "" && BuildConfig.VERSION_NAME != updateInfo?.tagName) {
+ val updateAvailableDialog = UpdateAvailableDialog(
+ updateInfo?.tagName!!,
+ updateInfo?.updateUrl!!
+ )
+ updateAvailableDialog.show(childFragmentManager, "UpdateAvailableDialog")
+ }
+}
+
+fun getUpdateInfo(): UpdateInfo? {
+ val latest = URL("https://api.github.com/repos/libre-tube/LibreTube/releases/latest")
+ val json = StringBuilder()
+ val urlConnection: HttpsURLConnection?
+ urlConnection = latest.openConnection() as HttpsURLConnection
+ val br = BufferedReader(InputStreamReader(urlConnection.inputStream))
+
+ var line: String?
+ while (br.readLine().also { line = it } != null) json.append(line)
+
+ // Parse and return json data
+ val jsonRoot = JSONObject(json.toString())
+ if (jsonRoot.has("tag_name") &&
+ jsonRoot.has("html_url") &&
+ jsonRoot.has("assets")
+ ) {
+ val updateUrl = jsonRoot.getString("html_url")
+ val jsonAssets: JSONArray = jsonRoot.getJSONArray("assets")
+ for (i in 0 until jsonAssets.length()) {
+ val jsonAsset = jsonAssets.getJSONObject(i)
+ if (jsonAsset.has("name")) {
+ val name = jsonAsset.getString("name")
+ if (name.endsWith(".apk")) {
+ val tagName = jsonRoot.getString("name")
+ Log.i("", "Lastest version: $tagName")
+ return UpdateInfo(updateUrl, tagName)
+ }
+ }
+ }
+ }
+ return null
+}
+
+// data class for the update info, required to return the data
+data class UpdateInfo(
+ val updateUrl: String,
+ val tagName: String
+)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3d8c4f410..efbd62c9d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -116,4 +116,6 @@
Piped
YouTube
Play on background
+ Version %1$s is available
+ There is a new update available. Click okay to become redirected to the update page on GitHub.
\ No newline at end of file