我想将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.
从这些输出中,我假定连接和发送部分正在运行。但是,由于未调用客户端(Android应用)上的onMessage()
,因此无法从Websocket服务器接收数据。
如何解决这个问题?
谢谢。
答案 0 :(得分:0)
万一其他人看到了这个问题,那是因为您在有机会从服务器收到任何东西之前关闭了onOpen方法中的Web套接字。您应该删除以下行:
webSocket.close(NORMAL_CLOSURE_STATUS, obj2.toString());
当您不再使用Web套接字连接时,请稍后再关闭。
其他所有内容看起来都很不错,并且可以照原样工作。