Search...

Thursday, December 29, 2011

How to use UPNP search in android?


Copy the below classes in your project and call TestUpnp class.


Main-


public class TestUpnp{


public static void main(String args[]){


    TestUPNPDevice[] devices = TestUpnpManager.getInstance()


.discoverDevices(TestvUPNPConstant.ALL_UPNP_DEVICES, null);

        for(TestUPNPDevice:devices){
             //print searched devices.

         }

     }


}

(0) TestUpnpManager 
package com.code.upnp;

/***
 *
 * Upnp Manager class.
 *
 *
 */
import java.io.IOException;
import com.directv.common.lib.upnp.util.DirectvDiscovery;
import com.directv.common.lib.upnp.util.DirectvUPNPDevice;

public class TestUpnpManager {

private static DirectvUpnpManager singleton = null;

private DirectvUpnpManager() {
}

public final static DirectvUpnpManager getInstance() {

synchronized (DirectvUpnpManager.class) {

if (singleton == null) {
singleton = new DirectvUpnpManager();
}

}
return singleton;
}

public DirectvUPNPDevice[] discoverDevices(String searchTarget,
String manufacName) throws IOException, Exception {

return DirectvDiscovery.discoverDevices(searchTarget, manufacName);
}

}




(1)TestDiscovery.java

package com.code.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import com.Test.navigator.TestApplication;

import android.util.Log;

public class TestDiscovery {

// XML tag name returned from each device.
private final static String DEVICE_TYPE = "deviceType";
private final static String FRIENDLY_NAME = "friendlyName";
private final static String MANUFACTURER = "manufacturer";
private final static String MANUFACTURER_URL = "manufacturerURL";
private final static String MODEL_DESC = "modelDescription";
private final static String MODEL_NAME = "modelName";
private final static String MODEL_NUMBER = "modelNumber";
private final static String UDN = "UDN";
private final static String URL_BASE = "URLBase";
private static boolean DEBUG = TestApplication.showLogs();

public TestDiscovery(){
DEBUG = TestApplication.showLogs();
}

/***
* It will send the http request using supplied url
*
* @param url
* @return http reponse.
* @throws URISyntaxException
* @throws ClientProtocolException
* @throws IOException
*/
static public InputStream getUrlData(String url) throws URISyntaxException,
ClientProtocolException, IOException {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet method = new HttpGet(new URI(url));

HttpResponse res = client.execute(method);
return res.getEntity().getContent();
}

/***
* Parse the XML response by using Pull parser and set bean for device
*
*
* @param location
* @return Device Object
* @throws IOException
* @throws Exception
*/

static public TestUPNPDevice getDeviceInfo(String location)
throws IOException, Exception {

TestUPNPDevice device = new TestUPNPDevice();

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();

xpp.setInput(new InputStreamReader(getUrlData(location)));

int eventType = xpp.getEventType();
String currentTagName = null;
while (eventType != XmlPullParser.END_DOCUMENT) {

if (eventType == XmlPullParser.START_TAG) {
currentTagName = xpp.getName();

if(DEBUG){
Log.d("TAG NAME", currentTagName);
}

} else if (eventType == XmlPullParser.TEXT) {

if (currentTagName != null) {

if (currentTagName.equalsIgnoreCase(DEVICE_TYPE)) {
device.setDeviceType(xpp.getText());
} else if (currentTagName.equalsIgnoreCase(FRIENDLY_NAME)) {
device.setFriendlyName(xpp.getText());
} else if (currentTagName.equalsIgnoreCase(MANUFACTURER)) {
device.setManufacturer(xpp.getText());
} else if (currentTagName
.equalsIgnoreCase(MANUFACTURER_URL)) {
device.setManufacturerURL(xpp.getText());
} else if (currentTagName.equalsIgnoreCase(MODEL_DESC)) {
device.setModelDescription(xpp.getText());
} else if (currentTagName.equalsIgnoreCase(MODEL_NAME)) {
device.setModelName(xpp.getText());
} else if (currentTagName.equalsIgnoreCase(MODEL_NUMBER)) {
device.setModelNumber(xpp.getText());
} else if (currentTagName.equalsIgnoreCase(UDN)) {
device.setUDN(xpp.getText());
} else if (currentTagName.equalsIgnoreCase(URL_BASE)) {
device.setUrlBase(xpp.getText());
}

if(DEBUG){
Log.d("TAG VALUE", xpp.getText());
}
currentTagName = null;
}

}
eventType = xpp.next();
}

return device;

}

/***
*
* Main method to start searching UPNP devices.
*
*
* @param searchTarget
* @param manufacName
* @return array of Device object
* @throws IOException
* @throws Exception
*/

public static TestUPNPDevice[] discoverDevices(String searchTarget,
String manufacName) throws IOException, Exception {
if (searchTarget == null || searchTarget.trim().length() == 0) {
throw new IllegalArgumentException("Illegal searchTarget");
}

final Map<String, TestUPNPDevice> devices = new HashMap<String, TestUPNPDevice>();
final String manufacturerName = manufacName;

// Implement the device discovery handler.
TestDiscoveryResultsHandler handler = new TestDiscoveryResultsHandler() {

public void discoveredDevice(String usn, URL location)
throws IOException, Exception {

if(DEBUG){
Log.i("NEW", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
Log.i("DEVICE LOCATION", location.toString());
Log.i("DEVICE USN", usn);
}

TestUPNPDevice searchedDevice = getDeviceInfo(location
.toString());
if (searchedDevice != null) {

if (manufacturerName != null
&& searchedDevice.getManufacturer() != null) {
// Only the requested manufacturer device should be
// added.
if (searchedDevice.getManufacturer().equalsIgnoreCase(
manufacturerName)) {
devices.put(usn, searchedDevice);
}
} else {
devices.put(usn, searchedDevice);
}

}

}
};

// Register the device discovery handler so that it should be call when
// each device is discovered.

TestDiscoveryListener.getInstance().registerResultsHandler(handler,
searchTarget);

// Find the User Internet address and send the Multicast message
for (Enumeration<?> e = NetworkInterface.getNetworkInterfaces(); e
.hasMoreElements();) {
NetworkInterface intf = (NetworkInterface) e.nextElement();
for (Enumeration<?> adrs = intf.getInetAddresses(); adrs
.hasMoreElements();) {
InetAddress adr = (InetAddress) adrs.nextElement();
if (adr instanceof Inet4Address && !adr.isLoopbackAddress()) {
sendSearchMessage(adr, TestUPNPConstant.DEFAULT_TTL,
TestUPNPConstant.DEFAULT_MX, searchTarget);
}
}
}

// Wait for sometime to get response from all the upnp devices on
// network.
try {
Thread.sleep(TestUPNPConstant.DEFAULT_TIMEOUT);
} catch (InterruptedException ex) {
// don't care
}

// Unregister the device discovery handler.
TestDiscoveryListener.getInstance().unRegisterResultsHandler(
handler, searchTarget);

// Create array to put all the searched devices.
int j = 0;

TestUPNPDevice[] rootDevices = new TestUPNPDevice[devices.size()];
for (Iterator<TestUPNPDevice> i = devices.values().iterator(); i.hasNext();) {

rootDevices[j++] = (TestUPNPDevice) i.next();
}
if(DEBUG){
Log.i("TOTAL DEVICE FOUND", rootDevices.length + "");
}
return rootDevices;

}

/**
* Sends an SSDP search message on the network
*
* @param src
*            the sender ip
* @param ttl
*            the time to live
* @param mx
*            the mx field
* @param searchTarget
*            the search target
* @throws IOException
*             if some IO errors occurs during search
*/
public static void sendSearchMessage(InetAddress src, int ttl, int mx,
String searchTarget) throws IOException {

InetSocketAddress adr = new InetSocketAddress(
InetAddress.getByName(TestUPNPConstant.SSDP_IP),
TestUPNPConstant.SSDP_PORT);

java.net.MulticastSocket skt = new java.net.MulticastSocket(null);
skt.bind(new InetSocketAddress(src,
TestUPNPConstant.DEFAULT_SSDP_SEARCH_PORT));
skt.setTimeToLive(ttl);
StringBuffer packet = new StringBuffer();
packet.append("M-SEARCH * HTTP/1.1\r\n");
packet.append("HOST: ").append(TestUPNPConstant.SSDP_IP).append(":")
.append(TestUPNPConstant.SSDP_PORT).append("\r\n");
packet.append("MAN: \"ssdp:discover\"\r\n");
packet.append("MX: ").append(mx).append("\r\n");
packet.append("ST: ").append(searchTarget).append("\r\n")
.append("\r\n");
if (TestUPNPConstant.ENABLE_LOG) {
System.out.println("Sending discovery message on "
+ TestUPNPConstant.SSDP_IP + ":"
+ TestUPNPConstant.SSDP_PORT
+ "multicast address from ip " + src.getHostAddress()
+ ":\n" + packet.toString());
}
String toSend = packet.toString();
byte[] pk = toSend.getBytes();
skt.send(new DatagramPacket(pk, pk.length, adr));
skt.disconnect();
skt.close();
}

}

(2)TestDiscoveryListener.java

package com.code.util;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/****
 *
 *
 *
 * This class has the logic to listen the multicast response and process it.
 *
 *
 *
 */
public class TestDiscoveryListener implements Runnable {

private static boolean MATCH_IP = true;
private Map<String, Set<TestDiscoveryResultsHandler>> registeredHandlers = new HashMap<String, Set<TestDiscoveryResultsHandler>>();
private final Object REGISTRATION_PROCESS = new Object();
private final static TestDiscoveryListener singleton = new TestDiscoveryListener();
private boolean inService = false;
private boolean daemon = true;
private java.net.MulticastSocket skt;
private DatagramPacket input;

private TestDiscoveryListener() {
}

public final static TestDiscoveryListener getInstance() {
return singleton;
}

/**
* Sets the listener as a daemon thread
*
* @param daemon
*            daemon thread
*/
public void setDaemon(boolean daemon) {
this.daemon = daemon;
}

/**
* Registers an SSDP response message handler
*
* @param resultsHandler
*            the SSDP response message handler
* @param searchTarget
*            the search target
* @throws IOException
*             if some errors occurs during SSDP search response messages
*             listener thread startup
*/
public void registerResultsHandler(
TestDiscoveryResultsHandler resultsHandler, String searchTarget)
throws IOException, Exception {
synchronized (REGISTRATION_PROCESS) {
if (!inService)
startDevicesListenerThread();
Set<TestDiscoveryResultsHandler> handlers = registeredHandlers.get(searchTarget);
if (handlers == null) {
handlers = new HashSet<TestDiscoveryResultsHandler>();
registeredHandlers.put(searchTarget, handlers);
}
handlers.add(resultsHandler);
}
}

/**
* Unregisters an SSDP response message handler
*
* @param resultsHandler
*            the SSDP response message handler
* @param searchTarget
*            the search target
*/
public void unRegisterResultsHandler(
TestDiscoveryResultsHandler resultsHandler, String searchTarget) {
synchronized (REGISTRATION_PROCESS) {
Set<TestDiscoveryResultsHandler> handlers = registeredHandlers.get(searchTarget);
if (handlers != null) {
handlers.remove(resultsHandler);
if (handlers.size() == 0) {
registeredHandlers.remove(searchTarget);
}
}
if (registeredHandlers.size() == 0) {
stopDevicesListenerThread();
}
}
}

private void startDevicesListenerThread() throws IOException, Exception {
synchronized (singleton) {
if (!inService) {

this.startMultiCastSocket();
Thread deamon = new Thread(this,
"TestDiscoveryListener daemon");
deamon.setDaemon(daemon);
deamon.start();
while (!inService) {
// wait for the thread to be started let's wait a few ms
try {
Thread.sleep(2);
} catch (InterruptedException ex) {
// don t care
}
}
}
}
}

private void stopDevicesListenerThread() {
synchronized (singleton) {
inService = false;
}
}

private void startMultiCastSocket() throws IOException {
int bindPort = TestUPNPConstant.DEFAULT_SSDP_SEARCH_PORT;

skt = new java.net.MulticastSocket(null);
skt.bind(new InetSocketAddress(InetAddress.getByName("0.0.0.0"),
bindPort));
skt.setTimeToLive(TestUPNPConstant.DEFAULT_TTL);
skt.setSoTimeout(TestUPNPConstant.DEFAULT_TIMEOUT);
skt.joinGroup(InetAddress.getByName(TestUPNPConstant.SSDP_IP));

byte[] buf = new byte[2048];
input = new DatagramPacket(buf, buf.length);

}

public void run() {
if (!Thread.currentThread().getName()
.equals("TestDiscoveryListener daemon")) {
throw new RuntimeException("No right to call this method");
}
inService = true;
while (inService) {
try {
listenBroadCast();
} catch (SocketTimeoutException ex) {
// ignoring

} catch (IOException ioEx) {
// if(TestApplication.showLogs() == true){
// Log.e("IOException","IO Exception during UPNP TestDiscoveryListener messages listening thread" + ioEx);
// }

} catch (Exception ex) {
// if(TestApplication.showLogs() == true){
// Log.e("Exception", "Fatal Error during UPNP TestDiscoveryListener messages listening thread, thread will exit" + ex);
// }
inService = false;
}
}

try {
skt.leaveGroup(InetAddress.getByName(TestUPNPConstant.SSDP_IP));
skt.close();
} catch (Exception ex) {
// ignoring
}
}

private void listenBroadCast() throws IOException, Exception {

skt.receive(input);
InetAddress from = input.getAddress();
String received = new String(input.getData(), input.getOffset(),
input.getLength());

TestHttpResponse msg = null;
try {
msg = new TestHttpResponse(received);
} catch (IllegalArgumentException ex) {

// if(TestApplication.showLogs() == true){
// Log.i("SKIPPING", "Skipping uncompliant HTTP message " + received);
// }

return;
}
String header = msg.getHeader();
if (header != null && header.startsWith("HTTP/1.1 200 OK")
&& msg.getHTTPHeaderField("st") != null) {
// probably a search repsonse !
String deviceDescrLoc = msg.getHTTPHeaderField("location");
if (deviceDescrLoc == null || deviceDescrLoc.trim().length() == 0) {
// if(TestApplication.showLogs() == true){
// Log.i("SKIPPING","Skipping SSDP message, missing HTTP header 'location' field");
// }

return;
}
URL loc = new URL(deviceDescrLoc);
if (MATCH_IP) {
InetAddress locHost = InetAddress.getByName(loc.getHost());
if (!from.equals(locHost)) {
// if(TestApplication.showLogs() == true){
// Log.i("SKIPPING", "Discovery message sender IP " + from + " does not match device description IP " + locHost);
// }
return;
}
}

// if(TestApplication.showLogs() == true){
// Log.i("PROCESSING", "Processing " + deviceDescrLoc + " device description location ");
// }

String st = msg.getHTTPHeaderField("st");
if (st == null || st.trim().length() == 0) {
// if(TestApplication.showLogs() == true){
// Log.i("SKIPPING", "Skipping SSDP message, missing HTTP header 'st' field");
// }

return;
}
String usn = msg.getHTTPHeaderField("usn");
if (usn == null || usn.trim().length() == 0) {
// if(TestApplication.showLogs() == true){
// Log.i("SKIPPING", "Skipping SSDP message, missing HTTP header 'usn' field");
// }
return;
}

synchronized (REGISTRATION_PROCESS) {
Set<TestDiscoveryResultsHandler> handlers = registeredHandlers.get(st);
if (handlers != null) {
for (Iterator<TestDiscoveryResultsHandler> i = handlers.iterator(); i.hasNext();) {
TestDiscoveryResultsHandler handler = (TestDiscoveryResultsHandler) i
.next();
handler.discoveredDevice(usn, loc);
}
}
}
} else {
// if(TestApplication.showLogs() == true){
// Log.i("SKIPPING", "Skipping uncompliant HTTP message"+ received);
// }
}
}
}


(3)TestDiscoveryResultsHandler.java


package com.code.util;

/****
 *
 * This interface is used to handle discovered devices.
 *
 */

import java.io.IOException;

public interface TestDiscoveryResultsHandler {

public void discoveredDevice(String usn, java.net.URL location)
throws IOException, Exception;

}


(4)TestHttpResponse.java

package com.code.util;

import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * Process the http response and store it for future use.
 *
 *
 */
public class TestHttpResponse {

private String header;
private Map<String, String> fields;
private String body;

/**
* Constructor of the response, will try to parse the raw response data
*
* @param rawHttpResponse
*            the raw response data
* @throws IllegalArgumentException
*             if some error occurs during parsing
*/
protected TestHttpResponse(String rawHttpResponse)
throws IllegalArgumentException {
if (rawHttpResponse == null || rawHttpResponse.trim().length() == 0) {
throw new IllegalArgumentException("Empty HTTP response message");
}
boolean bodyParsing = false;
StringBuffer bodyParsed = new StringBuffer();
fields = new HashMap<String, String>();
String[] lines = rawHttpResponse.split("\\r\\n");
this.header = lines[0].trim();

for (int i = 1; i < lines.length; i++) {

String line = lines[i];
if (line.length() == 0) {
// line break before body
bodyParsing = true;
} else if (bodyParsing) {
// we parse the message body
bodyParsed.append(line).append("\r\n");
} else {
// we parse the header
if (line.length() > 0) {
int delim = line.indexOf(':');
if (delim != -1) {
String key = line.substring(0, delim).toUpperCase();
String value = line.substring(delim + 1).trim();
fields.put(key, value);
} else {
throw new IllegalArgumentException(
"Invalid HTTP message header :" + line);
}
}
}
}
if (bodyParsing) {
body = bodyParsed.toString();
}
}

public String getHeader() {
return header;
}

public String getBody() {
return body;
}

public String getHTTPFieldElement(String fieldName, String elementName)
throws IllegalArgumentException {
String fieldNameValue = getHTTPHeaderField(fieldName);
if (fieldName != null) {

StringTokenizer tokenizer = new StringTokenizer(
fieldNameValue.trim(), ",");
while (tokenizer.countTokens() > 0) {
String nextToken = tokenizer.nextToken().trim();
if (nextToken.startsWith(elementName)) {
int index = nextToken.indexOf("=");
if (index != -1) {
return nextToken.substring(index + 1).trim();
}
}
}
}
throw new IllegalArgumentException("HTTP element field " + elementName
+ " is not present");
}

public String getHTTPHeaderField(String fieldName)
throws IllegalArgumentException {
String field = (String) fields.get(fieldName.toUpperCase());
if (field == null) {
throw new IllegalArgumentException("HTTP field " + fieldName
+ " is not present");
}
return field;
}

}



(5)TestUPNPConstant.java

package com.code.util;

/****
 *
 * This class contains Constants which are used during Upnp Device search over
 * network.
 *
 */
public class TestUPNPConstant {

public final static String ALL_UPNP_DEVICES = "upnp:rootdevice";
public final static String UPNP_MEDIA_RENDERER_DEVICES = "urn:schemas-upnp-org:device:MediaRenderer:1";

public static final int DEFAULT_MX = 3;
public static final int DEFAULT_TTL = 4;
public static final int DEFAULT_TIMEOUT = 5000;
public static final int DEFAULT_SSDP_SEARCH_PORT = 1901;
public final static String SSDP_IP = "239.255.255.250";
public final static int SSDP_PORT = 1900;
public static final boolean ENABLE_LOG = false;

public final static String MANUFACTURER_NAME = "Test";

}


(6)TestUPNPDevice 

package com.code.util;

/****
 *
 * This is a bean class for UPNP Device.
 *
 */
public class TestUPNPDevice {

private String deviceType;
private String friendlyName;
private String manufacturer;
private String manufacturerURL;

private String modelDescription;
private String modelName;
private String modelNumber;
private String urlBase;
private String UDN;

public String getDeviceType() {
return deviceType;
}

public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}

public String getFriendlyName() {
return friendlyName;
}

public void setFriendlyName(String friendlyName) {
this.friendlyName = friendlyName;
}

public String getManufacturer() {
return manufacturer;
}

public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}

public String getManufacturerURL() {
return manufacturerURL;
}

public void setManufacturerURL(String manufacturerURL) {
this.manufacturerURL = manufacturerURL;
}

public String getModelDescription() {
return modelDescription;
}

public void setModelDescription(String modelDescription) {
this.modelDescription = modelDescription;
}

public String getModelName() {
return modelName;
}

public void setModelName(String modelName) {
this.modelName = modelName;
}

public String getModelNumber() {
return modelNumber;
}

public void setModelNumber(String modelNumber) {
this.modelNumber = modelNumber;
}

public String getUrlBase() {
return urlBase;
}

public void setUrlBase(String urlBase) {
this.urlBase = urlBase;
}

public String getUDN() {
return UDN;
}

public void setUDN(String uDN) {
UDN = uDN;
}

}






No comments:

Post a Comment