Skip to content

Commit 4131616

Browse files
authored
storage-ktx: add callbackFlow for upload/download progress (#4139)
* add kotlin flows to storage * update api.txt file * add group to storage/ktx.gradle
1 parent 988ff71 commit 4131616

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

firebase-storage/ktx/api.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,27 @@ package com.google.firebase.storage.ktx {
1515
method @Nullable public static operator String component3(@NonNull com.google.firebase.storage.ListResult);
1616
method @Nullable public static operator android.net.Uri component4(@NonNull com.google.firebase.storage.UploadTask.TaskSnapshot);
1717
method @NonNull public static com.google.firebase.storage.FirebaseStorage getStorage(@NonNull com.google.firebase.ktx.Firebase);
18+
method @NonNull public static <T extends com.google.firebase.storage.StorageTask.SnapshotBase> kotlinx.coroutines.flow.Flow<com.google.firebase.storage.ktx.TaskState<T>> getTaskState(@NonNull com.google.firebase.storage.StorageTask<T>);
1819
method @NonNull public static com.google.firebase.storage.FirebaseStorage storage(@NonNull com.google.firebase.ktx.Firebase, @NonNull String url);
1920
method @NonNull public static com.google.firebase.storage.FirebaseStorage storage(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app);
2021
method @NonNull public static com.google.firebase.storage.FirebaseStorage storage(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app, @NonNull String url);
2122
method @NonNull public static com.google.firebase.storage.StorageMetadata storageMetadata(@NonNull kotlin.jvm.functions.Function1<? super com.google.firebase.storage.StorageMetadata.Builder,kotlin.Unit> init);
2223
}
2324

25+
public abstract class TaskState<T> {
26+
}
27+
28+
public static final class TaskState.InProgress<T> extends com.google.firebase.storage.ktx.TaskState<T> {
29+
ctor public TaskState.InProgress(@Nullable T snapshot);
30+
method public T getSnapshot();
31+
property public final T snapshot;
32+
}
33+
34+
public static final class TaskState.Paused<T> extends com.google.firebase.storage.ktx.TaskState<T> {
35+
ctor public TaskState.Paused(@Nullable T snapshot);
36+
method public T getSnapshot();
37+
property public final T snapshot;
38+
}
39+
2440
}
2541

firebase-storage/ktx/ktx.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ plugins {
1717
id 'kotlin-android'
1818
}
1919

20+
group = "com.google.firebase"
21+
2022
firebaseLibrary {
2123
releaseWith project(':firebase-storage')
2224
publishJavadoc = true
@@ -61,6 +63,7 @@ dependencies {
6163
implementation project(':firebase-storage')
6264
implementation 'androidx.annotation:annotation:1.1.0'
6365
implementation 'com.google.android.gms:play-services-tasks:18.0.1'
66+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion"
6467

6568
androidTestImplementation 'junit:junit:4.12'
6669
androidTestImplementation "com.google.truth:truth:$googleTruthVersion"

firebase-storage/ktx/src/main/kotlin/com/google/firebase/storage/ktx/Storage.kt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package com.google.firebase.storage.ktx
1616

1717
import androidx.annotation.Keep
18+
import com.google.android.gms.tasks.OnCompleteListener
1819
import com.google.firebase.FirebaseApp
1920
import com.google.firebase.components.Component
2021
import com.google.firebase.components.ComponentRegistrar
@@ -23,10 +24,19 @@ import com.google.firebase.platforminfo.LibraryVersionComponent
2324
import com.google.firebase.storage.FileDownloadTask
2425
import com.google.firebase.storage.FirebaseStorage
2526
import com.google.firebase.storage.ListResult
27+
import com.google.firebase.storage.OnPausedListener
28+
import com.google.firebase.storage.OnProgressListener
2629
import com.google.firebase.storage.StorageMetadata
2730
import com.google.firebase.storage.StorageReference
31+
import com.google.firebase.storage.StorageTask
32+
import com.google.firebase.storage.StorageTaskScheduler
2833
import com.google.firebase.storage.StreamDownloadTask
2934
import com.google.firebase.storage.UploadTask
35+
import kotlinx.coroutines.cancel
36+
import kotlinx.coroutines.channels.awaitClose
37+
import kotlinx.coroutines.channels.trySendBlocking
38+
import kotlinx.coroutines.flow.Flow
39+
import kotlinx.coroutines.flow.callbackFlow
3040

3141
/** Returns the [FirebaseStorage] instance of the default [FirebaseApp]. */
3242
val Firebase.storage: FirebaseStorage
@@ -133,6 +143,47 @@ operator fun ListResult.component2(): List<StorageReference> = prefixes
133143
*/
134144
operator fun ListResult.component3(): String? = pageToken
135145

146+
/**
147+
* Starts listening to this task's progress and emits its values via a [Flow].
148+
*
149+
* - When the returned flow starts being collected, it attaches the following listeners:
150+
* [OnProgressListener], [OnPausedListener], [OnCompleteListener].
151+
* - When the flow completes the listeners will be removed.
152+
*/
153+
val <T : StorageTask<T>.SnapshotBase> StorageTask<T>.taskState: Flow<TaskState<T>>
154+
get() = callbackFlow {
155+
val progressListener = OnProgressListener<T> { snapshot ->
156+
StorageTaskScheduler.getInstance().scheduleCallback {
157+
trySendBlocking(TaskState.InProgress(snapshot))
158+
}
159+
}
160+
val pauseListener = OnPausedListener<T> { snapshot ->
161+
StorageTaskScheduler.getInstance().scheduleCallback {
162+
trySendBlocking(TaskState.Paused(snapshot))
163+
}
164+
}
165+
166+
// Only used to close or cancel the Flows, doesn't send any values
167+
val completionListener = OnCompleteListener<T> { task ->
168+
if (task.isSuccessful) {
169+
close()
170+
} else {
171+
val exception = task.exception
172+
cancel("Error getting the TaskState", exception)
173+
}
174+
}
175+
176+
addOnProgressListener(progressListener)
177+
addOnPausedListener(pauseListener)
178+
addOnCompleteListener(completionListener)
179+
180+
awaitClose {
181+
removeOnProgressListener(progressListener)
182+
removeOnPausedListener(pauseListener)
183+
removeOnCompleteListener(completionListener)
184+
}
185+
}
186+
136187
internal const val LIBRARY_NAME: String = "fire-stg-ktx"
137188

138189
/** @suppress */
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.google.firebase.storage.ktx
2+
3+
/**
4+
* Used to emit events about the progress of storage tasks.
5+
*/
6+
abstract class TaskState<T> private constructor() {
7+
/**
8+
* Called periodically as data is transferred and can be used to populate an upload/download indicator.
9+
*/
10+
class InProgress<T>(val snapshot: T) : TaskState<T>()
11+
12+
/**
13+
* Called any time the upload/download is paused.
14+
*/
15+
class Paused<T>(val snapshot: T) : TaskState<T>()
16+
}

0 commit comments

Comments
 (0)