.java文件源碼(供參考,請使用前自行作修改):
1 package com.example.hello; 2 3 import java.io.DataInputStream; 4 import java.io.DataOutputStream; 5 import java.io.IOException; 6 import java.net.Socket; 7 import java.util.Timer; 8 import java.util.TimerTask; 9 10 import android.os.Bundle; 11 import android.os.Handler; 12 import android.os.Message; 13 import android.app.Activity; 14 import android.view.KeyEvent; 15 import android.view.Menu; 16 import android.view.View; 17 import android.view.View.OnClickListener; 18 import android.widget.Button; 19 import android.widget.CompoundButton; 20 import android.widget.EditText; 21 import android.widget.ImageView; 22 import android.widget.Switch; 23 import android.widget.TextView; 24 25 public class MainActivity extends Activity { 26 27 private Switch light00,light01,light02; 28 private TextView current_ip,socketstate,notice1; 29 private int[] temperature=new int[1]; 30 private TextView[] tv_temperature=new TextView[temperature.length]; 31 32 private EditText et_ip1,et_ip2,et_ip3,et_ip4,et_port; 33 //private EditText et_deviceID; 34 private Button btn_set_ip,delete_socket,fengmingqi1,jdq_off,jdq_on; 35 private ImageView light_00,light_01,light_02; 36 private ImageView jidianqi1; 37 38 private int port = 8080; 39 private String IP=""; 40 private Socket socket=null; 41 Thread thread1=null,thread2=null; 42 private byte[] tcp_receive_buf=new byte[DataPackage_Length]; 43 private static final int DataPackage_Length=15; //只接收15個字符(數據包長度為15) 44 private DataInputStream dataInputStream=null; 45 private DataOutputStream dataOutputStream=null; 46 47 private static final String deviceID = "03"; //用於串口通信時,定義本地設備ID 48 private static final String datapackage_headflag = "A"; //用於串口通信時,定義數據包頭部的驗證標記 49 50 //----------通信監測----------// 51 private boolean NeedToCheckTCP = false; 52 private boolean heartbeat = false; //心跳包(用來協助監測通信是否斷開) 53 private Timer timer_TCPMonitor=null; 54 55 //----------產生發送數據的間隔----------// 56 private boolean SendCMD_WaitFlag = false; 57 private Timer timer_SetSendCMD_Interval=null; 58 void SetSendCMD_Interval(int Interval) 59 { 60 timer_SetSendCMD_Interval=new Timer(); 61 timer_SetSendCMD_Interval.schedule(new TimerTask() { 62 @Override 63 public void run() { 64 SendCMD_WaitFlag = false; 65 } 66 },Interval,600000); //定時器開始工作 67 } 68 69 //----------定時器控制指令的發送----------// 70 private Timer timer_SendCMD=null; 71 72 //----------------------------通信協議----------------------------// 73 /* 74 客戶端數據包格式解釋(長度恆為15): 75 例如:A01_fmq_01Off___# 76 A--------數據包的開始標記(可以為A到Z,意味着數據包可以有26種) 77 01-----設備代號 78 fmq_01Off___--------指令(長度恆為10),指令的前4個人字符是指令頭部,指令的后6個字符是指令尾部 79 #---------數據包的結束標記 80 81 服務器端數據包格式解釋(長度恆為15): 82 例如:A02_SenT010250# 83 A--------數據包的開始標記(可以為A到Z,意味着數據包可以有26種) 84 02-----設備代號 85 SenT010250--------指令(長度恆為10),指令的前4個人字符是指令頭部,指令的后6個字符是指令尾部 86 #---------數據包的結束標記 87 */ 88 89 //---------------------------------固定發送數據包集------------------------------// 90 private static final String tcp_data_try=datapackage_headflag+deviceID+"_Try!______#"; 91 private static final String tcp_data_SenT00=datapackage_headflag+deviceID+"_SenT00____#"; 92 private static final String tcp_data_fmq00off=datapackage_headflag+deviceID+"_fmq_00Off_#"; 93 private static final String tcp_data_fmq00on=datapackage_headflag+deviceID+"_fmq_00On__#"; 94 private static final String tcp_data_jdq00off=datapackage_headflag+deviceID+"_jdq_00Off_#"; 95 private static final String tcp_data_jdq00on=datapackage_headflag+deviceID+"_jdq_00On__#"; 96 private static final String tcp_data_light00on=datapackage_headflag+deviceID+"_Ligt00On__#"; 97 private static final String tcp_data_light00off=datapackage_headflag+deviceID+"_Ligt00Off_#"; 98 private static final String tcp_data_light01on=datapackage_headflag+deviceID+"_Ligt01On__#"; 99 private static final String tcp_data_light01off=datapackage_headflag+deviceID+"_Ligt01Off_#"; 100 private static final String tcp_data_light02on=datapackage_headflag+deviceID+"_Ligt02On__#"; 101 private static final String tcp_data_light02off=datapackage_headflag+deviceID+"_Ligt02Off_#"; 102 private static final String tcp_data_socketoff=datapackage_headflag+deviceID+"_SockOff__#"; 103 104 private boolean connectflag=false; 105 private boolean openfmq00=false; 106 107 @Override 108 protected void onCreate(Bundle savedInstanceState) { 109 super.onCreate(savedInstanceState); 110 setContentView(R.layout.activity_main); 111 112 current_ip=(TextView)findViewById(R.id.tv_current_ip); 113 socketstate=(TextView)findViewById(R.id.tv_socketstate); 114 notice1=(TextView)findViewById(R.id.tv_notice1); 115 tv_temperature[0]=(TextView)findViewById(R.id.tv_temperature00); 116 et_ip1=(EditText)findViewById(R.id.et_ip1); 117 et_ip2=(EditText)findViewById(R.id.et_ip2); 118 et_ip3=(EditText)findViewById(R.id.et_ip3); 119 et_ip4=(EditText)findViewById(R.id.et_ip4); 120 et_port=(EditText)findViewById(R.id.et_port); 121 //et_deviceID=(EditText)findViewById(R.id.et_deviceID); 122 btn_set_ip=(Button)findViewById(R.id.btn_setip); 123 delete_socket=(Button)findViewById(R.id.btn_deletesocket); 124 fengmingqi1=(Button)findViewById(R.id.btn_fmq1); 125 jdq_off=(Button)findViewById(R.id.btn_jidianqi_off); 126 jdq_on=(Button)findViewById(R.id.btn_jidianqi_on); 127 light00=(Switch)findViewById(R.id.sw_light00); 128 light01=(Switch)findViewById(R.id.sw_light01); 129 light02=(Switch)findViewById(R.id.sw_light02); 130 light_00=(ImageView)findViewById(R.id.image_light00); 131 light_01=(ImageView)findViewById(R.id.image_light01); 132 light_02=(ImageView)findViewById(R.id.image_light02); 133 jidianqi1=(ImageView)findViewById(R.id.image_jidianqi1); 134 135 current_ip.setText("暫無"); 136 137 light00.setTextOff("關閉"); 138 light00.setTextOn("打開"); 139 light01.setTextOff("關閉"); 140 light01.setTextOn("打開"); 141 light02.setTextOff("關閉"); 142 light02.setTextOn("打開"); 143 144 light00.setEnabled(false); 145 light01.setEnabled(false); 146 light02.setEnabled(false); 147 148 //控制light 149 light00.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 150 @Override 151 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 152 light00.setEnabled(false); 153 if(light00.isChecked()){ 154 if(tcp_send_data(tcp_data_light00on,4)){ 155 light_00.setImageDrawable(getResources().getDrawable(R.drawable.open_light)); 156 light00.setEnabled(true); //涉及到UI操作,但此行代碼是主線程執行的,所以不會導致程序崩毀 157 } 158 } 159 else{ 160 if(tcp_send_data(tcp_data_light00off,4)){ 161 light_00.setImageDrawable(getResources().getDrawable(R.drawable.close_light)); 162 light00.setEnabled(true); 163 } 164 } 165 } 166 }); 167 //控制light 168 light01.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 169 @Override 170 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 171 light01.setEnabled(false); 172 if(light01.isChecked()){ 173 if(tcp_send_data(tcp_data_light01on,4)){ 174 light_01.setImageDrawable(getResources().getDrawable(R.drawable.open_light)); 175 light01.setEnabled(true); 176 } 177 } 178 else{ 179 if(tcp_send_data(tcp_data_light01off,4)){ 180 light_01.setImageDrawable(getResources().getDrawable(R.drawable.close_light)); 181 light01.setEnabled(true); 182 } 183 } 184 } 185 }); 186 //控制light 187 light02.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 188 @Override 189 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 190 light02.setEnabled(false); 191 if(light02.isChecked()){ 192 if(tcp_send_data(tcp_data_light02on,4)){ 193 light_02.setImageDrawable(getResources().getDrawable(R.drawable.open_light)); 194 light02.setEnabled(true); 195 } 196 } 197 else{ 198 if(tcp_send_data(tcp_data_light02off,4)){ 199 light_02.setImageDrawable(getResources().getDrawable(R.drawable.close_light)); 200 light02.setEnabled(true); 201 } 202 } 203 } 204 }); 205 //測試蜂鳴器 206 fengmingqi1.setOnClickListener(new OnClickListener() { 207 @Override 208 public void onClick(View arg0) { 209 if(connectflag==true){ 210 if(openfmq00==true){ 211 if(tcp_send_data(tcp_data_fmq00off,3000)){ 212 openfmq00=false; 213 fengmingqi1.setText("啟動蜂鳴器"); 214 } 215 } 216 else{ 217 if(tcp_send_data(tcp_data_fmq00on,4)){ 218 openfmq00=true; 219 fengmingqi1.setText("關閉蜂鳴器"); 220 } 221 } 222 } 223 } 224 }); 225 //控制繼電器 226 jdq_off.setOnClickListener(new OnClickListener() { 227 @Override 228 public void onClick(View arg0) { 229 if(connectflag==true){ 230 if(tcp_send_data(tcp_data_jdq00off,4)){ 231 jidianqi1.setImageDrawable(getResources().getDrawable(R.drawable.jidianqi_off)); 232 } 233 } 234 } 235 }); 236 //控制繼電器 237 jdq_on.setOnClickListener(new OnClickListener() { 238 @Override 239 public void onClick(View arg0) { 240 if(connectflag==true){ 241 if(tcp_send_data(tcp_data_jdq00on,4)){ 242 jidianqi1.setImageDrawable(getResources().getDrawable(R.drawable.jidianqi_on)); 243 } 244 } 245 } 246 }); 247 //建立socket連接 248 btn_set_ip.setOnClickListener(new OnClickListener() { 249 @Override 250 public void onClick(View arg0) { 251 setsocket(); 252 } 253 }); 254 //刪除socket 255 delete_socket.setOnClickListener(new OnClickListener() { 256 @Override 257 public void onClick(View arg0) { 258 if(connectflag==true){ 259 tcp_send_data(tcp_data_socketoff,4); 260 DeleteSocket(); 261 Message message=new Message(); 262 message.what=5; 263 handler.sendMessage(message); //發送Messgae給與主線程綁定的handler,讓主線程來作出響應,主要是讓主線程做一些UI的操作 264 } 265 } 266 }); 267 } 268 269 /*----------------設置按返回鍵會將程序后台運行而不是關閉-------------------*/ 270 public boolean onKeyDown(int keyCode, KeyEvent event) { 271 if (keyCode == KeyEvent.KEYCODE_BACK) { 272 moveTaskToBack(false); //false保留后台運行 true不保留后台運行 273 return true; 274 } 275 return super.onKeyDown(keyCode, event); 276 } 277 /*---------------------------------------------------------------------------*/ 278 279 /*------------------------------自定義函數---------------------------------*/ 280 //TCP發送數據,返回一個布爾值,用來確定是否發送數據成功 281 boolean tcp_send_data(String str,int MinInterval){ 282 while(SendCMD_WaitFlag); //等待結束上一次發送數據所要求的間隔,以保證每次發送出去的數據包都能被正確接收處理 try{ 283 if(timer_SetSendCMD_Interval != null){ 284 timer_SetSendCMD_Interval.cancel(); //注意:timer對象在沒有工作的時候,不能對其進行cancel,否則會導致程序崩毀 285 timer_SetSendCMD_Interval=null; 286 } 287 //SendCMD_WaitFlag = true; 288 try{ 289 dataOutputStream.write(str.getBytes()); 290 dataOutputStream.flush(); 291 SetSendCMD_Interval(MinInterval); 292 return true; 293 } 294 catch(IOException e){ 295 Message message=new Message(); 296 message.what=3; 297 message.obj="socket連接失敗!"; 298 handler.sendMessage(message); 299 DeleteSocket(); 300 SendCMD_WaitFlag = false; 301 return false; 302 } 303 } 304 305 void DeleteSocket(){ 306 connectflag=false; 307 SendCMD_WaitFlag = false; 308 if(timer_TCPMonitor!=null){timer_TCPMonitor.cancel();timer_TCPMonitor=null;} 309 if(timer_SendCMD!=null){timer_SendCMD.cancel();timer_SendCMD=null;} 310 if(socket!=null) { try{socket.close();}catch(IOException a){}} 311 if(thread2!=null) { thread2.interrupt(); thread2=null;} //destroy和stop方法對於thread類對象來說都是不可取的 312 if(thread1!=null) { thread1.interrupt(); thread1=null;} //先暫停線程的運行,然后再解除線程映射 313 } 314 private void startConnected() 315 { 316 //建立連接前進行初始化 317 DeleteSocket(); 318 319 thread2=new Thread(new Runnable() { //創建一個沒有標識符映射的子線程,因為創建socket是不能交給主線程來實現的 320 public void run() { 321 try{ 322 socket=new Socket(IP,port); //建立SOCKET連接 323 socket.setSoTimeout(1000); //在對socket輸入流進行讀操作的時候,會嘗試進行1000ms的讀取操作 324 325 dataInputStream=new DataInputStream(socket.getInputStream()); //創建輸入數據流 326 dataOutputStream=new DataOutputStream(socket.getOutputStream()); //創建輸出數據流 327 } 328 //catch(SocketTimeoutException e){} 329 catch (IOException e) { 330 Message message=new Message(); 331 message.what=3; 332 message.obj="socket連接失敗!"; 333 handler.sendMessage(message); 334 return; 335 } 336 337 //剛開始創建連接,進行一次連接測試,檢查是否連接成功 338 if(tcp_send_data(tcp_data_try,30)){ 339 Message message=new Message(); 340 connectflag=true; 341 message.what=4; 342 handler.sendMessage(message); 343 } 344 else{ 345 return; 346 } 347 348 //--------------------------建立連接后進行初始化--------------------------// 349 //不斷嘗試讀取接收緩沖區的數據 350 TryRead_ReceivedBuffer(); 351 //每隔1000ms獲取一次溫度值數據 352 timer_SendCMD=new Timer(); 353 timer_SendCMD.schedule(new TimerTask() { //定時器要執行的任務盡可能在以這種方式設定,以免出現麻煩 354 @Override 355 public void run() { 356 tcp_send_data(tcp_data_SenT00,60); //建議獲取一次溫度值后產生60ms發送間隔 357 } 358 },100,1000); 359 //循環發送特定數據包出去,根據反饋以確定是否斷開連接,如果反饋到心跳包,則表明連接沒有斷開 360 NeedToCheckTCP = false; 361 timer_TCPMonitor=new Timer(); 362 timer_TCPMonitor.schedule(new TimerTask() { //定時器要執行的任務盡可能在以這種方式設定,以免出現麻煩 363 @Override 364 public void run() { 365 Message message=new Message(); 366 if (NeedToCheckTCP) //檢查是否接收到心跳包 367 { 368 NeedToCheckTCP = false; 369 if (heartbeat) 370 { 371 heartbeat = false; 372 } 373 else 374 { 375 DeleteSocket(); 376 message.what=3; 377 message.obj="已斷開連接,因為沒有接收到心跳包!"; 378 handler.sendMessage(message); 379 } 380 } 381 else //請求接收者反饋心跳包,以確認連接是否出現異常 382 { 383 NeedToCheckTCP = true; 384 tcp_send_data(tcp_data_try,25); 385 } 386 } 387 },2000,2000); 388 } 389 }); 390 thread2.start(); 391 } 392 //更新UI這種操作必須由主線程來實現,否則會導致程序崩毀 393 private Handler handler = new Handler(){ 394 @Override 395 public void handleMessage(Message msg){ 396 switch(msg.what){ 397 case 1: 398 if(temperature[msg.arg1]<0){ 399 tv_temperature[msg.arg1].setText(Integer.toString(temperature[msg.arg1] / 10) + "." + Integer.toString((temperature[msg.arg1] % 10)*(-1)) + "℃"); 400 } 401 else{ 402 tv_temperature[msg.arg1].setText("+"+Integer.toString(temperature[msg.arg1] / 10) + "." + Integer.toString((temperature[msg.arg1] % 10)) + "℃"); 403 } 404 notice1.setText(msg.obj.toString()); 405 break; 406 case 2: 407 408 break; 409 case 3: 410 light00.setEnabled(false); 411 light01.setEnabled(false); 412 light02.setEnabled(false); 413 notice1.setText(msg.obj.toString()); 414 socketstate.setText(" 未連接!"); 415 break; 416 case 4: 417 notice1.setText("socket連接成功!"); 418 socketstate.setText(" 已連接!"); 419 light00.setEnabled(true); 420 light01.setEnabled(true); 421 light02.setEnabled(true); 422 break; 423 case 5: 424 light00.setEnabled(false); 425 light01.setEnabled(false); 426 light02.setEnabled(false); 427 notice1.setText("手動斷開連接!"); 428 socketstate.setText(" 未連接!"); 429 break; 430 case 6: 431 //temperature[0].setText(Integer.toString(num++)); //測試專用 432 notice1.setText(msg.obj.toString()); //之所以要加toString()是因為msg.obj是指一個通用對象,必須要對這個通用對象轉換成某類對象才能被使用 433 break; 434 default: 435 436 break; 437 } 438 } 439 }; 440 //處理串口接收數據包函數(成功處理數據包則返回true,否則返回false) 441 public boolean Deal_UART_RecData(String ReceStr){ 442 Message message=new Message(); 443 if(ReceStr.length()==DataPackage_Length){ 444 if(ReceStr.substring(0, 1).equals(datapackage_headflag)&&(ReceStr.substring(14, 15).equals("#"))){ //數據包頭尾標記驗證 445 try{ 446 switch(Integer.parseInt(ReceStr.substring(1, 2))){ //識別設備D的第1位數字 447 case 0: 448 switch(Integer.parseInt(ReceStr.substring(2, 3))){ //識別設備ID的第2位數字 449 case 2: 450 if(ReceStr.substring(4, 8).equals("SenT")){ //判斷指令頭部是否為"SenT" A02_SenT00-245# 451 try{ //注意:"-12"轉int類型正確 ,“+12”轉int類型異常 ,"12"轉int類型正確 452 message.arg1=Integer.parseInt(ReceStr.substring(8, 10)); 453 if(message.arg1<tv_temperature.length){ 454 temperature[message.arg1]=Integer.parseInt(ReceStr.substring(10, 14)); 455 message.obj="更新溫度傳感器值成功"; 456 message.what=1; 457 handler.sendMessage(message); //請求主線程進行UI操作,以處理接收到的數據 458 return true; 459 } 460 } 461 catch(NumberFormatException b) //:string轉int異常 462 { 463 message.what=6; 464 message.obj="接收的指令:指令尾部異常"; 465 handler.sendMessage(message); //請求主線程進行UI操作,以處理接收到的數據 466 return false; 467 } 468 } 469 if(ReceStr.substring(4, 8).equals("Beat")){ //判斷指令頭部是否為"Beat" 470 heartbeat = true; 471 return true; 472 } 473 message.what=6; 474 message.obj="接收的指令:指令頭部異常"; 475 handler.sendMessage(message); //請求主線程進行UI操作,以處理接收到的數據 476 return false; 477 default: 478 message.what=6; 479 message.obj="接收的數據包:設備ID異常"; 480 handler.sendMessage(message); //請求主線程進行UI操作,以處理接收到的數據 481 return false; 482 } 483 default: 484 message.what=6; 485 message.obj="接收的數據包:設備ID異常"; 486 handler.sendMessage(message); //請求主線程進行UI操作,以處理接收到的數據 487 return false; 488 } 489 } 490 catch(NumberFormatException b){ //:string轉int異常 491 message.what=6; 492 message.obj="接收的數據包:設備ID異常"; 493 handler.sendMessage(message); //請求主線程進行UI操作,以處理接收到的數據 494 return false; 495 } 496 497 } 498 message.what=6; 499 message.obj="接收的數據包:頭尾標記驗證異常"; 500 handler.sendMessage(message); //請求主線程進行UI操作,以處理接收到的數據 501 return false; 502 } 503 message.what=6; 504 message.obj="接收的數據包:長度異常"; 505 handler.sendMessage(message); //請求主線程進行UI操作,以處理接收到的數據 506 return false; 507 } 508 private void TryRead_ReceivedBuffer(){ 509 thread1=new Thread(new Runnable() { 510 @Override 511 public void run() { 512 while (socket!=null&&!socket.isClosed()) { //循環檢測是否接收到新的數據 513 if(dataInputStream!=null) 514 { 515 try { 516 //為保證正確處理接收到的數據,2次接收的間隔必須要足夠大(如要涉及費時操作建議2秒),即要保證接收緩沖區不能出現一條或以上的指令,不然就是多指令混在緩沖區,那么讀出來的時候,相當於是把多條指令同時進行處理,這會出錯 517 dataInputStream.read(tcp_receive_buf); //循環嘗試讀取接收緩沖區的數據,每次嘗試持續時間為1s,假如有數據來到,則將數據讀到數組里去,緩沖區自動清除讀過的字節,時間到了卻沒有數據來到,則拋出異常 518 519 String receive_str=new String(tcp_receive_buf); //將tcp_receive_buf數組的值進行映射,轉換出string,注意:空字符也會進行映射 520 for(byte i=0;i<15;i++){ //清空tcp_receive_buf數組 521 tcp_receive_buf[i]=0; 522 } 523 //下面嘗試對接收到的數據包(receive_str)進行處理 524 if(Deal_UART_RecData(receive_str)){ 525 526 } 527 else{ 528 529 } 530 } 531 catch (IOException e) { 532 //如果沒有接收到數據則執行下面的代碼 533 534 } 535 } 536 } 537 } 538 }); 539 thread1.start(); 540 } 541 private void setsocket() { 542 String ip1 = et_ip1.getText().toString(); 543 String ip2 = et_ip2.getText().toString(); 544 String ip3 = et_ip3.getText().toString(); 545 String ip4 = et_ip4.getText().toString(); 546 String port = et_port.getText().toString(); 547 548 if (isIP(ip1) && isIP(ip2) && isIP(ip3) && isIP(ip4) && isPort(port)) 549 { 550 IP = ip1 + "." + ip2 + "." + ip3 + "." + ip4; 551 current_ip.setText(IP + ":" + port); 552 startConnected(); 553 554 } 555 else { 556 //Toast.makeText(this, "IP或Port輸入有誤", Toast.LENGTH_SHORT).show(); 557 socketstate.setText("IP或Port格式輸入有誤!"); 558 } 559 } 560 //port格式檢查 561 private boolean isPort(String s) { 562 int i = -1; 563 try { 564 i = Integer.parseInt(s); 565 } catch (NumberFormatException e) { 566 e.printStackTrace(); 567 return false; 568 } 569 if ((i > 0) && (i<65536)) { 570 port = i; // 設置端口 571 return true; 572 } 573 else { 574 return false; 575 } 576 } 577 //IP格式檢查 578 private boolean isIP(String s) { 579 int i = -1; 580 try { 581 i = Integer.parseInt(s); 582 } 583 catch (NumberFormatException e) { 584 e.printStackTrace(); 585 return false; 586 } 587 if ((i >= 0) && (i < 256)) { 588 return true; 589 } 590 else { 591 return false; 592 } 593 } 594 /*--------------------------------------------------------------------------------*/ 595 596 @Override 597 public boolean onCreateOptionsMenu(Menu menu) { 598 // Inflate the menu; this adds items to the action bar if it is present. 599 getMenuInflater().inflate(R.menu.main, menu); 600 return true; 601 } 602 603 }
.XML文件源碼(供參考,請使用前自行作修改):
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:id="@+id/LinearLayout1" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:orientation="vertical" 7 android:paddingBottom="@dimen/activity_vertical_margin" 8 android:paddingLeft="@dimen/activity_horizontal_margin" 9 android:paddingRight="@dimen/activity_horizontal_margin" 10 android:paddingTop="@dimen/activity_vertical_margin" 11 tools:context=".MainActivity" > 12 13 <LinearLayout 14 android:layout_width="match_parent" 15 android:layout_height="wrap_content" > 16 17 <TextView 18 android:id="@+id/textView1" 19 android:layout_width="wrap_content" 20 android:layout_height="wrap_content" 21 android:text="當前連接:" /> 22 23 <TextView 24 android:id="@+id/tv_current_ip" 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" 27 android:layout_weight="0.28" 28 android:text="暫無" 29 android:textSize="15sp" /> 30 31 </LinearLayout> 32 33 <LinearLayout 34 android:layout_width="match_parent" 35 android:layout_height="wrap_content" > 36 37 <TextView 38 android:id="@+id/textView3" 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:text="IP:" /> 42 43 <EditText 44 android:id="@+id/et_ip1" 45 android:layout_width="wrap_content" 46 android:layout_height="wrap_content" 47 android:layout_weight="1" 48 android:text="192" 49 android:ems="10" > 50 51 <requestFocus /> 52 </EditText> 53 54 <TextView 55 android:id="@+id/textView4" 56 android:layout_width="wrap_content" 57 android:layout_height="wrap_content" 58 android:text="." /> 59 60 <EditText 61 android:id="@+id/et_ip2" 62 android:layout_width="wrap_content" 63 android:layout_height="wrap_content" 64 android:layout_weight="1" 65 android:text="168" 66 android:ems="10" /> 67 68 <TextView 69 android:id="@+id/textView5" 70 android:layout_width="wrap_content" 71 android:layout_height="wrap_content" 72 android:text="." /> 73 74 <EditText 75 android:id="@+id/et_ip3" 76 android:layout_width="wrap_content" 77 android:layout_height="wrap_content" 78 android:layout_weight="1" 79 android:ems="10" /> 80 81 <TextView 82 android:id="@+id/textView6" 83 android:layout_width="wrap_content" 84 android:layout_height="wrap_content" 85 android:text="." /> 86 87 <EditText 88 android:id="@+id/et_ip4" 89 android:layout_width="wrap_content" 90 android:layout_height="wrap_content" 91 android:layout_weight="1" 92 android:ems="10" /> 93 </LinearLayout> 94 95 <LinearLayout 96 android:layout_width="match_parent" 97 android:layout_height="wrap_content" > 98 99 <TextView 100 android:id="@+id/textView7" 101 android:layout_width="wrap_content" 102 android:layout_height="wrap_content" 103 android:text="PORT" /> 104 105 <EditText 106 android:id="@+id/et_port" 107 android:layout_width="76dp" 108 android:layout_height="wrap_content" 109 android:ems="10" /> 110 111 <Button 112 android:id="@+id/btn_setip" 113 android:layout_width="92dp" 114 android:layout_height="wrap_content" 115 android:text="連接" /> 116 117 <Button 118 android:id="@+id/btn_deletesocket" 119 android:layout_width="match_parent" 120 android:layout_height="wrap_content" 121 android:text="斷開" /> 122 </LinearLayout> 123 124 <TextView 125 android:id="@+id/textView2" 126 android:layout_width="wrap_content" 127 android:layout_height="wrap_content" 128 android:text="下面是控制面板:" /> 129 130 <LinearLayout 131 android:layout_width="match_parent" 132 android:layout_height="wrap_content" > 133 134 <TextView 135 android:id="@+id/textView8" 136 android:layout_width="wrap_content" 137 android:layout_height="wrap_content" 138 android:layout_gravity="right" 139 android:layout_marginLeft="70dp" 140 android:text="溫度傳感器值:" /> 141 142 <TextView 143 android:id="@+id/tv_temperature00" 144 android:layout_width="wrap_content" 145 android:layout_height="wrap_content" 146 android:layout_weight="2" 147 android:text="暫無" /> 148 149 </LinearLayout> 150 151 <LinearLayout 152 android:layout_width="match_parent" 153 android:layout_height="wrap_content" > 154 155 <ImageView 156 android:id="@+id/image_light00" 157 android:layout_width="74dp" 158 android:layout_height="66dp" 159 android:layout_weight="1" 160 android:src="@drawable/close_light" /> 161 162 <ImageView 163 android:id="@+id/image_light01" 164 android:layout_width="74dp" 165 android:layout_height="66dp" 166 android:layout_weight="1" 167 android:src="@drawable/close_light" /> 168 169 <ImageView 170 android:id="@+id/image_light02" 171 android:layout_width="74dp" 172 android:layout_height="66dp" 173 android:layout_weight="1" 174 android:src="@drawable/close_light" /> 175 </LinearLayout> 176 177 <LinearLayout 178 android:layout_width="match_parent" 179 android:layout_height="wrap_content" > 180 181 <Switch 182 android:id="@+id/sw_light00" 183 android:layout_width="wrap_content" 184 android:layout_height="wrap_content" 185 android:layout_weight="1" /> 186 187 <Switch 188 android:id="@+id/sw_light01" 189 android:layout_width="wrap_content" 190 android:layout_height="wrap_content" 191 android:layout_weight="1" /> 192 193 <Switch 194 android:id="@+id/sw_light02" 195 android:layout_width="wrap_content" 196 android:layout_height="wrap_content" 197 android:layout_weight="1" /> 198 </LinearLayout> 199 200 <LinearLayout 201 android:layout_width="match_parent" 202 android:layout_height="wrap_content" > 203 204 <Button 205 android:id="@+id/btn_jidianqi_on" 206 android:layout_width="wrap_content" 207 android:layout_height="wrap_content" 208 android:layout_gravity="bottom" 209 android:layout_weight="1" 210 android:text="吸合" /> 211 212 <ImageView 213 android:id="@+id/image_jidianqi1" 214 android:layout_width="wrap_content" 215 android:layout_height="86dp" 216 android:layout_weight="3.08" 217 android:src="@drawable/jidianqi_off" /> 218 219 <Button 220 android:id="@+id/btn_jidianqi_off" 221 android:layout_width="wrap_content" 222 android:layout_height="wrap_content" 223 android:layout_gravity="bottom" 224 android:layout_weight="1" 225 android:text="斷開" /> 226 </LinearLayout> 227 228 <Button 229 android:id="@+id/btn_fmq1" 230 android:layout_width="wrap_content" 231 android:layout_height="wrap_content" 232 android:layout_gravity="center_horizontal" 233 android:text="啟動蜂鳴器" /> 234 235 <LinearLayout 236 android:layout_width="match_parent" 237 android:layout_height="wrap_content" > 238 239 <TextView 240 android:id="@+id/textView9" 241 android:layout_width="wrap_content" 242 android:layout_height="wrap_content" 243 android:text="當前連接狀態:" /> 244 245 <TextView 246 android:id="@+id/tv_socketstate" 247 android:layout_width="wrap_content" 248 android:layout_height="wrap_content" 249 android:text="未連接" /> 250 251 </LinearLayout> 252 253 <LinearLayout 254 android:layout_width="match_parent" 255 android:layout_height="wrap_content" > 256 257 <TextView 258 android:id="@+id/textView10" 259 android:layout_width="wrap_content" 260 android:layout_height="wrap_content" 261 android:text="消息通知欄:" /> 262 263 <TextView 264 android:id="@+id/tv_notice1" 265 android:layout_width="wrap_content" 266 android:layout_height="wrap_content" 267 android:text="" /> 268 269 </LinearLayout> 270 271 </LinearLayout>
程序界面如下:
與ESP8266透傳模塊(作socket服務器端)連接后,對單片機進行遠程控制。
想要完整工程文件或疑問可以私聊我~
請另外觀看項目的2個部分:
1)局域網控制系統-下位機-單片機
2)局域網控制系統-上位機-PC機
尊重作者的勞動,轉載請記得注明來源:http://www.cnblogs.com/weifeng727/p/5618100.html