Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package org.futo.inputmethod.updates
import android.app.job.JobInfo
import android.app.job.JobScheduler
import android.content.ComponentName
import android.content.Context
import android.os.Build
import android.util.Log
import androidx.datastore.preferences.core.edit
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.internal.closeQuietly
import org.futo.inputmethod.latin.uix.dataStore
import org.futo.inputmethod.latin.uix.getSetting
import java.lang.Exception
const val UPDATE_URL = "https://voiceinput.futo.org/SuperSecretKeyboard/keyboard_version"
suspend fun checkForUpdate(): UpdateResult? {
return withContext(Dispatchers.IO) {
val httpClient = OkHttpClient()
val request = Request.Builder().method("GET", null).url(UPDATE_URL).build()
try {
val response = httpClient.newCall(request).execute()
val body = response.body
val result = if (body != null) {
val data = body.string().lines()
body.closeQuietly()
val latestVersion = data[0].toInt()
val latestVersionUrl = data[1]
val latestVersionString = data[2]
if(latestVersionUrl.startsWith("https://voiceinput.futo.org/") || latestVersionUrl.startsWith("https://keyboard.futo.org/")){
UpdateResult(
nextVersion = latestVersion,
apkUrl = latestVersionUrl,
nextVersionString = latestVersionString
)
} else {
null
}
} else {
null
}
response.closeQuietly()
result
} catch (e: Exception) {
null
}
}
}
suspend fun checkForUpdateAndSaveToPreferences(context: Context): Boolean {
val updateResult = checkForUpdate()
if(updateResult != null) {
withContext(Dispatchers.IO) {
context.dataStore.edit {
it[LAST_UPDATE_CHECK_RESULT] = Json.encodeToString(updateResult)
}
}
return true
}
return false
}
suspend fun retrieveSavedLastUpdateCheckResult(context: Context): UpdateResult? {
return UpdateResult.fromString(context.getSetting(LAST_UPDATE_CHECK_RESULT, ""))
}
const val JOB_ID: Int = 15782788
fun scheduleUpdateCheckingJob(context: Context) {
val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
if(jobScheduler.getPendingJob(JOB_ID) != null) {
Log.i("UpdateChecking", "Job already scheduled, no need to do anything")
return
}
var jobInfoBuilder = JobInfo.Builder(JOB_ID, ComponentName(context, UpdateCheckingService::class.java))
.setPeriodic(1000 * 60 * 60 * 24 * 2) // every two days
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) // on unmetered Wi-Fi
.setPersisted(true) // persist after reboots
// Update checking has minimum priority
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
jobInfoBuilder = jobInfoBuilder.setPriority(JobInfo.PRIORITY_MIN)
}
jobScheduler.schedule(jobInfoBuilder.build())
}