我有一个与wifi-direct一起使用的聊天应用程序。两个移动设备正确连接Wifi-Direct。
客户端设备正确地向服务器设备发送文本消息。 问题是服务器设备尝试向客户端设备发送文本。
仅当两个设备同时按下发送按钮时,服务器的消息才会显示在客户端设备中。这是因为只有当按下发送按钮时,才会启动服务器或客户端类的实例,并调用套接字的read
功能。
有谁能告诉我哪里错了?
我应该如何异步接收消息,我的意思是每当其他设备按下发送按钮时。
这是MainActivity
:
public class MainActivity extends AppCompatActivity {
Button startButton;
TextView devicesList;
ListView listView;
static TextView msg;
Intent chatPage;
boolean serverOrClient;
private final IntentFilter intentFilter = new IntentFilter();
WifiP2pManager mManager;
WifiP2pManager.Channel mChannel;
BroadcastReceiver mReceiver;
IntentFilter mIntentFilter;
public static ArrayList<WifiP2pDevice> peers = new ArrayList<>();
private WifiP2pDeviceAdapter adapter;
private ArrayAdapter myAdapter;
ArrayList<String> deviceNames;
public void showMsg (String message){
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startButton = (Button) findViewById(R.id.startButton);
listView = (ListView) findViewById(R.id.listitem);
//msg = (TextView) findViewById(R.id.msg);
initFilter();
//adapter = new WifiP2pDeviceAdapter(this,peers);
//listView.setAdapter(adapter);
deviceNames = new ArrayList<>();
for(int i = 0 ; i < peers.size() ; i++){
deviceNames.add(peers.get(i).deviceName.toString());
}
myAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, deviceNames );
listView.setAdapter(myAdapter);
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
int position = i; //Integer.parseInt(v.getTag().toString());
WifiP2pDevice device = peers.get(position);
switch (device.status){
case WifiP2pDevice.AVAILABLE:
case WifiP2pDevice.CONNECTED:
case WifiP2pDevice.INVITED:
connect(device);
break;
case WifiP2pDevice.FAILED:
case WifiP2pDevice.UNAVAILABLE:
Toast.makeText(getApplicationContext(), String.format(Locale.getDefault(),"status=%d",device.status),Toast.LENGTH_SHORT).show();
break;
}
}
});
}
private void initFilter() {
// Indicates a change in the Wi-Fi P2P status.
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
// Indicates a change in the list of available peers.
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
// Indicates the state of Wi-Fi P2P connectivity has changed.
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
// Indicates this device's details have changed.
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
}
/* register the broadcast receiver with the intent values to be matched */
@Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, intentFilter);
discoverPeers();
}
/* unregister the broadcast receiver */
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
stopPeerDiscovery();
}
private void discoverPeers(){
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.e("discover","onSuccess");
}
@Override
public void onFailure(int reason) {
}
});
}
private void stopPeerDiscovery(){
mManager.stopPeerDiscovery(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
showMsg("stopPeerDiscovery: onSuccess");
Log.e("stopPeerDiscovery","onSuccess");
}
@Override
public void onFailure(int reason) {
switch (reason){
case WifiP2pManager.ERROR:
Log.e("stopPeerDiscovery","ERROR");
break;
case WifiP2pManager.P2P_UNSUPPORTED:
Log.e("stopPeerDiscovery","P2P_UNSUPPORTED");
break;
case WifiP2pManager.BUSY:
Log.e("stopPeerDiscovery","BUSY");
break;
case WifiP2pManager.NO_SERVICE_REQUESTS:
Log.e("stopPeerDiscovery","NO_SERVICE_REQUESTS");
break;
}
}
});
}
public void connect(final WifiP2pDevice device) {
// Picking the selected device found on the network.
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
Log.i("deviceAddress connect", String.valueOf(device.deviceAddress));
mManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.e("connect","onSuccess");
showMsg("connected.");
}
@Override
public void onFailure(int reason) {
switch (reason){
case WifiP2pManager.ERROR:
Log.e("connect","ERROR");
break;
case WifiP2pManager.P2P_UNSUPPORTED:
Log.e("connect","P2P_UNSUPPORTED");
break;
case WifiP2pManager.BUSY:
Log.e("connect","BUSY");
break;
case WifiP2pManager.NO_SERVICE_REQUESTS:
Log.e("connect","NO_SERVICE_REQUESTS");
break;
}
}
});
}
public void openChat(WifiP2pInfo wifiP2pInfo, boolean serverOrClient){ //false for client and vice versa
Log.i("wifiP2pinfo MActivity", String.valueOf(wifiP2pInfo));
//serverOrClient = false;
chatPage = new Intent(getApplicationContext(), Chat.class).putExtra("serverOrClient",serverOrClient);
chatPage.putExtra("WifiP2pInfo",wifiP2pInfo);
startActivity(chatPage);
}
public void search(View v) {
onResume();
Log.e("peers",peers.toString());
for(int i = 0 ; i < peers.size() ; i++){
deviceNames.add(peers.get(i).deviceName.toString());
}
myAdapter.notifyDataSetChanged();
}
}
服务器类:
public class Server extends Thread {
InetAddress address;
public static int PORT = 1234;
String msgToSend;
public Server(InetAddress groupOwnerAddress){
address = groupOwnerAddress;
}
@Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(PORT,5,address);
Socket socket = null;
while (true){
socket = serverSocket.accept();
System.out.println("Add connection:"+socket.getInetAddress()+":"+socket.getPort());
new HandlerThread(socket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class HandlerThread implements Runnable {
private Socket socket;
public HandlerThread(Socket client) {
socket = client;
new Thread(this).start();
}
public void run() {
Log.i("in ane doros shod",Chat.msgToSend );
try {
// Read client data
DataInputStream input = new DataInputStream(socket.getInputStream());
//This should pay attention to the write method of the client output stream,
// otherwise it will throw EOFException
String clientInputStr = input.readUTF();
// Processing client data
System.out.println("Client sent over the content:" + clientInputStr);
Chat.updateMessagesfromClient(clientInputStr);
// Reply to the client
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
msgToSend = Chat.getMsgToSend();
if( msgToSend != null) {
out.writeUTF(msgToSend);
Chat.updateMessagesfromServer(msgToSend);
}
msgToSend = "";
input.close();
} catch (Exception e) {
System.out.println("server run abnormal: " + e.getMessage());
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception e) {
socket = null;
System.out.println("server finally abnormal:" + e.getMessage());
}
}
}
}
}
}
客户类:
public class Client extends Thread {
InetAddress address;
String msgToSend;
public Client(InetAddress address){
this.address = address;
}
@Override
public void run() {
communication();
}
private void communication(){
Socket socket = null;
try {
//Create a stream socket and connect it to the
//specified port number on the specified host
socket = new Socket(address, Server.PORT);
//Read server data
DataInputStream input = new DataInputStream(socket.getInputStream());
//Send data to the server
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
msgToSend = Chat.getMsgToSend();
if(msgToSend != null ) {
out.writeUTF(msgToSend);
Chat.updateMessagesfromClient(msgToSend);
}
msgToSend = null;
String ret = input.readUTF();
Log.i("server returns: " , ret);
Log.i("in ane doros shod",Chat.msgToSend );
Chat.updateMessagesfromServer(ret);
input.close();
} catch (Exception e) {
System.out.println("Client exception:" + e.getMessage());
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
socket = null;
System.out.println("Clients finally abnormal:" + e.getMessage());
}
}
}
}
}
和启动客户端或服务器的聊天类obj:
public class Chat extends AppCompatActivity {
TextView otherDevicename;
Button sendBbutton;
EditText textTosend;
static String msgToSend;
Server server;
Client client;
InetAddress mygroupOwnerAddress;
boolean serverOrClient;
WifiP2pInfo wifiP2pInfo;
public static ArrayList<String> msg_content = new ArrayList<>();
public static ListView messages;
public static ArrayAdapter msg_adapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_page);
serverOrClient = getIntent().getBooleanExtra("serverOrClient",true);
wifiP2pInfo = getIntent().getExtras().getParcelable("WifiP2pInfo");
Log.i("WPI chat" , wifiP2pInfo.toString() );
if(wifiP2pInfo != null) {
setSender(wifiP2pInfo, serverOrClient);
}
sendBbutton = (Button) findViewById(R.id.sendButton);
textTosend = (EditText) findViewById(R.id.textToSend);
messages = (ListView) findViewById(R.id.messages);
msg_adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, msg_content );
msg_content.add("The chat goes Below...");
messages.setAdapter(msg_adapter);
otherDevicename = (TextView) findViewById(R.id.otherDeviceName);
otherDevicename.setText("this is a new chat");
msgToSend = "thisShitIsNull";
}
public void showMsg(String message){ Toast.makeText(this, message, Toast.LENGTH_LONG).show(); }
public static String getMsgToSend() {
return msgToSend;
}
public void fuckingSend(View view){
EditText textTosend2 = (EditText) findViewById(R.id.textToSend);
if(String.valueOf(textTosend2.getText()) != null){
msgToSend = String.valueOf(textTosend2.getText());
showMsg(msgToSend+" from Fucking Send.");
if(serverOrClient == true){ // for server
updateMessagesfromServer("");
server = new Server( wifiP2pInfo.groupOwnerAddress );
server.start();
}else{ // for client
updateMessagesfromClient("");
client = new Client( wifiP2pInfo.groupOwnerAddress );
client.start();
}
}
Log.i("msg to send:",msgToSend);
}
private void setSender(WifiP2pInfo wifiP2pInfo, boolean serverOrClient) {
mygroupOwnerAddress = wifiP2pInfo.groupOwnerAddress;
if (wifiP2pInfo.groupFormed && wifiP2pInfo.isGroupOwner && serverOrClient == true) {
// Do whatever tasks are specific to the group owner.
// One common case is creating a server thread and accepting
// incoming connections.
server = new Server(mygroupOwnerAddress);
server.start();
showMsg("server created.");
} else if (wifiP2pInfo.groupFormed && serverOrClient == false) {
// The other device acts as the client. In this case,
// you'll want to create a client thread that connects to the group
// owner.
client = new Client(mygroupOwnerAddress);
client.start();
showMsg("client created");
}
}
static void updateMessagesfromServer(String msgs){
if(msgs != null){
msg_adapter.notifyDataSetChanged();
}
}
public static void updateMessagesfromClient(String ret) {
if(ret != null){
msg_adapter.notifyDataSetChanged();
}
}
}
这是github上的项目链接:link