Android上UDP組播無法接收數據的問題

来源:http://www.cnblogs.com/Ralap/archive/2017/06/06/Android_udp_multcast_solution.html
-Advertisement-
Play Games

最近,想做一個跨平臺的區域網的文件傳輸軟體,思路是組播設備信息,TCP連接傳輸文件。於是進行了一次簡單的UDP組播測試,發現Android對於UDP組播接收數據的支持即極為有限。 部分代碼如下 1 package com.hsocket.Udp; 2 3 import java.io.IOExcep ...


  最近,想做一個跨平臺的區域網的文件傳輸軟體,思路是組播設備信息,TCP連接傳輸文件。於是進行了一次簡單的UDP組播測試,發現Android對於UDP組播接收數據的支持即極為有限。

部分代碼如下

 1 package com.hsocket.Udp;
 2 
 3 import java.io.IOException;
 4 import java.net.DatagramPacket;
 5 import java.net.DatagramSocket;
 6 
 7 public class UdpReceiver {
 8     protected DatagramSocket client=null;
 9     private OnReceiveListener mOnReceiveListener=null;
10     private Thread thrRecv=null;
11     protected int port=0;
12     public UdpReceiver(int port){
13         this.port=port;
14     }
15     protected DatagramSocket Create() throws IOException{
16         return new DatagramSocket(this.port);
17     }
18     public void addOnReceiveListener(OnReceiveListener mOnReceiveListener){
19         this.mOnReceiveListener=mOnReceiveListener;
20     }
21     public void Stop(){
22         if(this.thrRecv!=null) this.thrRecv.interrupt();
23         this.Close();
24     }
25     public void Listen() throws IOException{
26         this.Close();
27         this.client=this.Create();
28         if(this.thrRecv!=null) this.thrRecv.interrupt();
29         this.thrRecv=new Thread(new Runnable() {
30             @Override
31             public void run() {
32                 while(!Thread.interrupted()){
33                     ReceiveEventArgs args=new ReceiveEventArgs();
34                     try {
35                         DatagramPacket packet=UdpReceiver.this.Receive();
36                         args.Address=packet.getAddress();
37                         args.Result=packet.getData();
38                         args.Length=packet.getLength();
39                         args.Error=false;
40                     } catch (IOException e) {
41                         e.printStackTrace();
42                         args.Exception=e;
43                         args.Error=true;
44                     }
45                     UdpReceiver.this.OnReceive(args);
46                     if(UdpReceiver.this.mOnReceiveListener!=null)
47                         UdpReceiver.this.mOnReceiveListener.OnReceive(UdpReceiver.this, args);
48                 }
49             }
50         });
51         this.thrRecv.start();
52     }
53     protected DatagramPacket Receive() throws IOException{
54         byte[] recvBuf = new byte[4096];
55         DatagramPacket recvPacket= new DatagramPacket(recvBuf , recvBuf.length);
56         this.client.receive(recvPacket);
57         return recvPacket;
58     }
59     protected void Close(){
60         if(this.client!=null) this.client.close();
61     }
62     protected void OnReceive(ReceiveEventArgs args){
63         
64     }
65 }
View Code
 1 package com.hsocket.Udp;
 2 
 3 import java.io.IOException;
 4 import java.net.DatagramSocket;
 5 import java.net.InetAddress;
 6 import java.net.MulticastSocket;
 7 
 8 public class UdpMultcastReceiver extends UdpReceiver {
 9 
10     private InetAddress multicastAddr=null;
11     public UdpMultcastReceiver(InetAddress multicastAddr,int port) {
12         super(port);
13         this.multicastAddr=multicastAddr;
14     }
15 
16     @Override
17     protected DatagramSocket Create() throws IOException {
18         MulticastSocket socket=new MulticastSocket(this.port);
19         socket.joinGroup(this.multicastAddr);
20         socket.setLoopbackMode(false);
21         return socket;
22     }
23 }
View Code

  發現UDP組播接收數據在部分機型存在問題,與系統有極大關係。小米、華為的手機的深度定製系統對UDP的封殺極為嚴重。

  首先是組播鎖,Android的Wifi,預設情況下是不接受組播的,見:http://developer.android.com/reference/android/net/wifi/WifiManager.MulticastLock.html

要想打開組播功能,有以下幾個步驟:

  • 在Manifest文件中加入:android.permission.CHANGE_WIFI_MULTICAST_STATE,這個許可權
  • 獲取到MulticastLock對象,這個對象不能直接實例化,要通過WifiManager間接得到,工廠模式
  • 調用MulticastLock對象的acquire方法,獲取到組播鎖
  • 相應的,用完組播,為了不浪費電力,要調用MulticastLock的release方法釋放鎖
WifiManager wifiManager=(WifiManager)getSystemService(Context.WIFI_SERVICE); 
        multicastLock=wifiManager.createMulticastLock("multicast.test"); 
        multicastLock.acquire(); 

  其次,即使獲取到組播鎖,但部分機型依舊無法接收到廣播,因為部分Android有多網卡,預設是迴環外卡,IP為127.0.0.1,無法加入組播,需用MulticastSocket::setNetworkInterface來設置組播網卡

mMulticastSocket.setNetworkInterface(NetworkInterface.getByName("wlan0"));

  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 變數的作用域是可以訪問該變數的代碼區域。一般情況下,確定作用域遵循以下規則: 1.只要類在某個作用域內,其欄位(也稱為成員變數)也在該作用域內(這句話可以簡單的理解為,類中定義的欄位可以在類中的任意地方被訪問到)。 2.局部變數存在於表示聲明該變數的塊語句或方法結束的有花括弧之前的作用域內。(註意... ...
  • 本文源自《.NET通信框架的設計、實現與應用》書稿第一章內容 類庫是一些類的集合,只要我們將一些可以復用的類集中放到一個Library中,我們就可以稱其為一個類庫。 類庫中的許多元素(如類、結構、介面、枚舉、委托等)之間可能有一些關聯,但這些關聯通常用於支持一個類概念或介面概念的完整表達。 如果我們 ...
  • 代碼: RootViewController.h RootViewController.m ...
  • 轉載自http://www.runoob.com/w3cnote/android-tutorial-customer-baseadapter.html 作者:coder-pig 本節引言: 如題,本節給大家帶來的是構建一個可復用的自定義BaseAdapter,我們每每涉及到ListView Grid ...
  • 接手一個項目,有一個問題需要修改:輪播圖不能手動滑動,手動滑動輪播圖只會觸發側滑菜單。 猜測:viewpager控制項(輪播圖)的觸摸事件被SlidingMenu控制項(側滑菜單,非第三方項目,乃是上個開發人員自定義的)攔截了。 基於這個猜測,我自定義一個ViewPager,重寫dispatchTouc ...
  • 淺談Kotlin(一):簡介及Android Studio中配置 淺談Kotlin(二):基本類型、基本語法、代碼風格 淺談Kotlin(三):類 淺談Kotlin(四):控制流 本篇介紹Kotlin的控制流語法(if,for,while,when....) 一、if 語句 1、基本用法: 2、判斷 ...
  • 使用微信插件 cordova plugin add cordova-plugin-wechat --variable wechatappid=YOUR_WECHAT_APPID; $scope.sharechat=function(scene,title, desc, url, thumb){// ...
  • 很早之前就聽說過RecyclerView這個組件了,但一直很忙沒時間學習。趁著周末,就花了一天時間來學習RecyclerView。 準備工作 在Android Studio里新建一個Android項目,添加以下工具: 前兩個工具就不說了,基本每個Android項目都會用到,第三個就是使用Recycl ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...