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

Usage with react-native-navigation #13

Closed
rafaelcorreiapoli opened this issue Nov 4, 2016 · 7 comments
Closed

Usage with react-native-navigation #13

rafaelcorreiapoli opened this issue Nov 4, 2016 · 7 comments

Comments

@rafaelcorreiapoli
Copy link

rafaelcorreiapoli commented Nov 4, 2016

Hello! I started using exponent today and now i'm trying to use https://github.com/wix/react-native-navigation in my exponent's project

The problem is that react-native-navigation requires you to start the root of your app in a different way:
index.ios.js

import { Navigation } from 'react-native-navigation';

import { registerScreens } from './screens';
registerScreens(); // this is where you register all of your app's screens

// start the app
Navigation.startTabBasedApp({
  tabs: [
    {
      label: 'One',
      screen: 'example.FirstTabScreen', // this is a registered name for a screen
      icon: require('../img/one.png'),
      selectedIcon: require('../img/one_selected.png'),
      title: 'Screen One'
    },
    {
      label: 'Two',
      screen: 'example.SecondTabScreen',
      icon: require('../img/two.png'),
      selectedIcon: require('../img/two_selected.png'),
      title: 'Screen Two'
    }
  ]
});

And I noticed that exponent requires you to start your app with this special function:
Exponent.registerRootComponent(App);

That probably does a lot more than the normal one

Is it possible to use these two technologies together?

@brentvatne
Copy link
Member

tiensonqin pushed a commit to tiensonqin/exponent that referenced this issue Dec 7, 2016
- Push notifications aren't currently working on iOS10 because this: http://stackoverflow.com/a/39615693/659988

fbshipit-source-id: fbc5034
@rangerscience
Copy link

This seems like it should be resolvable if people from both projects can put their heads together - Expo requires an App object to be supplied, and presumable, at some point React-Native-Navigation produces that object. Just need to expose things at the proper point in the pipeline...?

@feldrok
Copy link

feldrok commented Oct 26, 2017

Please, we would love support of react-native-navigation, looks so smooth and easy to use compared to other solutions...

@javidjamae
Copy link

React Navigation has a lot of issues. It would be great to have an alternative choice in Expo with React Native Navigation.

@sebasibarguen
Copy link

Is there any plans for supporting react-native-nagivation?

@camdagr8
Copy link

Would love to have this.

@anp
Copy link
Contributor

anp commented Jan 2, 2018

Hi everyone! Please use the feature request board to vote for feature requests so we can look at everything in one place when evaluating what to work on. Thanks!

ide added a commit that referenced this issue Oct 13, 2018
….0 and 0.5.1

RN 0.57 and some of its dependencies (Fresco) updated to use SoLoader 0.5.1, which introduced breaking changes compared to 0.1.0. Namely, `SoLoader.loadLibrary` now returns a boolean instead of nothing. This causes old Java bytecode -- including older Expo ABIs -- that was looking for `void SoLoader.loadLibrary` to fail because the method is not defined.

The behavior of SoLoader is seemingly otherwise compatible, so we may be able to just add the old method back. This commit adds a custom SoLoader AAR and overrides the version from Maven so that we use it when building Expo, but unimodules can depend on Maven's SoLoader 0.5.1 in the build.gradle files and work with the latest RN (0.57) and address issues like https://github.com/expo/expo-gl/issues/2.

Test Plan: Built the Android client and loaded the published NavigationPlayground project, which uses SDK 30. Without this patch, the app crashes and adb logcat shows an error with SoLoader missing the void `loadLibrary` method. With this patch, NavigationPlayground (SDK 30) loads.

Also unpacked the APK and examined the DEX files (classes3.dex specifically) and verified that both the old and new SoLoader methods are defined:

```
    #13              : (in Lcom/facebook/soloader/SoLoader;)
      name          : 'loadLibrary'
      type          : '(Ljava/lang/String;)V'
      access        : 0x0009 (PUBLIC STATIC)
      code          -
      registers     : 1
      ins           : 1
      outs          : 1
      insns size    : 4 16-bit code units
      catches       : (none)
      positions     :
        0x0000 line=840
      locals        :
        0x0000 - 0x0004 reg=0 shortName Ljava/lang/String;
    #14              : (in Lcom/facebook/soloader/SoLoader;)
      name          : 'loadLibrary'
      type          : '(Ljava/lang/String;)Z'
      access        : 0x0009 (PUBLIC STATIC)
      code          -
      registers     : 2
      ins           : 1
      outs          : 2
      insns size    : 6 16-bit code units
      catches       : (none)
      positions     :
        0x0000 line=455
      locals        :
        0x0000 - 0x0006 reg=1 shortName Ljava/lang/String;
```

---

There is some sorcery to the AAR so these are some notes. Implementing the new and old SoLoader methods is complicated by the fact that we can't add the old method to the SoLoader.java source and recompile SoLoader. Java does not support return-type dispatch, so `void loadLibrary(String)` and `boolean loadLibrary(String)` fail to compile when together.

However, JVM bytecode does allow for two methods with the same name and parameter types but different return values to co-exist. (In fact, some bytecode obfuscators use this behavior as they make take two differently-named Java methods with different return types and produce JVM bytecode with the same method name and different return types.) By editing the bytecode directly we can support the old and new SoLoader interfaces simultaneously.

To do this, I found the SoLoader AAR from the Gradle cache, extracted it, then extracted classes.jar and found SoLoader.class. In a JVM bytecode editor I added a new method:

```
  public static void loadLibrary(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokestatic  #635                // Method loadLibrary:(Ljava/lang/String;)Z
         4: pop
         5: return
      LineNumberTable:
        line 840: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0 shortName   Ljava/lang/String;
```

The implementation of this method was written by hand, which seems error-prone so I verified it three ways:

- Wrote a small test class with a similar method and inspected its bytecode and ensured it matched the new SoLoader method's bytecode.
- Ran the modified .class file through a decompiler and verified the Java code looked right.
- Wrote a small test class that called into the actual modified .class file and verified I could invoke the underlying `SoLoader.loadLibrary` method i.e. the thin patched method was working.
ide added a commit that referenced this issue Oct 15, 2018
….0 and 0.5.1

RN 0.57 and some of its dependencies (Fresco) updated to use SoLoader 0.5.1, which introduced breaking changes compared to 0.1.0. Namely, `SoLoader.loadLibrary` now returns a boolean instead of nothing. This causes old Java bytecode -- including older Expo ABIs -- that was looking for `void SoLoader.loadLibrary` to fail because the method is not defined.

The behavior of SoLoader is seemingly otherwise compatible, so we may be able to just add the old method back. This commit adds a custom SoLoader AAR and overrides the version from Maven so that we use it when building Expo, but unimodules can depend on Maven's SoLoader 0.5.1 in the build.gradle files and work with the latest RN (0.57) and address issues like https://github.com/expo/expo-gl/issues/2.

Test Plan: Built the Android client and loaded the published NavigationPlayground project, which uses SDK 30. Without this patch, the app crashes and adb logcat shows an error with SoLoader missing the void `loadLibrary` method. With this patch, NavigationPlayground (SDK 30) loads.

Also unpacked the APK and examined the DEX files (classes3.dex specifically) and verified that both the old and new SoLoader methods are defined:

```
    #13              : (in Lcom/facebook/soloader/SoLoader;)
      name          : 'loadLibrary'
      type          : '(Ljava/lang/String;)V'
      access        : 0x0009 (PUBLIC STATIC)
      code          -
      registers     : 1
      ins           : 1
      outs          : 1
      insns size    : 4 16-bit code units
      catches       : (none)
      positions     :
        0x0000 line=840
      locals        :
        0x0000 - 0x0004 reg=0 shortName Ljava/lang/String;
    #14              : (in Lcom/facebook/soloader/SoLoader;)
      name          : 'loadLibrary'
      type          : '(Ljava/lang/String;)Z'
      access        : 0x0009 (PUBLIC STATIC)
      code          -
      registers     : 2
      ins           : 1
      outs          : 2
      insns size    : 6 16-bit code units
      catches       : (none)
      positions     :
        0x0000 line=455
      locals        :
        0x0000 - 0x0006 reg=1 shortName Ljava/lang/String;
```

---

There is some sorcery to the AAR so these are some notes. Implementing the new and old SoLoader methods is complicated by the fact that we can't add the old method to the SoLoader.java source and recompile SoLoader. Java does not support return-type dispatch, so `void loadLibrary(String)` and `boolean loadLibrary(String)` fail to compile when together.

However, JVM bytecode does allow for two methods with the same name and parameter types but different return values to co-exist. (In fact, some bytecode obfuscators use this behavior as they make take two differently-named Java methods with different return types and produce JVM bytecode with the same method name and different return types.) By editing the bytecode directly we can support the old and new SoLoader interfaces simultaneously.

To do this, I found the SoLoader AAR from the Gradle cache, extracted it, then extracted classes.jar and found SoLoader.class. In a JVM bytecode editor I added a new method:

```
  public static void loadLibrary(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokestatic  #635                // Method loadLibrary:(Ljava/lang/String;)Z
         4: pop
         5: return
      LineNumberTable:
        line 840: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0 shortName   Ljava/lang/String;
```

The implementation of this method was written by hand, which seems error-prone so I verified it three ways:

- Wrote a small test class with a similar method and inspected its bytecode and ensured it matched the new SoLoader method's bytecode.
- Ran the modified .class file through a decompiler and verified the Java code looked right.
- Wrote a small test class that called into the actual modified .class file and verified I could invoke the underlying `SoLoader.loadLibrary` method i.e. the thin patched method was working.
ide pushed a commit that referenced this issue Dec 19, 2018
Added a few paragraphs on custom icon font usage with Exponent. Currently, the information needed to understand how this works is located in three different places, so I tried to sum it all up in one generic example for people to get an overview of how it works.

This was my first time using  markup, so hopefully I didn'\''t mess anything up 🙏

Cheers!

Closes #13
@lock lock bot added the outdated label Jun 15, 2019
@lock lock bot locked and limited conversation to collaborators Jun 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants