react-native-track-player: Issues with Samsung Galaxy devices (NullPointerException in MusicBinder, MusicModule IllegaStatelException)

Describe the bug

Dear,

I can’t very much describe the bug, I just see a lot of crashes happening with mostly Samsung Galaxy (around 70% of the devices are Samsung Galaxy) and some Xiaomi’s. I noticed two crashes that are very common in my app.

Mainly:

java.lang.NullPointerException: 
  at com.guichaguri.trackplayer.service.MusicBinder.post (MusicBinder.java:22)
  at com.guichaguri.trackplayer.module.MusicModule.waitForConnection (MusicModule.java:94)
  at com.guichaguri.trackplayer.module.MusicModule.stop (MusicModule.java:334)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java:372)
  at com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java:151)
  at com.facebook.react.bridge.queue.NativeRunnable.run (Native Method)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java:27)
  at android.os.Looper.loop (Looper.java:246)
  at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java:226)
  at java.lang.Thread.run (Thread.java:923)

This is the most common crash. The other one that is most common is:

java.lang.IllegalStateException: 
  at android.app.ContextImpl.startServiceCommon (ContextImpl.java:1795)
  at android.app.ContextImpl.startService (ContextImpl.java:1740)
  at android.content.ContextWrapper.startService (ContextWrapper.java:738)
  at android.content.ContextWrapper.startService (ContextWrapper.java:738)
  at com.guichaguri.trackplayer.module.MusicModule.waitForConnection (MusicModule.java:106)
  at com.guichaguri.trackplayer.module.MusicModule.add (MusicModule.java:195)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java:372)
  at com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java:151)
  at com.facebook.react.bridge.queue.NativeRunnable.run (Native Method)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java:27)
  at android.os.Looper.loop (Looper.java:246)
  at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java:226)
  at java.lang.Thread.run (Thread.java:923)

To Reproduce I have no clue how to reproduce it. I never experienced the problem myself.

Environment (please complete the following information): Run react-native info in your project and share the content.

What react-native-track-player version are you using? Version 1.2.7

Are you testing on a real device or in the simulator? Which OS version are you running? Real devices. I see these crashes in Play Console, mostly reported on Android 11 and Android 10.

Code In Home.js (mainscreen)

const setup = async () => {
  await TrackPlayer.setupPlayer({});
  await TrackPlayer.updateOptions({
    stopWithApp: true,
    capabilities: [
      TrackPlayer.CAPABILITY_PLAY,
      TrackPlayer.CAPABILITY_PAUSE,
      TrackPlayer.CAPABILITY_STOP
    ],
    compactCapabilities: [ 
      TrackPlayer.CAPABILITY_PLAY,
      TrackPlayer.CAPABILITY_PAUSE,
      TrackPlayer.CAPABILITY_STOP
    ],
  })};
setup();

The Player.js (player)

async InitTrackPlayer() {


  this.setState({paused: false});
      const { navigation } = this.props;
   const streamID = navigation.getParam('streamID', 'NO-ID');


     fetch(`https://xxx.xxx.xxx/getinfoviajson.php?streamID=${streamID}`, {
         method: "POST",
   })
     .then(response => response.json())
     .then(responseJson => {
       this.setState({
         streamName: responseJson.streamName,
         desc: responseJson.streamDesc_app,
         mountpoint: responseJson.mountpoint,
         fullStreamURL: responseJson.fullStreamURL,
         imageURL: responseJson.imageURL,
         phone_app: responseJson.phone_app,
         phone_app_plus: responseJson.phone_app_plus,
         streamURLJSON: responseJson.streamURL,
       });


var streambyJSON = this.state.streamURLJSON

const start = async () => {

 // Add a track to the queue
 await TrackPlayer.add({
   id: `${streamID}`,
   url: streambyJSON,
   artist: '',
   title: '',
   artwork: '',
});

};

start();





});


     };

The snippet to update the metadata

 async trackupdate() {
        const trackId = await TrackPlayer.getCurrentTrack();
    await TrackPlayer.updateMetadataForTrack(trackId, {
        title: this.state.nowPlaying,
        artist: this.state.streamName,
        artwork: this.state.imageURL,
    });
}

The snippet that actions to certain statusses (set the correct button or reset the stream when the new stream mountpoint is not the same as the stream of a previous mountpoint)

async getPlayerStatus() {
 const { navigation } = this.props;
 const streamID = navigation.getParam('streamID', 'NO-ID');  
let state = await TrackPlayer.getState();
let thisIsPlaying = await TrackPlayer.getCurrentTrack();

if (state == 'playing') {
  this.setState({DoesPlay: true});
}

if (state == 'idle') {
  this.setState({DoesPlay: false});
}

if (state == 'ready') {
  this.setState({DoesPlay: false});
}

if (state == '1') {
  this.setState({DoesPlay: false});
}

if (state == '2') {
  this.setState({DoesPlay: false});
}

if (state == '3') {
  this.setState({DoesPlay: true});
}

if (thisIsPlaying != streamID)  {
  var statePlayer = this.state.DoesPlay;
  this.setState({DoesPlay: false});
   // alert(statePlayer);
   //  alert (state);
   if (Platform.OS === 'ios') {
    await TrackPlayer.stop();
  }
else {
  const { navigation } = this.props;
  const streamID = navigation.getParam('streamID', 'NO-ID');
     await TrackPlayer.reset();
  }


}
}

componentDidMount and componentWillUnmount

 componentDidMount() {
this.getPlayerStatus();

   this.setState({paused: false});
       const { navigation } = this.props;


 this.InitTrackPlayer();
 this.trackupdate();


        TrackPlayer.addEventListener('remote-play', () => {
TrackPlayer.play();
  });

    TrackPlayer.addEventListener('remote-pause', () => {
this.PauseClick();
  });
 
    TrackPlayer.addEventListener('remote-duck', () => {
  TrackPlayer.stop();
  this.setState({DoesPlay: false});
  this.InitTrackPlayer();

  }); 

    TrackPlayer.addEventListener('remote-stop', () => {
    TrackPlayer.stop();
  }); 

}

componentWillUnmount() {

}

Any idea’s what causes this problem? Thanks guys!

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 22 (6 by maintainers)

Most upvoted comments

I’ve migrated an app from 1.x to 2.0.3 and this happens every time the app starts on Andriod.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.APPNAME, PID: 6627
    java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
        at com.guichaguri.trackplayer.service.metadata.MetadataManager.updateOptions(MetadataManager.java:114)
        at com.guichaguri.trackplayer.service.MusicBinder.updateOptions(MusicBinder.java:49)
        at com.guichaguri.trackplayer.module.MusicModule.onServiceConnected(MusicModule.java:76)
        at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1954)
        at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1986)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

We’re rewriting our Android module and making the binder/service/notification parts more stable and robust as part of https://github.com/DoubleSymmetry/react-native-track-player/discussions/1264

We expect this issue to be fixed as part of that effort. We’re aiming to have the first pre-release soon.