flask + kotlin 中的改造无法访问具有 IP 地址的 API 端点(无法连接到 /127.0.0.1:5000)
flask + retrofit in kotlin cannot acces API endpoint with IP address (Failed to connect to /127.0.0.1:5000)
我在 flask 中创建了一个 api,其中包含 returns 经度、纬度和 ID。我想在我自己的 android 设备中获得该响应。我用邮递员测试了 api,我也可以通过 phone 浏览器使用
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 地址仍然会出错。
堆栈跟踪显然与代码不匹配。
当打算连接到一个 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 流量所必需的。
在 RetrofitInstance.kt 中,在 BASE_URL 之后添加“/”,这样它看起来像这样:
private val retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL + "/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
我在 flask 中创建了一个 api,其中包含 returns 经度、纬度和 ID。我想在我自己的 android 设备中获得该响应。我用邮递员测试了 api,我也可以通过 phone 浏览器使用 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 地址仍然会出错。
堆栈跟踪显然与代码不匹配。
当打算连接到一个 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 流量所必需的。
在 RetrofitInstance.kt 中,在 BASE_URL 之后添加“/”,这样它看起来像这样:
private val retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL + "/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}