Reputation: 21
I want to write a UPnP control point application for Android using the CyberGarage "CyberLink for Java" API. To test the API I implemented a very simple application. In this application a UPnP control point actively searches for any UPnP root devices, listens for responses and device notifications, and prints a list of the devices, which are available on the network.
The app runs on an Android phone, but none of the UPnP devices on my network are found. I tried this on two different Android phones. To check out if this is an Android specific problem, I implemented the same functionality as a Java console application. Interestingly enough the Java console application works absolutely fine and always shows all of the UPnP devices on my network!
So why does this not work on Android? Note, in the Android app I had to implement the network specific functionality on a seperate thread using AsyncTask. Otherwise I get errors, because I am not supposed to run this on the UI thread. But this should not be the problem, am I right?
Below the source code of the two applications.
Android application:
MainActivity.java
package com.example.controller_v1;
import org.cybergarage.upnp.DeviceList;
import org.cybergarage.upnp.UPnP;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Process;
import android.util.Log;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR);
new StartControlPointTask().execute();
}
private class StartControlPointTask extends AsyncTask {
public static final String TAG = "StartControlPointTask";
@Override
protected Object doInBackground(Object... params) {
Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
MyControlPoint controlPoint = new MyControlPoint();
controlPoint.start();
// controlPoint.search();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
DeviceList rootDevices = controlPoint.getDeviceList();
int numDevices = rootDevices.size();
if (numDevices > 0) {
for (int i = 0; i < numDevices; i++) {
Log.i(TAG, "device " + i + ": " + rootDevices.getDevice(i).getFriendlyName());
}
} else {
Log.i(TAG, "no root devices found");//
}
return null;
}
}
}
MyControlPoint.java
package com.example.controller_v1;
import org.cybergarage.upnp.ControlPoint;
import org.cybergarage.upnp.device.NotifyListener;
import org.cybergarage.upnp.device.SearchResponseListener;
import org.cybergarage.upnp.ssdp.SSDPPacket;
import android.util.Log;
public class MyControlPoint extends ControlPoint implements NotifyListener, SearchResponseListener {
public MyControlPoint() {
addNotifyListener(this);
addSearchResponseListener(this);
}
@Override
public void deviceNotifyReceived(SSDPPacket ssdpPacket) { // NotifyListener
final String TAG = "deviceNotifyReceived";
Log.i(TAG, "executed");
}
@Override
public void deviceSearchResponseReceived(SSDPPacket ssdpPacket) { // SearchResponseListener
final String TAG = "deviceSearchResponseReceived";
Log.i(TAG, "executed");
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.controller_v1"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.controller_v1.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>
Java console application:
Main.java
import org.cybergarage.upnp.DeviceList;
import org.cybergarage.upnp.UPnP;
public class Main {
public Main() {
UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR);
MyControlPoint controlPoint = new MyControlPoint();
controlPoint.start();
// controlPoint.search();
try {
Thread.sleep(5000); // wait for devices to be found
} catch (InterruptedException e) {
e.printStackTrace();
}
DeviceList rootDevices = controlPoint.getDeviceList();
int numDevices = rootDevices.size();
if (numDevices > 0) {
for (int i = 0; i < numDevices; i++) {
System.out.println("found device " + i + ": " + rootDevices.getDevice(i).getFriendlyName());
}
} else {
System.out.println("no root devices found");
}
}
public static void main(String[] args) {
new Main();
}
}
MyControlPoint.java
import org.cybergarage.upnp.ControlPoint;
import org.cybergarage.upnp.device.NotifyListener;
import org.cybergarage.upnp.device.SearchResponseListener;
import org.cybergarage.upnp.ssdp.SSDPPacket;
public class MyControlPoint extends ControlPoint implements /*DeviceChangeListener,*/ NotifyListener, SearchResponseListener {
public MyControlPoint() {
addNotifyListener(this);
addSearchResponseListener(this);
}
@Override
public void deviceNotifyReceived(SSDPPacket packet) { // NotifyListener
System.out.println("deviceNotifyReceived");
}
@Override
public void deviceSearchResponseReceived(SSDPPacket packet) { // SearchResponseListener
System.out.println("deviceSearchReceived");
}
}
I don't have any idea, why the java console application works and the android application doesn't. I don't get any answer from the documentation. Can anybody help me?
Upvotes: 2
Views: 7171
Reputation: 3961
In my case it is displaying all the devices, may be because I'm checking with Phone rather emulator.
Upvotes: 1
Reputation: 31
I lifted your code, compiled it using Eclipse ADT and it ran perfectly on a virtual machine (VMWare player) running Android 4.0 (eeepc).
There is an Android section on CyberGarage website that does say that CyberLink doesn't run on the emulator yet as it doesn't support multicast yet, perhaps that is/was your problem.
Hope not too late to help. Andrew
Upvotes: 1