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

useFunctionsEmulator doesn't work on real device #4810

Closed
cjam opened this issue Jan 21, 2021 · 8 comments · Fixed by #4851
Closed

useFunctionsEmulator doesn't work on real device #4810

cjam opened this issue Jan 21, 2021 · 8 comments · Fixed by #4851
Labels
platform: android type: bug New bug report Workflow: Needs Review Pending feedback or review from a maintainer.

Comments

@cjam
Copy link

cjam commented Jan 21, 2021

After quite a while trying to figure out why my android device couldn't connect to my functions emulator on local host I finally traced through the code and found this section:

if (isAndroid && _origin) {
if (_origin.startsWith('http://localhost')) {
_origin = _origin.replace('http://localhost', 'http://10.0.2.2');
}
if (_origin.startsWith('http://127.0.0.1')) {
_origin = _origin.replace('http://127.0.0.1', 'http://10.0.2.2');
}

Which will work great for emulators, but breaks real devices since 10.0.2.2 is only within emulators. So ideally, you only want to run this code if it is running within an Android Emulator. Otherwise, if on a physical device it should be left as localhost and reverse proxied via

adb reverse tcp:5001 tcp:5001

@mikehardy
Copy link
Collaborator

Hmmm we use this pattern in a lot of locations (and in other repos as well - FlutterFire). Will have to think about this one.

@cjam
Copy link
Author

cjam commented Jan 21, 2021

Sure thing. I'm definitely not an android expert, so perhaps my device is misconfigured? You guys are doing testing on actual devices or all emulators?

@mikehardy
Copy link
Collaborator

I think the expectation is that if you run it on a real device, you'll configure it for the IP of the actual machine hosting the emulator?

@mikehardy
Copy link
Collaborator

I personally am running emulators 99.9% of the time and supporting the same via E2E testing in CI. On Android especially since the only differences between emulator and real device is cloud messaging (which is normally not tested in any sort of automated way) there isn't much need to run against real devices until final checks before launch, for me

@mikehardy
Copy link
Collaborator

Related thought: even if we maintain the expectation that this mapping is acceptable and we expect real IP addresses for real devices, this obviously violates principle of least surprise and is hard to figure out. Code should log that we're remapping when it happens, and docs should mention it it as a minimum reaction to the issue

@mikehardy mikehardy added type: bug New bug report platform: android Type: Docs Workflow: Needs Review Pending feedback or review from a maintainer. labels Jan 21, 2021
@cjam
Copy link
Author

cjam commented Jan 21, 2021

I have written/and am using a package (https://github.com/cjam/react-native-spotify-remote) that wraps the Spotify SDK's and requires being run on a device with spotify (hence why I can't use the emulator).

I was trying to follow the same pattern that was being used by the react native package (with the adb reverse) as it doesn't involve having to change environment variables for ip address etc and can be scripted into the development workflow easily.

I'm grabbing the packager HOST / PORT like this

import { NativeModules } from 'react-native';

const scriptURL = NativeModules.SourceCode.scriptURL;
const address = scriptURL.split('://')[1].split('/')[0];
const hostname = address.split(':')[0];
const port = address.split(':')[1];

export const PACKAGER_HOST = hostname;
export const PACKAGER_PORT = port;

Then using it within my firebase service wrapper like this:

constructor(){
        this._app = firebase.app();
        this._links = firebaseLinks();
        this._auth = firebaseAuth(this._app);
        this._functions = firebaseFunctions(this._app);

        if (__DEV__) {           
            // PACKAGER_HOST 
            // On iOS = Machine IP Address
            // on Android = localhost 
            // on Android Emulator = ??  (I suspect 10.0.2.2)
            this._db = this._app.database(`http://${PACKAGER_HOST}:9000?ns=${this._app.options.projectId}`);
            this._functions.useFunctionsEmulator(`http://${PACKAGER_HOST}:5001`);
        } 
       //....
}

So perhaps you're right, just passing the IP Address in an environment variable would work, I suspect this is likely why using the authEmulator wasn't working as well (for me).

mikehardy added a commit that referenced this issue Feb 2, 2021
For developer experience, we remap localhost / 127.0.0.1 on android to the
canonical android emulator IP address for the host machine. This is best most
of the time but is quite unexpected if you run on a real device and try to do
adb reverse port mapping for the emulator port and use localhost, only to find
that you can't connect to the emulator because of this remapping

This PR adds a note to the docs and a console.log so developers are aware of
the behavior

Fixes #4810
mikehardy added a commit that referenced this issue Feb 3, 2021
For developer experience, we remap localhost / 127.0.0.1 on android to the
canonical android emulator IP address for the host machine. This is best most
of the time but is quite unexpected if you run on a real device and try to do
adb reverse port mapping for the emulator port and use localhost, only to find
that you can't connect to the emulator because of this remapping

This PR adds a note to the docs and a console.log so developers are aware of
the behavior

Fixes #4810
@mikehardy
Copy link
Collaborator

docs have been updated and as of next release if the remapping happens, it will print to console that it happened and what to do if it is not what you want. Thanks for reporting this, sorry for the frustration - I imagine it was an unexpected surprise when you discovered it!

@cjam
Copy link
Author

cjam commented Feb 3, 2021

Thanks @mikehardy. I found a few things that morning. One was this behavior, and the other was a bug in the Firebase cli, so I suppose it's partially positive? 👍

androidIsForVivek pushed a commit to androidIsForVivek/react-native-firebase that referenced this issue Aug 9, 2021
For developer experience, we remap localhost / 127.0.0.1 on android to the
canonical android emulator IP address for the host machine. This is best most
of the time but is quite unexpected if you run on a real device and try to do
adb reverse port mapping for the emulator port and use localhost, only to find
that you can't connect to the emulator because of this remapping

This PR adds a note to the docs and a console.log so developers are aware of
the behavior

Fixes invertase#4810
androidIsForVivek pushed a commit to androidIsForVivek/react-native-firebase that referenced this issue Sep 15, 2021
For developer experience, we remap localhost / 127.0.0.1 on android to the
canonical android emulator IP address for the host machine. This is best most
of the time but is quite unexpected if you run on a real device and try to do
adb reverse port mapping for the emulator port and use localhost, only to find
that you can't connect to the emulator because of this remapping

This PR adds a note to the docs and a console.log so developers are aware of
the behavior

Fixes invertase#4810
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform: android type: bug New bug report Workflow: Needs Review Pending feedback or review from a maintainer.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants