【问题标题】:flask + retrofit in kotlin cannot acces API endpoint with IP address (Failed to connect to /127.0.0.1:5000)kotlin 中的烧瓶 + 改造无法使用 IP 地址访问 API 端点(无法连接到 /127.0.0.1:5000)
【发布时间】:2021-10-21 19:29:28
【问题描述】:

我在烧瓶中创建了一个 api,它返回经度、纬度和 id。我想在我自己的安卓设备中得到这个响应。我用邮递员测试了这个api,我也可以通过手机浏览器访问它
URL = "http://192.168.0.185:3000"

尝试通过改造来访问它会产生很长的错误轨迹,我无法弄清楚。

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.posttest, PID: 2144
    java.net.ConnectException: Failed to connect to /127.0.0.1:5000
        at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:285)
        at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:195)
        at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:249)
        at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:108)
        at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:76)
        at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:245)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197)
        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:502)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: java.net.ConnectException: failed to connect to /127.0.0.1 (port 5000) from /127.0.0.1 (port 37738) after 10000ms: isConnected failed: ECONNREFUSED (Connection refused)

我尝试了在我的模拟器上运行应用程序然后尝试使用
URL ="http://10.0.2.2:3000"

访问它的方法

它仍然给我错误。我怎样才能做到这一点?这是我的 api 响应的样子:

我的 Flask 服务器代码很简单

app = Flask(__name__)
api = Api(app)
api.add_resource(LocationValues, '/adamapi')

@app.route('/')
def hello():
    return 'Hello,REST'

if __name__ == '__main__':
    app.run("0.0.0.0",debug=True,port= 3000)

Resource.py

    def get(self):
        connection = sqlite3.connect('db.sqlite')
        cursor = connection.cursor()
        query = "SELECT * FROM location WHERE id = 1"
        result = cursor.execute(query).fetchone()
        connection.close()
        if result:
            return {'item': {'measure_id': result[0], 'longitude': result[1], 'latitude': result[2]}}
        return {"message": "Wrong get request"}, 400

还有 Kotlin 文件
Contants.kt

class Constants {
    companion object{
        const val BASE_URL = "http://192.168.0.185:3000"
    }
}

DataClass.kt

data class Post(
    val item: Item
)

data class Item(
    val latitude: Double,
    val longitude: Double,
    val measure_id: Int
)

SimpleApi.kt

interface SimpleApi {
    @GET("adamapi")
    suspend fun getPost(): Post
}

Repository.kt

class Repository {
    suspend fun getPost(): Post {
        return RetrofitInstance.api.getPost()

    }
}

RetrofitInstance.kt

object RetrofitInstance {

    private val retrofit  by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

    }
    val api:SimpleApi by lazy {
        retrofit.create(SimpleApi::class.java)
    }
}

MainViewModel and MainViewModelFactory classes in .kt

class MainViewModel(private  val repository: Repository):ViewModel() {
    val myResponse: MutableLiveData<Post> = MutableLiveData()
    fun getPost (){
        viewModelScope.launch {
            val response :Post = repository.getPost()
            myResponse.value = response
        }
    }
}


class MainViewModelFactory (private val repository:Repository):ViewModelProvider.Factory {
    override fun <T: ViewModel?> create (modelClass: Class<T>):T{
        return MainViewModel(repository) as T
    }
}

我在 Manifest 文件中添加了 Internet 权限。此外,这里的解释也不适用于我的设备-> https://medium.com/analytics-vidhya/how-to-make-client-android-application-with-flask-for-server-side-8b1d5c55446e
我的两台设备都在使用 Wifi。

错误:

更新:按照@martin-zeitler 的回答它现在可以在模拟器上运行。但是使用我的 ipv4 地址仍然会出错。

【问题讨论】:

    标签: android kotlin flask retrofit


    【解决方案1】:

    在 RetrofitInstance.kt 中,在 BASE_URL 之后添加“/”,所以它看起来像这样:

    private val retrofit  by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL + "/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    
    }
    

    【讨论】:

      【解决方案2】:

      堆栈跟踪显然与代码不匹配。

      当打算连接到一个 IP 地址时,应该说明它:

      companion object {
          const val BASE_URL = "http://10.0.2.2:3000/"
      }
      

      然后在src/debug/res/xml/network_security_config.xml添加备用配置:

      <?xml version="1.0" encoding="utf-8"?>
      <!-- Debug Network Security Configuration -->
      <network-security-config
          xmlns:tools="http://schemas.android.com/tools">
          <base-config
              tools:ignore="InsecureBaseConfiguration"
              cleartextTrafficPermitted="true">
              <trust-anchors>
                  <certificates src="system"/>
              </trust-anchors>
          </base-config>
      </network-security-config>
      

      还要引用AndroidManifest.xml

      <application
          ...
          android:networkSecurityConfig="@xml/network_security_config" />
      

      这是在调试时允许纯文本 HTTP 流量所必需的。

      【讨论】:

      • 好的,它可以在我的安卓模拟器上运行,我怎样才能让它在物理设备上运行?在 ipconfig 我有以下 IPv4 地址。 . . . . . . . . . . : 192.168.0.185 但是这个 BASE_URL = "192.168.0.185:3000" 不起作用。我有 java.net.SocketTimeoutException: failed to connect to /10.0.2.2 (port 3000) from /192.168.0.66 (port 34030) after 10000ms
      • @yras8 这是相当收缩的。错误消息如何与该 IP 匹配?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-04
      • 2018-05-09
      • 1970-01-01
      • 2020-02-05
      • 2014-08-28
      相关资源
      最近更新 更多