Django Channels 不向 Android App 发送消息
Posted
技术标签:
【中文标题】Django Channels 不向 Android App 发送消息【英文标题】:Django Channels dont sent message to Android App 【发布时间】:2019-07-25 11:23:03 【问题描述】:我想将https://channels.readthedocs.io/en/latest/tutorial/part_2.html 的官方 django 频道教程应用到一个简单的 android 应用程序中。
在https://medium.com/@ssaurel/learn-to-use-websockets-on-android-with-okhttp-ba5f00aea988,我找到了一个简单的项目,但它使用http://www.websocket.org/echo.html 提供的Echo WebSocket 服务器。
我复制粘贴了同一个项目,但使用 django 通道将 Echo WebSocket 服务器替换为我自己的 websocket 服务器。
代码如下:
public class MainActivity extends AppCompatActivity
private static final String TAG = "MainActivity";
private Button start;
private TextView output;
private OkHttpClient client;
private final class EchoWebSocketListener extends WebSocketListener
private static final int NORMAL_CLOSURE_STATUS = 1000;
@Override
public void onOpen(WebSocket webSocket, Response response)
Log.d(TAG, "onOpen() is called.");
JSONObject obj = new JSONObject();
JSONObject obj2 = new JSONObject();
try
obj.put("message" , "Hello");
obj2.put("message", "Goodbye!");
catch (JSONException e)
e.printStackTrace();
webSocket.send(obj.toString());
//webSocket.send("What's up ?");
//webSocket.send(ByteString.decodeHex("deadbeef"));
webSocket.close(NORMAL_CLOSURE_STATUS, obj2.toString());
@Override
public void onMessage(WebSocket webSocket, String text)
Log.d(TAG, "onMessage() for String is called.");
output("Receiving : " + text);
@Override
public void onMessage(WebSocket webSocket, ByteString bytes)
Log.d(TAG, "onMessage() for ByteString is called.");
output("Receiving bytes : " + bytes.hex());
@Override
public void onClosing(WebSocket webSocket, int code, String reason)
Log.d(TAG, "onClosing() is called.");
webSocket.close(NORMAL_CLOSURE_STATUS, null);
output("Closing : " + code + " / " + reason);
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response)
Log.d(TAG, "onFailure() is called.");
output("Error : " + t.getMessage());
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.start);
output = (TextView) findViewById(R.id.output);
client = new OkHttpClient();
start.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
start();
);
void start()
Request request = new Request.Builder().url("ws://192.168.122.1:8080/ws/chat/lobby/").build();
EchoWebSocketListener listener = new EchoWebSocketListener();
WebSocket ws = client.newWebSocket(request, listener);
client.dispatcher().executorService().shutdown();
private void output(final String txt)
runOnUiThread(new Runnable()
@Override
public void run()
output.setText(output.getText().toString() + "\n\n" + txt);
);
要向/从服务器发送和接收消息,他们使用 okhttp3 库中的 WebSocketListener。
我的consumers.py
文件与 Django 频道教程中的相同。更具体地说,我使用了相同的设置。
尽管如此,为了在同一页面上,我发布了我的 consumers.py
文件的样子:
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
import json
class SignallingConsumer(WebsocketConsumer):
def connect(self):
print("connect() is called.")
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# Join room group
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name
)
self.accept()
def disconnect(self, close_code):
print("disconnect() is called.")
# Leave room group
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
def receive(self, text_data):
print("receive() is called with " + text_data)
text_data_json = json.loads(text_data)
message = text_data_json['message']
print("message contains: " + message)
# Send message to room group
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
'type': 'chat_message',
'message': message
)
# Receive message from room group
def chat_message(self, event):
print("the message from the event is: " + event['message'])
message = event['message']
# Send message to WebSocket
self.send(text_data=json.dumps(
'message': message
))
我添加了一些打印内容以更好地了解幕后情况,并更改了消费者的名称,因为我想稍后在了解基础知识后将其用作另一个项目的信号服务器。
在控制台上,我得到以下信息:
System check identified no issues (0 silenced).
July 25, 2019 - 10:34:24
Django version 2.2.3, using settings 'signalingserver.settings'
Starting ASGI/Channels version 2.2.0 development server at http://192.168.122.1:8080/
Quit the server with CONTROL-C.
WebSocket HANDSHAKING /ws/chat/lobby/ [192.168.122.1:54194]
connect() is called.
WebSocket CONNECT /ws/chat/lobby/ [192.168.122.1:54194]
receive() is called with "message":"Hello"
message contains: Hello
WebSocket DISCONNECT /ws/chat/lobby/ [192.168.122.1:54194]
the message from the event is: Hello
disconnect() is called.
我的 LogCat 输出如下:
07-25 12:35:22.754 5297-5319/com.celik.abdullah.simplewebsocketproject D/MainActivity: onOpen() is called.
07-25 12:35:22.810 5297-5319/com.celik.abdullah.simplewebsocketproject D/MainActivity: onClosing() is called.
从这些输出中,我假设连接和发送部分正在运行。但是从 websocket 服务器接收数据不起作用,因为我的客户端(android 应用程序)上的 onMessage()
没有被调用。
如何解决?
提前谢谢你。
【问题讨论】:
【参考方案1】:如果其他人看到这一点,问题是因为您在有机会从服务器接收任何返回之前关闭了 onOpen 方法中的 Web 套接字。您应该删除该行:
webSocket.close(NORMAL_CLOSURE_STATUS, obj2.toString());
当您不再使用网络套接字连接时,稍后调用 close。
其他一切看起来都很棒,并且按原样工作。
【讨论】:
以上是关于Django Channels 不向 Android App 发送消息的主要内容,如果未能解决你的问题,请参考以下文章
django 频道 channels.exceptions.Channels Full
Django Channels 是不是使用 ws:// 协议前缀在 Django 视图或 Channels 应用程序之间进行路由?
Django使用Channels实现WebSocket--下篇