1

I am creating a local music player using react native, Google play music and other local music players on android or ios usually don't take time loading the music on the user's phone, I am making use of the https://www.npmjs.com/package/react-native-get-music-files to load the music on the user's phone then I'll display it in a scroll view, The music takes time to load and also takes time to render, Is there a way to load the music once from the user's phone, then when the app is reloaded it won't have to load the music again, it will be there already, so the app will just check for new music and old music if there is. This is my code below

 import React, { Component } from 'react'; import { Platform, StyleSheet, Text, Image, Dimensions, StatusBar, ScrollView, View, DeviceEventEmitter, FlatList, ActivityIndicator } from 'react-native'; import Splash from './components/Splash'; import Home from './components/Home'; import MusicFiles from 'react-native-get-music-files'; import Permissions from 'react-native-permissions'; const instructions = Platform.select({ ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu', android: 'Double tap R on your keyboard to reload,\n' + 'Shake or press menu button for dev menu', }); export default class App extends Component{ millisToMinutesAndSeconds(millis) { var minutes = Math.floor(millis / 60000); var seconds = ((millis % 60000) / 1000).toFixed(0); return (seconds == 60 ? (minutes+1) + ":00" : minutes + ":" + (seconds < 10 ? "0" : "") + seconds); } componentDidMount() { this.setState({loaded: false}); Permissions.request('storage').then(response => { this.setState({ photoPermission: response }) }) MusicFiles.getAll({ id : true, blured : false, artist : true, duration : true, //default : true cover : true, //default : true, title : true, cover : true, batchNumber : 1, //get 5 songs per batch minimumSongDuration : 10000, //in miliseconds, fields : ['title','artwork','duration','artist','genre','lyrics','albumTitle'] }); } componentWillMount() { DeviceEventEmitter.addListener( 'onBatchReceived', (params) => { this.setState({songs : [ ...this.state.songs, ...params.batch ]}, this.setState({loaded: true})); } ) } constructor(props) { super(props); this.state = { timePassed: false, photoPermission: '', songs: [], loaded: true, loading: false }; } render() { if (!this.state.loaded) { return ( <Splash/> ); } else { return ( <View style={styles.linearGradient}> <Home songs={this.state.songs}/> </View> ); } } } Home.js render() { const lyrics = this.props.songs.map((song, index) => <View style={styles.musicBox} key={index}> <View style={{width: 57, height: 59, borderRadius: 9, marginLeft: 15}}> <Image resizeMode="contain" style={{alignSelf: 'center', borderRadius: 9, width: 57, height: 59}} source={{uri: song.cover}}/> </View> <View style={styles.TextBox}> <Text numberOfLines={1} style={{fontFamily: 'nexaBold', fontSize: 20, color: 'white', flex: 1}}> {song.title} </Text> <View style={{flexDirection: 'row', }}> <Text numberOfLines={1} style={{fontFamily: 'nexaLight', fontSize: 10, color: '#917D7D', marginRight: 5, }}> {song.author} </Text> <View style={{alignSelf:'center',width: 2, height: 2, borderRadius: 1, backgroundColor: '#917D7D',marginRight: 5}}> </View> <Text style={{fontFamily: 'nexaLight', fontSize: 10, color: '#917D7D'}}> {this.millisToMinutesAndSeconds(song.duration)} </Text></View> </View> </View> ); const music = <ScrollView overScrollMode={'never'} keyboardShouldPersistTaps='always'> {lyrics}</ScrollView>; const shadowOpt = { color: "#000", border: 12, opacity: '0.08', radius: 12, x: 0, y: 1, }; return ( <View style={{flex: 1}}> <View style={styles.linearGradient}> {music} </View> </View> ); } 

1 Answer 1

3

I've used react-native-get-music-files and its slow as hell.

You can use redux and redux-persist to cache and load the files, instead of scanning the phone every time user opens the app.

EDIT

The function that fetches the media. You need to first ask for permission to access external storage (Android).

async function getAssets() { try { let fetchedFiles = await MusicFiles.getAll({ blured : false, artist : true, duration : true, genre : false, title : true, cover : true, album: true }); return fetchedFiles; } catch (e) { getAssets(); } }; 

After the media files are fetched you can clean them up a bit and then dispatch them to a reducer, making them part of the state.

dispatch({ type: 'get_media_success', payload: mediaAssets}); 

These media files will automatically persist between app restarts. You just need to correctly configure your store with redux-persist.

My store.js file:

import { createStore, compose, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import { persistStore, persistReducer } from 'redux-persist'; import { AsyncStorage } from 'react-native'; import reducers from '../Reducers'; const persistConfig = { key: 'root', storage: AsyncStorage, blacklist: ['search'] //Anything you don't want to persist goes here }; const persistedReducer = persistReducer(persistConfig, reducers); export const store = createStore(persistedReducer, {}, compose(applyMiddleware(thunk))); export const persistor = persistStore(store); 

Then import persistor & store and wrap your root component like so:

<PersistGate loading={null} persistor={persistor}> <Provider store={store}> <RootComponent/> </Provider> </PersistGate> 
Sign up to request clarification or add additional context in comments.

4 Comments

What of AsyncStorage
Redux Persist is itself a wrapper around AsyncStorage. It'll be harder to manage so many files if you go for Vanilla AsyncStorage.
Please can you send link to the code where you used redux persist and react native get music files, redux persist has been giving me issues
@AdokiyeIruene I've updated my answer. Hope this helps you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.