無網絡環境下的Android端數據傳輸
對於無網絡的數據傳輸方式:
- NFC :適用於體量小指令數據傳輸,大數據量傳輸,速度較慢且不穩定,但是建立連接過程很快。
- WIFI直連:傳輸速度快,可傳輸數據量大,但是連接過程複雜。
- 藍牙:常規的藍牙區別於低功耗藍牙(沒有涉及),常規藍牙需要發現設備,配對設備
- 熱點TCP/IP方式
方式很多,就先記錄下嘗試過的一種吧:第四種方式
- 服務端創建網絡
創建熱點,這裏採用的是反射機制調用系統的API方法,創建約定的名稱的熱點,創建成功之後會自動打開wifi熱點
public boolean setWifiApEnabled() { // disable WiFi in any case //wifi和熱點不能同時打開,所以打開熱點的時候需要關閉wifi mWifiManager.setWifiEnabled(false); try { //熱點的配置類 WifiConfiguration apConfig = new WifiConfiguration(); //配置熱點的名稱(可以在名字後面加點隨機數什麼的) apConfig.SSID = GlobData.WIFIAPSSID; //配置熱點的密碼 apConfig.preSharedKey = GlobData.WIFIAPPASSWORD; /***配置熱點的其他信息 加密方式**/ apConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); apConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN); //用WPA密碼方式保護 apConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA); apConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); apConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); apConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); apConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); apConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); //通過反射調用設置熱點 Method method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE); //返回熱點打開狀態 return (Boolean) method.invoke(mWifiManager, apConfig, true); } catch (Exception e) { return false; } }
- 客戶端連接網絡
- 掃描附近的網絡,添加廣播接收網絡變化及掃描結果
- 添加網絡,當掃描結果包含已約定SSID的熱點,則添加到WiFi列表
- 連接該網絡網絡,
/** * 是否已連接指定wifi */ public boolean isConnected(String ssid) { WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); if (wifiInfo == null) { return false; } switch (wifiInfo.getSupplicantState()) { case AUTHENTICATING: case ASSOCIATING: case ASSOCIATED: case FOUR_WAY_HANDSHAKE: case GROUP_HANDSHAKE: case COMPLETED: return wifiInfo.getSSID().replace("\"", "").equals(ssid); default: return false; } }
public boolean connect(@NonNull String ssid, @NonNull String password) { boolean isConnected = isConnected(ssid);//當前已連接至指定wifi if (isConnected) { return true; } int id = -1; for (WifiConfiguration c:mWifiManager.getConfiguredNetworks()){ if(c.SSID.equals("\"" + GlobData.WIFIAPSSID + "\"")){ id = c.networkId; } mWifiManager.disableNetwork(c.networkId); } if(-1==id){ int networkId = mWifiManager.addNetwork(CreateWifiInfo(ssid, password, 3)); if(-1!=networkId){ id =networkId; } } if(-1==id){ for (WifiConfiguration c:mWifiManager.getConfiguredNetworks()){ if(c.SSID.equals(GlobData.WIFIAPSSID)){ id = c.networkId; break; } } } if(-1!=id){ boolean result = mWifiManager.enableNetwork(id, true); return true; } return false; }
- 服務端開放ServerSoket
public class ServerThread extends Thread { private ServerSocket serverSocket = null; private Handler handler; private Socket socket; private volatile boolean isRun =true; private InputStream inputStream; private OutputStream outputStream; public ServerThread(Handler handler) { this.handler = handler; try { serverSocket = new ServerSocket(GlobData.WIFIAPPORT);//監聽本機的12345端口 } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { if(null==serverSocket){ try { serverSocket = new ServerSocket(GlobData.WIFIAPPORT);//監聽本機的12345端口 } catch (IOException e) { e.printStackTrace(); } } while (isRun) { try { Log.i("ListennerThread", "阻塞"); //阻塞,等待設備連接 if (serverSocket != null) { socket = serverSocket.accept(); Message message = Message.obtain(); message.what = GlobData.DEVICE_CONNECTED; handler.sendMessage(message); inputStream = socket.getInputStream(); outputStream = socket.getOutputStream(); new Thread(new Runnable() { @Override public void run() { byte[] buffer = new byte[4*1024]; int bytes = 0; try { bytes = inputStream.read(buffer); } catch (IOException e) { e.printStackTrace(); } if (bytes > 0) { final byte[] data = new byte[bytes]; System.arraycopy(buffer, 0, data, 0, bytes); Message message1 = Message.obtain(); message1.what = GlobData.SEND_MSG_SUCCSEE; Bundle bundle = new Bundle(); bundle.putString("MSG", new String(data)); message1.setData(bundle); handler.sendMessage(message1); Log.i("ClinentConnectThread", "讀取到數據:" + new String(data)); } } }).start(); } } catch (Exception e) { e.printStackTrace(); interrupt(); } } } /** * 發送數據 */ public void sendData(final String msg) { new Thread(new Runnable() { @Override public void run() { if (outputStream != null) { try { // byte[] len =new byte[8]{msg.getBytes("UTF-8").length}; // outputStream.write(msg.getBytes("UTF-8")); // outputStream.flush(); outputStream.write(msg.getBytes("UTF-8")); outputStream.flush(); outputStream.write("tpriend".getBytes("UTF-8")); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); Message message = Message.obtain(); message.what = GlobData.SEND_MSG_ERROR; Bundle bundle = new Bundle(); bundle.putString("MSG", new String(msg)); message.setData(bundle); handler.sendMessage(message); } } } }).start(); } public void close() { try { if(null!=outputStream){ outputStream.close(); outputStream = null; } if(null!=inputStream){ inputStream.close(); inputStream = null; } if (serverSocket != null) { serverSocket.close(); serverSocket = null; } if (socket != null) { socket.close(); socket=null; } this.isRun=false; } catch (IOException e) { e.printStackTrace(); } } }
- 客戶端連接Sokect
public class ClientThread extends Thread { private Socket socket; private Handler handler; private InputStream inputStream; private OutputStream outputStream; private volatile boolean isRun = true; public ClientThread(Socket socket, Handler handler) { this.socket = socket; this.handler = handler; } @Override public void run() { if (socket == null) { return; } handler.sendEmptyMessage(GlobData.DEVICE_CONNECTED); try { //獲取數據流 inputStream = socket.getInputStream(); outputStream = socket.getOutputStream(); InputStream inputStream = socket.getInputStream(); byte[] bytes = new byte[4*1024]; int len = -1; StringBuilder sb = new StringBuilder(); while ((isRun && (len = inputStream.read(bytes)) != -1)) { // 注意指定編碼格式,發送方和接收方一定要統一,建議使用UTF-8 String str = new String(bytes, 0, len, "UTF-8"); if (str.contains("tpriend")) { str =str.substring(0,str.indexOf("tpriend")); sb.append(str); Message message = Message.obtain(); message.what = GlobData.GET_MSG; Bundle bundle = new Bundle(); bundle.putString("MSG", sb.toString()); message.setData(bundle); handler.sendMessage(message); sb = new StringBuilder(); new Thread(new Runnable() { @Override public void run() { try { outputStream.write("tpriend".getBytes("UTF-8")); } catch (IOException e) { e.printStackTrace(); } try { outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } else { sb.append(str); } } } catch (Exception e) { e.printStackTrace(); } } public void close() { try { if(null!=outputStream){ outputStream.close(); outputStream = null; } if(null!=inputStream){ inputStream.close(); inputStream = null; } if (socket != null) { socket.close(); socket=null; } this.isRun=false; } catch (IOException e) { e.printStackTrace(); } } } 這邊是服務端發的數據,當然客戶端服務端誰發都可以,視情況而定,至此一個簡單的基於熱點傳輸的例子就結束了