Android Socket 發送廣播包的那些坑

來源:互聯網
上載者:User

標籤:android   socket   廣播包   hotspot   broadcast   

Socket廣播包經常被用於區域網路內的兩台裝置之間互相發現和訊息傳遞,在Android應用開發過程中,也經常會遇到這樣的需求,例如:兩台Android裝置之間、Android與手環等智能硬體之間、Android與Windows電腦之間等等。


本文主要介紹在Android中使用Socket開發廣播包程式時需要注意的編程事項,以及解決方案。


首先給出一段Android發送廣播包的範例程式碼:


DatagramSocket socket = new DatagramSocket(8000);socket.setBroadcast(true);InetAddress addr = InetAddress.getByName("255.255.255.255");byte[] buffer = "Hello World".getBytes();DatagramPacket packet = new DatagramPacket(buffer,buffer.length);packet.setAddress(addr);packet.setPort(8086);socket.send(packet);


下面分析其中需要注意的地方:


1. 不要在主線程中發送廣播包


當然,這個做Android開發的人應該都知道,不能在UI線程中執行任何網路訪問相關的操作,由於廣播包的發送也屬於網路操作,因此必須放到單獨的線程中執行。


2. 廣播位址不建議使用“255.255.255.255”


上述代碼中,廣播包的目標地址設定為了“255.255.255.255”,其實,這並不是一種推薦的做法。


“255.255.255.255” 是一種受限的廣播位址,常用於在電腦不知道自己IP地址的時候發送,比如裝置啟動時向DHCP伺服器索要地址等等,一般情況下,路由器不會轉寄目標為受限廣播位址的廣播包。


而且,有些路由器/Wi-Fi熱點不支援該廣播位址(例如:用Android手機做Wi-Fi熱點的時候),因此在程式中會出現“ENETUNREACH (Network is unreachable)”的異常,因此,為了保證程式成功發送廣播包,建議使用直接廣播位址,例如:當前IP地址是 192.168.1.100,子網路遮罩是 255.255.255.0 的情況下,廣播位址為:192.168.1.255,(具體的推算方法這裡就不展開了,可以參考電腦網路相關書籍)。


那麼,如何得到本網段的直接廣播位址呢,下面是stackoverflow上面有位大牛分享的代碼:


public static InetAddress getBroadcastAddress(Context context) throws UnknownHostException {    WifiManager wifi = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);    DhcpInfo dhcp = wifi.getDhcpInfo();    if(dhcp==null) {        return InetAddress.getByName("255.255.255.255");    }    int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;    byte[] quads = new byte[4];    for (int k = 0; k < 4; k++)        quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);    return InetAddress.getByAddress(quads);}


直接使用該函數即可得到正確的“廣播位址”,通過setAddress函數設定到DatagramPacket對象中即可。


3. Android設定為Wi-Fi熱點時的廣播位址


這是個比較大的坑,當Android裝置被設定為Wi-Fi熱點的時候,上面的函數得到的地址是"0.0.0.0",因此,我們需要探究當Android裝置被設定為Wi-Fi熱點的時候,它的IP地址究竟是多少?


有人研究了Android底層源碼發現,當Android裝置被設定為Wi-Fi熱點的時候,其IP地址是hardcode寫死在源碼中的,地址是:“192.168.43.1”,對應的廣播位址是:"192.168.43.255"


為此,我們需要寫個函數來判斷一下當前Android手機是否處於Wi-Fi熱點模式下,如果是,則應該使用上面給出的這個廣播位址,這裡給出程式碼範例:


protected static Boolean isWifiApEnabled(Context context) {    try {        WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);          Method method = manager.getClass().getMethod("isWifiApEnabled");        return (Boolean)method.invoke(manager);    }    catch (NoSuchMethodException e) {        e.printStackTrace();    }    catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)  {        e.printStackTrace();}    return false;}


Android SDK並沒有開放判斷是否處於熱點模式的API,因此,我們需要通過反射的方式來得到,另外,注意添加許可權: 


<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />


4. 小結


本文涉及到的代碼被封裝到了一個Broadcaster.java的檔案中,可以在博文最後的附件中下載,也可以從下面的地址下載:


https://github.com/Jhuster/Android/blob/master/Socket/Broadcaster.java


關於Android Socket發送廣播包的那些坑就總結到這裡了,有任何疑問或者建議歡迎留言或者來信[email protected]交流,或者關注我的新浪微博 @盧_俊 擷取最新的文章和資訊。



本文出自 “對影成三人” 部落格,請務必保留此出處http://ticktick.blog.51cto.com/823160/1707858

Android Socket 發送廣播包的那些坑

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.