diff --git a/src/com/connectsdk/device/ConnectableDevice.java b/src/com/connectsdk/device/ConnectableDevice.java index d63230e5..d5696886 100644 --- a/src/com/connectsdk/device/ConnectableDevice.java +++ b/src/com/connectsdk/device/ConnectableDevice.java @@ -97,6 +97,10 @@ public class ConnectableDevice implements DeviceServiceListener { Map services; + private String serviceId; + + public boolean isConnecting = false; + public boolean featuresReady = false; public ConnectableDevice() { @@ -323,11 +327,18 @@ public List getListeners() { * It is always necessary to call connect on a ConnectableDevice, even if it contains no connectable DeviceServices. */ public void connect() { - for (DeviceService service : services.values()) { - if (!service.isConnected()) { - service.connect(); + new Thread(new Runnable() { + @Override + public void run() { + isConnecting = true; + for (DeviceService service : services.values()) { + if (!service.isConnected()) { + service.connect(); + } + } + isConnecting = false; } - } + }).start(); } /** @@ -365,7 +376,10 @@ public boolean isConnected() { } } - return connectedCount >= services.size(); + // In case of Service Integration, a device is assumed as connected, + // if a service in the device is connected. + return connectedCount >= 1; + //return connectedCount >= services.size(); } // @endcond @@ -927,4 +941,12 @@ private int getConnectedServiceCount() { } // @endcond + + public void setServiceId(String srvId) { + serviceId = srvId; + } + + public String getServiceId() { + return serviceId; + } } diff --git a/src/com/connectsdk/device/DevicePickerListView.java b/src/com/connectsdk/device/DevicePickerListView.java index 76b27eb0..095529e5 100644 --- a/src/com/connectsdk/device/DevicePickerListView.java +++ b/src/com/connectsdk/device/DevicePickerListView.java @@ -52,7 +52,7 @@ public void run() { } @Override - public void onDeviceAdded(DiscoveryManager manager, final ConnectableDevice device) { + public void onDeviceAdded(final DiscoveryManager manager, final ConnectableDevice device) { Util.runOnUI(new Runnable () { @Override public void run() { @@ -73,9 +73,12 @@ public void run() { if (d.getIpAddress().equals(device.getIpAddress())) { if (d.getFriendlyName().equals(device.getFriendlyName())) { - pickerAdapter.remove(d); - pickerAdapter.insert(device, i); - return; + if (!manager.isServiceIntegrationEnabled() && + d.getServiceId().equals(device.getServiceId())) { + pickerAdapter.remove(d); + pickerAdapter.insert(device, i); + return; + } } } diff --git a/src/com/connectsdk/discovery/DiscoveryManager.java b/src/com/connectsdk/discovery/DiscoveryManager.java index 3f924d47..853ad466 100644 --- a/src/com/connectsdk/discovery/DiscoveryManager.java +++ b/src/com/connectsdk/discovery/DiscoveryManager.java @@ -143,6 +143,36 @@ public enum PairingLevel { // @endcond + /** + * If serviceIntegrationEnabled is false (default), all services look like in different devices. + * If serviceIntegrationEnabled is true, services in a device are managed by one device instance. + */ + private boolean serviceIntegrationEnabled = false; + + public void setServiceIntegration(boolean value) { + serviceIntegrationEnabled = value; + } + + public boolean isServiceIntegrationEnabled() { + return serviceIntegrationEnabled; + } + + /** + * Use device name and IP for identification of device, + * because some devices have multiple device instances with same IP. + * (i.e., a device including docker containers with host network setting.) + * And if service integration is false (default), all services look like different devices. + */ + private String getDeviceKey(ConnectableDevice device) { + if (isServiceIntegrationEnabled()) return device.getFriendlyName() + device.getIpAddress(); + return device.getFriendlyName() + device.getIpAddress() + device.getServiceId(); + } + + private String getDeviceKey(ServiceDescription srvDesc) { + if (isServiceIntegrationEnabled()) return srvDesc.getFriendlyName() + srvDesc.getIpAddress(); + return srvDesc.getFriendlyName() + srvDesc.getIpAddress() + srvDesc.getServiceID(); + } + /** * Initilizes the Discovery manager with a valid context. This should be done as soon as possible and it should use getApplicationContext() as the Discovery manager could persist longer than the current Activity. * @@ -321,8 +351,7 @@ public void setCapabilityFilters(List capabilityFilters) { for (ConnectableDevice device: allDevices.values()) { if (deviceIsCompatible(device)) { - String devKey = device.getFriendlyName() + device.getIpAddress(); - compatibleDevices.put(devKey, device); + compatibleDevices.put(getDeviceKey(device), device); handleDeviceAdd(device); } @@ -595,8 +624,7 @@ public void handleDeviceAdd(ConnectableDevice device) { if (!deviceIsCompatible(device)) return; - String devKey = device.getFriendlyName() + device.getIpAddress(); - compatibleDevices.put(devKey, device); + compatibleDevices.put(getDeviceKey(device), device); for (DiscoveryManagerListener listenter: discoveryListeners) { listenter.onDeviceAdded(this, device); @@ -604,7 +632,7 @@ public void handleDeviceAdd(ConnectableDevice device) { } public void handleDeviceUpdate(ConnectableDevice device) { - String devKey = device.getFriendlyName() + device.getIpAddress(); + String devKey = getDeviceKey(device); if (deviceIsCompatible(device)) { if (device.getIpAddress() != null && compatibleDevices.containsKey(devKey)) { @@ -724,10 +752,7 @@ public void onCapabilityUpdated(ConnectableDevice device, List added, Li public void onServiceAdded(DiscoveryProvider provider, ServiceDescription serviceDescription) { Log.d(Util.T, "Service added: " + serviceDescription.getFriendlyName() + " (" + serviceDescription.getServiceID() + ")"); - // Use device name and IP for identification of device, - // because some devices have multiple device instances with same IP. - // (i.e., a device including docker containers with host network setting.) - String devKey = serviceDescription.getFriendlyName() + serviceDescription.getIpAddress(); + String devKey = getDeviceKey(serviceDescription); boolean deviceIsNew = !allDevices.containsKey(devKey); ConnectableDevice device = null; @@ -754,6 +779,7 @@ public void onServiceAdded(DiscoveryProvider provider, ServiceDescription servic device.setFriendlyName(serviceDescription.getFriendlyName()); device.setLastDetection(Util.getTime()); device.setLastKnownIPAddress(serviceDescription.getIpAddress()); + device.setServiceId(serviceDescription.getServiceID()); // TODO: Implement the currentSSID Property in DiscoveryManager // device.setLastSeenOnWifi(currentSSID); @@ -783,7 +809,7 @@ public void onServiceRemoved(DiscoveryProvider provider, ServiceDescription serv Log.d(Util.T, "onServiceRemoved: friendlyName: " + serviceDescription.getFriendlyName()); - String devKey = serviceDescription.getFriendlyName() + serviceDescription.getIpAddress(); + String devKey = getDeviceKey(serviceDescription); ConnectableDevice device = allDevices.get(devKey); if (device != null) { diff --git a/src/com/connectsdk/service/WebOSTVService.java b/src/com/connectsdk/service/WebOSTVService.java index 20b1c79c..a603ed58 100644 --- a/src/com/connectsdk/service/WebOSTVService.java +++ b/src/com/connectsdk/service/WebOSTVService.java @@ -224,10 +224,11 @@ public static DiscoveryFilter discoveryFilter() { @Override public boolean isConnected() { + if (this.socket == null) return false; if (DiscoveryManager.getInstance().getPairingLevel().compareTo(PairingLevel.PROTECTED) >= 0) { - return this.socket != null && this.socket.isConnected() && this.socket.getClientKey() != null; + return this.socket.isConnected() && this.socket.getClientKey() != ""; } else { - return this.socket != null && this.socket.isConnected(); + return this.socket.isConnected(); } } diff --git a/src/com/connectsdk/service/airplay/AirPlayServiceSocketClient.java b/src/com/connectsdk/service/airplay/AirPlayServiceSocketClient.java index 58839ed2..2381e100 100644 --- a/src/com/connectsdk/service/airplay/AirPlayServiceSocketClient.java +++ b/src/com/connectsdk/service/airplay/AirPlayServiceSocketClient.java @@ -74,17 +74,13 @@ public void pair(final String pin) { public void run() { try { airPlayAuth.doPairing(pin); - } catch (Exception ex) { - ex.printStackTrace(); - } - - try { socket = airPlayAuth.authenticate(); state = State.REGISTERED; if (mListener != null) { mListener.onConnect(); } } catch (Exception ex) { + state = State.INITIAL; ex.printStackTrace(); mListener.onRegistrationFailed(new ServiceCommandError(ex.toString())); } @@ -102,27 +98,37 @@ public void connect() { state = State.CONNECTING; } - new Thread(new Runnable() { - @Override - public void run() { - try { - socket = airPlayAuth.authenticate(); - state = State.REGISTERED; - if (mListener != null) { - mListener.onConnect(); - } - } catch (Exception e) { - try { - airPlayAuth.startPairing(); - if (mListener != null) - mListener.onBeforeRegister(mPairingType); - } catch (Exception ex) { - ex.printStackTrace(); - mListener.onRegistrationFailed(new ServiceCommandError(ex.toString())); - } + try { + socket = airPlayAuth.authenticate(); + state = State.REGISTERED; + if (mListener != null) { + mListener.onConnect(); + } + } catch (Exception e) { + try { + airPlayAuth.startPairing(); + if (mListener != null) + mListener.onBeforeRegister(mPairingType); + } catch (Exception ex) { + ex.printStackTrace(); + mListener.onRegistrationFailed(new ServiceCommandError(ex.toString())); + } + } + + int count = 0; + while(state == State.CONNECTING){ + try { + count++; + Thread.sleep(100); + if (count > 200) { + mListener.onRegistrationFailed(new ServiceCommandError("Pairing Timeout")); + break; } + } catch (InterruptedException e) { + e.printStackTrace(); + mListener.onRegistrationFailed(new ServiceCommandError(e.toString())); } - }).start(); + } } public void disconnect() { @@ -131,7 +137,7 @@ public void disconnect() { airPlayAuth = null; state = State.INITIAL; try { - socket.close(); + if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); }