@@ -86,6 +86,10 @@ namespace internal {
8686 " Lcom/google/firebase/storage/FileDownloadTask;" ), \
8787 X (Delete, " delete" , \
8888 " ()Lcom/google/android/gms/tasks/Task;" ), \
89+ X (List, " list" , \
90+ " (I)Lcom/google/android/gms/tasks/Task;" ), \
91+ X (ListWithToken, " list" , \
92+ " (ILjava/lang/String;)Lcom/google/android/gms/tasks/Task;" ), \
8993 X (ToString, " toString" , \
9094 " ()Ljava/lang/String;" )
9195// clang-format on
@@ -96,6 +100,19 @@ METHOD_LOOKUP_DEFINITION(storage_reference,
96100 " com/google/firebase/storage/StorageReference" ,
97101 STORAGE_REFERENCE_METHODS )
98102
103+ // clang-format off
104+ #define LIST_RESULT_METHODS (X ) \
105+ X (GetItems, " getItems" , " ()Ljava/util/List;" ), \
106+ X (GetPrefixes, " getPrefixes" , " ()Ljava/util/List;" ), \
107+ X (GetPageToken, " getPageToken" , " ()Ljava/lang/String;" )
108+ // clang-format on
109+
110+ METHOD_LOOKUP_DECLARATION (list_result, LIST_RESULT_METHODS )
111+ METHOD_LOOKUP_DEFINITION (list_result,
112+ PROGUARD_KEEP_CLASS
113+ " com/google/firebase/storage/ListResult" ,
114+ LIST_RESULT_METHODS )
115+
99116enum StorageReferenceFn {
100117 kStorageReferenceFnDelete = 0 ,
101118 kStorageReferenceFnGetBytes ,
@@ -105,6 +122,7 @@ enum StorageReferenceFn {
105122 kStorageReferenceFnUpdateMetadata ,
106123 kStorageReferenceFnPutBytes ,
107124 kStorageReferenceFnPutFile ,
125+ kStorageReferenceFnList ,
108126 kStorageReferenceFnCount ,
109127};
110128
@@ -309,6 +327,49 @@ void StorageReferenceInternal::FutureCallback(JNIEnv* env, jobject result,
309327 file_download_task_task_snapshot::kGetBytesTransferred ));
310328 data->impl ->Complete <size_t >(data->handle , kErrorNone , status_message,
311329 [bytes](size_t * size) { *size = bytes; });
330+ } else if (result && env->IsInstanceOf (result, list_result::GetClass ())) {
331+ LogDebug (" FutureCallback: Completing a Future from a ListResult." );
332+ // Complete a Future<StorageListResult> from a Java ListResult object.
333+ jobject prefixes_list = env->CallObjectMethod (
334+ result, list_result::GetMethodId (list_result::kGetPrefixes ));
335+ jobject items_list = env->CallObjectMethod (
336+ result, list_result::GetMethodId (list_result::kGetItems ));
337+ jstring page_token_jstr = static_cast <jstring>(env->CallObjectMethod (
338+ result, list_result::GetMethodId (list_result::kGetPageToken )));
339+
340+ std::vector<StorageReference> prefixes;
341+ std::vector<StorageReference> items;
342+ std::string page_token = util::JStringToString (env, page_token_jstr);
343+
344+ if (prefixes_list) {
345+ int size = env->CallIntMethod (prefixes_list, util::list::GetMethodId (util::list::kSize ));
346+ for (int i = 0 ; i < size; ++i) {
347+ jobject ref_obj = env->CallObjectMethod (prefixes_list, util::list::GetMethodId (util::list::kGet ), i);
348+ prefixes.push_back (StorageReference (new StorageReferenceInternal (data->storage , ref_obj)));
349+ env->DeleteLocalRef (ref_obj);
350+ }
351+ env->DeleteLocalRef (prefixes_list);
352+ }
353+
354+ if (items_list) {
355+ int size = env->CallIntMethod (items_list, util::list::GetMethodId (util::list::kSize ));
356+ for (int i = 0 ; i < size; ++i) {
357+ jobject ref_obj = env->CallObjectMethod (items_list, util::list::GetMethodId (util::list::kGet ), i);
358+ items.push_back (StorageReference (new StorageReferenceInternal (data->storage , ref_obj)));
359+ env->DeleteLocalRef (ref_obj);
360+ }
361+ env->DeleteLocalRef (items_list);
362+ }
363+
364+ if (page_token_jstr) env->DeleteLocalRef (page_token_jstr);
365+
366+ data->impl ->Complete <StorageListResult>(
367+ data->handle , kErrorNone , status_message,
368+ [prefixes, items, page_token](StorageListResult* list_result) {
369+ internal::StorageListResultInternal* list_result_internal = new internal::StorageListResultInternal (
370+ prefixes, items, page_token);
371+ *list_result = internal::StorageListResultInternal::AsStorageListResult (list_result_internal);
372+ });
312373 } else {
313374 LogDebug (" FutureCallback: Completing a Future from a default result." );
314375 // Unknown or null result type, treat this as a Future<void> and just
@@ -541,6 +602,49 @@ Future<Metadata> StorageReferenceInternal::UpdateMetadataLastResult() {
541602 future ()->LastResult (kStorageReferenceFnUpdateMetadata ));
542603}
543604
605+ Future<StorageListResult> StorageReferenceInternal::List (
606+ int max_results_per_page, const char * page_token) {
607+ ReferenceCountedFutureImpl* future_impl = future ();
608+ FutureHandle handle = future_impl->Alloc <StorageListResult>(kStorageReferenceFnList );
609+
610+ JNIEnv* env = storage_->app ()->GetJNIEnv ();
611+ jstring page_token_string =
612+ page_token ? env->NewStringUTF (page_token) : nullptr ;
613+ jobject task = nullptr ;
614+
615+ if (page_token_string) {
616+ task = env->CallObjectMethod (
617+ obj_, storage_reference::GetMethodId (storage_reference::kListWithToken ),
618+ (jint)max_results_per_page, page_token_string);
619+ env->DeleteLocalRef (page_token_string);
620+ } else {
621+ task = env->CallObjectMethod (
622+ obj_, storage_reference::GetMethodId (storage_reference::kList ),
623+ (jint)max_results_per_page);
624+ }
625+
626+ if (util::LogException (env, kLogLevelWarning ,
627+ " StorageReference::List(): Call to list() failed." )) {
628+ future_impl->Complete (handle, kErrorUnknown , " Call to list() failed." );
629+ } else {
630+ util::RegisterCallbackOnTask (
631+ env, task,
632+ reinterpret_cast <util::TaskFinishedCallback>(
633+ StorageReferenceInternal::FutureCallback),
634+ new FutureCallbackData (handle, future_impl, storage_,
635+ kStorageReferenceFnList ),
636+ storage_resources::GetClass (storage_resources::kApiExecutor ));
637+ }
638+ env->DeleteLocalRef (task);
639+
640+ return ListLastResult ();
641+ }
642+
643+ Future<StorageListResult> StorageReferenceInternal::ListLastResult () {
644+ return static_cast <const Future<StorageListResult>&>(
645+ future ()->LastResult (kStorageReferenceFnList ));
646+ }
647+
544648std::string StorageReferenceInternal::name () {
545649 JNIEnv* env = storage_->app ()->GetJNIEnv ();
546650 jstring name_jstring = static_cast <jstring>(env->CallObjectMethod (
0 commit comments