您的位置:首页 > 移动开发 > Android开发

android设备局域网中快速搜索之cling方式

2017-07-07 11:28 344 查看
语音在线听书demo:http://blog.csdn.net/ls0609/article/details/71519203

语音记账demo:http://blog.csdn.net/ls0609/article/details/72765789

基于JavaScript用olamisdk实现web端语音识别语义理解(speex压缩)

http://blog.csdn.net/ls0609/article/details/73920229

在物联网时代,有时需要在局域网中快速搜索设备,本片讲述cling搜索的一个例子。

UPnP全名是Universal Plug and Play,主要是微软在推行的一个标准。简单的来说,UPnP 最大的愿景就是希望任何设备只要一接上网络,所有在网络上的设备马上就能知道有新设备加入,这些设备彼此之间能互相沟通,更能直接使用或控制它,一切都不需要设定,完全的Plug and Play。

cling就是采用了这个协议来进行服务端的注册和客户端的扫描发现。

服务端注册后,客户端扫描大概时间在2-5秒,就像windows平台局域网刷新群组内成员一样迅速,如下图扫描结果:



首先看服务端如何注册

public class MainActivity extends Activity implements PropertyChangeListener {

// DOC:CLASS
private static final Logger log = Logger.getLogger(MainActivity.class.getName());

// DOC:SERVICE_BINDING
private AndroidUpnpService upnpService;

private UDN udn = new UDN(UUID.randomUUID()); // TODO: Not stable!

private ServiceConnection serviceConnection = new ServiceConnection() {

public void onServiceConnected(ComponentName className, IBinder service) {
upnpService = (AndroidUpnpService) service;

LocalService<SwitchPower> switchPowerService = getSwitchPowerService();

// Register the device when this activity binds to the service for the first time
if (switchPowerService == null) {
try {
LocalDevice binaryLightDevice = createDevice();

Toast.makeText(MainActivity.this, R.string.registeringDevice,
Toast.LENGTH_SHORT).show();
upnpService.getRegistry().addDevice(binaryLightDevice);

switchPowerService = getSwitchPowerService();

11461
} catch (Exception ex) {
log.log(Level.SEVERE, "Creating BinaryLight device failed", ex);
Toast.makeText(MainActivity.this, R.string.createDeviceFailed,
Toast.LENGTH_SHORT).show();
return;
}
}

// Obtain the state of the power switch and update the UI
setLightbulb(switchPowerService.getManager().getImplementation().getStatus());

// Start monitoring the power switch
switchPowerService.getManager().getImplementation().getPropertyChangeSupport()
.addPropertyChangeListener(MainActivity.this);

}

public void onServiceDisconnected(ComponentName className) {
upnpService = null;
}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DOC:LOGGING
// Fix the logging integration between java.util.logging and Android internal logging
// org.seamless.util.logging.LoggingUtil.resetRootHandler(
//    new FixedAndroidLogHandler()
// );
// Logger.getLogger("org.fourthline.cling").setLevel(Level.FINEST);
// DOC:LOGGING

setContentView(R.layout.light);

getApplicationContext().bindService(
new Intent(this, AndroidUpnpServiceImpl.class),
serviceConnection,
Context.BIND_AUTO_CREATE
);
}

@Override
protected void onDestroy() {
super.onDestroy();

// Stop monitoring the power switch
LocalService<SwitchPower> switchPowerService = getSwitchPowerService();
if (switchPowerService != null)
switchPowerService.getManager().getImplementation().getPropertyChangeSupport()
.removePropertyChangeListener(this);

getApplicationContext().unbindService(serviceConnection);
}

protected LocalService<SwitchPower> getSwitchPowerService() {
if (upnpService == null)
return null;

LocalDevice binaryLightDevice;
if ((binaryLightDevice = upnpService.getRegistry().getLocalDevice(udn, true)) == null)
return null;

return (LocalService<SwitchPower>)
binaryLightDevice.findService(new UDAServiceType("SwitchPower", 1));
}
// DOC:SERVICE_BINDING

@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, R.string.switchRouter).setIcon(android.R.drawable.ic_menu_revert);
menu.add(0, 1, 0, R.string.toggleDebugLogging).setIcon(android.R.drawable.ic_menu_info_details);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
if (upnpService != null) {
Router router = upnpService.get().getRouter();
try {
if (router.isEnabled()) {
Toast.makeText(this, R.string.disablingRouter,
Toast.LENGTH_SHORT).show();
router.disable();
} else {
Toast.makeText(this, R.string.enablingRouter,
Toast.LENGTH_SHORT).show();
router.enable();
}
} catch (RouterException ex) {
Toast.makeText(this, getText(R.string.errorSwitchingRouter) +
ex.toString(), Toast.LENGTH_LONG).show();
ex.printStackTrace(System.err);
}
}
break;
case 1:
Logger logger = Logger.getLogger("org.fourthline.cling");
if (logger.getLevel() != null && !logger.getLevel().equals(Level.INFO)) {
Toast.makeText(this, R.string.disablingDebugLogging,
Toast.LENGTH_SHORT).show();
logger.setLevel(Level.INFO);
} else {
Toast.makeText(this, R.string.enablingDebugLogging,
Toast.LENGTH_SHORT).show();
logger.setLevel(Level.FINEST);
}
break;
}
return false;
}

// DOC:PROPERTY_CHANGE
public void propertyChange(PropertyChangeEvent event) {
// This is regular JavaBean eventing, not UPnP eventing!
if (event.getPropertyName().equals("status")) {
log.info("Turning light: " + event.getNewValue());
setLightbulb((Boolean) event.getNewValue());
}
}

protected void setLightbulb(final boolean on) {
runOnUiThread(new Runnable() {
public void run() {
ImageView imageView = (ImageView) findViewById(R.id.light_imageview);
imageView.setImageResource(on ? R.drawable.light_on :
R.drawable.light_off);
// You can NOT externalize this color into /res/values/colors.xml.
//Go on, try it!
imageView.setBackgroundColor(on ? Color.parseColor("#9EC942") :
Color.WHITE);
}
});
}
// DOC:PROPERTY_CHANGE

// DOC:CREATE_DEVICE
protected LocalDevice createDevice()
throws ValidationException, LocalServiceBindingException {

DeviceType type =
new UDADeviceType("BinaryLight", 1);

DeviceDetails details =
new DeviceDetails(
"MusicBox",//"Friendly Binary Light",
new ManufacturerDetails("ACME"),
new ModelDetails("Music_box_11000", "10.3.172.27", "v1")//new ModelDetails("AndroidLight", "A light with on/off switch.", "v1")
);

LocalService service = new AnnotationLocalServiceBinder().read(SwitchPower.class);

service.setManager(new DefaultServiceManager<SwitchPower>(service, SwitchPower.class));

return new LocalDevice(
new DeviceIdentity(udn),
type,
details,
createDefaultDeviceIcon(),
service
);
}


服务端注册了一个ServiceConnection,createDevice()函数中的DeviceDetails中加入了设备的描述

upnpService.getRegistry().addDevice(binaryLightDevice);注册了这个设备到服务端,只有注册了才能搜索到。

再来看看扫描的客户端代码:

public class MainActivity extends ListActivity {

// DOC:CLASS
// DOC:SERVICE_BINDING
private ArrayAdapter<DeviceDisplay> listAdapter;

private BrowseRegistryListener registryListener = new BrowseRegistryListener();

private AndroidUpnpService upnpService;

private ServiceConnection serviceConnection = new ServiceConnection() {

public void onServiceConnected(ComponentName className, IBinder service) {
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();
}

public void onServiceDisconnected(ComponentName className) {
upnpService = null;
}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Fix the logging integration between java.util.logging and Android internal logging
org.seamless.util.logging.LoggingUtil.resetRootHandler(
new FixedAndroidLogHandler()
);
// Now you can enable logging as needed for various categories of Cling:
// Logger.getLogger("org.fourthline.cling").setLevel(Level.FINEST);

listAdapter = new ArrayAdapter<DeviceDisplay>(this, android.R.layout.simple_list_item_1);
setListAdapter(listAdapter);

// This will start the UPnP service if it wasn't already started
getApplicationContext().bindService(
new Intent(this, AndroidUpnpServiceImpl.class),
serviceConnection,
Context.BIND_AUTO_CREATE
);
}

@Override
protected void onDestroy() {
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);
}
// DOC:SERVICE_BINDING

// DOC:MENU
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, R.string.searchLAN).setIcon(android.R.drawable.ic_menu_search);
// DOC:OPTIONAL
menu.add(0, 1, 0, R.string.switchRouter).setIcon(android.R.drawable.ic_menu_revert);
menu.add(0, 2, 0, R.string.toggleDebugLogging).setIcon(android.R.drawable.ic_menu_info_details);
// DOC:OPTIONAL
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
if (upnpService == null)
break;
Toast.makeText(this, R.string.searchingLAN, Toast.LENGTH_SHORT).show();
upnpService.getRegistry().removeAllRemoteDevices();
upnpService.getControlPoint().search();
break;
// DOC:OPTIONAL
case 1:
if (upnpService != null) {
Router router = upnpService.get().getRouter();
try {
if (router.isEnabled()) {
Toast.makeText(this, R.string.disablingRouter,
Toast.LENGTH_SHORT).show();
router.disable();
} else {
Toast.makeText(this, R.string.enablingRouter,
Toast.LENGTH_SHORT).show();
router.enable();
}
} catch (RouterException ex) {
Toast.makeText(this, getText(R.string.errorSwitchingRouter) +
ex.toString(), Toast.LENGTH_LONG).show();
ex.printStackTrace(System.err);
}
}
break;
case 2:
Logger logger = Logger.getLogger("org.fourthline.cling");
if (logger.getLevel() != null && !logger.getLevel().equals(Level.INFO)) {
Toast.makeText(this, R.string.disablingDebugLogging,
Toast.LENGTH_SHORT).show();
logger.setLevel(Level.INFO);
} else {
Toast.makeText(this, R.string.enablingDebugLogging,
Toast.LENGTH_SHORT).show();
logger.setLevel(Level.FINEST);
}
break;
// DOC:OPTIONAL
}
return false;
}
// DOC:MENU

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
AlertDialog dialog = new AlertDialog.Builder(this).create();
dialog.setTitle(R.string.deviceDetails);
DeviceDisplay deviceDisplay = (DeviceDisplay)l.getItemAtPosition(position);
dialog.setMessage(deviceDisplay.getDetailsMessage());
dialog.setButton(
getString(R.string.OK),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
}
);
dialog.show();
TextView textView = (TextView) dialog.findViewById(android.R.id.message);
textView.setTextSize(12);
super.onListItemClick(l, v, position, id);
}

protected class BrowseRegistryListener extends DefaultRegistryListener {

/* Discovery performance optimization for very slow Android devices! */
@Override
public void remoteDeviceDiscoveryStarted(Registry registry,
RemoteDevice device)
{
deviceAdded(device);
}

@Override
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) */

@Override
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
deviceAdded(device);
}

@Override
public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
deviceRemoved(device);
}

@Override
public void localDeviceAdded(Registry registry, LocalDevice device) {
deviceAdded(device);
}

@Override
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) {
runOnUiThread(new Runnable() {
public void run() {
listAdapter.remove(new DeviceDisplay(device));
}
});
}
}

protected class DeviceDisplay {

Device device;

public DeviceDisplay(Device device) {
this.device = device;
}

public Device getDevice() {
return device;
}

// DOC:DETAILS
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));
}
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().getFriendlyName() +" "
+getDevice().getDetails().getModelDetails().getModelName()+
getDevice().getDetails().getModelDetails().getModelDescription();
return name;//device.isFullyHydrated() ? name : name + " *";
}
}
}


当ServiceConnection,onServiceConnected后,执行for循环添加设备

for (Device device : upnpService.getRegistry().getDevices()) {

registryListener.deviceAdded(device);

}

通过关联listview进行显示,

在下面函数中,可以看到搜索到设备的具体信息

public String toString() {
String name = getDevice().getDetails().getFriendlyName() +" "
+getDevice().getDetails().getModelDetails().getModelName()+
getDevice().getDetails().getModelDetails().getModelDescription();
return name;//device.isFullyHydrated() ? name : name + " *";
}


代码下载地址

语音在线听书demo:http://blog.csdn.net/ls0609/article/details/71519203

语音记账demo:http://blog.csdn.net/ls0609/article/details/72765789

基于javascript用olamisdk实现web端语音识别语义理解(speex压缩)

http://blog.csdn.net/ls0609/article/details/73920229
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息