如何将 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