如何使用 Flask 后端构建一个简单的 Android 应用程序?
Flask 是Python的 API,它允许我们构建 Web 应用程序。它是由 Armin Ronacher 开发的。 Flask 的框架比 Django 的框架更明确,也更容易学习,因为它实现一个简单的 web 应用程序的基础代码更少。 Web-Application Framework 或 Web Framework 是模块和库的集合,可帮助开发人员编写应用程序,而无需编写协议、线程管理等低级代码。 Flask 基于 WSGI(Web 服务器网关接口)工具包和 Jinja2 模板引擎。下面的文章将演示如何在开发 Android 应用程序时将 Flask 用于后端。
分步实施
第一步:安装烧瓶
打开终端输入以下命令安装flask
pip install flask
第二步:在build.gradle文件中添加OkHttp依赖
OkHttp 是 Square 开发的用于发送和接收基于 HTTP 的网络请求的库。为了在 Android 应用程序中发出 HTTP 请求,我们使用 OkHttp。该库用于进行同步和异步调用。如果网络调用是同步的,则代码将等待我们从尝试与之通信的服务器获得响应。这可能会导致延迟或性能滞后。如果网络调用是异步的,则执行不会等到服务器响应,应用程序才会运行,如果服务器响应,将执行回调。
安卓依赖
在 Android Studio 的 build.gradle 文件中添加以下依赖
implementation("com.squareup.okhttp3:okhttp:4.9.0")
第 3 步:使用 AndroidManifest.XML 文件
在
在
android:usesCleartextTraffic="true">
第 4 步: Python脚本
- @app.route(“/”) 与 showHomePage()函数相关联。假设服务器运行在一个 IP 地址为 192.168.0.113,端口号为 5000 的系统上。现在,如果在浏览器中输入 URL“http://192.168.0.113:5000/”,将执行 showHomePage函数,它将返回响应“这是主页”。
- app.run() 将在本地主机上托管服务器,而 app.run(host=”0.0.0.0″) 将在机器的 IP 地址上托管服务器
- 默认情况下将使用端口 5000,我们可以使用 app.run() 中的 'port' 参数更改它
Python
from flask import Flask
# Flask Constructor
app = Flask(__name__)
# decorator to associate
# a function with the url
@app.route("/")
def showHomePage():
# response from the server
return "This is home page"
if __name__ == "__main__":
app.run(host="0.0.0.0")
XML
Java
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
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 {
// declare attribute for textview
private TextView pagenameTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pagenameTextView = findViewById(R.id.pagename);
// creating a client
OkHttpClient okHttpClient = new OkHttpClient();
// building a request
Request request = new Request.Builder().url("http://192.168.0.113:5000/").build();
// making call asynchronously
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
// called if server is unreachable
public void onFailure(@NotNull Call call, @NotNull IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "server down", Toast.LENGTH_SHORT).show();
pagenameTextView.setText("error connecting to the server");
}
});
}
@Override
// called if we get a
// response from the server
public void onResponse(
@NotNull Call call,
@NotNull Response response)
throws IOException {pagenameTextView.setText(response.body().string());
}
});
}
}
Python
from flask import Flask
# import request
from flask import request
app = Flask(__name__)
@app.route("/")
def showHomePage():
return "This is home page"
@app.route("/debug", methods=["POST"])
def debug():
text = request.form["sample"]
print(text)
return "received"
if __name__ == "__main__":
app.run(host="0.0.0.0")
XML
Java
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class DummyActivity extends AppCompatActivity {
private EditText editText;
private Button button;
private OkHttpClient okHttpClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dummy);
editText = findViewById(R.id.dummy_text);
button = findViewById(R.id.dummy_send);
okHttpClient = new OkHttpClient();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String dummyText = editText.getText().toString();
// we add the information we want to send in
// a form. each string we want to send should
// have a name. in our case we sent the
// dummyText with a name 'sample'
RequestBody formbody
= new FormBody.Builder()
.add("sample", dummyText)
.build();
// while building request
// we give our form
// as a parameter to post()
Request request = new Request.Builder().url("http://192.168.0.113:5000/debug")
.post(formbody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(
@NotNull Call call,
@NotNull IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "server down", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.body().string().equals("received")) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "data recieved", Toast.LENGTH_SHORT).show();
}
});
}
}
});
}
});
}
}
运行Python脚本
运行Python脚本,服务器将被托管。
步骤 5:使用 activity_main.xml 文件
- 创建一个约束布局。
- 将 ID 为“pagename”的 TextView 添加到约束布局以显示来自服务器的响应
- 因此,将以下代码添加到 android studio 的activity_main.xml文件中。
XML
第 6 步:使用MainActivity。 Java文件
转到主活动。 Java文件,参考如下代码。首先,我们需要一个 OkHttp Client 来发起请求
OkHttpClient okhttpclient = new OkHttpClient();
接下来,使用服务器的 URL 创建一个请求。在我们的例子中,它是“http://192.168.0.113:5000/”。注意 URL 末尾的“/”,我们正在发送对主页的请求。
Request request = new Request.Builder().url("http://192.168.0.113:5000/").build();
现在,使用上述请求进行调用。完整代码如下。如果服务器关闭或无法访问,将调用 onFailure(),因此我们在 TextView 中显示一个文本,说“服务器关闭”。如果请求成功,将调用 onResponse()。我们可以使用我们在 onResponse() 中收到的 Response 参数访问响应
// to access the response we get from the server
response.body().string;
下面是MainActivity的代码。 Java文件。代码中添加了注释以更详细地理解代码。
Java
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
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 {
// declare attribute for textview
private TextView pagenameTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pagenameTextView = findViewById(R.id.pagename);
// creating a client
OkHttpClient okHttpClient = new OkHttpClient();
// building a request
Request request = new Request.Builder().url("http://192.168.0.113:5000/").build();
// making call asynchronously
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
// called if server is unreachable
public void onFailure(@NotNull Call call, @NotNull IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "server down", Toast.LENGTH_SHORT).show();
pagenameTextView.setText("error connecting to the server");
}
});
}
@Override
// called if we get a
// response from the server
public void onResponse(
@NotNull Call call,
@NotNull Response response)
throws IOException {pagenameTextView.setText(response.body().string());
}
});
}
}
Note:
- Make sure the Android Application runs on a device that is connected to the same network as the system which hosted the server. (if the flask server is running on a machine that is connected to ‘ABC’ WIFI, we need to connect our android device to the same ‘ABC’ network)
- If the Application is failing to connect to the server, make sure your firewall allows connections on port 5000. If not, create an inbound rule in firewall advanced settings.
输出:
第 7 步:检查在Python编辑器中发出的请求
如果发出请求,我们可以看到发出请求的设备的 IP 地址、发出请求的时间和请求类型(在我们的例子中请求类型是 GET)。
POST 请求
我们可以使用 okhttp 客户端通过服务器发送数据。将以下行添加到导入语句
from flask import request
我们需要将路由的方法设置为 POST。让我们添加一个方法并将路由关联到它。该方法将我们在android应用程序中输入的文本打印到pycharm中的控制台。在showHomePage()方法之后添加以下几行。
@app.route("/debug", methods=["POST"])
def debug():
text = request.form["sample"]
print(text)
return "received"
完整的脚本如下
Python
from flask import Flask
# import request
from flask import request
app = Flask(__name__)
@app.route("/")
def showHomePage():
return "This is home page"
@app.route("/debug", methods=["POST"])
def debug():
text = request.form["sample"]
print(text)
return "received"
if __name__ == "__main__":
app.run(host="0.0.0.0")
创建一个虚拟活动。 Android Studio 中的Java 。一旦我们从服务器的showHomePage()方法得到响应,这个活动就会开始。在MainActivity 的onResponse() 回调中添加以下行。Java。
Intent intent = new Intent(MainActivity.this, DummyActivity.class);
startActivity(intent);
finish();
步骤 1:使用 activity_dummy.xml 文件
- 添加一个 ID 为 dummy_text 的 EditText。
- 添加一个带有 id dummy_send 和文本“send”的按钮。
XML
第 2 步:使用 DummyActivity。 Java文件
- 我们使用表单通过 OkHTTP 客户端发送数据。
- 在构建我们的请求时,我们将此表单作为参数传递给 post()。
- 添加一个 onClickListener() 以发出 POST 请求。
- 如果数据被发送,并且我们得到了响应,我们会显示一个 toast 确认数据已被接收。
下面是DummyActivity的代码。 Java文件。代码中添加了注释以更详细地理解代码。
Java
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class DummyActivity extends AppCompatActivity {
private EditText editText;
private Button button;
private OkHttpClient okHttpClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dummy);
editText = findViewById(R.id.dummy_text);
button = findViewById(R.id.dummy_send);
okHttpClient = new OkHttpClient();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String dummyText = editText.getText().toString();
// we add the information we want to send in
// a form. each string we want to send should
// have a name. in our case we sent the
// dummyText with a name 'sample'
RequestBody formbody
= new FormBody.Builder()
.add("sample", dummyText)
.build();
// while building request
// we give our form
// as a parameter to post()
Request request = new Request.Builder().url("http://192.168.0.113:5000/debug")
.post(formbody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(
@NotNull Call call,
@NotNull IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "server down", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.body().string().equals("received")) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "data recieved", Toast.LENGTH_SHORT).show();
}
});
}
}
});
}
});
}
}
输出:
检查 Flask 控制台
在这里我们可以看到 android 应用程序发出了一个 POST 请求。我们甚至可以看到我们通过服务器发送的数据