Skip to content

Commit

Permalink
[distribution] Small API tweaks (#291)
Browse files Browse the repository at this point in the history
  • Loading branch information
chromy authored Oct 25, 2024
1 parent 192acff commit c289b47
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 4 deletions.
3 changes: 3 additions & 0 deletions distribution/distribution/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<meta-data
android:name="com.emergetools.distribution.API_KEY"
android:value="${emerge.distribution.apiKey}" />
<meta-data
android:name="com.emergetools.distribution.TAG"
android:value="${emerge.distribution.tag}" />

<provider android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.net.Uri
import com.emergetools.distribution.internal.DistributionInternal
import kotlinx.serialization.Serializable
import okhttp3.OkHttpClient
import java.util.concurrent.CompletableFuture

/**
* The public Android SDK for Emerge Tools Build Distribution.
Expand All @@ -32,11 +33,22 @@ object Distribution {

/**
* Check to see if an updated version of the current app exists.
* A suspendable function which asynchronously finds the latest available version by querying
* the Emerge
* @return The current
*/
suspend fun checkForUpdate(context: Context): UpdateStatus {
return DistributionInternal.checkForUpdate(context)
}

/**
* A non-coroutine, non-blocking version of `checkForUpdate` designed for use with Jetpack
* Compose.
*/
fun checkForUpdateCompletableFuture(context: Context): CompletableFuture<UpdateStatus> {
return DistributionInternal.checkForUpdateCompletableFuture(context)
}

/**
* Download the provided update.
*/
Expand All @@ -62,15 +74,40 @@ data class DistributionOptions(
val tag: String? = null,
)

/**
* An available update that it is possible to upgrade to.
*/
@Serializable
data class UpdateInfo(
/**
* The Emerge id for the update build.
*/
val id: String,

/**
* The Emerge tag for the update build.
*/
val tag: String,

/**
* The version of the update.
*/
val version: String,

/**
* The package name of the update app.
*/
val appId: String,

/**
* A signed URL for downloading the update.
*/
val downloadUrl: String,
)

/**
* The result of checking for an update.
*/
sealed class UpdateStatus {
class Error(val message: String) : UpdateStatus()
class NewRelease(val info: UpdateInfo) : UpdateStatus()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ import android.util.Log
import com.emergetools.distribution.DistributionOptions
import com.emergetools.distribution.UpdateInfo
import com.emergetools.distribution.UpdateStatus
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.future.asCompletableFuture
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
Expand All @@ -27,9 +31,11 @@ import okhttp3.Request
import okhttp3.Response
import okhttp3.internal.closeQuietly
import java.io.IOException
import java.util.concurrent.CompletableFuture
import kotlin.coroutines.resumeWithException

private const val MANIFEST_TAG_API_KEY = "com.emergetools.distribution.API_KEY"
private const val MANIFEST_TAG_TAG_KEY = "com.emergetools.distribution.TAG"

internal fun getApiKey(metadata: Bundle): String? {
val apiKey = metadata.getString(MANIFEST_TAG_API_KEY, null)
Expand All @@ -39,6 +45,14 @@ internal fun getApiKey(metadata: Bundle): String? {
return apiKey
}

internal fun getTag(metadata: Bundle): String? {
val tag = metadata.getString(MANIFEST_TAG_TAG_KEY, null)
if (tag == "") {
return null
}
return tag
}

@Serializable
internal data class CheckForUpdatesMessageResult(
val message: String
Expand Down Expand Up @@ -79,7 +93,7 @@ private fun decodeResult(body: String?): UpdateStatus {

private class State(
val handler: Handler,
val tag: String,
val tag: String?,
val apiKey: String?,
private var okHttpClient: OkHttpClient?
) {
Expand Down Expand Up @@ -113,16 +127,28 @@ object DistributionInternal {

val handler = Handler(looper)

// apiKey may be null if
// apiKey may be null if build distribution is disabled.
val metaData = context.packageManager.getApplicationInfo(
context.packageName,
PackageManager.GET_META_DATA
).metaData
val apiKey = getApiKey(metaData)

val tag = options.tag ?: "release"
// tag:
// - defaults to ""
// - can be set from the manifest
// - and overridden by init argument (via state)
var tag = ""
val manifestTag = getTag(metaData)
if (manifestTag != null) {
tag = manifestTag
}
val optionsTag = options.tag
if (optionsTag != null) {
tag = optionsTag
}

state = State(handler, tag, apiKey, options.okHttpClient)
state = State(handler = handler, tag = tag, apiKey = apiKey, okHttpClient = options.okHttpClient)
}

private fun getState(): State? {
Expand All @@ -133,6 +159,17 @@ object DistributionInternal {
return theState
}

@OptIn(DelicateCoroutinesApi::class)
fun checkForUpdateCompletableFuture(context: Context): CompletableFuture<UpdateStatus> {
// GlobalScope is correct here since we're converting this to a CompletableFuture immediately.
// The calling code is opting out of structured concurrency and takes responsibility for waiting
// for (or canceling) the future.
val job = GlobalScope.async {
return@async checkForUpdate(context)
}
return job.asCompletableFuture()
}

suspend fun checkForUpdate(context: Context): UpdateStatus {
try {
val state = getState()
Expand Down
1 change: 1 addition & 0 deletions distribution/sample/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

manifestPlaceholders["emerge.distribution.apiKey"] = ""
manifestPlaceholders["emerge.distribution.tag"] = ""

vectorDrawables {
useSupportLibrary = true
Expand Down

0 comments on commit c289b47

Please sign in to comment.