Android WiFi通信可发送数据但无法接收Handler响应问题求助
Android WiFi TCP通信接收无响应问题(Handler未被调用)
我正在开发一款实现Android与WiFi设备通信的App,目前数据发送正常,但无法接收设备响应,核心原因是负责接收的Handler从未被调用。
Wifi终端页面代码(wifi_terminal类)
public class wifi_terminal extends AppCompatActivity { ListView logListView; private static ChatAdapter adapter; private ArrayList<ChatMessage> chatHistory; Button sendButton; EditText editText; TCPConversation wifiCommn; byte[] resbyts; String response; boolean aBoolean =false; boolean isInDiagstate =false; boolean stopLiveParams =false; private Context context; private final String TAG = "WIFI Terminal Activity"; Timer timer; WifiSemaphoreService wifiSemaphoreService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wifi_terminal); init(); } @Override public void onBackPressed() { super.onBackPressed(); finish(); } private void init(){ context = wifi_terminal.this; wifiSemaphoreService = new WifiSemaphoreService(); wifiCommn = Singletone.getTcpConversation(); wifiCommn.AssignHandler(mhandler); TCPConversation.responseCase =1; logListView= findViewById(R.id.loglistView); logListView.setItemsCanFocus(true); logListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); loadDummyHistory(); sendButton = findViewById(R.id.sendTextid); editText= findViewById(R.id.editTextid); sendButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(wifiCommn!=null && !wifiCommn.CheckConnection()) { String message=editText.getText().toString(); if(!message.equals("")) { message=message+"\r\n"; final String finalMessage = message; Thread thread = new Thread(new Runnable() { @Override public void run() { wifiCommn.responseCase =1; wifiCommn.Send(finalMessage.getBytes()); final String finalMessage1 = finalMessage.replace("\r\n","").toString(); PrintConv( finalMessage1,true); runOnUiThread(new Runnable() { @Override public void run() { editText.setText(""); } }); } }); thread.start(); } else { Toast.makeText(context, "Enter some command!", Toast.LENGTH_SHORT).show(); } } else { PrintConv( "SOCKET CONN LOST",true); Toast.makeText(wifi_terminal.this, "SOCKET CONN LOST", Toast.LENGTH_SHORT).show(); } } }); } Handler mhandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message message) { switch(message.what) { case 11: resbyts = (byte[]) message.obj; response= new String(resbyts); if(response.length()>0){ response = response.replace("\r\n","").toString(); aBoolean =true; PrintConv(response,false); } else{ PrintConv("No Response",false); } break; case 22: String responseString=(String) message.obj; if(wifiCommn!=null && wifiCommn.CheckConnection()) { wifiCommn.TerminateConnection(); PrintConv("CONNECTION LOST",false); } Toast.makeText(context, responseString, Toast.LENGTH_SHORT).show(); finish(); break; } return true; } }); public void displayMessage(ChatMessage message) { adapter.add(message); adapter.notifyDataSetChanged(); scroll(); } private void scroll() { logListView.setSelection(logListView.getCount() - 1); } private void loadDummyHistory() { chatHistory = new ArrayList<>(); ChatMessage msg = new ChatMessage(); msg.setId(1); msg.setMe(false); msg.setDate(DateFormat.getDateTimeInstance().format(new Date())); chatHistory.add(msg); adapter = new ChatAdapter(wifi_terminal.this, new ArrayList<ChatMessage>()); logListView.setAdapter(adapter); } public void PrintConv(final String msg, final boolean val) { runOnUiThread(new Runnable() { @Override public void run() { ChatMessage chatMessage = new ChatMessage(); chatMessage.setId(11);//dummy chatMessage.setMessage(msg); chatMessage.setDate(DateFormat.getDateTimeInstance().format(new Date())); chatMessage.setMe(val); displayMessage(chatMessage); } }); } }
WiFi通信核心类(WifiComm类)
public class WifiComm { private Socket socket; Handler handler; private boolean minusOne =false; public static int responseCase; private int counter; private Timer timer; ArrayList<Integer> arr_byte = new ArrayList<Integer>(); static ArrayList<Byte> readMessage2 = new ArrayList<>(); public WifiComm(Socket socket1) { socket = socket1; Receiving recievingThread = new Receiving(socket); recievingThread.start(); } public void AssignHandler(Handler mhandler) { handler = mhandler; } static byte[] tempBuffer = new byte[2048]; public class Receiving extends Thread { private Receiving(Socket socket1) { socket =socket1; } @Override public void run() { boolean recieveData =false; ArrayList<Byte> readMessage1 = new ArrayList<>(); StringBuilder readMessage2 = new StringBuilder(); ArrayList<Byte> readMessage3 = new ArrayList<>(); minusOne =false; tempBuffer = new byte[2048]; while (true) { try { int size=0; size = socket.getInputStream().read(tempBuffer); // Log.e("E",new String(tempBuffer)); // Log.e("Socket res:",new String(tempBuffer)); switch (responseCase) { case 1:/*Checks response until "\n" comes*/ //readMessage1 = new StringBuilder(); String read = new String(tempBuffer,0,size); for (int i = 0; i < size; i++) { if (tempBuffer[i] == ':') { recieveData = true; readMessage1.add(tempBuffer[i]); } else if (tempBuffer[i] == '\n') { readMessage1.add(tempBuffer[i]); byte[] tempByte = new byte[readMessage1.size()]; for (int j = 0; j < readMessage1.size(); j++) { tempByte[j] = readMessage1.get(j); } Log.e("BC1",readMessage1.toString()); readMessage1 = new ArrayList<>(); handler.obtainMessage(11, tempByte).sendToTarget(); // CollectLogData(" RX :"+new String(tempByte)); recieveData = false; tempBuffer = new byte[2048]; } else { if (recieveData) { readMessage1.add(tempBuffer[i]); } } } break; case 2:/*Checks response until "#" comes*/ String read2 = new String(tempBuffer); Log.e("BC2",read2); for(int i=0; i<tempBuffer.length; i++) { switch (read2.charAt(i)) { case '\n': readMessage2.append(read2.charAt(i)); tempBuffer = new byte[2048]; byte[] temp2 =readMessage2.toString().getBytes(); handler.obtainMessage(11, temp2).sendToTarget(); //Log.e("BC n :",readMessage2.toString()); readMessage2 = new StringBuilder(); break; default: readMessage2.append(read2.charAt(i)); break; } } break; case 3: try { Log.e("BC Res :",new String(tempBuffer)); for(int i=0 ; i<size ; i++) { if(size>=2 && tempBuffer[i] == 4 && tempBuffer[i-1]!=5) { readMessage3.add(tempBuffer[i]); byte[] tempByte = new byte[readMessage3.size()]; for(int j=0;j<readMessage3.size();j++) { tempByte[j] = readMessage3.get(j); } handler.obtainMessage(11, tempByte).sendToTarget(); Log.e("BC ResBytes STN:",new String(tempBuffer)); readMessage3.clear(); readMessage3 = new ArrayList<>(); tempBuffer = new byte[8094]; } else { readMessage3.add(tempBuffer[i]); } } } catch (Exception e) { // CollectLogData(" excp @ STN hanlder :"+e.getMessage()); e.printStackTrace(); } break; } } catch (IOException e) { minusOne=true; handler.obtainMessage(22, "Socket Connection Lost!").sendToTarget(); e.printStackTrace(); break; } } } } public static void clearBuffer() { readMessage2 = new ArrayList<>(); } public void Send(final byte[] bite) { final byte[] msg; msg=bite; Thread t = new Thread(new Runnable() { @Override public void run() { try { socket.getOutputStream().write(msg); Log.e("BlueComm SENT ",new String(msg)); } catch (IOException e) { e.printStackTrace(); } } }); t.start(); } public void TerminateConnection() { if(socket.isConnected()) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } public boolean CheckConnection() { /*Something made socket disconnected*/ return minusOne; } }
问题排查与修复建议
1. Handler赋值时机错误
WifiComm构造函数中直接启动了接收线程,但此时Handler还未通过AssignHandler方法赋值,导致接收线程中handler为null,无法发送消息。
修复:将接收线程的启动逻辑从构造函数中分离,改为手动调用:
// WifiComm类修改 public WifiComm(Socket socket1) { socket = socket1; } public void startReceiving() { Receiving recievingThread = new Receiving(socket); recievingThread.start(); } // wifi_terminal的init方法修改 wifiCommn = Singletone.getTcpConversation(); wifiCommn.AssignHandler(mhandler); WifiComm.responseCase = 1; // 修正类名错误(原代码写的是TCPConversation) wifiCommn.startReceiving(); // 先赋值Handler再启动线程
2. responseCase类名不匹配
原代码中设置的是TCPConversation.responseCase=1,但实际接收线程使用的是WifiComm.responseCase,导致switch分支未进入预期的case 1。
修复:统一改为WifiComm.responseCase=1。
3. 数据接收触发条件限制过严
case 1的逻辑要求必须先接收到:才开始收集数据,直到\n才发送消息。如果设备响应中没有:,则永远不会触发Handler消息。
修复:根据实际设备响应格式调整逻辑,比如直接收集所有字节直到换行:
case 1:/*Checks response until "\n" comes*/ String read = new String(tempBuffer,0,size); for (int i = 0; i < size; i++) { if (tempBuffer[i] == '\n') { readMessage1.add(tempBuffer[i]); byte[] tempByte = new byte[readMessage1.size()]; for (int j = 0; j < readMessage1.size(); j++) { tempByte[j] = readMessage1.get(j); } Log.e("BC1", new String(tempByte)); readMessage1.clear(); if (handler != null) { // 增加空判断避免NPE handler.obtainMessage(11, tempByte).sendToTarget(); } tempBuffer = new byte[2048]; } else { readMessage1.add(tempBuffer[i]); // 直接收集所有字节 } } break;
4. 增加调试日志
在接收线程读取到数据后,添加日志确认是否真的接收到设备响应:
size = socket.getInputStream().read(tempBuffer); Log.e("Receiving", "Received " + size + " bytes: " + new String(tempBuffer, 0, size));
内容的提问来源于stack exchange,提问作者HarmanPreet Singh
相关产品推荐
相关产品推荐

