mapbox / mapbox-navigation-android

Mapbox Navigation SDK for Android
https://docs.mapbox.com/android/navigation/overview/
Other
622 stars 319 forks source link

NavigationView doesn't show all instructions and crash in React Native #3050

Open andfs opened 4 years ago

andfs commented 4 years ago

I'm trying to build a navigation component to use in a React Native project. In this project, I need to show the navigation inside a View, so I can't use the NavigationLauncher because it wraps the navigation on the entire screen. I've been trying to create a View that extends the Mapbox's NavigationView and it almost worked well. The problem is that the text in summaryView does not appear. But if I change the orientation of the phone (and only if I change it) it appears. If I click in the instructionsView the app crashes. I'm using the last stable version on Navigation SDK 0.42.6. Here is the code with some comments:

https://gist.github.com/andfs/dc833e70b6d9cfcb1fd3b85865c704c0

Here is a gif that shows the problem. As you can see the time remaining text doesn't appear:

navigationProblem

When the app crashes, Android Studio show me this error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.navdemo, PID: 1346
    java.lang.RuntimeException: All children of ConstraintLayout must have ids to use ConstraintSet
        at androidx.constraintlayout.widget.ConstraintSet.applyToInternal(ConstraintSet.java:804)
        at androidx.constraintlayout.widget.ConstraintSet.applyTo(ConstraintSet.java:789)
        at com.mapbox.services.android.navigation.ui.v5.instruction.InstructionView.updateLandscapeConstraintsTo(InstructionView.java:833)
        at com.mapbox.services.android.navigation.ui.v5.instruction.InstructionView.showInstructionList(InstructionView.java:360)
        at com.mapbox.services.android.navigation.ui.v5.instruction.InstructionView$6.onClick(InstructionView.java:573)
        at android.view.View.performClick(View.java:7869)
        at android.view.View.performClickInternal(View.java:7838)
        at android.view.View.access$3600(View.java:886)
        at android.view.View$PerformClick.run(View.java:29362)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8016)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Guardiola31337 commented 4 years ago

Hey @andfs thanks for reaching out and report your issue.

Would you mind re-testing / confirming if OP is still an issue in 1.0.0? You can review the developer documentation to start building with the Mapbox Navigation SDK v1.0 for Android and check out the migration guide to transition your project from the "legacy" Navigation SDK to the 1.0 version and let us know if you have any questions or run into issues. We would love your feedback.

cc @abhishek1508

andfs commented 4 years ago

@Guardiola31337 thanks for answering :)

I'll try at the weekend and give you a feedbadk

rossmartin commented 4 years ago

Hey @andfs I have this exact same issue with react native and I figured out a solution (although I wish it were more ideal). I am using the SDK version 1.1.2 in my native wrapper that returns the NavigationView.

Originally I had to do what you were doing on init with programmatically showing the UI buttons like this -

retrieveFeedbackButton().show();
retrieveSoundButton().show();

I was able to get rid of that code after discovering that if you modify the height of a sibling component of MapboxNavigationView after it has rendered in react native then everything will show and it will render correctly. Here is an example -

import * as React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import MapboxNavigation from 'react-native-mapbox-navigation';

export const SomeComponent = () => {
  const [uiHeight, setUiHeight] = React.useState(123);

  React.useEffect(() => {
    setTimeout(() => {
      setUiHeight(124);
    });
  }, []);

  return (
    <View style={styles.flexIt}>
      <MapboxNavigation
        origin={[-97.760288, 30.273566]}
        destination={[-97.918842, 30.494466]}
        shouldSimulateRoute={true}
        onProgressChange={event => {}}
        onNavigationStart={() => {
          setTimeout(() => {
            setUiHeight(125);
          }, 7000);
        }}
        style={styles.flexIt}
      />
      <View
        style={{
          height: uiHeight,
          justifyContent: 'center',
          alignItems: 'center',
        }}
      >
        <Text style={{ fontSize: 26 }}>Some UI Here</Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  flexIt: {
    flex: 1,
  },
});

I added an onNavigationStart callback in my wrapper that is called when onNavigationRunning fires. My view class implements NavigationListener.

I have written this wrapper for android in kotlin and I think we will be open sourcing it. I will post back here if we do and also if I can find a better solution. I'm sure that if you modify the height of the MapboxNavigation component when necessary you would also get the same effect. I was able to get the iOS side of things for this wrapper running much easier.

rossmartin commented 4 years ago

Ok here is a "better" solution that doesn't rely on the onNavigationRunning.

import * as React from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
import MapboxNavigation from 'react-native-mapbox-navigation';

import { useInterval } from '../../hooks/useInterval'; // https://overreacted.io/making-setinterval-declarative-with-react-hooks/

export const SomeComponent = () => {
  const [footerUiHeight, setFooterUiHeight] = React.useState(123);

  if (Platform.OS === 'android') {
    useInterval(() => {
      setFooterUiHeight(footerUiHeight === 123 ? 123.1 : 123);
    }, 1000);
  }

  return (
    <View style={styles.flexIt}>
      <MapboxNavigation
        origin={[-97.760288, 30.273566]}
        destination={[-97.918842, 30.494466]}
        shouldSimulateRoute={true}
        onProgressChange={event => {}}
        onError={event => {}}
        style={styles.flexIt}
      />
      <View
        style={{
          height: footerUiHeight,
          justifyContent: 'center',
          alignItems: 'center',
        }}
      >
        <Text style={{ fontSize: 26 }}>Some UI Here</Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  flexIt: {
    flex: 1,
  },
});

Basically you can see here that I adjust the height of the sibling View by 1/10 of a pixel every second. This isn't ideal but it fixes the rendering issue that we both experience. It's such a minor adjustment that I can't notice it even looking for it. When I get some more time I'll see if I can find a better solution. I tried lots of things on the native side before coming to this approach.

andfs commented 4 years ago

\o/ I'm so happy in Reading this. I'll try It and give you a feedback. Thanks in advance. This feature is Still on hold in my project cause I didn't have found a solution. Thank you

rossmartin commented 4 years ago

I think this stems from this root cause - https://github.com/facebook/react-native/issues/17968

I tried some of those solutions mentioned inn the thread but without success.

andfs commented 4 years ago

@rossmartin I tried yesterday but my project is outdated to use the 1.1.2 version of mapbox navigation. I'll have to change somethings to update it.

But doing what you said, my project didn't crash \o/

I wasn't able to show the instructions view, but now I can continue to work in this. Thank you so much. If you opensource this component I'll try to help :D

rossmartin commented 4 years ago

Hey @andfs we open sourced the wrapper that we made for react native. You can get it on npm and view it here on github - https://github.com/homeeondemand/react-native-mapbox-navigation

rossmartin commented 4 years ago

For anyone that comes to this thread for this react native issue - here is how I solved the rendering issue with android on the native side: https://github.com/homeeondemand/react-native-mapbox-navigation/commit/4fceba358224cb3bc5ee9a649320723c4dea0ea8

andfs commented 4 years ago

@rossmartin what great news man \o/

I`ll try it in next weekend

abhishek1508 commented 2 years ago

Thanks for using the Mapbox Navigation SDK for Android and being a valued customer.

Mapbox will be soon deprecating any support for v0 and v1 versions of the SDK. To facilitate this transition we’re launching a new drop-in UI component into v2, equivalent to the existing NavigationView v1 in its design goals, however with a more modern and customizable API.

We plan to launch this new drop-in UI component as a Developer Preview feature in April, as part of the v2.5 series. Since you are using NavigationView with v1, we’d love to hear your feedback so that we can incorporate it ahead of a GA release.

If you’re interested in having early access to the upcoming drop-in UI for v2 and its documentation, drop a comment on this ticket or send an email to abhishek.kejriwal@mapbox.com

/cc @zugaldia @AhmerKhan1