Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ANDROID] App Crashing In Combination with React Native Navigation #117

Open
SydneyTR opened this issue Sep 30, 2017 · 19 comments
Open

[ANDROID] App Crashing In Combination with React Native Navigation #117

SydneyTR opened this issue Sep 30, 2017 · 19 comments

Comments

@SydneyTR
Copy link

SydneyTR commented Sep 30, 2017

I am getting an error on Android (Google Pixel SDK25 8.0.0) when I run an app app that has React Native Navigation in combination with React Native Audio Streaming.

I get the following error:

09-30 16:41:40.535 3828-3828/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.xm, PID: 3828 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference at com.audioStreaming.ReactNativeAudioStreamingModule.getClassActivity(ReactNativeAudioStreamingModule.java:43) at com.audioStreaming.Signal.setData(Signal.java:66) at com.audioStreaming.ReactNativeAudioStreamingModule.onServiceConnected(ReactNativeAudioStreamingModule.java:78) at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1453) at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1481) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

The MainApplication.java is build up like this:

` package com.xm;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import com.reactnativenavigation.NavigationApplication;
import com.audioStreaming.ReactNativeAudioStreamingPackage;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends NavigationApplication {

@Override
public boolean isDebug() {
    // Make sure you are using BuildConfig from your own application
    return BuildConfig.DEBUG;
}

protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new ReactNativeAudioStreamingPackage()
    );
}

@Override
public List<ReactPackage> createAdditionalReactPackages() {
    return getPackages();
}

} `

When I remove the line new ReactNativeAudioStreamingPackage() the app will work. What am i doing wrong here or how can i fix it?

@bbdroid
Copy link

bbdroid commented Oct 4, 2017

I am getting this issue too. :( Is there any fixes for this?

@BunHouth
Copy link

BunHouth commented Oct 5, 2017

i also get the same problem.
I have solve it by

android/src/main/java/com/audioStreaming/ReactNativeAudioStreamingModule.java

public Class<?> getClassActivity() {
 -    if (this.clsActivity == null) {
 -      this.clsActivity = getCurrentActivity().getClass();
 +    Activity activity = getCurrentActivity();
 +    if (this.clsActivity == null && activity != null) {
 +        this.clsActivity = activity.getClass();
      }
      return this.clsActivity;
    }

@callmejm
Copy link

I have same issue , anyone solved it ?

@mrsydster
Copy link

mrsydster commented Oct 21, 2017

@JayricMok: I solved my problem by applying the fixed code from from @BunHouth in;

android/src/main/java/com/audioStreaming/ReactNativeAudioStreamingModule.java

public Class<?> getClassActivity() {
 -    if (this.clsActivity == null) {
 -      this.clsActivity = getCurrentActivity().getClass();
 +    Activity activity = getCurrentActivity();
 +    if (this.clsActivity == null && activity != null) {
 +        this.clsActivity = activity.getClass();
      }
      return this.clsActivity;
    }

@bbdroid
Copy link

bbdroid commented Oct 22, 2017

But this breaks control panel on notification.

@callmejm
Copy link

@mrsydster @BunHouth I applied , still having same issue

@BunHouth
Copy link

@JayricMok can you show me your issue.

@callmejm
Copy link

@BunHouth i facing this issue #122

@BunHouth
Copy link

@JayricMok Are you also using wix-react-native-navigation ? if you not using react-native-navigation it should be work without any error. is your project is available on github?.

@callmejm
Copy link

@BunHouth i using react-navigation https://reactnavigation.org/docs/intro/

@BunHouth
Copy link

@JayricMok it should not problem with that navigation. can you show me your error?

@mrsydster
Copy link

@bdavid68 @JayricMok: Ahh the reason I am not getting that issue is because I disabled the notification from Audio Streaming. I am using Music Control instead for the notification control.

@callmejm
Copy link

@mrsydster can you explain more about how you mix the music control with audio streaming ?

@SydneyTR
Copy link
Author

I use Audio Streaming for steaming the audio (obviously) and than I replaced the notifications control with Music Control. This is my code for the player:

/** @flow */

import React from 'react';
import Reflux from 'reflux';
import {
  Image,
  StyleSheet,
  ActivityIndicator,
  View,
  Text,
  DeviceEventEmitter,
  TouchableOpacity,
  Platform,
} from 'react-native';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';

import { ReactNativeAudioStreaming } from 'react-native-audio-streaming';
import MusicControl from 'react-native-music-control';


export default class Player extends Reflux.Component {
  _onPress: Function;
  _initializeMusicControl: Function;
  _updateMusicControlTitle: Function;
  _updateMusicControlState: Function;
  _playerStop: Function;
  _playerStart: Function;
  subscription: Object;

  constructor(props: Object) {
    super(props);
    this.state = {
      streamUrl: "[INSERT YOUR STREAMING URL HERE]",
      status: "STOPPED",
      artist: "",
      song: "",
      onair: "",
    };
    this._onPress = this._onPress.bind(this);
  }
  componentDidMount() {
    this.subscription = DeviceEventEmitter.addListener(
      'AudioBridgeEvent', (evt) => {
        // We just want meta update for song name
        if (evt.status === "METADATA_UPDATED" && evt.key === 'StreamTitle') {            
            this.setState({
              onair: evt.value,
              artist: evt.value.split(' - ')[0],
              song: evt.value.split(' - ')[1],
            });
        } else if (evt.status != "METADATA_UPDATED") {
            this.setState(evt);
        }
      }
    );
    ReactNativeAudioStreaming.getStatus((error, msg) => {
      (error) ? console.log(error) : this.setState({status: msg.status})
    });
    this._initializeMusicControl();
  }
  _initializeMusicControl() {
    MusicControl.enableBackgroundMode(true)
    MusicControl.enableControl('closeNotification', true, {when: 'never'})
    MusicControl.on('play', this._playerStart.bind(this))
    MusicControl.on('pause', this._playerStop.bind(this))
    this._updateMusicControlTitle(true)
    this._updateMusicControlState()
  }

  _updateMusicControlTitle(initial) {
    // Android does not support changing title via MusicControl.updatePlayback,
    // so we need to send all information via setNowPlaying every time.
    if (Platform.OS === 'android' || initial) {
      MusicControl.setNowPlaying({
        artist: this.state.artist,
        title: this.state.song, 
        artwork: Platform.select({
          // https://github.com/tanguyantoine/react-native-music-control/issues/46
          ios: resolveAssetSource(require('../images/artwork.png')).uri,
          android: require('../images/artwork.png'),
        }),
        // iOS determines playback state depending on 'speed', so we need to set
        // it in the initial setNowPlaying for correct initial state to be set.
        speed: this._musicControlState() == MusicControl.STATE_STOPPED ? 0 : 1,
      });
    } else {
      MusicControl.updatePlayback({
        artist: this.state.artist,
        title: this.state.song,
      });
    }
  }
  _musicControlState() {
    switch (this.state.status) {
      case "PLAYING":
      case "STREAMING":
        return MusicControl.STATE_PLAYING;
      case "BUFFERING":
        return MusicControl.STATE_BUFFERING;
    }
    return MusicControl.STATE_STOPPED;
  }

  _updateMusicControlState() {
    state = this._musicControlState();
    if (state == MusicControl.STATE_STOPPED) {
      MusicControl.enableControl('play', true);
      MusicControl.enableControl('pause', false);
    } else {
      MusicControl.enableControl('play', false);
      MusicControl.enableControl('pause', true);
    }
    MusicControl.updatePlayback({state: state});
  }

  componentDidUpdate(prevProps: Object, prevState: Object) {
    if (prevState.song != this.state.song) {
      this._updateMusicControlTitle(false);
    }
    if (prevState.status != this.state.status) {
      this._updateMusicControlState();
    }
  }

  componentWillUnmount() {
    this.subscription.remove();
    MusicControl.resetNowPlaying();
    ReactNativeAudioStreaming.stop();
  }

  _playerStart() {
    ReactNativeAudioStreaming.play(this.state.streamUrl, { showIniOSMediaCenter: false, showInAndroidNotifications: false});
  }

  _playerStop() {
    ReactNativeAudioStreaming.stop();
  }

  _onPress() {
    switch (this.state.status) {
      case "PAUSED":
        ReactNativeAudioStreaming.resume();
        break;
      case "STOPPED":
      case "ERROR":
        this._playerStart();
        break;
      case "PLAYING":
      case "STREAMING":
      case "BUFFERING":
        this._playerStop();
        break;
    }
  }

  render() { 
    return (
      <View style={styles.controlElements}>
        <PlayingBlock styleBlock={styles.nowBlock}
                      styleTitle={styles.nowTitle}
                      styleSubTitle={styles.nowSubTitle}
                      title="Now playing:"
                      text={this.state.onair}/>
        <TouchableOpacity onPress={this._onPress}>
          <PlayButton status={this.state.status}/>
        </TouchableOpacity>
      </View>
    )
  }
}

class PlayingBlock extends React.Component {
  render() {
    var title = " ";
    var text = " ";
    if (this.props.text) {
      title = this.props.title;
      text = this.props.text;
    }
    return (
      <View style={this.props.styleBlock}>
        <Text style={this.props.styleTitle} numberOfLines={2}>
          {title}
        </Text>
        <Text style={this.props.styleSubTitle} numberOfLines={2}>
          {text}
        </Text>
      </View>
    );
  }
}

class PlayButton extends React.Component {
  render() {
    var button;
    switch (this.props.status) {
      case "PLAYING":
      case "STREAMING":
        button = <Image style={styles.playButton}
            source={require('../images/pause.png')}/>;
        break;
      case "PAUSED":
      case "STOPPED":
      case "ERROR":
        button = <Image style={styles.playButton}
            source={require('../images/play.png')}/>;
        break;
      case "BUFFERING":
      case "BUFFERING_START":
      case "START_PREPARING":
        button = <ActivityIndicator
            animating={true} style={styles.playButton}/>;
        break;
    }
    return button
  }
}

const styles = StyleSheet.create({
  controlElements: {
    alignItems: 'center',
    justifyContent: 'space-between',
    flexDirection: 'column',
  },
  playButton: {
    width: 22,
    height: 29,
    margin: 40,
  },
  nowBlock: {
    alignItems: 'center',
  },
  nowTitle: {
    fontSize: 15,
    paddingBottom: 5, 
    color: '#00418c',
    fontFamily: 'FiraSans-BoldItalic'
  },
  nowSubTitle: {
    fontSize: 24,
    color: '#00418c',
    textAlign: 'center',
    fontFamily: 'FiraSans-BoldItalic'
  },
});

@callmejm
Copy link

@SydneyTR where to put your code ? put it inside react-native-audio-streaming folder ?

@mrsydster
Copy link

@JayricMok: No this is just a component I wrote for the app, this can go into one of your screens, on which you want to display your player

@callmejm
Copy link

callmejm commented Oct 27, 2017

@SydneyTR now im using this modules Player , maybe i should try your Player , will let you know how, thanks btw.

@callmejm
Copy link

callmejm commented Nov 2, 2017

@SydneyTR in your _playerStart function i have to set the showIniOSMediaCenter and showInAndroidNotifications to true, if not when i click play app will crash

@callmejm
Copy link

callmejm commented Nov 2, 2017

@SydneyTR how you disabled the notification from Audio Streaming ?

waskosky added a commit to waskosky/react-native-audio-streaming that referenced this issue Apr 12, 2019
Fix to sporadic NullPointerException issue found at tlenclos#117 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants