响应本地Android获取在连接到本地API时失败

响应本地Android获取在连接到本地API时失败,android,react-native,Android,React Native,我在react原生Android应用程序中使用FetchAPI向本地API发出请求。我通常从react web apps的http://localhost:8163. 我正在调试模式下在物理设备上测试我的应用程序。我在某个地方读到,react native无法像web应用程序一样查询localhost。显然,您必须使用http://10.0.2.2:[PORT\u NUMBER\u HERE]/是的别名`http://127.0.0.1:根据Android仿真器码头的数据,这里有[端口号]。我不

我在react原生Android应用程序中使用FetchAPI向本地API发出请求。我通常从react web apps的http://localhost:8163.

我正在调试模式下在物理设备上测试我的应用程序。我在某个地方读到,react native无法像web应用程序一样查询localhost。显然,您必须使用
http://10.0.2.2:[PORT\u NUMBER\u HERE]/
是的别名`http://127.0.0.1:根据Android仿真器码头的数据,这里有[端口号]。我不确定这是否是我在物理设备上测试时应该做的

我的获取代码如下所示:

fetchToken() {
    fetch('http://10.0.2.2:8163/extension/auth', {
        method: 'GET',
        headers: {
            'Accept': 'application/json',
            'Content-type': 'application/json'
        }
    })
    .then((response)) => console.log('successful fetchToken response: ', response.json()))
    .catch((error) => console.log('fetchToken error: ', error))
    .done();
}
请求总是挂起一段时间,然后到达
catch
块,出现无帮助的错误
TypeError:networkrequest失败(…)
。检查本地API的日志,他们根本不注册请求


因此,我不知道是否正确查询本地API以获取所需的资源,如果是,我不知道获取失败的原因。

您无法访问本地开发服务器,因为该端口尚未由ADB转发。当您运行
react native run android
时,react native会将端口8081映射到USB上的移动设备。当您断开USB连接时,您将无法再刷新或热重新加载代码。因此,在这种情况下,您可以做两件事,要么像React Native一样映射本地服务器端口,要么使用本地IP地址

  • 映射端口

    这仅在使用Android 6.0+时有效。要使用ADB转发端口,请在终端中运行以下命令:

    adb reverse tcp:8163 tcp:8163
    
    这将把您的本地
    8163
    端口映射到手机的
    8163
    端口。您将能够通过这种方式访问您的开发服务器

  • 使用本地IP地址

    您还可以在React Native development应用程序上使用您的本地IP重新加载它们,而无需USB。摇动您的设备或长按菜单按钮打开开发者菜单。打开
    开发设置
    ,然后点击
    调试设备的服务器主机和端口
    。在这里,您可以输入机器的本地IP,端口号为
    8081
    。例如,如果您的机器的IP为
    192.168.1.100
    ,则您需要在此处输入
    192.168.1.100:8081
    ,以便成功连接。现在我们已经讨论了可以重新加载应用程序的问题。之后,当您想使用本地计算机的开发服务器时,请使用与服务器端口号相同的IP


  • 你应该很乐意这样做。

    有同样/类似的问题-我花了整整两天的时间才解决。我使用一台带有VisualStudio代码的Win10机器、连接的Android设备和一个本地PHP服务器作为API。也许这会对某人有所帮助:

  • 电缆->尝试不同的USB电缆,在我的3根电缆中只有一根有效
  • 连接模式->非常重要,我必须选择PTP模式才能工作
  • 同一网络->手机和PC必须在同一网络上
  • 专用网络->该网络必须是专用网络,公用网络不工作
  • IP->在PowerShell中运行ipconfig并获取您的IP4地址
  • 防火墙->接受防火墙提示
  • PHP服务器->使用“PHP-S{your IP}:8081”启动内置PHP服务器
  • 测试PHP服务器->创建index.PHP并在手机上打开{your IP}:8081
  • 获取->创建获取脚本(下面的示例)
  • fetch('http://{your-IP}:8081/'))
    .then((response)=>response.json())
    .然后((responseJson)=>{
    this.setState({message:responseJson.message.data})
    })
    .catch((错误)=>{
    控制台错误(error);
    }); 
    如果您在Expo开发者工具中使用Metro Bundler
    使用连接LAN ip地址
    

    如何在react native中使用

    使用postman的示例图像RESTAPI

    希望这会有所帮助:)


    也许我提建议迟到了,但这对我有帮助


    您应该尝试运行以下命令来访问localhost或127.0.0.1或您计算机的ip

    adb -s <device_name> reverse tcp:backend_port tcp:backend_port
    
    现在,您可以在组件中使用如下所示

    import React from 'react';
    import {View,Image,TextInput, TouchableOpacity, StyleSheet, ImageBackground, AsyncStorage} from 'react-native';
    import {Text,Button} from 'native-base';
        export class Login extends React.Component{
        constructor(props){
            super(props);
            this.state={username:'',password:''}
          }
          login = () =>{
            fetch('http://localhost:3000/users',{
              method:'POST',
                headers:{
                  'Accept':'application/json',
                  'Content-Type':'application/json'
                },
                body:JSON.stringify({
                  username:this.state.username,
                  password:this.state.password
                })
            })
            .then((response)=>response.json())
            .then((res)=>{
              if(res.success===true){
                var username=res.message;
                AsyncStorage.setItem('username',username);
                this.props.navigation.navigate('app');
                alert("Login success");
              } else{
                alert("Invalid Credentials");
              }
            })
            .done();
          }
        render(){
          return (
        <View style={styles.content}>
                    <Text style={styles.logo}>- WELCOME -</Text>
                    <View>
                      <TextInput underlineColorAndroid='transparent' style={styles.input} placeholder="Username"
                      onChangeText={(username)=>this.setState({username})}
                      value={this.state.username}>
                      </TextInput>
                      <TextInput secureTextEntry={true} underlineColorAndroid='transparent' style={styles.input} placeholder="Password"
                      onChangeText={(password)=>this.setState({password})}
                      value={this.state.password}>
                      </TextInput>
                    </View>
                    <TouchableOpacity onPress={this.login} style={styles.buttonContainer}>
                      <Text style={styles.buttonText}>LOGIN</Text>
                    </TouchableOpacity>
                  </View>
        );
        }
        }
        const styles = StyleSheet.create({
          container:{
            flex:1,
          },
          content:{
            opacity:0.9,
            backgroundColor:'white',
            borderWidth:2,
            margin:10,
            alignItems: 'center',
          },
          logo:{
            justifyContent: 'center',
            alignItems: 'center',
            fontSize:45,
            color:'black',
            textShadowColor:'gray',
            textShadowRadius:10
          },
          input:{
            borderRadius:10,
            padding:10,
            color:'black',
            borderWidth:2,
            borderColor:'lightgray',
            width:200,
            margin:5
          },
          buttonContainer:{
            margin:10,
            padding:10,
            justifyContent: 'center',
            alignItems: 'center',
          },
          buttonText:{
            borderRadius:100,
            padding:10,
            backgroundColor:'magenta',
            color:'white',
            textAlign:'center',
            width:100
          }
    
        });
    
    从“React”导入React;
    从“react native”导入{View、Image、TextInput、TouchableOpacity、样式表、ImageBackground、AsyncStorage};
    从'native base'导入{Text,Button};
    导出类登录扩展React.Component{
    建造师(道具){
    超级(道具);
    this.state={用户名:'',密码:'}
    }
    登录=()=>{
    取('http://localhost:3000/users',{
    方法:'POST',
    标题:{
    “接受”:“应用程序/json”,
    “内容类型”:“应用程序/json”
    },
    正文:JSON.stringify({
    用户名:this.state.username,
    密码:this.state.password
    })
    })
    .then((response)=>response.json())
    。然后((res)=>{
    如果(res.success==true){
    var username=res.message;
    AsyncStorage.setItem('username',username);
    this.props.navigation.navigate('app');
    警报(“登录成功”);
    }否则{
    警报(“无效凭证”);
    }
    })
    .完成();
    }
    render(){
    返回(
    -欢迎光临-
    this.setState({username})}
    值={this.state.username}>
    this.setState({password})}
    值={this.state.password}>
    登录
    );
    }
    }
    const styles=StyleSheet.create({
    容器:{
    弹性:1,
    },
    内容:{
    不透明度:0.9,
    背景颜色:'白色',
    边界宽度:2,
    差额:10,
    对齐项目:“居中”,
    },
    标志:{
    为内容辩护:“中心”,
    对齐项目:“居中”,
    
    adb -s emulator-5554 reverse tcp:3000 tcp:3000
    
    import React from 'react';
    import {View,Image,TextInput, TouchableOpacity, StyleSheet, ImageBackground, AsyncStorage} from 'react-native';
    import {Text,Button} from 'native-base';
        export class Login extends React.Component{
        constructor(props){
            super(props);
            this.state={username:'',password:''}
          }
          login = () =>{
            fetch('http://localhost:3000/users',{
              method:'POST',
                headers:{
                  'Accept':'application/json',
                  'Content-Type':'application/json'
                },
                body:JSON.stringify({
                  username:this.state.username,
                  password:this.state.password
                })
            })
            .then((response)=>response.json())
            .then((res)=>{
              if(res.success===true){
                var username=res.message;
                AsyncStorage.setItem('username',username);
                this.props.navigation.navigate('app');
                alert("Login success");
              } else{
                alert("Invalid Credentials");
              }
            })
            .done();
          }
        render(){
          return (
        <View style={styles.content}>
                    <Text style={styles.logo}>- WELCOME -</Text>
                    <View>
                      <TextInput underlineColorAndroid='transparent' style={styles.input} placeholder="Username"
                      onChangeText={(username)=>this.setState({username})}
                      value={this.state.username}>
                      </TextInput>
                      <TextInput secureTextEntry={true} underlineColorAndroid='transparent' style={styles.input} placeholder="Password"
                      onChangeText={(password)=>this.setState({password})}
                      value={this.state.password}>
                      </TextInput>
                    </View>
                    <TouchableOpacity onPress={this.login} style={styles.buttonContainer}>
                      <Text style={styles.buttonText}>LOGIN</Text>
                    </TouchableOpacity>
                  </View>
        );
        }
        }
        const styles = StyleSheet.create({
          container:{
            flex:1,
          },
          content:{
            opacity:0.9,
            backgroundColor:'white',
            borderWidth:2,
            margin:10,
            alignItems: 'center',
          },
          logo:{
            justifyContent: 'center',
            alignItems: 'center',
            fontSize:45,
            color:'black',
            textShadowColor:'gray',
            textShadowRadius:10
          },
          input:{
            borderRadius:10,
            padding:10,
            color:'black',
            borderWidth:2,
            borderColor:'lightgray',
            width:200,
            margin:5
          },
          buttonContainer:{
            margin:10,
            padding:10,
            justifyContent: 'center',
            alignItems: 'center',
          },
          buttonText:{
            borderRadius:100,
            padding:10,
            backgroundColor:'magenta',
            color:'white',
            textAlign:'center',
            width:100
          }
    
        });
    
    {
      expo host :http://192.168.0.109:{Your Port}/The name for your API
    }
    
        ngrok http (port no of backend services)
    
    eg:ngrok http 8081
    
    http://10.0.2.2:3000
    
    http://localhost:3000