Skip to content

Commit d0e393c

Browse files
migrate to our backend for updates
Signed-off-by: androidacy-user <opensource@androidacy.com>
1 parent a9122f5 commit d0e393c

6 files changed

Lines changed: 109 additions & 94 deletions

File tree

app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ android {
3838
applicationId = "com.fox2code.mmm"
3939
minSdk = 24
4040
targetSdk = 33
41-
versionCode = 75
41+
versionCode = 76
4242
versionName = "2.1.2"
4343
vectorDrawables {
4444
useSupportLibrary = true

app/src/main/java/com/fox2code/mmm/AppUpdateManager.kt

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.fox2code.mmm
22

3+
import com.fox2code.mmm.androidacy.AndroidacyRepoData
34
import com.fox2code.mmm.utils.io.Files.Companion.write
45
import com.fox2code.mmm.utils.io.net.Http.Companion.doHttpGet
56
import org.json.JSONObject
@@ -8,20 +9,20 @@ import java.io.File
89
import java.io.FileInputStream
910
import java.io.IOException
1011
import java.io.InputStream
11-
import java.nio.charset.StandardCharsets
1212

1313
// See https://docs.github.com/en/rest/reference/repos#releases
1414
@Suppress("unused")
1515
class AppUpdateManager private constructor() {
16+
var changes: String? = null
1617
private val compatDataId = HashMap<String, Int>()
1718
private val updateLock = Any()
1819
private val compatFile: File = File(MainApplication.INSTANCE!!.filesDir, "compat.txt")
19-
private var latestRelease: String?
20+
private var latestRelease: Int?
2021
private var lastChecked: Long
2122

2223
init {
2324
latestRelease = MainApplication.bootSharedPreferences
24-
?.getString("updater_latest_release", BuildConfig.VERSION_NAME)
25+
?.getInt("latest_vcode", BuildConfig.VERSION_CODE)
2526
lastChecked = 0
2627
if (compatFile.isFile) {
2728
try {
@@ -40,27 +41,29 @@ class AppUpdateManager private constructor() {
4041
lastChecked < System.currentTimeMillis() - 60000L
4142
) return force && peekShouldUpdate()
4243
synchronized(updateLock) {
44+
Timber.d("Checking for app updates")
4345
if (lastChecked != this.lastChecked) return peekShouldUpdate()
44-
try {
45-
val release =
46-
JSONObject(String(doHttpGet(RELEASES_API_URL, false), StandardCharsets.UTF_8))
47-
var latestRelease: String? = null
48-
var preRelease = false
49-
// get latest_release from tag_name translated to int
50-
if (release.has("tag_name")) {
51-
latestRelease = release.getString("tag_name")
52-
preRelease = release.getBoolean("prerelease")
53-
}
54-
Timber.d("Latest release: %s, isPreRelease: %s", latestRelease, preRelease)
55-
if (latestRelease == null) return false
56-
if (preRelease) {
57-
this.latestRelease = "99999999" // prevent updating to pre-release
58-
return false
46+
// make a request to https://production-api.androidacy.com/ammm/updates/check with appVersionCode and token/device_id/client_id
47+
var token = AndroidacyRepoData.token
48+
if (!AndroidacyRepoData.getInstance().isValidToken(token)) {
49+
Timber.w("Invalid token, not checking for updates")
50+
token = AndroidacyRepoData.getInstance().requestNewToken()
51+
}
52+
val deviceId = AndroidacyRepoData.generateDeviceId()
53+
val clientId = BuildConfig.ANDROIDACY_CLIENT_ID
54+
val url = "https://production-api.androidacy.com/ammm/updates/check?appVersionCode=${BuildConfig.VERSION_CODE}&token=$token&device_id=$deviceId&client_id=$clientId"
55+
val response = doHttpGet(url, false)
56+
// convert response to string
57+
val responseString = String(response, Charsets.UTF_8)
58+
Timber.d("Response: $responseString")
59+
// json response has a boolean shouldUpdate and an int latestVersion
60+
JSONObject(responseString).let {
61+
if (it.getBoolean("shouldUpdate")) {
62+
latestRelease = it.getInt("latestVersion")
63+
MainApplication.bootSharedPreferences?.edit()
64+
?.putInt("latest_vcode", latestRelease!!)?.apply()
5965
}
60-
this.latestRelease = latestRelease
61-
this.lastChecked = System.currentTimeMillis()
62-
} catch (ioe: Exception) {
63-
Timber.e(ioe)
66+
this.changes = it.getString("changelog")
6467
}
6568
}
6669
return peekShouldUpdate()
@@ -83,8 +86,8 @@ class AppUpdateManager private constructor() {
8386
var currentVersion = 0
8487
var latestVersion = 0
8588
try {
86-
currentVersion = BuildConfig.VERSION_NAME.replace("\\D".toRegex(), "").toInt()
87-
latestVersion = latestRelease!!.replace("v", "").replace("\\D".toRegex(), "").toInt()
89+
currentVersion = BuildConfig.VERSION_CODE
90+
latestVersion = latestRelease!!
8891
} catch (ignored: NumberFormatException) {
8992
}
9093
return currentVersion < latestVersion

app/src/main/java/com/fox2code/mmm/SetupActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.fox2code.rosettax.LanguageActivity
2323
import com.fox2code.rosettax.LanguageSwitcher
2424
import com.google.android.material.bottomnavigation.BottomNavigationItemView
2525
import com.google.android.material.button.MaterialButton
26+
import com.google.android.material.checkbox.MaterialCheckBox
2627
import com.google.android.material.dialog.MaterialAlertDialogBuilder
2728
import com.google.android.material.materialswitch.MaterialSwitch
2829
import com.topjohnwu.superuser.internal.UiThreadHandler
@@ -173,7 +174,7 @@ class SetupActivity : FoxActivity(), LanguageActivity {
173174
// Setup button
174175
val setupButton = view.findViewById<BottomNavigationItemView>(R.id.setup_finish)
175176
// on clicking setup_agree_eula, enable the setup button if it's checked, if it's not, disable it
176-
val agreeEula = view.findViewById<MaterialSwitch>(R.id.setup_agree_eula)
177+
val agreeEula = view.findViewById<MaterialCheckBox>(R.id.setup_agree_eula)
177178
agreeEula.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
178179
setupButton.isEnabled = isChecked
179180
}

app/src/main/java/com/fox2code/mmm/UpdateActivity.kt

Lines changed: 51 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.os.Bundle
77
import android.view.View
88
import androidx.core.content.FileProvider
99
import com.fox2code.foxcompat.app.FoxActivity
10+
import com.fox2code.mmm.androidacy.AndroidacyRepoData
1011
import com.fox2code.mmm.utils.io.net.Http
1112
import com.google.android.material.bottomnavigation.BottomNavigationItemView
1213
import com.google.android.material.bottomnavigation.BottomNavigationView
@@ -177,11 +178,10 @@ class UpdateActivity : FoxActivity() {
177178
progressIndicator.isIndeterminate = true
178179
}
179180
// check for update
180-
val shouldUpdate = AppUpdateManager.appUpdateManager.peekShouldUpdate()
181+
val shouldUpdate = AppUpdateManager.appUpdateManager.checkUpdate(true)
181182
// if shouldUpdate is true, then we have an update
182183
if (shouldUpdate) {
183184
runOnUiThread {
184-
185185
// set status text to update available
186186
statusTextView.setText(R.string.update_available)
187187
// set button text to download
@@ -190,15 +190,25 @@ class UpdateActivity : FoxActivity() {
190190
button.tooltipText = getString(R.string.download_update)
191191
}
192192
button.isEnabled = true
193+
// set changelog text. changelog could be markdown, so we need to convert it
194+
val changelogTextView = findViewById<MaterialTextView>(R.id.update_changelog)
195+
val markwon = Markwon.create(this@UpdateActivity)
196+
markwon.setMarkdown(changelogTextView,
197+
AppUpdateManager.appUpdateManager.changes.toString()
198+
)
193199
}
194200
// return
195201
} else {
196202
runOnUiThread {
197203
// set status text to no update available
198204
statusTextView.setText(R.string.no_update_available)
205+
// set changelog text. changelog could be markdown, so we need to convert it
206+
val changelogTextView = findViewById<MaterialTextView>(R.id.update_changelog)
207+
val markwon = Markwon.create(this@UpdateActivity)
208+
markwon.setMarkdown(changelogTextView,
209+
AppUpdateManager.appUpdateManager.changes.toString()
210+
)
199211
}
200-
// set progress bar to error
201-
// return
202212
}
203213
runOnUiThread {
204214
progressIndicator.isIndeterminate = false
@@ -213,9 +223,20 @@ class UpdateActivity : FoxActivity() {
213223
runOnUiThread { progressIndicator.isIndeterminate = true }
214224
// get status text view
215225
val statusTextView = findViewById<MaterialTextView>(R.id.update_progress_text)
216-
var lastestJSON: ByteArray? = ByteArray(0)
226+
val lastestJSON: ByteArray?
227+
// get changelog from
228+
// make a request to https://production-api.androidacy.com/ammm/updates/check with appVersionCode and token/device_id/client_id
229+
// and the changelog is the json string in changelog
230+
var token = AndroidacyRepoData.token
231+
if (!AndroidacyRepoData.getInstance().isValidToken(token)) {
232+
Timber.w("Invalid token, not checking for updates")
233+
token = AndroidacyRepoData.getInstance().requestNewToken()
234+
}
235+
val deviceId = AndroidacyRepoData.generateDeviceId()
236+
val clientId = BuildConfig.ANDROIDACY_CLIENT_ID
237+
val url = "https://production-api.androidacy.com/ammm/updates/check?appVersionCode=${BuildConfig.VERSION_CODE}&token=$token&device_id=$deviceId&client_id=$clientId"
217238
try {
218-
lastestJSON = Http.doHttpGet(AppUpdateManager.RELEASES_API_URL, false)
239+
lastestJSON = Http.doHttpGet(url, false)
219240
} catch (e: Exception) {
220241
// when logging, REMOVE the json from the log
221242
Timber.e(e, "Error downloading update info")
@@ -224,46 +245,34 @@ class UpdateActivity : FoxActivity() {
224245
progressIndicator.setProgressCompat(100, false)
225246
statusTextView.setText(R.string.error_download_update)
226247
}
248+
return
227249
}
228250
// convert to JSON
229-
val latestJSON = JSONObject(String(lastestJSON!!))
230-
val changelog = latestJSON.getString("body")
231-
// set changelog text. changelog could be markdown, so we need to convert it to HTML
232-
val changelogTextView = findViewById<MaterialTextView>(R.id.update_changelog)
233-
val markwon = Markwon.builder(this).build()
234-
runOnUiThread { markwon.setMarkdown(changelogTextView, changelog) }
235-
// we already know that there is an update, so we can get the latest version of our architecture. We're going to have to iterate through the assets to find the one we want
236-
val assets = latestJSON.getJSONArray("assets")
237-
// get the asset we want
238-
var asset: JSONObject? = null
239-
// iterate through assets until we find the one that contains Build.SUPPORTED_ABIS[0]
240-
while (Objects.isNull(asset)) {
241-
for (i in 0 until assets.length()) {
242-
val asset1 = assets.getJSONObject(i)
243-
if (asset1.getString("name").contains(Build.SUPPORTED_ABIS[0])) {
244-
asset = asset1
245-
break
246-
}
247-
}
248-
}
249-
// if asset is null, then we are in a bad state
250-
if (Objects.isNull(asset)) {
251-
// set status text to error
252-
runOnUiThread {
253-
statusTextView.setText(R.string.error_no_asset)
254-
// set progress bar to error
255-
progressIndicator.isIndeterminate = false
256-
progressIndicator.setProgressCompat(100, false)
257-
}
258-
// return
259-
return
251+
val latestJSON = JSONObject(String(lastestJSON))
252+
val changelog = latestJSON.getString("changelog")
253+
runOnUiThread {
254+
// set changelog text. changelog could be markdown, so we need to convert it
255+
val changelogTextView = findViewById<MaterialTextView>(R.id.update_changelog)
256+
val markwon = Markwon.create(this@UpdateActivity)
257+
markwon.setMarkdown(changelogTextView, changelog)
260258
}
261259
// get the download url
262-
val downloadUrl = asset?.getString("browser_download_url")
263-
// get the download size
264-
val downloadSize = asset?.getLong("size")
260+
var downloadUrl = url.replace("check", "download")
261+
// append arch to download url. coerce anything like arm64-* or aarch64-* to arm64 and anything like arm-* or armeabi-* to arm
262+
downloadUrl += if (Build.SUPPORTED_ABIS[0].contains("arm64") || Build.SUPPORTED_ABIS[0].contains("aarch64")) {
263+
"&arch=arm64"
264+
} else if (Build.SUPPORTED_ABIS[0].contains("arm") || Build.SUPPORTED_ABIS[0].contains("armeabi")) {
265+
"&arch=arm"
266+
} else if (Build.SUPPORTED_ABIS[0].contains("x86_64")) {
267+
"&arch=x86_64"
268+
} else if (Build.SUPPORTED_ABIS[0].contains("x86")) {
269+
"&arch=x86"
270+
} else {
271+
// assume universal and hope for the best, because we don't know what to do
272+
Timber.w("Unknown arch ${Build.SUPPORTED_ABIS[0]} when downloading update, assuming universal")
273+
"&arch=universal"
274+
}
265275
runOnUiThread {
266-
267276
// set status text to downloading update
268277
statusTextView.text = getString(R.string.downloading_update, 0)
269278
// set progress bar to 0
@@ -273,9 +282,8 @@ class UpdateActivity : FoxActivity() {
273282
// download the update
274283
var update = ByteArray(0)
275284
try {
276-
update = Http.doHttpGet(downloadUrl!!) { downloaded: Int, total: Int, _: Boolean ->
285+
update = Http.doHttpGet(downloadUrl) { downloaded: Int, total: Int, _: Boolean ->
277286
runOnUiThread {
278-
279287
// update progress bar
280288
progressIndicator.setProgressCompat(
281289
(downloaded.toFloat() / total.toFloat() * 100).toInt(),
@@ -308,19 +316,6 @@ class UpdateActivity : FoxActivity() {
308316
// return
309317
return
310318
}
311-
// if update is not the same size as the download size, then we are in a bad state
312-
if (update.size.toLong() != downloadSize) {
313-
runOnUiThread {
314-
315-
// set status text to error
316-
statusTextView.setText(R.string.error_download_update)
317-
// set progress bar to error
318-
progressIndicator.isIndeterminate = false
319-
progressIndicator.setProgressCompat(100, false)
320-
}
321-
// return
322-
return
323-
}
324319
// set status text to installing update
325320
runOnUiThread {
326321
statusTextView.setText(R.string.installing_update)

0 commit comments

Comments
 (0)