diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ContentLauncherLaunchURLExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ContentLauncherLaunchURLExampleFragment.java index 5f0d7c6d16677f..529730257b3d6b 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ContentLauncherLaunchURLExampleFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ContentLauncherLaunchURLExampleFragment.java @@ -27,9 +27,6 @@ import com.R; import com.matter.casting.core.CastingPlayer; import com.matter.casting.core.Endpoint; -import com.matter.casting.core.MatterEndpoint; -import com.matter.casting.support.MatterCallback; -import com.matter.casting.support.MatterError; import java.util.List; import java.util.Optional; @@ -79,41 +76,29 @@ public View onCreateView( } // TODO: complete command invocation API implementation - ((MatterEndpoint) endpoint) - .getDeviceProxy( - new MatterCallback() { - @Override - public void handle(Long device) { - Log.d(TAG, "getDeviceProxy success. Device: " + device); + ChipClusters.ContentLauncherCluster cluster = + endpoint.getCluster(ChipClusters.ContentLauncherCluster.class); + if (cluster == null) { + Log.e( + TAG, + "Could not get ContentLauncherCluster for endpoint with ID: " + endpoint.getId()); + } - if (device != null) { - ChipClusters.ContentLauncherCluster cluster = - new ChipClusters.ContentLauncherCluster(device, endpoint.getId()); - Log.d(TAG, "Content launcher cluster created " + cluster); - cluster.launchURL( - new ChipClusters.ContentLauncherCluster.LauncherResponseCallback() { - @Override - public void onSuccess(Integer status, Optional data) { - Log.d(TAG, "Content launcher success " + status + data); - } + cluster.launchURL( + new ChipClusters.ContentLauncherCluster.LauncherResponseCallback() { + @Override + public void onSuccess(Integer status, Optional data) { + Log.d(TAG, "Content launcher success " + status + data); + } - @Override - public void onError(Exception error) { - Log.e(TAG, "Content launcher failure " + error); - } - }, - "my test url", - Optional.of("my display str"), - Optional.empty()); - } - } - }, - new MatterCallback() { - @Override - public void handle(MatterError err) { - Log.e(TAG, "getDeviceProxy err" + err); - } - }); + @Override + public void onError(Exception error) { + Log.e(TAG, "Content launcher failure " + error); + } + }, + "my test url", + Optional.of("my display str"), + Optional.empty()); }; return inflater.inflate(R.layout.fragment_content_launcher, container, false); } diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/Endpoint.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/Endpoint.java index 6d1b63555aad08..f906b80235700c 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/Endpoint.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/Endpoint.java @@ -17,9 +17,11 @@ package com.matter.casting.core; +import chip.devicecontroller.ChipClusters; import com.matter.casting.support.DeviceTypeStruct; import java.util.List; +/** This represents an Endpoint on a CastingPlayer e.g. a Speaker or a Matter Content App */ public interface Endpoint { int getId(); @@ -29,5 +31,9 @@ public interface Endpoint { List getDeviceTypeList(); + /** Get an instance of a cluster based on its Class */ + T getCluster(Class clusterClass); + + /** Get the CastingPlayer that this Endpoint is a part of. */ CastingPlayer getCastingPlayer(); } diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterEndpoint.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterEndpoint.java index 286777dee86b31..9a020349fe5ce6 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterEndpoint.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterEndpoint.java @@ -16,14 +16,23 @@ */ package com.matter.casting.core; +import android.util.Log; +import chip.devicecontroller.ChipClusters; import com.matter.casting.support.DeviceTypeStruct; import com.matter.casting.support.MatterCallback; import com.matter.casting.support.MatterError; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public class MatterEndpoint implements Endpoint { private static final String TAG = MatterEndpoint.class.getSimpleName(); + private static final long MAX_WAIT_FOR_DEVICE_PROXY_SEC = 5000; protected long _cppEndpoint; @Override @@ -39,10 +48,28 @@ public class MatterEndpoint implements Endpoint { public native List getDeviceTypeList(); @Override - public native CastingPlayer getCastingPlayer(); + public T getCluster(Class clusterClass) { + try { + Constructor constructor = clusterClass.getDeclaredConstructor(long.class, int.class); + Long deviceProxy = getDeviceProxy(); + if (deviceProxy == null) { + Log.e(TAG, "Could not get DeviceProxy while constructing cluster object"); + return null; + } + return constructor.newInstance(deviceProxy, getId()); + } catch (InstantiationException + | IllegalAccessException + | InvocationTargetException + | NoSuchMethodException e) { + Log.e( + TAG, + "Could not create cluster object for " + clusterClass.getSimpleName() + " exc: " + e); + return null; + } + } - public native void getDeviceProxy( - MatterCallback successCallback, MatterCallback failureCallback); + @Override + public native CastingPlayer getCastingPlayer(); @Override public String toString() { @@ -61,4 +88,32 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(getId()); } + + private Long getDeviceProxy() { + CompletableFuture deviceProxyFuture = new CompletableFuture<>(); + getDeviceProxy( + new MatterCallback() { + @Override + public void handle(Long deviceProxy) { + deviceProxyFuture.complete(deviceProxy); + } + }, + new MatterCallback() { + @Override + public void handle(MatterError response) { + deviceProxyFuture.completeExceptionally( + new RuntimeException("Failed on getDeviceProxy: " + response)); + } + }); + + try { + return deviceProxyFuture.get(MAX_WAIT_FOR_DEVICE_PROXY_MS, TimeUnit.MILLISECONDS); + } catch (ExecutionException | InterruptedException | TimeoutException e) { + Log.e(TAG, "Exception while waiting on getDeviceProxy future: " + e); + return null; + } + } + + protected native void getDeviceProxy( + MatterCallback successCallback, MatterCallback failureCallback); }