Skip to content

Commit 9f75c02

Browse files
msluszniakclaude
andcommitted
fix: use RNFS.downloadFile on Android to avoid background downloader tasksMap bug
The @kesha-antonov/react-native-background-downloader library on Android loses the task reference in its JS-side tasksMap, causing the done callback to never fire even after a successful download. Fall back to RNFS.downloadFile on Android which reliably resolves the promise on completion. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 92b1648 commit 9f75c02

File tree

1 file changed

+57
-1
lines changed

1 file changed

+57
-1
lines changed

packages/bare-resource-fetcher/src/ResourceFetcher.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import {
3838
ProgressHandlerParams,
3939
} from '@kesha-antonov/react-native-background-downloader';
4040
import * as RNFS from '@dr.pogodin/react-native-fs';
41-
import { Image } from 'react-native';
41+
import { Image, Platform } from 'react-native';
4242
import { RNEDirectory } from './constants/directories';
4343
import {
4444
ResourceSource,
@@ -92,6 +92,11 @@ interface BareResourceFetcherInterface extends ResourceFetcherAdapter {
9292
handleRemoteFile(
9393
sourceExtended: ResourceSourceExtended
9494
): Promise<string[] | string | null>;
95+
handleRemoteFileAndroid(
96+
sourceExtended: ResourceSourceExtended,
97+
source: ResourceSource,
98+
uri: string
99+
): Promise<string[] | string | null>;
95100
}
96101

97102
/**
@@ -514,6 +519,10 @@ export const BareResourceFetcher: BareResourceFetcherInterface = {
514519
}
515520
await ResourceFetcherUtils.createDirectoryIfNoExists();
516521

522+
if (Platform.OS === 'android') {
523+
return this.handleRemoteFileAndroid(sourceExtended, source, uri);
524+
}
525+
517526
return new Promise((resolve, reject) => {
518527
const task = createDownloadTask({
519528
id: filename,
@@ -557,6 +566,53 @@ export const BareResourceFetcher: BareResourceFetcherInterface = {
557566
});
558567
},
559568

569+
async handleRemoteFileAndroid(
570+
sourceExtended: ResourceSourceExtended,
571+
source: ResourceSource,
572+
uri: string
573+
): Promise<string[] | string | null> {
574+
const rnfsDownload = RNFS.downloadFile({
575+
fromUrl: uri,
576+
toFile: sourceExtended.cacheFileUri!,
577+
progress: (res: { bytesWritten: number; contentLength: number }) => {
578+
if (res.contentLength > 0) {
579+
sourceExtended.callback!(res.bytesWritten / res.contentLength);
580+
}
581+
},
582+
progressInterval: 500,
583+
});
584+
585+
const downloadResource: DownloadResource = {
586+
task: {
587+
stop: () => RNFS.stopDownload(rnfsDownload.jobId),
588+
pause: () => {},
589+
resume: () => {},
590+
} as unknown as DownloadTask,
591+
status: DownloadStatus.ONGOING,
592+
extendedInfo: sourceExtended,
593+
};
594+
this.downloads.set(source, downloadResource);
595+
596+
try {
597+
const result = await rnfsDownload.promise;
598+
if (result.statusCode < 200 || result.statusCode >= 300) {
599+
this.downloads.delete(source);
600+
throw new RnExecutorchError(
601+
RnExecutorchErrorCode.ResourceFetcherDownloadFailed,
602+
`Failed to fetch resource from '${uri}', status: ${result.statusCode}`
603+
);
604+
}
605+
return await this.completeDownload(sourceExtended, source);
606+
} catch (error) {
607+
this.downloads.delete(source);
608+
if (error instanceof RnExecutorchError) throw error;
609+
throw new RnExecutorchError(
610+
RnExecutorchErrorCode.ResourceFetcherDownloadFailed,
611+
`Failed to fetch resource from '${uri}', context: ${error}`
612+
);
613+
}
614+
},
615+
560616
/**
561617
* Reads the contents of a file as a string.
562618
*

0 commit comments

Comments
 (0)