Download and upload large files on iOS & Android — even when your app is in the background or terminated.
- 📥 Background Downloads - Downloads continue even when app is in background or terminated
- 📤 Background Uploads - Upload files reliably in the background
- ⏸️ Pause/Resume - Full pause and resume support on both iOS and Android
- 🔄 Re-attach to Downloads - Reconnect to ongoing downloads after app restart
- 📊 Progress Tracking - Real-time progress updates with customizable intervals
- 🔒 Custom Headers - Support for authentication and custom request headers
- 📱 Expo Support - Config plugin for easy Expo integration
- ⚡ New Architecture - Full TurboModules support for React Native
- 📝 TypeScript - Complete TypeScript definitions included
The Problem: Standard network requests in React Native are tied to your app's lifecycle. When the user switches to another app or the OS terminates your app to free memory, your downloads stop. For small files this is fine, but for large files (videos, podcasts, documents) this creates a frustrating user experience.
The Solution: Both iOS and Android provide system-level APIs for background file transfers:
- iOS:
NSURLSession- handles downloads in a separate process, continuing even after your app is terminated - Android: A combination of
DownloadManagerfor system-managed downloads, Foreground Services for pause/resume support, and MMKV for persistent state storage
The Challenge: These APIs are powerful but complex. Downloads run in a separate process, so your app might restart from scratch while downloads are still in progress. Keeping your UI in sync with background downloads requires careful state management.
This Library: @kesha-antonov/react-native-background-downloader wraps these native APIs in a simple, unified JavaScript interface. Start a download, close your app, reopen it hours later, and seamlessly reconnect to your ongoing downloads with a single function call.
- ✨ Features
- 💡 Why?
- 📖 Table of Contents
- 📋 Requirements
- 📦 Installation
- 🚀 Usage
- ⚙️ Advanced Configuration
- 📚 API
- 📱 Platform Notes
- ❓ Troubleshooting
- 🧪 Example App
- 💡 Use Cases
- 🔄 Migration Guide
- 🤝 Contributing
- 👥 Authors
- 📄 License
| Requirement | Version |
|---|---|
| React Native | >= 0.70.0 |
| iOS | >= 15.1 |
| Android | API 24+ (Android 7.0) |
| Expo | SDK 50+ (with config plugin) |
Note: For older React Native versions (0.57.0 - 0.69.x), use version 2.x of this library.
Step 1: Install the package
npx expo install @kesha-antonov/react-native-background-downloaderStep 2: Add the config plugin to your app.json or app.config.js:
{
"expo": {
"plugins": [
"@kesha-antonov/react-native-background-downloader"
]
}
}Plugin Options (optional)
// app.config.js
export default {
expo: {
plugins: [
["@kesha-antonov/react-native-background-downloader", {
mmkvVersion: "2.2.4", // Customize MMKV version on Android
skipMmkvDependency: true // Skip if you want to add MMKV manually
}]
]
}
}| Option | Type | Default | Description |
|---|---|---|---|
mmkvVersion |
string | '2.2.4' |
The version of MMKV to use on Android. |
skipMmkvDependency |
boolean | false |
Skip adding MMKV dependency. Set to true if you're using react-native-mmkv to avoid duplicate class errors. The plugin auto-detects react-native-mmkv but you can use this option to explicitly skip. |
Step 3: Rebuild your app
npx expo prebuild --clean
npx expo run:ios # or npx expo run:androidThe plugin automatically handles:
- iOS: Adding the required
handleEventsForBackgroundURLSessionmethod to AppDelegate - Android: Adding the required MMKV dependency
Step 1: Install the package
yarn:
yarn add @kesha-antonov/react-native-background-downloadernpm:
npm install @kesha-antonov/react-native-background-downloaderStep 2: Install iOS pods
yarn:
cd ios && pod install && cd ..npm:
cd ios && pod install && cd ..Step 3: Configure iOS AppDelegate
React Native 0.77+ (Swift)
In your project bridging header file (e.g. ios/{projectName}-Bridging-Header.h):
#import <RNBackgroundDownloader.h>In your AppDelegate.swift:
func application(
_ application: UIApplication,
handleEventsForBackgroundURLSession identifier: String,
completionHandler: @escaping () -> Void
) {
RNBackgroundDownloader.setCompletionHandlerWithIdentifier(identifier, completionHandler: completionHandler)
}React Native < 0.77 (Objective-C)
In your AppDelegate.m:
#import <RNBackgroundDownloader.h>
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler
{
[RNBackgroundDownloader setCompletionHandlerWithIdentifier:identifier completionHandler:completionHandler];
}Step 4: Configure Android MMKV dependency
Add MMKV to your android/app/build.gradle:
dependencies {
implementation 'com.tencent:mmkv-shared:2.2.4'
}Note: If you're already using react-native-mmkv in your project, skip this step — it already includes MMKV.
import { Platform } from 'react-native'
import { createDownloadTask, completeHandler, directories } from '@kesha-antonov/react-native-background-downloader'
const jobId = 'file123'
let task = createDownloadTask({
id: jobId,
url: 'https://link-to-very.large/file.zip',
destination: `${directories.documents}/file.zip`,
metadata: {}
}).begin(({ expectedBytes, headers }) => {
console.log(`Going to download ${expectedBytes} bytes!`)
}).progress(({ bytesDownloaded, bytesTotal }) => {
console.log(`Downloaded: ${bytesDownloaded / bytesTotal * 100}%`)
}).done(({ bytesDownloaded, bytesTotal }) => {
console.log('Download is done!', { bytesDownloaded, bytesTotal })
// PROCESS YOUR STUFF
// FINISH DOWNLOAD JOB
completeHandler(jobId)
}).error(({ error, errorCode }) => {
console.log('Download canceled due to error: ', { error, errorCode });
})
// starts download
task.start()
// ...later
// Pause the task
await task.pause()
// Resume after pause
await task.resume()
// Cancel the task
await task.stop()The killer feature of this library: reconnect to downloads and uploads that continued running while your app was closed, or resume paused tasks from a previous session.
When the OS terminates your app to free memory, background transfers keep running. When your app restarts, call getExistingDownloadTasks() or getExistingUploadTasks() to get back in sync. Paused tasks are also preserved and can be resumed with task.resume().
💡 Tip: Use meaningful task IDs (not random UUIDs) so you can match tasks to your UI components after restart.
Downloads:
import { getExistingDownloadTasks } from '@kesha-antonov/react-native-background-downloader'
const lostTasks = await getExistingDownloadTasks()
for (const task of lostTasks) {
console.log(`Found download: ${task.id}`)
task.progress(({ bytesDownloaded, bytesTotal }) => {
console.log(`Downloaded: ${bytesDownloaded / bytesTotal * 100}%`)
}).done(({ location, bytesDownloaded, bytesTotal }) => {
console.log('Download complete!', { location, bytesDownloaded, bytesTotal })
}).error(({ error, errorCode }) => {
console.log('Download failed:', { error, errorCode })
})
}Uploads:
import { getExistingUploadTasks } from '@kesha-antonov/react-native-background-downloader'
const lostUploads = await getExistingUploadTasks()
for (const task of lostUploads) {
console.log(`Found upload: ${task.id}`)
task.progress(({ bytesUploaded, bytesTotal }) => {
console.log(`Uploaded: ${bytesUploaded / bytesTotal * 100}%`)
}).done(({ responseCode, responseBody }) => {
console.log('Upload complete!', { responseCode, responseBody })
}).error(({ error, errorCode }) => {
console.log('Upload failed:', { error, errorCode })
})
}Uploading a file
import { Platform } from 'react-native'
import { createUploadTask, completeHandler, directories } from '@kesha-antonov/react-native-background-downloader'
const jobId = 'upload123'
let task = createUploadTask({
id: jobId,
url: 'https://your-server.com/upload',
source: `${directories.documents}/photo.jpg`,
method: 'POST', // or 'PUT', 'PATCH'
fieldName: 'file', // multipart form field name
mimeType: 'image/jpeg',
parameters: {
userId: '123',
description: 'My photo'
},
metadata: {}
}).begin(({ expectedBytes }) => {
console.log(`Going to upload ${expectedBytes} bytes!`)
}).progress(({ bytesUploaded, bytesTotal }) => {
console.log(`Uploaded: ${bytesUploaded / bytesTotal * 100}%`)
}).done(({ responseCode, responseBody, bytesUploaded, bytesTotal }) => {
console.log('Upload is done!', { responseCode, responseBody })
// PROCESS YOUR STUFF
// FINISH UPLOAD JOB
completeHandler(jobId)
}).error(({ error, errorCode }) => {
console.log('Upload canceled due to error: ', { error, errorCode })
})
// starts upload
task.start()
// ...later
// Pause the task (platform support may vary)
await task.pause()
// Resume after pause
await task.resume()
// Cancel the task
await task.stop()Updating headers on paused downloads
If your download uses authentication tokens that expire, you can update the headers of a paused download before resuming it. This is useful when auth tokens refresh while a download is paused:
import { getExistingDownloadTasks } from '@kesha-antonov/react-native-background-downloader'
// Get paused downloads
const tasks = await getExistingDownloadTasks()
for (const task of tasks) {
if (task.state === 'PAUSED') {
// Update headers with new auth token before resuming
await task.setDownloadParams({
...task.downloadParams,
headers: {
...task.downloadParams?.headers,
Authorization: 'Bearer new-refreshed-token'
}
})
// Now resume with the updated headers
await task.resume()
}
}Notes:
setDownloadParams()is async and returnstrueif native headers were updated- Headers are only updated in the native layer when the task is in
PAUSEDstate - On iOS, the download will resume using HTTP Range headers with the new headers
- On Android, both in-memory and persisted paused state are updated
Use case: User pauses a large download, closes the app, and returns hours or days later. By then, the auth token has expired. This feature allows refreshing the token and updating headers before resuming, without restarting the download from scratch.
Using custom headers
If you need to send custom headers with your download request, you can do in it 2 ways:- Globally using
setConfig():
import { setConfig } from '@kesha-antonov/react-native-background-downloader'
setConfig({
headers: {
Authorization: 'Bearer 2we$@$@Ddd223',
}
})This way, all downloads with have the given headers.
- Per download by passing a headers object in the options of
createDownloadTask():
import { createDownloadTask, directories } from '@kesha-antonov/react-native-background-downloader'
const task = createDownloadTask({
id: 'file123',
url: 'https://link-to-very.large/file.zip'
destination: `${directories.documents}/file.zip`,
headers: {
Authorization: 'Bearer 2we$@$@Ddd223'
}
}).begin(({ expectedBytes, headers }) => {
console.log(`Going to download ${expectedBytes} bytes!`)
}).progress(({ bytesDownloaded, bytesTotal }) => {
console.log(`Downloaded: ${bytesDownloaded / bytesTotal * 100}%`)
}).done(({ location, bytesDownloaded, bytesTotal }) => {
console.log('Download is done!', { location, bytesDownloaded, bytesTotal })
}).error(({ error, errorCode }) => {
console.log('Download canceled due to error: ', { error, errorCode })
})
task.start()Headers given in createDownloadTask() are merged with the ones given in setConfig({ headers: { ... } }).
Configuring parallel downloads and network types
You can configure global settings for download behavior using setConfig():
Control how many simultaneous downloads can occur per host. This is useful for managing bandwidth and server load.
import { setConfig } from '@kesha-antonov/react-native-background-downloader'
// Set maximum parallel downloads to 8 (default is 4)
setConfig({
maxParallelDownloads: 8
})Note: This setting only affects iOS. Android's DownloadManager manages parallel downloads automatically and does not expose this configuration.
Control whether downloads are allowed over cellular (metered) networks:
import { setConfig } from '@kesha-antonov/react-native-background-downloader'
// Only allow downloads over WiFi (disable cellular data)
setConfig({
allowsCellularAccess: false
})
// Allow downloads over both WiFi and cellular (default)
setConfig({
allowsCellularAccess: true
})This is a cross-platform setting that works on both iOS and Android:
- iOS: Sets the
allowsCellularAccessproperty on the NSURLSession configuration - Android: Sets the
isAllowedOverMeteredflag on DownloadManager requests
Per-download override (Android only): On Android, you can override the global cellular setting for individual downloads using the isAllowedOverMetered option in createDownloadTask():
const task = createDownloadTask({
id: 'file123',
url: 'https://link-to-very.large/file.zip',
destination: `${directories.documents}/file.zip`,
isAllowedOverMetered: true // This download can use cellular even if global setting is false
})Enabling debug logs
The library includes verbose debug logging that can help diagnose download issues. Logging is disabled by default but can be enabled at runtime using setConfig(). Logging works in both debug and production/release builds.
import { setConfig } from '@kesha-antonov/react-native-background-downloader'
// Option 1: Enable native console logging (logs appear in Xcode/Android Studio console)
setConfig({
isLogsEnabled: true
})
// Option 2: Enable logging with a JavaScript callback to capture logs in your app
setConfig({
isLogsEnabled: true,
logCallback: (log) => {
// log.message - The debug message
// log.taskId - Optional task ID associated with the log (iOS only)
console.log('[BackgroundDownloader]', log.message)
// You can also send logs to your analytics/crash reporting service
// crashlytics.log(log.message)
}
})
// Disable logging
setConfig({
isLogsEnabled: false
})Notes:
- When
isLogsEnabledistrue, native debug logs (NSLog on iOS, Log.d/w/e on Android) are printed - The
logCallbackfunction is called for each native debug log (iOS only sends logs to callback currently) - Logs include detailed information about download lifecycle, session management, and errors
- In production builds, logs are only printed when explicitly enabled via
isLogsEnabled
Handling slow-responding URLs
This library automatically includes connection timeout improvements for slow-responding URLs. By default, the following headers are added to all download requests on Android:
Connection: keep-alive- Keeps the connection open for better handlingKeep-Alive: timeout=600, max=1000- Sets a 10-minute keep-alive timeoutUser-Agent: ReactNative-BackgroundDownloader/3.2.6- Proper user agent for better server compatibility
These headers help prevent downloads from getting stuck in "pending" state when servers take several minutes to respond initially. You can override these headers by providing your own in the headers option.
Handling URLs with many redirects (Android)
Android's DownloadManager has a built-in redirect limit that can cause ERROR_TOO_MANY_REDIRECTS for URLs with multiple redirects (common with podcast URLs, tracking services, CDNs, etc.).
To handle this, you can use the maxRedirects option to pre-resolve redirects before passing the final URL to DownloadManager:
import { Platform } from 'react-native'
import { createDownloadTask, directories } from '@kesha-antonov/react-native-background-downloader'
// Example: Podcast URL with multiple redirects
const task = createDownloadTask({
id: 'podcast-episode',
url: 'https://pdst.fm/e/chrt.fm/track/479722/arttrk.com/p/example.mp3',
destination: `${directories.documents}/episode.mp3`,
maxRedirects: 10, // Follow up to 10 redirects before downloading
}).begin(({ expectedBytes }) => {
console.log(`Going to download ${expectedBytes} bytes!`)
}).progress(({ bytesDownloaded, bytesTotal }) => {
console.log(`Downloaded: ${bytesDownloaded / bytesTotal * 100}%`)
}).done(({ location, bytesDownloaded, bytesTotal }) => {
console.log('Download is done!', { location, bytesDownloaded, bytesTotal })
}).error(({ error, errorCode }) => {
console.log('Download canceled due to error: ', { error, errorCode })
if (errorCode === 1005) { // ERROR_TOO_MANY_REDIRECTS
console.log('Consider increasing maxRedirects or using a different URL')
}
})
task.start()Notes on maxRedirects:
- Only available on Android (iOS handles redirects automatically)
- If not specified or set to 0, no redirect resolution is performed
- Uses HEAD requests to resolve redirects efficiently
- Falls back to original URL if redirect resolution fails
- Respects the same headers and timeouts as the main download
Notification Configuration (Android)
On Android 14+ (API 34), downloads use User-Initiated Data Transfer (UIDT) jobs which require notifications. Due to Android system requirements, notifications cannot be completely disabled when using UIDT jobs. However, you can control their visibility:
- When
showNotificationsEnabled: true- Full notifications with progress, title, and custom texts - When
showNotificationsEnabled: false(default) - Minimal silent notifications with lowest priority that are barely noticeable
Basic configuration:
import { setConfig } from '@kesha-antonov/react-native-background-downloader'
// Enable notifications and notification grouping with custom texts
setConfig({
showNotificationsEnabled: true, // Show full notifications (default: false - minimal silent notifications)
notificationsGrouping: {
enabled: true, // Enable grouping (default: false)
texts: {
downloadTitle: 'Download',
downloadStarting: 'Starting download...',
downloadProgress: 'Downloading... {progress}%',
downloadPaused: 'Paused',
downloadFinished: 'Download complete',
groupTitle: 'Downloads',
groupText: '{count} downloads in progress',
},
},
})
// Use minimal silent notifications (default behavior)
setConfig({
showNotificationsEnabled: false, // Minimal silent notifications (required by UIDT but barely visible)
})Notification grouping modes:
When downloading many files (e.g., thousands of photos), you can use the mode option to control how notifications are displayed:
| Mode | Description |
|---|---|
'individual' |
Default. Shows all individual notifications grouped together with a summary |
'summaryOnly' |
Shows only ONE notification with real-time aggregate progress (e.g., "45% - 5 files"). Individual UIDT notifications are collapsed into an invisible group. Ideal for bulk downloads |
import { setConfig } from '@kesha-antonov/react-native-background-downloader'
// For bulk downloads (e.g., syncing thousands of photos)
// Use 'summaryOnly' mode to show only ONE notification with aggregate progress
setConfig({
showNotificationsEnabled: true,
notificationsGrouping: {
enabled: true,
mode: 'summaryOnly', // Only show summary notification with progress bar
texts: {
groupTitle: 'Syncing Photos',
groupText: '{count} files downloading',
},
},
})Example: Batch downloading multiple files with grouped notifications:
import { setConfig, createDownloadTask, directories } from '@kesha-antonov/react-native-background-downloader'
// Configure for bulk downloads with single summary notification
setConfig({
showNotificationsEnabled: true,
notificationsGrouping: {
enabled: true,
mode: 'summaryOnly',
texts: {
groupTitle: 'Photo Sync',
groupText: '{count} photos downloading',
},
},
})
// Download multiple files - they all share ONE notification with aggregate progress
const photos = [
{ id: 'photo-1', url: 'https://example.com/photo1.jpg' },
{ id: 'photo-2', url: 'https://example.com/photo2.jpg' },
{ id: 'photo-3', url: 'https://example.com/photo3.jpg' },
// ... potentially thousands of files
]
const GROUP_ID = 'photo-sync-batch'
for (const photo of photos) {
const task = createDownloadTask({
id: photo.id,
url: photo.url,
destination: `${directories.documents}/${photo.id}.jpg`,
metadata: {
groupId: GROUP_ID, // Required for grouping
groupName: 'Photo Sync', // Displayed in notification title
},
})
.progress(({ bytesDownloaded, bytesTotal }) => {
// Progress tracked per file, notification shows aggregate progress
})
.done(() => {
console.log(`Downloaded ${photo.id}`)
})
.error(({ error }) => {
console.error(`Failed ${photo.id}:`, error)
})
task.start()
}
// User sees: ONE notification showing "45% - 3 files" with progress bar
// instead of 3 separate notifications cluttering the notification shade
// Notification automatically disappears when all downloads completeGrouping downloads by category:
When notification grouping is enabled, you can group related downloads (e.g., by album, playlist, podcast) by passing groupId and groupName in the task metadata:
import { createDownloadTask, directories } from '@kesha-antonov/react-native-background-downloader'
// Download album songs - they will be grouped under one notification
const task = createDownloadTask({
id: 'song-1',
url: 'https://example.com/albums/summer-hits/track01.mp3',
destination: `${directories.documents}/track01.mp3`,
metadata: {
groupId: 'album-summer-hits', // Unique identifier for the group
groupName: 'Summer Hits 2024', // Display name in notification title
},
})
task.start()Notification behavior during pause/resume:
When a download is paused on Android 14+:
- The background UIDT job is cancelled (to prevent downloads continuing in background)
- A detached "Paused" notification remains visible showing current progress
- When resumed, a new UIDT job is created and the notification switches to "Downloading" state
- When stopped, the notification is removed
- When app is closed, all download notifications are automatically removed
This ensures users always see the download status without unexpected background activity.
Configuration options:
| Option | Type | Default | Description |
|---|---|---|---|
showNotificationsEnabled |
boolean | false |
Show full download notifications. When false, creates minimal silent notifications (UIDT jobs require a notification, but it will be barely visible). This is a top-level config option. |
notificationsGrouping.enabled |
boolean | false |
Enable notification grouping |
notificationsGrouping.mode |
'individual' | 'summaryOnly' |
'individual' |
Notification display mode. Use 'summaryOnly' for bulk downloads to show only ONE notification with real-time aggregate progress |
notificationsGrouping.texts |
object | See below | Customizable notification texts |
Notification texts (notificationsGrouping.texts):
| Key | Default | Placeholders | Description |
|---|---|---|---|
downloadTitle |
'Download' |
— | Title for individual download notifications |
downloadStarting |
'Starting download...' |
— | Text when download is starting |
downloadProgress |
'Downloading... {progress}%' |
{progress} |
Progress text with current percentage (0-100) |
downloadPaused |
'Paused' |
— | Text when download is paused |
downloadFinished |
'Download complete' |
— | Text when download is finished |
groupTitle |
'Downloads' |
— | Title for group summary notification |
groupText |
'{count} download(s) in progress' |
{count} |
Group summary text with active downloads count |
Notes:
- Notifications cannot be completely disabled on Android 14+ due to UIDT requirements
- When
showNotificationsEnabled: false, notifications are created with minimal visibility (lowest priority, empty content) - Paused downloads show a non-ongoing notification (can be swiped away by user)
- Active downloads show an ongoing notification (cannot be swiped away)
- This feature only affects Android 14+ (API 34) where UIDT jobs are used
- On older Android versions, the standard DownloadManager notifications are shown
- iOS uses system download notifications and doesn't support custom grouping
- Use
mode: 'summaryOnly'when downloading many files to prevent notification spam - shows ONE notification with aggregate progress bar that updates in real-time
For complete API documentation, see the API Reference.
import {
setConfig,
createDownloadTask,
createUploadTask,
getExistingDownloadTasks,
getExistingUploadTasks,
completeHandler,
directories
} from '@kesha-antonov/react-native-background-downloader'| Function | Description |
|---|---|
createDownloadTask(options) |
Create a new download task |
createUploadTask(options) |
Create a new upload task |
getExistingDownloadTasks() |
Get downloads running in background |
getExistingUploadTasks() |
Get uploads running in background |
setConfig(config) |
Set global configuration |
completeHandler(jobId) |
Signal download completion to OS |
directories.documents |
Path to app's documents directory |
For detailed platform-specific information, see Platform Notes.
Key points:
- iOS: Uses
NSURLSessionfor true background downloads - Android: Uses
DownloadManager+ Foreground Services + MMKV - Pause/Resume: Works on both platforms (Android requires server Range header support)
Download stuck in "pending" state (Android)
This can happen with slow-responding servers. The library automatically adds keep-alive headers, but you can also try:
- Increase timeout by setting custom headers
- Check if the server supports the download URL
- Enable debug logs to see what's happening:
setConfig({ isLogsEnabled: true })
Duplicate class errors with react-native-mmkv (Android)
If you're using react-native-mmkv, you don't need to add the MMKV dependency manually - it's already included. The library uses compileOnly to avoid conflicts.
EXC_BAD_ACCESS crash on iOS with react-native-mmkv
This was fixed in v4.4.0. Update to the latest version. If you're not using react-native-mmkv, add pod 'MMKV', '>= 1.0.0' to your Podfile.
Downloads not resuming after app restart
Make sure to call getExistingDownloadTasks() at app startup and re-attach your callbacks. The task IDs you provide are used to identify downloads across restarts.
Google Play Console asking about Foreground Service
See the Google Play Console Declaration section for the required steps.
TypeToken errors in release builds (Android)
Add the Proguard rules mentioned in the Proguard Rules section.
The repository includes a full example app demonstrating all features:
cd example
yarn install
# iOS
cd ios && pod install && cd ..
yarn ios
# Android
yarn androidThe example app shows:
- Starting multiple downloads
- Pause/resume functionality
- Progress tracking with animations
- Re-attaching to background tasks
- File management
This library is perfect for apps that need reliable file transfers:
- 🎵 Music/Podcast Apps - Download episodes for offline listening
- 📚 E-book Readers - Download books in the background
- 🎬 Video Streaming - Offline video downloads
- 📁 File Managers - Large file transfers
- 🎮 Games - Download game assets and updates
- 📱 Enterprise Apps - Sync large documents and media
Upgrading from an older version? Check the Migration Guide for detailed instructions:
- v4.3.x → v4.4.0 - iOS MMKV dependency change
- v4.1.x → v4.2.0 - Android pause/resume support
- v4.0.x → v4.1.0 - MMKV dependency change
- v3.2.6 → v4.0.0 - Major API changes
See the Changelog for a complete list of changes in each version.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Install dependencies (
yarn install) - Make your changes
- Run tests (
yarn test) - Run linting (
yarn lint) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Install dependencies
yarn install
# Run tests
yarn test
# Run linting
yarn lint
# Build the Expo plugin
yarn build-plugin
# Run the example app
cd example && yarn install
yarn ios # or yarn androidMaintained by Kesha Antonov
Based on react-native-background-downloader by Elad Gil (unmaintained since 2019)
Please note that this project is maintained in free time. If you find it helpful, please consider becoming a sponsor.
