如何将 android 应用程序连接到 python flask 服务器?
How to connect android app to python flask server?
我正在尝试创建一个与 Flask python 服务器通信的简单 android 应用程序
这是应用程序代码:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java:
package com.example.flasktest2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("http://127.0.0.1:5000/").build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
TextView textView = findViewById(R.id.textview);
textView.setText("network not found");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
TextView textView = findViewById(R.id.textview);
textView.setText(response.body().string());
}
});
}
}
Hello.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello Ani'
@app.route('/one')
def hello_one():
return 'Hello one'
@app.route('/two')
def hello_two():
return 'Hello two'
if __name__ == "__main__":
app.run(host = '0.0.0.0')
服务器在我的网络中工作正常。如果我连接到我的 ipv4 地址后跟端口号 5000,例如从我的浏览器 http://127.0.0.1:5000/,甚至从我的 phone 的浏览器,“Hello Ani”出现在屏幕上,但我的应用程序没有似乎无法连接到服务器,我不知道为什么。
如果你能帮我解决这个问题,我将不胜感激。谢谢!
您好,我建议使用 retrofit 来调用服务。
示例
界面
package com.co.bicicletas.model.network
import com.co.bicicletas.model.entities.BodyLoginResponse
import com.co.bicicletas.model.entities.BodyPassResponse
import com.co.bicicletas.model.entities.LoginDTO
import com.co.bicicletas.model.entities.PassDTO
import io.reactivex.rxjava3.core.Single
import retrofit2.http.Body
import retrofit2.http.POST
interface BicicletasAPI {
@POST("/UMB/login/")
fun login(@Body body: LoginDTO) : Single<BodyLoginResponse.LoginResponseDTO>
@POST("/UMB/forgetPassword/")
fun pass(@Body body: PassDTO) : Single<BodyPassResponse>
}
实施
package com.co.bicicletas.model.network
import com.co.bicicletas.model.entities.BodyLoginResponse
import com.co.bicicletas.model.entities.BodyPassResponse
import com.co.bicicletas.model.entities.LoginDTO
import com.co.bicicletas.model.entities.PassDTO
import com.co.bicicletas.utils.Constants
import io.reactivex.rxjava3.core.Single
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
class BackendApiService {
private val api = Retrofit.Builder()
.baseUrl(Constants.BASE_URL) // Set the API base URL.
// Add converter factory for serialization and deserialization of objects.
/**
* A Converter.Factory converter which uses Gson for JSON.
*
* Because Gson is so flexible in the types it supports, this converter assumes that it can handle
* all types.
*/
.addConverterFactory(GsonConverterFactory.create())
.client(generateOkHttpClient())
/**
* **
* Add a call adapter factory for supporting service method return types other than.
*
* A CallAdapter.Factory call adapter which uses RxJava 3 for creating observables.
*
* Adding this class to Retrofit allows you to return an Observable, Flowable, Single, Completable
* or Maybe from service methods.
*/
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build() // Create the Retrofit instance using the configured values.
// Create an implementation of the API endpoints defined by the service interface in our case it is RandomDishAPI.
.create(BicicletasAPI::class.java)
private fun generateOkHttpClient(): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
return OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build()
}
fun doLogin(bodyLogin: LoginDTO) :
Single<BodyLoginResponse.LoginResponseDTO> {
return api.login(bodyLogin)
}
fun doResetPass(bodyPass: PassDTO): Single<BodyPassResponse> {
return api.pass(bodyPass)
}
}
网络安全
<application
android:name=".aplication.bicicletas.BicicletasApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Bicicletas"
android:usesCleartextTraffic="true">
XML
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.20.2.0</domain>
<domain includeSubdomains="true">10.20.2.0:9021</domain>
</domain-config>
</network-security-config>
link Retrfoti and demo
我正在尝试创建一个与 Flask python 服务器通信的简单 android 应用程序 这是应用程序代码:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java:
package com.example.flasktest2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("http://127.0.0.1:5000/").build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
TextView textView = findViewById(R.id.textview);
textView.setText("network not found");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
TextView textView = findViewById(R.id.textview);
textView.setText(response.body().string());
}
});
}
}
Hello.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello Ani'
@app.route('/one')
def hello_one():
return 'Hello one'
@app.route('/two')
def hello_two():
return 'Hello two'
if __name__ == "__main__":
app.run(host = '0.0.0.0')
服务器在我的网络中工作正常。如果我连接到我的 ipv4 地址后跟端口号 5000,例如从我的浏览器 http://127.0.0.1:5000/,甚至从我的 phone 的浏览器,“Hello Ani”出现在屏幕上,但我的应用程序没有似乎无法连接到服务器,我不知道为什么。
如果你能帮我解决这个问题,我将不胜感激。谢谢!
您好,我建议使用 retrofit 来调用服务。
示例
界面
package com.co.bicicletas.model.network
import com.co.bicicletas.model.entities.BodyLoginResponse
import com.co.bicicletas.model.entities.BodyPassResponse
import com.co.bicicletas.model.entities.LoginDTO
import com.co.bicicletas.model.entities.PassDTO
import io.reactivex.rxjava3.core.Single
import retrofit2.http.Body
import retrofit2.http.POST
interface BicicletasAPI {
@POST("/UMB/login/")
fun login(@Body body: LoginDTO) : Single<BodyLoginResponse.LoginResponseDTO>
@POST("/UMB/forgetPassword/")
fun pass(@Body body: PassDTO) : Single<BodyPassResponse>
}
实施
package com.co.bicicletas.model.network
import com.co.bicicletas.model.entities.BodyLoginResponse
import com.co.bicicletas.model.entities.BodyPassResponse
import com.co.bicicletas.model.entities.LoginDTO
import com.co.bicicletas.model.entities.PassDTO
import com.co.bicicletas.utils.Constants
import io.reactivex.rxjava3.core.Single
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
class BackendApiService {
private val api = Retrofit.Builder()
.baseUrl(Constants.BASE_URL) // Set the API base URL.
// Add converter factory for serialization and deserialization of objects.
/**
* A Converter.Factory converter which uses Gson for JSON.
*
* Because Gson is so flexible in the types it supports, this converter assumes that it can handle
* all types.
*/
.addConverterFactory(GsonConverterFactory.create())
.client(generateOkHttpClient())
/**
* **
* Add a call adapter factory for supporting service method return types other than.
*
* A CallAdapter.Factory call adapter which uses RxJava 3 for creating observables.
*
* Adding this class to Retrofit allows you to return an Observable, Flowable, Single, Completable
* or Maybe from service methods.
*/
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build() // Create the Retrofit instance using the configured values.
// Create an implementation of the API endpoints defined by the service interface in our case it is RandomDishAPI.
.create(BicicletasAPI::class.java)
private fun generateOkHttpClient(): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
return OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build()
}
fun doLogin(bodyLogin: LoginDTO) :
Single<BodyLoginResponse.LoginResponseDTO> {
return api.login(bodyLogin)
}
fun doResetPass(bodyPass: PassDTO): Single<BodyPassResponse> {
return api.pass(bodyPass)
}
}
网络安全
<application
android:name=".aplication.bicicletas.BicicletasApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Bicicletas"
android:usesCleartextTraffic="true">
XML
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.20.2.0</domain>
<domain includeSubdomains="true">10.20.2.0:9021</domain>
</domain-config>
</network-security-config>
link Retrfoti and demo