In this tutorial, we'll explore how to integrate essential features such as audio and video download, deleting specific content, clearing all downloads at once, and displaying a progress bar while downloading in a React Native application. This comprehensive guide will equip you with the tools and knowledge needed to enhance your app's offline capabilities, providing users with a seamless and interactive experience using the rn-fetch-blob library.๐ฑ
The Offline Content Management feature in React Native using RNFetchBlob allows users to download audio and video content for offline playback. This documentation provides a comprehensive guide on setting up, implementing, and managing offline content in a React Native application.๐๐ง
Let's dive in and unlock the potential of offline audio and video downloads in React Native!๐ก
Features๐ฏ๐
- Audio and Video Download: Seamlessly download audio and video content to enjoy offline.๐ฅ
- Check Download Status: Easily check if content is already downloaded with intuitive icons.โ๏ธโ
- Interactive Progress Bar: Stay informed with a circular progress bar and percentage display during downloads.๐๐
- Efficient Deletion: Delete individual downloaded content with a single tap for decluttering.๐๏ธ
- Bulk Deletion: Clear out your offline library by deleting all downloaded content at once.๐งน
๐ฌ Let's kick things off with a bang - check out our captivating demo video showcasing the download service in action!๐
Prerequisites๐๐ ๏ธ
- Knowledge of React Native development.
- Familiarity with JavaScript and React Native libraries.
- Installation of Node.js, npm/yarn, and React Native CLI.
- Basic understanding of file handling and storage concepts.
Setting Up the Project๐ ๏ธ๐ง
1). Create a new React Native project using the following command:
npx react-native init OfflineDownloadApp
2). Navigate to the project directory:
cd OfflineDownloadApp
3).Install the required dependencies:
npm install --save rn-fetch-blob
--- or ---
yarn add rn-fetch-blob
Package.json Dependencies
Below are the dependencies specified in the package.json
file for a React Native project:
{
"dependencies": {
"react": "18.2.0",
"react-native": "0.72.3",
"rn-fetch-blob": "^0.12.0"
},
}
Event Emission๐ข๐ข
The React Native Download Service emits events using DeviceEventEmitter
to provide feedback on download progress and completion.
-
downloadProgress:
Emits progress updates during the download process. -
downloadDone:
Emits an event when a download is completed. -
downloadError:
Emits an event in case of download errors.
Additional Notes๐๐
- This service uses
RNFetchBlob
for file operations and download management. - Metadata related to downloaded content is stored locally in a JSON file.
- Error handling and notifications are managed using
react-native-toast-message
.
Offline Content Management with RNFetchBlob in React Native ๐ฑ
1). Save Downloaded Content To User Device๐พ๐พ
Overview
The sendDownloadedDataToLocalDir
function is a crucial part of implementing offline content management in a React Native application using RNFetchBlob. This function handles the download process for audio and video content, saves downloaded content to local storage, and emits events to track download progress.
Parameters:
-
callback
: A callback function to be executed after the download completes. -
contentId
: The ID of the downloaded content. -
src
: The URL of the content to be downloaded. -
artistName
: The artist name associated with the content. -
songName
: The name of the song or content. -
posterImage
: The URL of the poster image associated with the content. -
isAudio
: A boolean indicating whether the content is audio or video.
These parameters can be customized according to your needs.
Usage Example:
sendDownloadedDataToLocalDir(callback, contentId, src, artistName, songName, posterImage, isAudio);
Code:
export const sendDownloadedDataToLocalDir = async (
callback = () => {},
contentId,
src,
artistName,
songName,
posterImage,
isAudio,
) => {
const {dirs} = RNFetchBlob.fs;
const dirToSave = Platform.OS === 'ios' ? dirs.DocumentDir : dirs.CacheDir;
const path = RNFetchBlob.fs.dirs.CacheDir + `/.file.json`;
var offlineMusicPlayerUrl = '';
var imageUrl = '';
var roundOffValue = 0;
let getNewTime = new Date().getTime();
const commonConfig = {
fileCache: true,
useDownloadManager: true,
notification: true,
title: songName,
path: isAudio
? `${dirToSave}/${getNewTime}.mp3`
: `${dirToSave}/${getNewTime}.mp4`,
mediaScannable: true,
description: 'file download',
};
const configOptions = Platform.select({
ios: {
fileCache: commonConfig.fileCache,
title: commonConfig.title,
path: commonConfig.path,
appendExt: isAudio ? 'mp3' : 'mp4',
},
android: commonConfig,
});
const startDownloadingTheRestContent = async cb => {
// for Images
try {
let res = await RNFetchBlob.config({
fileCache: true,
path: `${dirToSave}/${contentId}.webp`,
IOSBackgroundTask: true,
}).fetch('GET', posterImage, {});
if (res) {
imageUrl = res.path();
}
} catch (e) {}
var offlineObjData = {
contentId: contentId,
source: offlineMusicPlayerUrl,
artistName: artistName,
songName: songName,
downloadDate: new Date(),
posterImage: imageUrl,
isAudio: isAudio,
};
let offlinDonwloadList = [];
//fetching local downloads from storage
try {
let localDownloads = await RNFetchBlob.fs.readFile(path, 'utf8');
localDownloads = JSON.parse(localDownloads);
if (Array.isArray(localDownloads)) {
offlinDonwloadList = localDownloads;
}
} catch (e) {}
//adding new downloads
offlinDonwloadList.push(offlineObjData);
await RNFetchBlob.fs
.writeFile(path, JSON.stringify(offlinDonwloadList), 'utf8')
.then(r => {
cb && cb();
})
.catch(e => {});
};
// for video
if (src) {
RNFetchBlob.config(configOptions)
.fetch('get', src, {})
.progress((received, total) => {
const percentageValue = (received / total) * 100;
roundOffValue = Math.round(percentageValue);
var params = {
contentId: contentId,
source: src,
artistName: artistName,
songName: songName,
progressValue: JSON.stringify(roundOffValue),
};
DeviceEventEmitter.emit('downloadProgress', params);
DeviceEventEmitter.emit('downloadProgress', params);
})
.then(async res => {
let downloadContents = {};
if (Platform.OS === 'ios') {
await RNFetchBlob.fs.writeFile(commonConfig.path, res.data, 'base64');
offlineMusicPlayerUrl = commonConfig.path;
await startDownloadingTheRestContent(() => {
var params = {
contentId: contentId,
source: src,
artistName: artistName,
songName: songName,
progressValue: JSON.stringify(roundOffValue),
};
DeviceEventEmitter.emit('downloadDone', params);
DeviceEventEmitter.emit('downloadProgress', params);
});
} else {
// for Android
offlineMusicPlayerUrl = res.path();
startDownloadingTheRestContent(() => {
var params = {
contentId: contentId,
source: src,
artistName: artistName,
songName: songName,
progressValue: JSON.stringify(roundOffValue),
};
DeviceEventEmitter.emit('downloadDone', params);
DeviceEventEmitter.emit('downloadProgress', params);
});
}
})
.catch(err => {
callback('error');
DeviceEventEmitter.emit('downloadError', true);
});
}
};
2). Fetch Downloaded Content To User Device๐
Overview
The fetchDownloadedDataFromLocalDir
function is responsible for retrieving downloaded data from local storage in a React Native application. It reads a JSON file containing metadata of downloaded content, parses the data, and sends it to a callback function for further processing.
Parameters:
-
sendData:
A callback function to handle the fetched downloaded data.
Usage Example:
fetchDownloadedDataFromLocalDir(sendData);
Code:
export const fetchDownloadedDataFromLocalDir = async (sendData = () => {}) => {
const trackFolder =
Platform.OS === 'ios'
? RNFetchBlob.fs.dirs.DocumentDir
: RNFetchBlob.fs.dirs.CacheDir;
const MyPath = RNFetchBlob.fs.dirs.CacheDir + `/.file.json`;
await RNFetchBlob.fs
.ls(trackFolder)
.then(files => {})
.catch(err => {});
try {
let localDownloads = await RNFetchBlob.fs.readFile(MyPath, 'utf8');
localDownloads = JSON.parse(localDownloads);
if (Array.isArray(localDownloads)) {
sendData(localDownloads);
}
} catch (e) {}
};
3). Delete Downloaded Content To User Device๐๏ธ
Overview
The deleteContentFromLocalDir
function is responsible for deleting specific downloaded content from local storage in a React Native application. It reads a JSON file containing metadata of downloaded content, finds and removes the specified content based on its ID, and then updates the JSON file with the modified data.
Parameters:
downloadedId:
The ID of the downloaded item to be deleted.
Usage Example:
deleteContentFromLocalDir(downloadedId);
Code:
export const deleteContentFromLocalDir = async downloadedId => {
let jsonObj = [];
const MyPath = RNFetchBlob.fs.dirs.CacheDir + `/.file.json`;
try {
let localDownloads = await RNFetchBlob.fs.readFile(MyPath, 'utf8');
localDownloads = JSON.parse(localDownloads);
if (Array.isArray(localDownloads)) {
jsonObj = localDownloads;
}
} catch (e) {}
let flag = '';
const contentIdToFind = downloadedId;
jsonObj.map((item, index) => {
if (item.id === contentIdToFind) {
flag = index;
}
});
jsonObj.splice(flag, 1);
await RNFetchBlob.fs
.writeFile(MyPath, JSON.stringify(jsonObj), 'utf8')
.then(r => {})
.catch(e => {});
};
4). Delete All Downloaded Content To User Device๐งน๐งน
Overview
The deleteAllDownloadDataFromLocal
function is responsible for clearing all downloaded data from the local storage in a React Native application. It initializes an empty JSON object, converts it to a string, and writes it back to the JSON file, effectively removing all downloaded content records.
Usage Example:
deleteAllDownloadDataFromLocal();
Code:
export const deleteAllDownloadDataFromLocal = async () => {
let jsonObj = [];
const MyPath = RNFetchBlob.fs.dirs.CacheDir + `/.file.json`;
await RNFetchBlob.fs
.writeFile(MyPath, JSON.stringify(jsonObj), 'utf8')
.then(r => {})
.catch(e => {});
};
Note:๐๐
Only for iOS: When downloading audio or video content to the user's device, iOS changes the directory each time for security reasons. To handle this, the downloaded path is dynamically appended when fetching the downloaded content from the user's device, as iOS generates a new path each time.
For displaying downloaded images, add "file://" before the path in Android, as images may not display correctly in Android without this prefix.
Conclusion๐๐
In this documentation, we've explored the essential functions for managing downloaded data from local directories in React Native applications. These functions enable crucial operations like fetching, deleting specific content, and clearing all downloaded data from local storage. They address platform-specific considerations, such as dynamic path handling in iOS and path formatting in Android, ensuring seamless management of offline content. By leveraging these functions, developers can enhance user experience and efficiently handle downloaded data within their React Native apps. Experimenting with these functions will help tailor them to specific application requirements. Happy coding!๐๐ฑ
After reading the post consider the following:๐ค๐
- Subscribe to receive newsletters with the latest blog posts
- Download the source code for this post from my github
Top comments (2)
Good post
rn-fetch-blob
is not maintained anymore but there is a very promising fork of it. Keep it in mind.