diff --git a/build.gradle b/build.gradle
index 3dc52d0e..a4780412 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,5 +7,5 @@ plugins {
id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.21' apply false
- id 'com.mux.gradle.android.mux-android-distribution' version '1.0.3' apply false
-}
\ No newline at end of file
+ id 'com.mux.gradle.android.mux-android-distribution' version '1.1.0' apply false
+}
diff --git a/library/Module.md b/library/Module.md
new file mode 100644
index 00000000..e340b302
--- /dev/null
+++ b/library/Module.md
@@ -0,0 +1,54 @@
+# Module Mux Upload SDK
+
+The Mux Upload SDK processes and uploads video files to [Mux Video](https://www.mux.com/video) from
+a user's local device. It is part of a full-stack flow described in our
+guide, [Upload Files Directly](https://docs.mux.com/guides/video/upload-files-directly).
+
+Once you have your direct upload URL, you can use it to upload a file using this SDK.
+
+## Initializing the SDK
+
+This SDK must be initialized once with a `Context` before it can be used
+
+```kotlin
+// from your custom Application class, Activity, etc. The context isn't saved
+MuxUploadSdk.initialize(appContext = this)
+```
+
+## Starting a new upload
+
+The `MuxUpload` class can be used to start a video upload and observe its progress.
+
+```kotlin
+ // Start a new upload
+val upload = MuxUpload.Builder(myUploadUrl, myInputFile).build()
+upload.setResultListener { /*...*/ }
+upload.setProgressListener { /*...*/ }
+upload.start()
+```
+
+### Handling errors
+
+The upload SDK handles transient errors according to a customizable retry policy. Fatal errors are
+reported by `MuxUpload.setResultListener`.
+
+```kotlin
+upload.setResultListener { result ->
+ if (!result.isSuccess) {
+ notifyError()
+ } else {
+ /*...*/
+ }
+}
+```
+
+## Resuming uploads after process death
+
+Uploads managed by this SDK can be resumed after process death, or if network connectivity caused
+them to fail at some time in the past.
+
+```kotlin
+ MuxUploadManager.resumeAllCachedJobs()
+val upload = MuxUploadManager.findUploadByFile(myVideoFile)
+upload.setResultListener { /*...*/ }
+```
diff --git a/library/build.gradle b/library/build.gradle
index f3bfbaac..ca03fb46 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -38,7 +38,7 @@ muxDistribution {
groupIds just("com.mux.video")
publicReleaseIf releaseOnTag()
- packageJavadocs = releaseOnTag().call()
+ packageJavadocs = true
packageSources = true
publishIf { it.containsIgnoreCase("release") }
artifactoryConfig {
@@ -46,10 +46,14 @@ muxDistribution {
releaseRepoKey = 'default-maven-release-local'
devRepoKey = 'default-maven-local'
}
+ dokkaConfig {
+ moduleName = "Mux Upload SDK"
+ footer = "(c) " + new Date().format("yyyy") + " Mux, Inc. Have questions or need help?" +
+ " Contact support@mux.com"
+ }
}
dependencies {
-
implementation 'androidx.core:core-ktx:1.9.0'
implementation "com.squareup.okhttp3:logging-interceptor:4.11.0"
diff --git a/library/logo-icon.svg b/library/logo-icon.svg
new file mode 100644
index 00000000..533a67a4
--- /dev/null
+++ b/library/logo-icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/library/src/main/java/com/mux/video/upload/MuxUploadSdk.kt b/library/src/main/java/com/mux/video/upload/MuxUploadSdk.kt
index b57b5954..ede20dd2 100644
--- a/library/src/main/java/com/mux/video/upload/MuxUploadSdk.kt
+++ b/library/src/main/java/com/mux/video/upload/MuxUploadSdk.kt
@@ -2,6 +2,7 @@ package com.mux.video.upload
import android.content.Context
import android.util.Log
+import com.mux.video.upload.MuxUploadSdk.initialize
import com.mux.video.upload.api.MuxUploadManager
import com.mux.video.upload.internal.UploadJobFactory
import com.mux.video.upload.internal.UploadMetrics
@@ -11,13 +12,13 @@ import okhttp3.logging.HttpLoggingInterceptor
import java.util.concurrent.TimeUnit
/**
- * Uploads videos to Mux Video.
+ * This object allows you to get version info, enable logging, override the HTTP client, etc
*
- * TODO: This would be a good place to put usage
+ * Before using the SDK, you must call [initialize].
*/
object MuxUploadSdk {
/**
- * The current version of this SDK. Release builds of this SDK follow semver (https://semver.org)
+ * The current version of the SDK. Release builds of this SDK follow semver (https://semver.org)
*/
@Suppress("unused")
const val VERSION = BuildConfig.LIB_VERSION
@@ -56,12 +57,19 @@ object MuxUploadSdk {
.build()
}
- @Suppress("unused") @JvmOverloads
+ /**
+ * Initializes the SDK with the given Context. The Context instance isn't saved.
+ *
+ * @param appContext A Context for your app. The passed instance isn't saved
+ * @param resumeStoppedUploads If true, uploads that failed due to errors or process death will be automatically resumed
+ */
+ @Suppress("unused")
+ @JvmOverloads
fun initialize(appContext: Context, resumeStoppedUploads: Boolean = true) {
initializeUploadPersistence(appContext)
UploadMetrics.initialize(appContext)
- if (resumeStoppedUploads) {
+ if (resumeStoppedUploads) {
val upl = MuxUploadManager.resumeAllCachedJobs()
}
}
diff --git a/library/src/main/java/com/mux/video/upload/api/MuxUpload.kt b/library/src/main/java/com/mux/video/upload/api/MuxUpload.kt
index 965d9c9c..4a466ae5 100644
--- a/library/src/main/java/com/mux/video/upload/api/MuxUpload.kt
+++ b/library/src/main/java/com/mux/video/upload/api/MuxUpload.kt
@@ -10,14 +10,25 @@ import kotlinx.coroutines.*
import java.io.File
/**
- * Represents a task that does a single direct upload to a Mux Video asset previously created.
+ * Represents an upload of a video as a Mux Video asset. In order to use this SDK, you must first
+ * create a [direct upload](https://docs.mux.com/guides/video/upload-files-directly) server-side,
+ * then return that direct upload PUT URL to your app.
*
- * TODO: Talk about creating the upload: https://docs.mux.com/api-reference/video#operation/create-direct-upload
+ * Once you have a PUT URL, you can create and [start] your upload using the [Builder]
*
- * This prototype does a single streamed PUT request for the whole file and delivers results, but
- * the production version will have more sophisticated behavior.
+ * For example:
+ * ```
+ * // Start a new upload
+ * val upload = MuxUpload.Builder(myUploadUrl, myInputFile).build()
+ * upload.setResultListener { myHandleResult(it) }
+ * upload.setProgressListener { myHandleProgress(it) }
+ * upload.start()
+ * ```
*
- * Create an instance of this class with the [Builder]
+ * For full documentation on how to configure your upload, see the [Builder]
+ *
+ * @see Builder
+ * @see MuxUploadManager
*/
class MuxUpload private constructor(
private var uploadInfo: UploadInfo, private val autoManage: Boolean = true
@@ -29,7 +40,8 @@ class MuxUpload private constructor(
val videoFile: File get() = uploadInfo.file
/**
- * The most-currents state of the upload
+ * The current state of the upload. To be notified of state updates, you can use
+ * [setProgressListener] and [setResultListener]
*/
val currentState: Progress
get() = lastKnownState ?: uploadInfo.progressFlow?.replayCache?.firstOrNull() ?: Progress(
@@ -48,7 +60,7 @@ class MuxUpload private constructor(
private var _error: Exception? = null
/**
- * Returns true if the upload was successful
+ * True if the upload was successful, false otherwise
*/
val isSuccessful get() = _successful
private var _successful: Boolean = false
@@ -67,11 +79,17 @@ class MuxUpload private constructor(
}
/**
- * Starts this Upload. The Upload will continue in the background *even if this object is
- * destroyed*.
+ * Starts this Upload. You don't need to hold onto this object in order for the upload to
+ * complete, it will continue in parallel with the rest of your app. You can always get a handle
+ * to an ongoing upload by using [MuxUploadManager.findUploadByFile]
+ *
* To suspend the execution of the upload, use [pause]. To cancel it completely, use [cancel]
*
* @param forceRestart Start the upload from the beginning even if the file is partially uploaded
+ *
+ * @see pause
+ * @see cancel
+ * @see MuxUploadManager
*/
@JvmOverloads
fun start(forceRestart: Boolean = false) {
@@ -88,41 +106,57 @@ class MuxUpload private constructor(
// Get an updated UploadInfo with a job & event channels
uploadInfo = if (autoManage) {
// We may or may not get a fresh worker, depends on if the upload is already going
- MuxUploadManager.startJob(uploadInfo, forceRestart)
+ /*uploadInfo =*/ MuxUploadManager.startJob(uploadInfo, forceRestart)
} else {
// If we're not managing the worker, the job is purely internal to this object
- MuxUploadSdk.uploadJobFactory().createUploadJob(uploadInfo, coroutineScope)
+ /*uploadInfo =*/ MuxUploadSdk.uploadJobFactory().createUploadJob(uploadInfo, coroutineScope)
}
logger.i("MuxUpload", "started upload: ${uploadInfo.file}")
maybeObserveUpload(uploadInfo)
}
+ /**
+ * If the upload has not succeeded, this function will suspend until the upload completes and
+ * return the result
+ *
+ * If the upload had failed, it will be restarted and this function will suspend until it
+ * completes
+ *
+ * If the upload already succeeded, the old result will be returned immediately
+ */
@Throws
@Suppress("unused")
+ @JvmSynthetic
suspend fun awaitSuccess(): Result