Android上UDP组播无法接收数据的问题
16lz
2021-01-26
最近,想做一个跨平台的局域网的文件传输软件,思路是组播设备信息,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 @Override31 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 @Override17 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"));
转载于:https://www.cnblogs.com/Ralap/p/Android_udp_multcast_solution.html
更多相关文章
- 简单模拟Android中AlertDialog的Builder设计模式
- android获取网络图片
- Python 通过脚本获取Android的apk的部分属性,再通过加密算法生成
- Android:Activity(三):启动其他Activity并返回结果
- Android根据所设置的textSize获取字体高度和设置行高
- Android之判断是否安装某个应用
- Android稳定性问题分析时获取手机状态的ADB命令
- Android获取目录
- Java入侵检测(三)