react-native-music-control icon indicating copy to clipboard operation
react-native-music-control copied to clipboard

Android - Fatal Exception: java.lang.RuntimeException: Unable to create service com.tanguyantoine.react.MusicControlNotification$NotificationService: java.util.ConcurrentModificationException

Open The0racle opened this issue 6 years ago • 24 comments

Description

Getting this crash after updating to v0.99. It seems related to #221 which #220 supposedly fixed it. Here is the Stack trace: image

Looking at actions user took before the crash, makes me think the controls were not actually removed when app last terminated(or device locked), since app crashes right away when trying to play a new audio. Also, it happens only on OS 8.1.0+ and on Samsung devices.

I'm calling MusicControl.stopControl() when the specific component handling it is closed, but when app is terminated componentWillUnmount is not called. Not sure if that's related.

  1. Platform ?

    • [ ] iOS
    • [x ] Android
  2. Device

  • [ ] Simulator
  • [x] Real device

The0racle avatar Apr 06 '19 19:04 The0racle

Can you share some code?

tanguyantoine avatar Apr 08 '19 07:04 tanguyantoine

@tanguyantoine here is the component that handles the controls:

export default class LockScreenControls extends Component<Props> {
  static defaultProps = {
    currentFactTitle: null,
    currentItemTitle: '',
    imagePath: '',
    track: null,
    playing: false,
    currentTime: 0,
    duration: 0,
    audioLoading: false,
  }

  componentDidMount() {
    const controls = this._remoteControls(this.props.track !== null);
    controls.forEach(element => MusicControl.enableControl(element, true));
    this._registerForRemoteControlEvents();

    MusicControl.setNowPlaying({
      title: this.props.currentItemTitle,
      artwork: this.props.imagePath,
      album: this.props.track,
      artist: this.props.currentFactTitle,
      duration: this.props.duration,
    });
  }

  componentWillUnmount() {
    MusicControl.stopControl();
  }

  componentDidUpdate(prevProps) {
    if (prevProps.playing !== this.props.playing) {
      const state = this.props.playing ? MusicControl.STATE_PLAYING : MusicControl.STATE_PAUSED;
      MusicControl.updatePlayback({
        state,
        elapsedTime: this.props.currentTime,
      });
    }

    if ((prevProps.currentItemTitle !== this.props.currentItemTitle) || (prevProps.currentFactTitle !== this.props.currentFactTitle)) {
      MusicControl.setNowPlaying({
        title: this.props.currentItemTitle,
        artwork: this.props.imagePath,
        artist: this.props.currentFactTitle,
      });
    }
  }

  shouldComponentUpdate(nextProps) {
    return (nextProps.playing !== this.props.playing) || (nextProps.currentItemTitle !== this.props.currentItemTitle) || (nextProps.currentFactTitle !== this.props.currentFactTitle);
  }

  _remoteControls = (hasTrack) => {
    const controls = ['play', 'pause', 'skipForward', 'skipBackward'];
    if (hasTrack) {
      return [
        ...controls,
        'nextTrack',
        'previousTrack',
      ];
    }

    return controls;
  }

  _registerForRemoteControlEvents() {
    MusicControl.enableBackgroundMode(true);
    MusicControl.on('play', this.props.onPressPlay);
    MusicControl.on('pause', this.props.onPressPause);
    MusicControl.on('skipForward', () => this.props.onPressSkipForward(skipTime));
    MusicControl.on('skipBackward', () => this.props.onPressSkipBackward(skipTime));
    MusicControl.on('nextTrack', this.props.onPressNextTrack);
    MusicControl.on('previousTrack', this.props.onPressPreviousTrack);
  }

  render() {
    return null;
  }
}

The0racle avatar Apr 08 '19 16:04 The0racle

Just to give more context, our app supports background audio.

The0racle avatar Apr 08 '19 22:04 The0racle

if componentWillUnmount is not called then it's an issue with React not this library.

can you trye to render something else than null ?

tanguyantoine avatar Apr 09 '19 07:04 tanguyantoine

@tanguyantoine componentWillUnmount is never called when the app is terminated but that is just a shortcoming on React's side, not a bug. However, the native side does know when the application is terminated and I believe it's the responsibility of the native library to stop any running tasks related to it; otherwise, killing the app would always cause bugs with react-native-music-control.

Also, I could try to render something else but returning null is acceptable per RN docs.

The0racle avatar Apr 09 '19 18:04 The0racle

I am getting same crash in reports in play store.

jayeshanandani avatar Apr 15 '19 03:04 jayeshanandani

im getting same issue but only with Android 9

cinder92 avatar Apr 22 '19 15:04 cinder92

sorry I have absolutely no knowledge on Android 🤷‍♂️

tanguyantoine avatar Apr 23 '19 08:04 tanguyantoine

@The0racle What do you think about this. No android expert so last time i tried to fix this bug i thought onTaskRemoved was triggered more often then it seems to be. I think however onDestroy() might be the key. https://github.com/tanguyantoine/react-native-music-control/pull/254

roffelund avatar Apr 26 '19 12:04 roffelund

Hi, guys.

I had the same issue and I resolved it adding the permission <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> in the AndroidManifest.xml.

Regards.

alexkander avatar May 28 '19 06:05 alexkander

@arondn2 Should be added to readme.md https://github.com/tanguyantoine/react-native-music-control/pull/263

roffelund avatar May 28 '19 12:05 roffelund

@roffelund I'm on it

alexkander avatar May 28 '19 15:05 alexkander

@arondn2 I have that permission already. App still crashes.

The0racle avatar May 28 '19 20:05 The0racle

@The0racle Do you have the logs?

alexkander avatar May 28 '19 22:05 alexkander

Still facing this issue after adding permission to AndroidManifest.xml.

Logs below:

java.util.ConcurrentModificationException: null
    at java.util.ArrayList$Itr.next(ArrayList.java:860)
    at android.support.v4.app.NotificationCompatBuilder.<init>
    at android.support.v4.app.NotificationCompat$Builder.build
    at com.tanguyantoine.react.MusicControlNotification.prepareNotification
    at com.tanguyantoine.react.MusicControlNotification$NotificationService.onCreate
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:3535)
    at android.app.ActivityThread.-wrap4
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1817)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6758)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886)
java.lang.RuntimeException: Unable to create service com.tanguyantoine.react.MusicControlNotification$NotificationService: java.util.ConcurrentModificationException
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:3545)
    at android.app.ActivityThread.-wrap4
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1817)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6758)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886)

ouabing avatar May 31 '19 05:05 ouabing

@ouabing I am using android 8.1. Maybe you can try cleaning the android project and rebuilding. You can try with react-native link or specific react-native link react-native-music-control to be sure that everything is ok. Sorry for being of little help

alexkander avatar May 31 '19 05:05 alexkander

Thanks, @arondn2 . Our app has already released several build versions, the release script will clean the build cache before assembleRelease so I think cleaning & rebuilding won't fix this issue (at least for me).

Correct my previous comment, I checked our error tracker again, Android 8.0, 8.1, 9.0 devices have this issue.

ouabing avatar May 31 '19 06:05 ouabing

@ouabing @tanguyantoine @arondn2 could it be that the target SDK version has to be set to 28? Our project is currently set to 26 in build.gradle

image

The0racle avatar Jun 25 '19 23:06 The0racle

+1 @The0racle how did you solve this?

garfiaslopez avatar Oct 21 '19 16:10 garfiaslopez

@The0racle We are using targetSdkVersion 28

alexkander avatar Oct 21 '19 16:10 alexkander

@garfiaslopez unfortunately I haven't found a way to fix it yet. Changing to targetSdkVersion 28 didn't fix it either.

The0racle avatar Oct 21 '19 18:10 The0racle

Just for the record, this happens when I enable handleAudioInterruptions on Android.

mordonez-me avatar Dec 30 '19 08:12 mordonez-me

Reopening. I will investigate.

bradfloodx avatar May 28 '20 11:05 bradfloodx

Screenshot 2021-06-03 at 12 30 13 PM Does this make sense to anyone having advance JAVA knowledge? I am not sure if this might causing you an issue. You may look into this. It might help.

Path: /node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/MemoryPressureRouter.java RN: 0.63.2

krunalbad avatar Jun 03 '21 07:06 krunalbad