react-native-sound: cannot compile android with RN 0.53

I have:

  • react-native-cli: 2.0.1
  • react-native: 0.53.0

And i get:

node_modules/react-native-sound/android/src/main/java/com/zmxv/RNSound/RNSoundModule.java:43: error: cannot find symbol
    final ReactContext reactContext = this.context;
          ^
  symbol:   class ReactContext
  location: class RNSoundModule

any idea? 0.53 is not supported?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 5
  • Comments: 21

Most upvoted comments

@r3vox @sergey-tyan actually you just need to do yarn add react-native-sound@0.10.2. No need to remove the existing version before doing so, and also no need to unlink then re-link the module.

Take note that for v0.10.4 and older, Sound.setCategory doesn’t work on Android, so you can’t play sounds when the device is in silent mode.

v0.10.5 introduced the feature on Android, but then screwed up the sound keys, causing https://github.com/zmxv/react-native-sound/issues/362.

It’s already fixed on master branch, but then now master branch can’t even compile, at least on Android. This isn’t an issue with the RN version, as what @badpenguin originally thought. And there are multiple open issues (this, https://github.com/zmxv/react-native-sound/issues/380, https://github.com/zmxv/react-native-sound/issues/382) that all stem from the same problem. Do contributors even test if the code can compile before merging them into master branch? It’s as if people are expecting Java to perform implicit typecasting between Double and Integer types. And then there are also missing imports (e.g. ReactContext), as well as missing function definitions (e.g. sendEvent).

I’d like to contribute and help fix this, but then I’m not even sure what some of the contributors were trying to do with their commits. What kind of commit message (https://github.com/zmxv/react-native-sound/commit/fa95e5935ca13511d0199f8ac699e114c89d58eb) is “Need test”!? In fact, this commit, along with https://github.com/zmxv/react-native-sound/commit/ce1f59e6fa05d3582f7ecd895c5e06c5ba3db8a2 (changing Integer to Double), are the ones responsible for causing the Java module to fail to compile. The code posted by @Kroniac effectively undoes their changes. But I don’t think that’s a proper long term solution. Just my 2 cents.

I downgraded to react-native-sound^0.10.2 and it is working now

@esmatptr worked for me too @r3vox remove current version and install 0.10.2

react-native unlink react-native-sound
yarn remove react-native-sound
yarn add react-native-sound@0.10.2
react-native link react-native-sound

in your project folder go to node_modules\react-native-sound\android\src\main\java\com\zmxv\RNSound\RNSoundModule.java and replace all the file contents with following code:

package com.zmxv.RNSound;

import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.net.Uri;
import android.media.AudioManager;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.ExceptionsManagerModule;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.io.IOException;
import android.util.Log;

public class RNSoundModule extends ReactContextBaseJavaModule {
Map<Integer, MediaPlayer> playerPool = new HashMap<>();
ReactApplicationContext context;
final static Object NULL = null;
public RNSoundModule(ReactApplicationContext context) {
super(context);
this.context = context;
}
@override
public String getName() {
return "RNSound";
}
@reactmethod
public void prepare(final String fileName, final Integer key, final ReadableMap options, final Callback callback) {
MediaPlayer player = createMediaPlayer(fileName);
if (player == null) {
WritableMap e = Arguments.createMap();
e.putInt("code", -1);
e.putString("message", "resource not found");
return;
}
final RNSoundModule module = this;
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
boolean callbackWasCalled = false;
@override
public synchronized void onPrepared(MediaPlayer mp) {
if (callbackWasCalled) return;
callbackWasCalled = true;
module.playerPool.put(key, mp);
WritableMap props = Arguments.createMap();
props.putDouble("duration", mp.getDuration() * .001);
try {
callback.invoke(NULL, props);
} catch(RuntimeException runtimeException) {
// The callback was already invoked
Log.e("RNSoundModule", "Exception", runtimeException);
}
}
});
player.setOnErrorListener(new OnErrorListener() {
boolean callbackWasCalled = false;
@override
public synchronized boolean onError(MediaPlayer mp, int what, int extra) {
if (callbackWasCalled) return true;
callbackWasCalled = true;
try {
WritableMap props = Arguments.createMap();
props.putInt("what", what);
props.putInt("extra", extra);
callback.invoke(props, NULL);
} catch(RuntimeException runtimeException) {
// The callback was already invoked
Log.e("RNSoundModule", "Exception", runtimeException);
}
return true;
}
});
try {
player.prepareAsync();
} catch (IllegalStateException ignored) {
// When loading files from a file, we useMediaPlayer.create, which actually
// prepares the audio for us already. So we catch and ignore this error
}
}
protected MediaPlayer createMediaPlayer(final String fileName) {
int res = this.context.getResources().getIdentifier(fileName, "raw", this.context.getPackageName());
if (res != 0) {
return MediaPlayer.create(this.context, res);
}
if(fileName.startsWith("http://") || fileName.startsWith("https://")) {
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
Log.i("RNSoundModule", fileName);
try {
mediaPlayer.setDataSource(fileName);
} catch(IOException e) {
Log.e("RNSoundModule", "Exception", e);
return null;
}
return mediaPlayer;
}
File file = new File(fileName);
if (file.exists()) {
Uri uri = Uri.fromFile(file);
// Mediaplayer is already prepared here.
return MediaPlayer.create(this.context, uri);
}
return null;
}
@reactmethod
public void play(final Integer key, final Callback callback) {
MediaPlayer player = this.playerPool.get(key);
if (player == null) {
callback.invoke(false);
return;
}
if (player.isPlaying()) {
return;
}
player.setOnCompletionListener(new OnCompletionListener() {
boolean callbackWasCalled = false;
@override
public synchronized void onCompletion(MediaPlayer mp) {
if (!mp.isLooping()) {
if (callbackWasCalled) return;
callbackWasCalled = true;
try {
callback.invoke(true);
} catch (Exception e) {
//Catches the exception: java.lang.RuntimeException·Illegal callback invocation from native module
}
}
}
});
player.setOnErrorListener(new OnErrorListener() {
boolean callbackWasCalled = false;
@override
public synchronized boolean onError(MediaPlayer mp, int what, int extra) {
if (callbackWasCalled) return true;
callbackWasCalled = true;
callback.invoke(false);
return true;
}
});
player.start();
}
@reactmethod
public void pause(final Integer key, final Callback callback) {
MediaPlayer player = this.playerPool.get(key);
if (player != null && player.isPlaying()) {
player.pause();
}
callback.invoke();
}
@reactmethod
public void stop(final Integer key, final Callback callback) {
MediaPlayer player = this.playerPool.get(key);
if (player != null && player.isPlaying()) {
player.pause();
player.seekTo(0);
}
callback.invoke();
}
@reactmethod
public void release(final Integer key) {
MediaPlayer player = this.playerPool.get(key);
if (player != null) {
player.release();
this.playerPool.remove(key);
}
}
@reactmethod
public void setVolume(final Integer key, final Float left, final Float right) {
MediaPlayer player = this.playerPool.get(key);
if (player != null) {
player.setVolume(left, right);
}
}
@reactmethod
public void setLooping(final Integer key, final Boolean looping) {
MediaPlayer player = this.playerPool.get(key);
if (player != null) {
player.setLooping(looping);
}
}
@reactmethod
public void setSpeed(final Integer key, final Float speed) {
MediaPlayer player = this.playerPool.get(key);
if (player != null) {
player.setPlaybackParams(player.getPlaybackParams().setSpeed(speed));
}
}
@reactmethod
public void setCurrentTime(final Integer key, final Float sec) {
MediaPlayer player = this.playerPool.get(key);
if (player != null) {
player.seekTo((int)Math.round(sec * 1000));
}
}
@reactmethod
public void getCurrentTime(final Integer key, final Callback callback) {
MediaPlayer player = this.playerPool.get(key);
if (player == null) {
callback.invoke(-1, false);
return;
}
callback.invoke(player.getCurrentPosition() * .001, player.isPlaying());
}
//turn speaker on
@reactmethod
public void setSpeakerphoneOn(final Integer key, final Boolean speaker) {
MediaPlayer player = this.playerPool.get(key);
if (player != null) {
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
AudioManager audioManager = (AudioManager)this.context.getSystemService(this.context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setSpeakerphoneOn(speaker);
}
}
@reactmethod
public void enable(final Boolean enabled) {
// no op
}
@override
public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put("IsAndroid", true);
return constants;
}
}

Neither rolling back to RN 0.52.2 nor installing react-native-sound from master resolved this issue. ```` “react-native-sound”: “https://github.com/zmxv/react-native-sound.git”,


I am stumped.

What could have messed up both Android and iOS builds that even rolling back to 0.52.2 cannot fix?