为何Python Flask-SocketIO服务对接JS正常,Android Studio连接失败
问题原因及修复方案
核心问题列表
- 连接地址错误:Android端填写的
127.0.0.1是安卓设备/模拟器自身的回环地址,而非运行Python服务的主机地址。如果使用安卓模拟器,替换为10.0.2.2即可映射到主机回环地址;如果是真机连同一局域网,替换为电脑的局域网IP(比如192.168.x.x格式)。 - 版本不兼容:你JavaScript端用的是Socket.IO 4.x版本,需要保证Android端的Socket.IO客户端版本匹配,必须使用
2.x版本的安卓客户端(对应服务端Socket.IO 4.x),在模块级build.gradle中添加依赖:
implementation 'io.socket:socket.io-client:2.1.0'
- 未监听连接成功事件就发消息:
mSocket.connect()是异步操作,你调用完直接emit消息时连接还未建立,消息自然发不出去。需要和JS端逻辑一致,等connect事件触发后再发送数据。 - 发送数据格式错误:安卓端你拼接的是JSON字符串,服务端期望接收的是JSON对象,需要用
JSONObject封装参数,而不是传递字符串。 - 缺少网络权限配置:安卓默认禁止普通应用访问网络,且高版本系统默认禁止明文HTTP请求,需要在
AndroidManifest.xml中添加对应配置。
修正后的代码
AndroidManifest.xml 权限配置
<!-- 加在manifest标签下,application标签外 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 给application标签添加属性,允许明文HTTP请求 --> <application ... android:usesCleartextTraffic="true" ...>
修正后的Android主页面代码
public class MainActivity extends AppCompatActivity { private Socket mSocket; { try { // 注意这里地址替换为正确的主机地址 mSocket = IO.socket("http://10.0.2.2:420"); } catch (URISyntaxException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 监听连接成功事件后再发消息 mSocket.on(Socket.EVENT_CONNECT, args -> { String mUsername = "FatCat"; String message = "Hallo"; try { JSONObject data = new JSONObject(); data.put("username", mUsername); data.put("message", message); mSocket.emit("new_message", data); } catch (JSONException e) { e.printStackTrace(); } }); // 可选:监听连接错误事件方便排查问题 mSocket.on(Socket.EVENT_CONNECT_ERROR, args -> { for (Object arg : args) { Log.e("SOCKET_ERROR", arg.toString()); } }); mSocket.connect(); } @Override public void onDestroy() { super.onDestroy(); mSocket.disconnect(); mSocket.off(); } }
Python端冗余代码优化(可选)
你当前Python端重复注册了两次new_message事件,删掉其中一个即可,同时添加配置允许局域网访问:
app = Flask(__name__) app.config["SECRET_KEY"] = "key" # 解决跨域问题 socketio = SocketIO(app, cors_allowed_origins="*") @app.route("/") def index(): return render_template("x.html") @socketio.event def connect(): print("connected") @socketio.event def new_message(data): print({"username": data["username"], "message": data["message"]}) socketio.emit("new_message", {"username": data["username"], "message": data["message"]}) @socketio.event def disconnect(): print("disconnected") if __name__ == "__main__": # host设为0.0.0.0允许局域网其他设备访问 socketio.run(app, host="0.0.0.0", port=420, debug=True)
内容的提问来源于stack exchange,提问作者Yaquite
相关产品推荐
相关产品推荐

