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

Created on 20 Feb 2018  路  21Comments  路  Source: zmxv/react-native-sound

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?

Most helpful comment

@r3vox @sergey-tyan actually you just need to do yarn add [email protected]. 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.

All 21 comments

+1

I am seeing this build error on Android and other errors on iOS after upgrading my project to >= 0.53.0

Rolling back to 0.52.2 did not help?
"react": "^16.2.0", "react-native": "^0.52.2",

The strange thing is brand new project made from scratch builds fine?

[Android + iOS] Build errors incompatible types: Double cannot be converted to Integer, etc. #380

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?

is there any solution for this yet?

java:43: error: cannot find symbol
final ReactContext reactContext = this.context;

I have the same issue, is there any fix for that?

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;
}
}

Since i was in an hurry i solved switching to https://github.com/jsierles/react-native-audio

@badpenguin my above solution works. You can try it out if you plan to switch back to react-native-sound

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

How I can downgraded react-native-sound?

@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 [email protected]
react-native link react-native-sound

@r3vox @sergey-tyan actually you just need to do yarn add [email protected]. 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.

For anyone who's interested, I've created a fork and modified from v0.10.5 (which is the latest version that compiles, and has the Sound.setCategory working for Android that I need), to include the fix for https://github.com/zmxv/react-native-sound/issues/362 that was done by @escobar5 . You can install it by doing

yarn remove react-native-sound
yarn add https://github.com/filbertteo/react-native-sound/#fix-key-for-0_10_5

Hope this helps you guys. Cheers! :)

Master and unstable have been updated. version 0.10.7 has been published. This should no longer be an issue.

I use latest version
"react-native-sound": "^0.10.7",
This problem persists,
@trepidity Please check

@trepidity as I've already mentioned in https://github.com/zmxv/react-native-sound/issues/379#issuecomment-367616346, the problem here is that Android can't compile, so it lies in the file https://github.com/zmxv/react-native-sound/blob/master/android/src/main/java/com/zmxv/RNSound/RNSoundModule.java, and if there are no fixes for it, it's not gonna work.

0.10.7 still has the issue, 0.10.4 works fine

@filbertteo Why don't you provide a PR with a proposed fix?

@trepidity As I mentioned, I'm not entirely sure what some of the contributors were trying to do with their commits. I'll try to find time to take a better look at the code and see if I can work on a fix.

@filbertteo yes, I agree. That mostly was me slowly stepping into the role that I have been. It's a growth pain and will get better. Thanks for your patience and being willing to work with the group.

try now.

Looks like this is resolved at this point.

And hey @filbertteo, I've recently joined as a maintainer. I'd love to have some capable help! Feel free to jump in if you'd like!

Was this page helpful?
0 / 5 - 0 ratings