react-native-sound icon indicating copy to clipboard operation
react-native-sound copied to clipboard

Stopped working after CodePush

Open GNarek opened this issue 5 years ago • 7 comments

:beetle: Description

Issue happens on release build. It's working perfect while the app receives updates through CodePush

Event if update is very simple, like style changes (not related with the react-native-sound). Other things in app works as before, there are no other issues or crashes.

:beetle: What is the observed behavior?

No any sound after receiving updates from Appcenter.

:beetle: What is the expected behavior?

It should continue working.

:beetle: Please post your code:

const windSound = new Sound(require('../../assets/sounds/wind.mp3'));
windSound.play();

Is your issue with...

  • [x] iOS
  • [x] Android

Are you using...

  • [x] React Native CLI (e.g. react-native run-android)

Which versions are you using?

"react-native-code-push": "^6.0.0",
"react-native-sound": "^0.11.0"

Does the problem occur on...

  • [x] Simulator
  • [x] Device

If your problem is happening on a device, which device?

  • Device: Tested on diffrent devices

GNarek avatar Jan 26 '20 18:01 GNarek

Have you tried to play the sound only in the callback instead of calling windSound.play() right after instantiating?

ex:

const windSound = new Sound(require('../../assets/sounds/wind.mp3'), err => {
     if (!err) {
         windSound.play();
    }
});

Also, it might be returning an error, you could try to log this error err somewhere

murilobast avatar Feb 14 '20 00:02 murilobast

@murilobast Thanks for response.

Just checked but not worked. and here is the error:

{ 
    "message": "resource not found",
    "code": -1
}

GNarek avatar Feb 14 '20 06:02 GNarek

I found workaround for android. I'm putting file into android/app/src/main/res/raw/wind.mp3

and call it like:

const windSound = new Sound('wind.mp3');
windSound.play();

But not sure about ios, where should I put files?

I tried to drag and drop files into xcode's project like in this tutorial but it didn't worked

GNarek avatar Feb 14 '20 13:02 GNarek

I found workaround for android. I'm putting file into android/app/src/main/res/raw/wind.mp3

and call it like:

const windSound = new Sound('wind.mp3');
windSound.play();

But not sure about ios, where should I put files?

I tried to drag and drop files into xcode's project like in this tutorial but it didn't worked

I ended up having the same issue. Codepush is messing with the audio url. Your workaround is what I did as well.

For iOS, you should open xcode and drag your audio files to your project, there's a guide in the readme.

The only problem is that I can't change the audio files without having to bundle and uploading to google play and apple store

murilobast avatar Feb 20 '20 00:02 murilobast

Now the sound stops playing after a while =/

Ex code:

import { useState, useEffect } from 'react'
import { AppState } from 'react-native'
import Sound from 'react-native-sound'

// Helpers
import randomBetween from '../helpers/randomBetween'

const BGM_KEYS = {
	main: 'bgm_1.mp3',
	battle: 'bgm_5.mp3'
}

const SFX_KEYS = {
	swing2: 'axe1.wav',
	swing3: 'axe4.wav',
	swing4: 'sword4.wav',
	hit1: 'monster2.wav',
	hit2: 'monster12.wav',
	hit3: 'bow1.wav',
	confirm: 'confirm.wav',
	cancel: 'cancel.wav',
	enter: 'enter.wav',
}

const enemySounds = ['swing2', 'swing2', 'swing3']
const playerSounds = ['hit1', 'hit2', 'hit3']

const arrayToObject = array => array.reduce((current, { key, value }) => {
	return {
		...current,
		[key]: value
	}
}, {})

export default function useAudioPlayback(muteBGM, muteSFX, advertiseActive) {
	const [inBackground, setInBackground] = useState(false)
	const [BGM, setBGM] = useState({})
	const [SFX, setSFX] = useState({})
	const [current, setCurrent] = useState('main')

	const playBGM = name => {
		const audio = BGM[name]
		if (!audio) return
		if (BGM[current]) BGM[current].stop()

		setCurrent(name)

		if (!muteBGM) {
			audio.setNumberOfLoops(-1)
			audio.play()
		}
	}

	const playSFX = type => {
		if (muteSFX) return
		const sounds = type === 'enemy' ? enemySounds : playerSounds
		const name = sounds[randomBetween(0, sounds.length - 1)]

		const audio = SFX[name]

		if (!audio) {
			console.warn('SFX not found', name)
			return
		}

		audio.setVolume(0.5)
		audio.stop()
		audio.currentTime = 0
		audio.play()
	}

	const playUI = name => {
		if (muteSFX) return

		const audio = SFX[name]
		if (!audio) {
			console.warn('SFX not found', name)
			return
		}

		audio.setVolume(1)
		audio.stop()
		audio.currentTime = 0
		audio.play()
	}

	const preload = () => {
		const BGMArray = Object.keys(BGM_KEYS).map(key => {
			const name = BGM_KEYS[key]
			const audio = new Sound(name, Sound.MAIN_BUNDLE, err => {
				if (!err) {
					audio.setNumberOfLoops(-1)
					audio.setVolume(0.7)
					if (key === 'main' && !muteBGM) audio.play()
				}
			})

			return {
				key,
				value: audio
			}
		})

		const SFXArray = Object.keys(SFX_KEYS).map(key => {
			const name = SFX_KEYS[key]
			const audio = new Sound(name, Sound.MAIN_BUNDLE, err => {
				console.log('SFX', name, err)
			})

			return {
				key,
				value: audio
			}
		})

		setBGM(arrayToObject(BGMArray))
		setSFX(arrayToObject(SFXArray))
	}

	const checkAudio = shouldMute => {
		if (shouldMute && BGM[current]) {
			BGM[current].pause()
		} else if (!shouldMute && BGM[current]) {
			BGM[current].setNumberOfLoops(-1)
			BGM[current].play()
		}
	}

	const handleAppStateChange = state => {
		setInBackground(state !== 'active')
	}

	useEffect(() => {
		preload()
		AppState.addEventListener('change', handleAppStateChange)
	}, [])

	useEffect(() => {
		checkAudio(muteBGM || inBackground || advertiseActive)
	}, [muteBGM, inBackground, advertiseActive])

	return {
		playBGM,
		playSFX,
		playUI
	}
}

murilobast avatar Feb 20 '20 00:02 murilobast

@murilobast have you been able to solve the issue? After doing some research on sound playback on Android I noticed that many people struggle with it. I think that Android isn't able to manage

a) the same sound played multiple times b) a large amount of preloaded sounds

due to memory issues. For example, I need to preload approx. 200 sounds (each just some kb in size). Depending on the Android device it is either fails during preloading at a random sound or after some playbacks. Loading (and unloading) sounds as they are used is not an option for me since I need immediate sound feedback after pressing a button.

I think you have/had a similar use case here. How did you handle this? Thanks!

sasweb avatar Jan 12 '21 20:01 sasweb

@murilobast have you been able to solve the issue? After doing some research on sound playback on Android I noticed that many people struggle with it. I think that Android isn't able to manage

a) the same sound played multiple times b) a large amount of preloaded sounds

due to memory issues. For example, I need to preload approx. 200 sounds (each just some kb in size). Depending on the Android device it is either fails during preloading at a random sound or after some playbacks. Loading (and unloading) sounds as they are used is not an option for me since I need immediate sound feedback after pressing a button.

I think you have/had a similar use case here. How did you handle this? Thanks!

I am facing the same issue. Did you by any chance found a solution for this issue?

sjonchhe avatar Mar 17 '23 05:03 sjonchhe