I have created demo for DLNA by using cling library. i've followed all the instructions given on cling android page. but it's giving me Out of Memory error. i've tested it on HTC salsa and Samsung Galaxy S3.
Log:
08-17 13:45:26.032: E/AndroidRuntime(1504): FATAL EXCEPTION: Thread 12 (Active: 4)
08-17 13:45:26.032: E/AndroidRuntime(1504): java.lang.OutOfMemoryError
08-17 13:45:26.032: E/AndroidRuntime(1504): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:97)
08-17 13:45:26.032: E/AndroidRuntime(1504): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:144)
08-17 13:45:26.032: E/AndroidRuntime(1504): at java.lang.StringBuilder.append(StringBuilder.java:125)
08-17 13:45:26.032: E/AndroidRuntime(1504): at org.teleal.common.http.Headers.readLine(Headers.java:193)
08-17 13:45:26.032: E/AndroidRuntime(1504): at org.teleal.common.http.Headers.<init>(Headers.java:73)
08-17 13:45:26.032: E/AndroidRuntime(1504): at org.teleal.cling.model.message.UpnpHeaders.<init>(UpnpHeaders.java:50)
08-17 13:45:26.032: E/AndroidRuntime(1504): at org.teleal.cling.transport.impl.DatagramProcessorImpl.readRequestMessage(DatagramProcessorImpl.java:127)
08-17 13:45:26.032: E/AndroidRuntime(1504): at org.teleal.cling.transport.impl.DatagramProcessorImpl.read(DatagramProcessorImpl.java:63)
08-17 13:45:26.032: E/AndroidRuntime(1504): at org.teleal.cling.transport.impl.MulticastReceiverImpl.run(MulticastReceiverImpl.java:125)
08-17 13:45:26.032: E/AndroidRuntime(1504): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
08-17 13:45:26.032: E/AndroidRuntime(1504): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
08-17 13:45:26.032: E/AndroidRuntime(1504): at java.lang.Thread.run(Thread.java:1102)
MainActivity:
package com.example.demodlns;
import org.teleal.cling.android.AndroidUpnpService;
import org.teleal.cling.android.AndroidUpnpServiceImpl;
import org.teleal.cling.model.meta.Device;
import org.teleal.cling.model.meta.LocalDevice;
import org.teleal.cling.model.meta.RemoteDevice;
import org.teleal.cling.model.meta.Service;
import org.teleal.cling.registry.DefaultRegistryListener;
import org.teleal.cling.registry.Registry;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.Toast;
public class MainActivity extends ListActivity {
private ArrayAdapter<DeviceDisplay> listAdapter;
private BrowseRegistryListener registryListener = new BrowseRegistryListener();
private AndroidUpnpService upnpService;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
upnpService = null;
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder service) {
// TODO Auto-generated method stub
Log.d("test", "service connection establish");
upnpService = (AndroidUpnpService) service;
// Clear the list
listAdapter.clear();
// Get ready for future device advertisements
upnpService.getRegistry().addListener(registryListener);
// Now add all devices to the list we already know about
for (Device device : upnpService.getRegistry().getDevices()) {
registryListener.deviceAdded(device);
}
// Search asynchronously for all devices, they will respond soon
upnpService.getControlPoint().search();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listAdapter = new ArrayAdapter<DeviceDisplay>(this, android.R.layout.simple_list_item_1);
setListAdapter(listAdapter);
bindService(new Intent(MainActivity.this, AndroidUpnpServiceImpl.class),serviceConnection, Context.BIND_AUTO_CREATE );
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (upnpService != null) {
upnpService.getRegistry().removeListener(registryListener);
}
// This will stop the UPnP service if nobody else is bound to it
getApplicationContext().unbindService(serviceConnection);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
menu.add(0, 0, 0, R.string.searchLAN).setIcon(android.R.drawable.ic_menu_search);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("test","ID:"+ item.getItemId());
if (item.getItemId() == 0 && upnpService != null) {
Log.d("test", "search");
upnpService.getRegistry().removeAllRemoteDevices();
upnpService.getControlPoint().search();
}
return false;
}
class BrowseRegistryListener extends DefaultRegistryListener {
/* Discovery performance optimization for very slow Android devices! */
public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device) {
deviceAdded(device);
}
public void remoteDeviceDiscoveryFailed(Registry registry, final RemoteDevice device, final Exception ex) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(
MainActivity.this,
"Discovery failed of '" + device.getDisplayString() + "': "
+ (ex != null ? ex.toString() : "Couldn't retrieve device/service descriptors"),
Toast.LENGTH_LONG
).show();
}
});
deviceRemoved(device);
}
/* End of optimization, you can remove the whole block if your Android handset is fast (>= 600 Mhz) */
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
deviceAdded(device);
}
public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
deviceRemoved(device);
}
public void localDeviceAdded(Registry registry, LocalDevice device) {
deviceAdded(device);
}
public void localDeviceRemoved(Registry registry, LocalDevice device) {
deviceRemoved(device);
}
public void deviceAdded(final Device device) {
runOnUiThread(new Runnable() {
public void run() {
DeviceDisplay d = new DeviceDisplay(device);
int position = listAdapter.getPosition(d);
if (position >= 0) {
// Device already in the list, re-set new value at same position
listAdapter.remove(d);
listAdapter.insert(d, position);
} else {
listAdapter.add(d);
}
}
});
}
public void deviceRemoved(final Device device) {
Log.d("test", "RDRemove");
runOnUiThread(new Runnable() {
public void run() {
listAdapter.remove(new DeviceDisplay(device));
}
});
}
}
class DeviceDisplay {
Device device;
public DeviceDisplay(Device device) {
this.device = device;
}
public Device getDevice() {
return device;
}
// DOC:DETAILSAndroidUpnpService
public String getDetailsMessage() {
StringBuilder sb = new StringBuilder();
if (getDevice().isFullyHydrated()) {
sb.append(getDevice().getDisplayString());
sb.append("\n\n");
for (Service service : getDevice().getServices()) {
sb.append(service.getServiceType()).append("\n");
}
} else {
sb.append(getString(R.string.deviceDetailsNotYetAvailable));
}
Log.d("test", "SB "+sb.toString());
return sb.toString();
}
// DOC:DETAILS
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DeviceDisplay that = (DeviceDisplay) o;
return device.equals(that.device);
}
@Override
public int hashCode() {
return device.hashCode();
}
@Override
public String toString() {
String name =
getDevice().getDetails() != null && getDevice().getDetails().getFriendlyName() != null
? getDevice().getDetails().getFriendlyName()
: getDevice().getDisplayString();
// Display a little star while the device is being loaded (see performance optimization earlier)
return device.isFullyHydrated() ? name : name + " *";
}
}
}
manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.demodlns"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_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.demodlns.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>
<service android:name="org.teleal.cling.android.AndroidUpnpServiceImpl"/>
</application>
</manifest>
am i missing something? any help appreciated.
thanks in advance.