我使用cling库为 DLNA 创建了演示。我已按照cling android page上给出的所有说明进行操作。但它给了我内存不足的错误。我已经在 HTC salsa 和三星 Galaxy S3 上对其进行了测试。
日志:
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)
主要活动:
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 + " *";
}
}
}
显现:
<?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>
我错过了什么吗?任何帮助表示赞赏。
提前致谢。