JmDNS是mDNS的Java實現,以下代碼演示如何使用JmDNS發現設備。
依賴
1 implementation "org.jmdns:jmdns:3.5.5"
回調:
1 import org.json.JSONArray; 2 3 public interface MdnsCallback { 4 void onDeviceFind(JSONArray jsonArray); 5 }
設備發現:
1 import android.content.Context; 2 import android.net.wifi.WifiInfo; 3 import android.net.wifi.WifiManager; 4 5 import org.json.JSONArray; 6 import org.json.JSONObject; 7 8 import java.net.InetAddress; 9 import java.net.UnknownHostException; 10 import java.nio.charset.StandardCharsets; 11 import java.util.HashMap; 12 import java.util.Map; 13 import java.util.Objects; 14 15 import javax.jmdns.JmDNS; 16 import javax.jmdns.ServiceEvent; 17 import javax.jmdns.ServiceInfo; 18 import javax.jmdns.ServiceListener; 19 20 public class MdnsDiscover { 21 22 private Context mContext; 23 private String mServiceName; 24 private JmDNS mJmdns; 25 private MdnsSearchThread mSearchThread; 26 private MdnsCallback mCallback; 27 private Map<String, JSONObject> jsonMap = new HashMap<>(); 28 29 public MdnsDiscover(Context context) { 30 mContext = context; 31 } 32 33 public void startSearch(String serviceName, MdnsCallback callback) { 34 mCallback = callback; 35 if (mSearchThread != null && mSearchThread.isRunning()) { 36 if (Objects.equals(mServiceName, serviceName)) { 37 return; 38 } 39 mSearchThread.interrupt(); 40 } 41 mServiceName = serviceName; 42 mSearchThread = new MdnsSearchThread(); 43 mSearchThread.start(); 44 } 45 46 public void stopSearch() { 47 if (mSearchThread != null && mSearchThread.isRunning()) { 48 mSearchThread.interrupt(); 49 mSearchThread = null; 50 } 51 } 52 53 private InetAddress getLocalIpAddress(WifiManager wifiManager) throws UnknownHostException { 54 WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 55 int intAddr = wifiInfo.getIpAddress(); 56 byte[] byteaddr = new byte[]{ 57 (byte) (intAddr & 255), 58 (byte) (intAddr >> 8 & 255), 59 (byte) (intAddr >> 16 & 255), 60 (byte) (intAddr >> 24 & 255)}; 61 return InetAddress.getByAddress(byteaddr); 62 } 63 64 private class MdnsSearchThread extends Thread { 65 66 private volatile boolean running = false; 67 68 @Override 69 public void run() { 70 WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE); 71 assert wifiManager != null; 72 WifiManager.MulticastLock multicastLock = wifiManager.createMulticastLock(getClass().getName()); 73 multicastLock.setReferenceCounted(false); 74 multicastLock.acquire();//to receive multicast packets 75 try { 76 ServiceListener listener = new JmdnsListener(); 77 boolean crash = false; 78 while (running) { 79 try { 80 if (crash) { 81 Thread.sleep(3000L); 82 } 83 jsonMap.clear(); 84 // 85 InetAddress addr = getLocalIpAddress(wifiManager); 86 // 87 mJmdns = JmDNS.create(addr); 88 mJmdns.addServiceListener(mServiceName, listener); 89 Thread.sleep(3000L); 90 mJmdns.removeServiceListener(mServiceName, listener); 91 mJmdns.close(); 92 // 93 if (running) { 94 sendCallback(); 95 } 96 crash = false; 97 } catch (Exception e) { 98 e.printStackTrace(); 99 crash = true; 100 } 101 } 102 } finally { 103 multicastLock.release(); 104 } 105 } 106 107 @Override 108 public synchronized void start() { 109 running = true; 110 super.start(); 111 } 112 113 @Override 114 public void interrupt() { 115 running = false; 116 super.interrupt(); 117 } 118 119 public boolean isRunning() { 120 return running; 121 } 122 } 123 124 private class JmdnsListener implements ServiceListener { 125 126 public void serviceAdded(ServiceEvent ev) { 127 mJmdns.requestServiceInfo(ev.getType(), ev.getName(), 1); 128 } 129 130 public void serviceRemoved(ServiceEvent ev) { 131 jsonMap.remove(ev.getName()); 132 } 133 134 public void serviceResolved(ServiceEvent ev) { 135 if (!jsonMap.containsKey(ev.getName())) { 136 JSONObject jsonObj = toJsonObject(ev.getInfo()); 137 jsonMap.put(ev.getName(), jsonObj); 138 } 139 } 140 } 141 142 private void sendCallback() { 143 if (mCallback != null) { 144 JSONArray jsonArray = new JSONArray(); 145 for (JSONObject jsonObj : jsonMap.values()) { 146 jsonArray.put(jsonObj); 147 } 148 mCallback.onDeviceFind(jsonArray); 149 } 150 } 151 152 /** 153 * mDNS數據格式解析 154 */ 155 private JSONObject toJsonObject(ServiceInfo sInfo) { 156 JSONObject jsonObj; 157 try { 158 jsonObj = new JSONObject(); 159 String ipv4 = ""; 160 if (sInfo.getInet4Addresses().length > 0) { 161 ipv4 = sInfo.getInet4Addresses()[0].getHostAddress(); 162 } 163 164 jsonObj.put("Name", sInfo.getName()); 165 jsonObj.put("IP", ipv4); 166 jsonObj.put("Port", sInfo.getPort()); 167 168 byte[] allInfo = sInfo.getTextBytes(); 169 int allLen = allInfo.length; 170 byte fLen; 171 for (int index = 0; index < allLen; index += fLen) { 172 fLen = allInfo[index++]; 173 byte[] fData = new byte[fLen]; 174 System.arraycopy(allInfo, index, fData, 0, fLen); 175 176 String fInfo = new String(fData, StandardCharsets.UTF_8); 177 if (fInfo.contains("=")) { 178 String[] temp = fInfo.split("="); 179 jsonObj.put(temp[0], temp[1]); 180 } 181 } 182 } catch (Exception e) { 183 e.printStackTrace(); 184 jsonObj = null; 185 } 186 return jsonObj; 187 } 188 }
初次發表博客,僅用於記錄以備將來查詢。如有謬誤,多謝指正。