The previous blog has introduced the SSDP protocol principle, this blog will achieve the implementation of Android SSDP protocol.
Key Technical Analysis: 1, send broadcast, need to send broadcast, so need to use MulticastSocket, socketaddress, inetaddress, need to master.
2, SSDP data report format; When the standard SSDP server resolves, the feature code used for segmented fields is "\ r \ n" and requires special attention.
3, access rights, need the Internet, to add the relevant rights of the network in the Mainfest.
Here is my source code:
1, Ssdpconstants.java
public class Ssdpconstants {
/* New Line definition */
public static final String NEWLINE = "\ r \ n";
public static final String ADDRESS = "239.255.255.250";
public static final int PORT = 1900;
public static final String Sl_msearch = "M-search * http/1.1";
public static final String SL_OK = "http/1.1 OK";
public static final String st_product = "St:urn:schemas-upnp-org:device:server:1";
public static final String Found = "St=urn:schemas-upnp-org:device:";
public static final String Root = "St:urn:schemas-upnp-org:device:dzba_homedp:1";
}
2, Ssdpsearchmsg. java
public class Ssdpsearchmsg {
Static final String host = "HOST:" + SSDP. ADDRESS + ":" + SSDP. PORT;
Static final String man = "man:\" Ssdp:discover\ "";
Static final String NEWLINE = "\ r \ n";
int MMX = 5; /* seconds to delay response */
String MST; /* Search Target */
Public ssdpsearchmsg (String ST) {
MST = ST;
}
public int getmmx () {
return MMX;
}
public void setmmx (int mMX) {
THIS.MMX = MMX;
}
Public String Getmst () {
return MST;
}
public void Setmst (String mST) {
This.mst = MST;
}
@Override
Public String toString () {
StringBuilder content = new StringBuilder ();
Content.append (Ssdp.sl_msearch). Append (NEWLINE);
Content.append (HOST). Append (NEWLINE);
Content.append (man). Append (NEWLINE);
Content.append ("MX:" + MMX). Append (NEWLINE);
Content.append (MST). Append (NEWLINE);
Content.append (NEWLINE);
return content.tostring ();
}
}
3, Ssdpsocket. java
public class Ssdpsocket {
SocketAddress Mssdpmulticastgroup;
MulticastSocket Mssdpsocket;
InetAddress broadcastaddress;
Public Ssdpsocket () throws IOException {
Mssdpsocket = new MulticastSocket (58000); Bind some random port for receiving datagram
BroadcastAddress = Inetaddress.getbyname (ssdpconstants.address);
Mssdpsocket.joingroup (broadcastaddress);
}
/* Used to send SSDP packet */
public void Send (String data) throws IOException {
Datagrampacket DP = new Datagrampacket (Data.getbytes (), Data.length (), broadcastaddress, Ssdpconstants.port);
Mssdpsocket.send (DP);
}
/* Used to receive SSDP packet */
Public Datagrampacket receive () throws IOException {
byte[] buf = new byte[1024];
Datagrampacket DP = new Datagrampacket (buf, buf.length);
Mssdpsocket.receive (DP);
return DP;
}
public void Close () {
if (mssdpsocket! = null) {
Mssdpsocket.close ();
}
}
}
4, SSDP. java
public class SSDP {
/* New Line definition */
public static final String NEWLINE = "\ r \ n";
public static final String ADDRESS = "239.255.255.250";
public static final int PORT = 1900;
public static final String st = "St";
public static final String location = ' location ';
public static final String NT = "NT";
public static final String NTS = "NTS";
/* Definitions of start line */
public static final String sl_notify = "NOTIFY * http/1.1";
public static final String Sl_msearch = "M-search * http/1.1";
public static final String SL_OK = "http/1.1 OK";
@SuppressWarnings ("resource")
public static string Parseheadervalue (string content, String headername) {
Scanner s = new Scanner (content);
S.nextline (); Skip the start line
while (S.hasnextline ()) {
String line = S.nextline ();
int index = Line.indexof (': ');
String Header = line.substring (0, index);
if (Headername.equalsignorecase (Header.trim ())) {
Return line.substring (index + 1). Trim ();
}
}
return null;
}
public static string Parseheadervalue (Datagrampacket dp, string headername) {
Return Parseheadervalue (New String (Dp.getdata ()), headername);
}
@SuppressWarnings ("resource")
public static string Parsestartline (string content) {
Scanner s = new Scanner (content);
return S.nextline ();
}
public static String Parsestartline (Datagrampacket dp) {
Return Parsestartline (New String (Dp.getdata ()));
}
}
5, Mainactivity. java
public class Mainactivity extends Activity implements Onclicklistener {
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Wifimanager wm = (Wifimanager) getsystemservice (Context.wifi_service);
Wifimanager.multicastlock Multicastlock = Wm.createmulticastlock ("Multicastlock");
Multicastlock.setreferencecounted (TRUE);
Multicastlock.acquire ();
Setcontentview (R.layout.activity_main);
(Button) This.findviewbyid (R.id.btnsendssdpsearch)). Setonclicklistener (this);
}
@Override
public void OnClick (View v) {
Switch (V.getid ()) {
Case R.id.btnsendssdpsearch:
New Thread (New Runnable () {
@Override
public void Run () {
Sendmsearchmessage ();
}
}). Start ();
Default
Break
}
}
private void Sendmsearchmessage () {
Ssdpsearchmsg searchcontentdirectory = new Ssdpsearchmsg (ssdpconstants.st_contentdirectory);
Ssdpsearchmsg searchavtransport = new Ssdpsearchmsg (ssdpconstants.st_avtransport);
Ssdpsearchmsg searchproduct = new Ssdpsearchmsg (ssdpconstants.root);
Ssdpsocket sock = null;
try {
Sock = new Ssdpsocket ();
for (int i = 0; i < 2; i++) {
Sock.send (Searchcontentdirectory.tostring ());
Sock.send (Searchavtransport.tostring ());
Sock.send (Searchproduct.tostring ());
// String s = "M-search * http/1.1 \ host= 239.255.255.250:1900 \ n man= \" Ssdp:discover\ "\ n mx:3 \ st= Upnp:rootdevice";
// Sock.send (s);
LOG.I ("-------------", "sent data: \ n" + searchproduct.tostring ());
}
while (true) {
Datagrampacket DP = sock.receive (); Here, I only receive the same packets I initially sent above
String c = new string (Dp.getdata ()). Trim ();
String ip = new String (Dp.getaddress (). toString ()). Trim ();
LOG.I ("------------", "received data: \ n" + C + "Source IP:" + IP);
}
} catch (IOException e) {
LOG.E ("M-search", E.getmessage ());
}
}
}
Interface XML is simple, with only one button
Mainfest.xml:
<?xml version= "1.0" encoding= "Utf-8"?>
<manifest xmlns:android= "Http://schemas.android.com/apk/res/android"
Package= "COM.EXAMPLE.SSDP"
Android:versioncode= "1"
Android:versionname= "1.0" >
<uses-sdk
Android:minsdkversion= "8"
Android:targetsdkversion= "/>"
<uses-permission android:name= "Android.permission.INTERNET"/>
<uses-permission android:name= "Android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name= "Android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name= "Android.permission.ACCESS_NETWORK_STATE"/>
<application
Android:allowbackup= "true"
android:icon= "@drawable/ic_launcher"
Android:label= "@string/app_name"
Android:theme= "@style/apptheme" >
<activity
Android:name= "Com.example.ssdp.MainActivity"
Android:label= "@string/app_name" >
<intent-filter>
<action android:name= "Android.intent.action.MAIN"/>
<category android:name= "Android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
Use notice: Need to have server side run, http://download.csdn.net/detail/zhu530548851/7451201 download source code, the source code is JS.
Place the server in the Linux system directory, enter the test directory, and execute node server.js.
Requires Linux installation with Nodejs:sudo apt-get install Nodejs
This allows the Android client to see information from the server from the log.
Android source code here: http://download.csdn.net/detail/zhu530548851/7451179
Personal hard work results, if reproduced, please indicate the source, thank you!