You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

机器学习方言检测模型转Android应用的连接与闪退问题排查

方言检测Android应用连接Flask后端问题排查与解决

问题描述

开发方言检测Android应用时,Flask后端模型通过Postman测试可正常返回预测结果,但Android端调用始终出现**java.net.ConnectException: Failed to connect to /127.0.0.*:**连接异常。尝试刷新DNS、指定端口、关闭防火墙等方法无效;将Android端URL替换为电脑IPv4地址后,连接错误消失,但应用在模拟器中直接闪退(设备配置16GB RAM,排除性能问题)。

代码片段

Android端MainActivity代码

public class MainActivity extends AppCompatActivity {

    EditText inputuser;
    Button detectnow;
    TextView result;
    String url = "http://127.0.0.1:8080/predict";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);

        inputuser = findViewById(R.id.input);
        detectnow = findViewById(R.id.translate);
        result = findViewById(R.id.result);

        detectnow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Get the user input text
                String userInput = inputuser.getText().toString();

                // Create JSON object with the user input
                JSONObject jsonBody = new JSONObject();
                try {
                    jsonBody.put("text", userInput);
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                // Create a request queue
                RequestQueue queue = Volley.newRequestQueue(MainActivity.this);

                // Create a JSON object request
                JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, jsonBody,
                        new Response.Listener<JSONObject>() {
                            @Override
                            public void onResponse(JSONObject response) {
                                try {
                                    // Get the predicted dialect from the response
                                    String predictedDialect = response.getString("predicted_dialect");

                                    // Set the predicted dialect to the result TextView
                                    result.setText("Predicted Dialect: " + predictedDialect);
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                            }
                        },
                        new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                // Handle errors
                                Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
                            }
                        });

                // Add the request to the request queue
                queue.add(jsonObjectRequest);
            }
        });
    }
}

Flask后端代码

from flask import Flask, request, jsonify
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.preprocessing import LabelEncoder

app = Flask(__name__)

# Load the dataset and preprocess it
df_dialect = pd.read_csv("dialect_list_balance.csv").dropna()
le = LabelEncoder()
vectorizer = CountVectorizer()
bag = vectorizer.fit_transform(df_dialect['sentence'])
features = bag.toarray()
vocab = vectorizer.get_feature_names_out()
df_bow = pd.DataFrame(features, columns=vocab)
df_bow['dialect_class'] = le.fit_transform(df_dialect['dialect'])

# Train the model
X = df_bow.iloc[:, :-1]
y = df_bow['dialect_class']
gb_clf = GradientBoostingClassifier()
gb_clf.fit(X, y)


@app.route('/predict', methods=['POST'])
def predict():
    # Get the input text from the request body
    input_text = request.json.get('text')

    # Preprocess the input text
    input_bag = vectorizer.transform([input_text])
    input_features = input_bag.toarray()

    # Predict the dialect of the input text
    prediction = gb_clf.predict(input_features)

    # Decode the predicted label to dialect class
    predicted_dialect = le.inverse_transform(prediction)[0]

    # Return the predicted dialect as a JSON response
    return jsonify({"predicted_dialect": predicted_dialect})


if __name__ == '__main__':
    app.run(debug=True, port=8080)

问题分析

  1. 127.0.0.1连接失败原因:Android模拟器中的127.0.0.1指向模拟器自身,而非运行Flask服务的电脑,因此无法建立连接。
  2. 替换IPv4后闪退原因:
    • 缺少网络权限或Android 9+默认禁止明文HTTP请求,导致网络请求触发异常。
    • 未处理空输入,构造JSON时可能抛出未捕获的异常,引发崩溃。
    • 错误处理中error.getMessage()可能为null,导致Toast显示时崩溃。

解决方案

1. 修正后端访问配置

  • 获取电脑的局域网IPv4地址(Windows用ipconfig,Mac/Linux用ip addr)。
  • 修改Flask启动代码,让服务监听所有网卡,允许局域网设备访问:
    if __name__ == '__main__':
        app.run(debug=True, port=8080, host='0.0.0.0')
    
  • 将Android端的url替换为电脑的IPv4地址,例如:
    String url = "http://192.168.1.100:8080/predict";
    

2. 配置Android网络权限与明文HTTP允许

  • 在AndroidManifest.xml中添加网络权限:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
  • 针对Android 9+允许明文HTTP请求(测试环境):
    在<application>标签中添加:
    android:usesCleartextTraffic="true"
    
    (正式环境建议配置HTTPS,或创建network_security_config.xml进行更精细的网络安全配置)

3. 修复Android端代码潜在崩溃点

  • 处理空输入,避免构造JSON时出错:
    detectnow.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String userInput = inputuser.getText().toString().trim();
            if (userInput.isEmpty()) {
                Toast.makeText(MainActivity.this, "请输入文本", Toast.LENGTH_SHORT).show();
                return;
            }
            // 后续JSON构造和请求代码...
        }
    });
    
  • 优化错误处理,避免null消息导致崩溃:
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            String errorMsg = error.getMessage() != null ? error.getMessage() : "请求失败";
            Toast.makeText(MainActivity.this, errorMsg, Toast.LENGTH_SHORT).show();
        }
    }
    

4. 验证网络连通性

  • 确保模拟器与电脑处于同一局域网。
  • 在模拟器浏览器中访问http://你的电脑IPv4:8080/predict,用POST请求测试是否能正常返回结果,确认网络路径通畅。

内容的提问来源于stack exchange,提问作者rahman auf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 01:50:59