diff --git a/examples/tv-casting-app/android/App/app/src/main/AndroidManifest.xml b/examples/tv-casting-app/android/App/app/src/main/AndroidManifest.xml
index 2a75df6e946d21..e551de818eb5b0 100644
--- a/examples/tv-casting-app/android/App/app/src/main/AndroidManifest.xml
+++ b/examples/tv-casting-app/android/App/app/src/main/AndroidManifest.xml
@@ -10,7 +10,6 @@
-
castingPlayerList = new ArrayList<>();
- // private FailureCallback failureCallback;
- private static SuccessCallback discoverySuccessCallback;
+ private static ArrayAdapter arrayAdapter;
// Get a singleton instance of the MatterCastingPlayerDiscovery
private static final CastingPlayerDiscovery matterCastingPlayerDiscovery =
@@ -77,15 +75,26 @@ public void onAdded(CastingPlayer castingPlayer) {
TAG,
"onAdded() Discovered CastingPlayer deviceId: " + castingPlayer.getDeviceId());
// Display CastingPlayer info on the screen
- if (discoverySuccessCallback != null) {
- discoverySuccessCallback.handle(castingPlayer);
- } else {
- Log.e(
- TAG,
- "onAdded() Warning: DiscoveryExampleFragment UX discoverySuccessCallback not set");
- }
+ new Handler(Looper.getMainLooper())
+ .post(
+ () -> {
+ final Optional playerInList =
+ castingPlayerList
+ .stream()
+ .filter(node -> castingPlayer.equals(node))
+ .findFirst();
+ if (playerInList.isPresent()) {
+ Log.d(
+ TAG,
+ "onAdded() Replacing existing CastingPlayer entry "
+ + playerInList.get().getDeviceId()
+ + " in castingPlayerList list");
+ arrayAdapter.remove(playerInList.get());
+ }
+ arrayAdapter.add(castingPlayer);
+ });
} else {
- Log.d(TAG, "onAdded()");
+ Log.d(TAG, "onAdded() CastingPlayer is null");
// Attempt to invoke interface method on a null object reference will throw an error
Log.d(
TAG,
@@ -96,20 +105,63 @@ public void onAdded(CastingPlayer castingPlayer) {
@Override
public void onChanged(CastingPlayer castingPlayer) {
- Log.i(
- TAG,
- "onChanged() Discovered changes to CastingPlayer with deviceId: "
- + castingPlayer.getDeviceId());
- // TODO: In following PRs. Consume changes to the provided CastingPlayer.
+ if (castingPlayer != null) {
+ Log.i(
+ TAG,
+ "onChanged() Discovered changes to CastingPlayer with deviceId: "
+ + castingPlayer.getDeviceId());
+ // Update the CastingPlayer on the screen
+ new Handler(Looper.getMainLooper())
+ .post(
+ () -> {
+ final Optional playerInList =
+ castingPlayerList
+ .stream()
+ .filter(node -> castingPlayer.equals(node))
+ .findFirst();
+ if (playerInList.isPresent()) {
+ Log.d(
+ TAG,
+ "onChanged() Updating existing CastingPlayer entry "
+ + playerInList.get().getDeviceId()
+ + " in castingPlayerList list");
+ arrayAdapter.remove(playerInList.get());
+ }
+ arrayAdapter.add(castingPlayer);
+ });
+ } else {
+ Log.d(TAG, "onChanged() CastingPlayer is null");
+ }
}
@Override
public void onRemoved(CastingPlayer castingPlayer) {
- Log.i(
- TAG,
- "onRemoved() Removed CastingPlayer with deviceId: "
- + castingPlayer.getDeviceId());
- // TODO: In following PRs. Consume CastingPlayer removed or lost from the network.
+ if (castingPlayer != null) {
+ Log.i(
+ TAG,
+ "onRemoved() Removed CastingPlayer with deviceId: "
+ + castingPlayer.getDeviceId());
+ // Remove CastingPlayer from the screen
+ new Handler(Looper.getMainLooper())
+ .post(
+ () -> {
+ final Optional playerInList =
+ castingPlayerList
+ .stream()
+ .filter(node -> castingPlayer.equals(node))
+ .findFirst();
+ if (playerInList.isPresent()) {
+ Log.d(
+ TAG,
+ "onRemoved() Removing existing CastingPlayer entry "
+ + playerInList.get().getDeviceId()
+ + " in castingPlayerList list");
+ arrayAdapter.remove(playerInList.get());
+ }
+ });
+ } else {
+ Log.d(TAG, "onRemoved() CastingPlayer is null");
+ }
}
};
@@ -142,49 +194,22 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
matterDiscoveryMessageTextView.setText(
getString(R.string.matter_discovery_message_initializing_text));
- ArrayAdapter arrayAdapter =
- new CastingPlayerCommissionerAdapter(getActivity(), castingPlayerList);
+ arrayAdapter = new CastingPlayerArrayAdapter(getActivity(), castingPlayerList);
final ListView list = getActivity().findViewById(R.id.castingPlayerList);
list.setAdapter(arrayAdapter);
Log.d(TAG, "onViewCreated() creating callbacks");
- this.discoverySuccessCallback =
- new SuccessCallback() {
- @Override
- public void handle(CastingPlayer castingPlayer) {
- Log.d(
- TAG,
- "SuccessCallback handle() CastingPlayer deviceId: " + castingPlayer.getDeviceId());
- new Handler(Looper.getMainLooper())
- .post(
- () -> {
- final Optional playerInList =
- castingPlayerList
- .stream()
- .filter(
- node -> castingPlayer.discoveredCastingPlayerHasSameSource(node))
- .findFirst();
- if (playerInList.isPresent()) {
- Log.d(
- TAG,
- "Replacing existing CastingPlayer entry "
- + playerInList.get().getDeviceId()
- + " in castingPlayerList list");
- arrayAdapter.remove(playerInList.get());
- }
- arrayAdapter.add(castingPlayer);
- });
- }
- };
-
+ // TODO: In following PRs. Enable startDiscoveryButton and stopDiscoveryButton when
+ // stopDiscovery is implemented in the core Matter SKD DNS-SD API. Enable in
+ // fragment_matter_discovery_example.xml
Button startDiscoveryButton = getView().findViewById(R.id.startDiscoveryButton);
startDiscoveryButton.setOnClickListener(
v -> {
Log.i(
TAG, "onViewCreated() startDiscoveryButton button clicked. Calling startDiscovery()");
- arrayAdapter.clear();
- if (!startDiscovery(15)) {
+ // arrayAdapter.clear();
+ if (!startDiscovery()) {
Log.e(TAG, "onViewCreated() startDiscovery() call Failed");
}
});
@@ -211,7 +236,7 @@ public void handle(CastingPlayer castingPlayer) {
public void onResume() {
super.onResume();
Log.i(TAG, "onResume() called. Calling startDiscovery()");
- if (!startDiscovery(15)) {
+ if (!startDiscovery()) {
Log.e(TAG, "onResume() Warning: startDiscovery() call Failed");
}
}
@@ -220,8 +245,11 @@ public void onResume() {
public void onPause() {
super.onPause();
Log.i(TAG, "onPause() called");
- stopDiscovery();
- scheduledFutureTask.cancel(true);
+ // stopDiscovery();
+ // Don't crash the app
+ if (scheduledFutureTask != null) {
+ scheduledFutureTask.cancel(true);
+ }
}
/** Interface for notifying the host. */
@@ -231,31 +259,26 @@ public interface Callback {
void handleConnectionButtonClicked(CastingPlayer castingPlayer);
}
- private boolean startDiscovery(int discoveryDuration) {
- Log.i(TAG, "startDiscovery() called, discoveryDuration: " + discoveryDuration + " seconds");
- if (discovering) {
- Log.e(TAG, "startDiscovery() Warning: already discovering, stop before starting");
- return false;
- }
+ private boolean startDiscovery() {
+ Log.i(TAG, "startDiscovery() called");
+
// Add the implemented CastingPlayerChangeListener to listen to changes in the discovered
// CastingPlayers
- MatterError errAdd =
+ MatterError err =
matterCastingPlayerDiscovery.addCastingPlayerChangeListener(castingPlayerChangeListener);
- if (errAdd.hasError()) {
- Log.e(TAG, "startDiscovery() addCastingPlayerChangeListener() called, errAdd: " + errAdd);
+ if (err.hasError()) {
+ Log.e(TAG, "startDiscovery() addCastingPlayerChangeListener() called, err Add: " + err);
return false;
}
// Start discovery
Log.i(TAG, "startDiscovery() calling startDiscovery()");
- MatterError errStart = matterCastingPlayerDiscovery.startDiscovery();
- if (errStart.hasError()) {
- Log.e(TAG, "startDiscovery() startDiscovery() called, errStart: " + errStart);
+ err = matterCastingPlayerDiscovery.startDiscovery(DISCOVERY_TARGET_DEVICE_TYPE);
+ if (err.hasError()) {
+ Log.e(TAG, "startDiscovery() startDiscovery() called, err Start: " + err);
return false;
}
- discovering = true;
- discoveryAttempt++;
- Log.i(TAG, "startDiscovery() started discovery attempt #" + discoveryAttempt);
+ Log.i(TAG, "startDiscovery() started discovery");
matterDiscoveryMessageTextView.setText(
getString(R.string.matter_discovery_message_discovering_text));
@@ -264,45 +287,38 @@ private boolean startDiscovery(int discoveryDuration) {
"startDiscovery() text set to: "
+ getString(R.string.matter_discovery_message_discovering_text));
+ // TODO: In following PRs. Enable this to auto-stop discovery after stopDiscovery is
+ // implemented in the core Matter SKD DNS-SD API.
// Schedule a service to stop discovery and remove the CastingPlayerChangeListener
// Safe to call if discovery is not running
- scheduledFutureTask =
- executorService.schedule(
- () -> {
- Log.i(
- TAG,
- "startDiscovery() executorService "
- + discoveryDuration
- + " seconds timer expired. Calling stopDiscovery() on attempt #"
- + discoveryAttempt);
- stopDiscovery();
- },
- discoveryDuration,
- TimeUnit.SECONDS);
+ // scheduledFutureTask =
+ // executorService.schedule(
+ // () -> {
+ // Log.i(
+ // TAG,
+ // "startDiscovery() executorService "
+ // + DISCOVERY_RUNTIME_SEC
+ // + " seconds timer expired. Auto-calling stopDiscovery()");
+ // stopDiscovery();
+ // },
+ // DISCOVERY_RUNTIME_SEC,
+ // TimeUnit.SECONDS);
return true;
}
private void stopDiscovery() {
- Log.i(TAG, "stopDiscovery() called on attempt #" + discoveryAttempt);
- boolean stopDiscoverySuccess = true;
- if (!discovering) {
- Log.e(TAG, "stopDiscovery() not discovering");
- return;
- }
+ Log.i(TAG, "stopDiscovery() called");
// Stop discovery
- MatterError errStop = matterCastingPlayerDiscovery.stopDiscovery();
- if (errStop.hasError()) {
+ MatterError err = matterCastingPlayerDiscovery.stopDiscovery();
+ if (err.hasError()) {
Log.e(
TAG,
- "stopDiscovery() MatterCastingPlayerDiscovery.stopDiscovery() called, errStop: "
- + errStop);
- stopDiscoverySuccess = false;
+ "stopDiscovery() MatterCastingPlayerDiscovery.stopDiscovery() called, err Stop: " + err);
} else {
// TODO: In following PRs. Implement stop discovery in the Android core API.
Log.d(TAG, "stopDiscovery() MatterCastingPlayerDiscovery.stopDiscovery() success");
- discovering = false;
}
matterDiscoveryMessageTextView.setText(
@@ -314,31 +330,26 @@ private void stopDiscovery() {
// Remove the CastingPlayerChangeListener
Log.i(TAG, "stopDiscovery() removing CastingPlayerChangeListener");
- MatterError errRemove =
+ err =
matterCastingPlayerDiscovery.removeCastingPlayerChangeListener(castingPlayerChangeListener);
- if (errRemove.hasError()) {
+ if (err.hasError()) {
Log.e(
TAG,
- "stopDiscovery() matterCastingPlayerDiscovery.removeCastingPlayerChangeListener() called, errRemove: "
- + errRemove);
- stopDiscoverySuccess = false;
- }
-
- if (!stopDiscoverySuccess) {
- Log.e(TAG, "stopDiscovery() Warning: complete with errors! Discovering: " + discovering);
+ "stopDiscovery() matterCastingPlayerDiscovery.removeCastingPlayerChangeListener() called, err Remove: "
+ + err);
}
}
}
-class CastingPlayerCommissionerAdapter extends ArrayAdapter {
+class CastingPlayerArrayAdapter extends ArrayAdapter {
private final List playerList;
private final Context context;
private LayoutInflater inflater;
- private static final String TAG = CastingPlayerCommissionerAdapter.class.getSimpleName();
+ private static final String TAG = CastingPlayerArrayAdapter.class.getSimpleName();
- public CastingPlayerCommissionerAdapter(Context context, List playerList) {
+ public CastingPlayerArrayAdapter(Context context, List playerList) {
super(context, 0, playerList);
- Log.i(TAG, "CastingPlayerCommissionerAdapter() constructor called");
+ Log.i(TAG, "CastingPlayerArrayAdapter() constructor called");
this.context = context;
this.playerList = playerList;
inflater = (LayoutInflater.from(context));
@@ -381,10 +392,9 @@ private String getCastingPlayerButtonText(CastingPlayer player) {
player.getDeviceType() > 0
? (aux.isEmpty() ? "" : ", ") + "Device Type: " + player.getDeviceType()
: "";
- aux = aux.isEmpty() ? aux : "\n" + aux;
+ aux += (aux.isEmpty() ? "" : ", ") + "Resolved IP: " + (player.getNumberIPs() > 0);
- // String preCommissioned = commissioner.isPreCommissioned() ? " (Pre-commissioned)" : "";
- // return main + aux + preCommissioned;
+ aux = aux.isEmpty() ? aux : "\n" + aux;
return main + aux;
}
}
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/CastingPlayer.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/CastingPlayer.java
index dfa7bf0d988e25..d359330f25ab97 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/CastingPlayer.java
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/CastingPlayer.java
@@ -19,6 +19,12 @@
import java.net.InetAddress;
import java.util.List;
+/**
+ * The CastingPlayer interface defines a Matter commissioner that is able to play media to a
+ * physical output or to a display screen which is part of the device (e.g. TV). It is discovered on
+ * the local network using Matter Commissioner discovery over DNS. It contains all the information
+ * about the service discovered/resolved.
+ */
public interface CastingPlayer {
boolean isConnected();
@@ -42,7 +48,11 @@ public interface CastingPlayer {
int getDeviceType();
- boolean discoveredCastingPlayerHasSameSource(Object o);
+ String toString();
+
+ boolean equals(Object o);
+
+ int hashCode();
// TODO: Implement in following PRs. Related to player connection implementation.
// List getEndpoints();
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/CastingPlayerDiscovery.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/CastingPlayerDiscovery.java
index 9455e3a75ef727..9f2a7f8faff68e 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/CastingPlayerDiscovery.java
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/CastingPlayerDiscovery.java
@@ -17,35 +17,94 @@
package com.matter.casting.core;
import android.util.Log;
+import com.matter.casting.support.MatterError;
import java.util.List;
+/**
+ * The CastingPlayerDiscovery interface defines the API to control Matter Casting Player discovery
+ * over DNS-SD, and to collect discovery results. Discovery is centrally managed by the native C++
+ * layer in the Matter SDK. This class exposes native functions to add and remove a
+ * CastingPlayerChangeListener, which contains the C++ to Java callbacks for when Casting Players
+ * are discovered, updated, or lost from the network. This class is a singleton.
+ */
public interface CastingPlayerDiscovery {
+ /**
+ * @return a list of Casting Players discovered during the current discovery session. This list is
+ * cleared when discovery stops.
+ */
List getCastingPlayers();
- com.matter.casting.support.MatterError startDiscovery();
+ /**
+ * Starts Casting Players discovery or returns an error.
+ *
+ * @param discoveryTargetDeviceType the target device type to be discovered using DNS-SD. 35
+ * represents device type of Matter Casting Player.
+ * @return a specific MatterError if the the operation failed or NO_ERROR if succeeded.
+ */
+ MatterError startDiscovery(int discoveryTargetDeviceType);
- com.matter.casting.support.MatterError stopDiscovery();
+ /**
+ * Stops Casting Players discovery or returns an error.
+ *
+ * @return a specific MatterError if the the operation failed or NO_ERROR if succeeded.
+ */
+ MatterError stopDiscovery();
- com.matter.casting.support.MatterError addCastingPlayerChangeListener(
- CastingPlayerChangeListener listener);
+ /**
+ * Adds a CastingPlayerChangeListener instance to be used during discovery. The
+ * CastingPlayerChangeListener contains the C++ to Java callbacks for when Casting Players are
+ * discovered, updated, or lost from the network. Should be called prior to calling
+ * MatterCastingPlayerDiscovery.startDiscovery().
+ *
+ * @param listener an instance of the CastingPlayerChangeListener to be implemented by the APIs
+ * consumer.
+ * @return a specific MatterError if the the operation failed or NO_ERROR if succeeded.
+ */
+ MatterError addCastingPlayerChangeListener(CastingPlayerChangeListener listener);
- com.matter.casting.support.MatterError removeCastingPlayerChangeListener(
- CastingPlayerChangeListener listener);
+ /**
+ * Removes CastingPlayerChangeListener from the native layer.
+ *
+ * @param listener the specific instance of CastingPlayerChangeListener to be removed.
+ * @return a specific MatterError if the the operation failed or NO_ERROR if succeeded.
+ */
+ MatterError removeCastingPlayerChangeListener(CastingPlayerChangeListener listener);
/**
- * The Casting Client discovers CastingPlayers using Matter Commissioner discovery over DNS-SD by
- * listening for CastingPlayer events as they are discovered, updated, or lost from the network.
+ * The CastingPlayerChangeListener can discover CastingPlayers by implementing the onAdded,
+ * onChanged and onRemoved callbacks which are called as CastingPlayers, are discovered, updated,
+ * or lost from the network. The onAdded(), onChanged() and onRemoved() callbacks must be
+ * implemented by the APIs client.
*/
abstract class CastingPlayerChangeListener {
static final String TAG = CastingPlayerChangeListener.class.getSimpleName();
+ /**
+ * Called by the native C++ layer when a Casting Player is added to the local network.
+ *
+ * @param castingPlayer the Casting Player added.
+ */
public abstract void onAdded(CastingPlayer castingPlayer);
+ /**
+ * Called by the native C++ layer when a Casting Player on the local network is changed.
+ *
+ * @param castingPlayer the Casting Player changed.
+ */
public abstract void onChanged(CastingPlayer castingPlayer);
+ /**
+ * Called by the native C++ layer when a Casting Player is removed from the local network.
+ *
+ * @param castingPlayer the Casting Player removed.
+ */
public abstract void onRemoved(CastingPlayer castingPlayer);
+ /**
+ * The following methods are used to catch possible exceptions thrown by the methods above, when
+ * not implemented correctly.
+ */
protected final void _onAdded(CastingPlayer castingPlayer) {
try {
onAdded(castingPlayer);
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterCastingPlayer.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterCastingPlayer.java
index da0ce3a68125a6..fdf8b4e2cc74fd 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterCastingPlayer.java
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterCastingPlayer.java
@@ -16,14 +16,17 @@
*/
package com.matter.casting.core;
-import android.util.Log;
import java.net.InetAddress;
import java.util.List;
import java.util.Objects;
-/** The Matter Commissioner (e.g. TV) discovered using Matter Commissioner discovery. */
+/**
+ * A Matter Casting Player represents a Matter commissioner that is able to play media to a physical
+ * output or to a display screen which is part of the device (e.g. TV). It is discovered on the
+ * local network using Matter Commissioner discovery over DNS. It contains all the information about
+ * the service discovered/resolved.
+ */
public class MatterCastingPlayer implements CastingPlayer {
- private static final String TAG = MatterCastingPlayer.class.getSimpleName();
private boolean connected;
private String deviceId;
private String deviceName;
@@ -48,8 +51,6 @@ public MatterCastingPlayer(
int productId,
int vendorId,
int deviceType) {
- Log.d(TAG, "MatterCastingPlayer() constructor, building player with deviceId: " + deviceId);
- Log.d(TAG, "MatterCastingPlayer() constructor, building player with deviceName: " + deviceName);
this.connected = connected;
this.deviceId = deviceId;
this.hostName = hostName;
@@ -63,11 +64,19 @@ public MatterCastingPlayer(
this.deviceType = deviceType;
}
+ /**
+ * @return a boolean indicating whether a Casting Player instance is connected to the TV Casting
+ * App.
+ */
@Override
public boolean isConnected() {
return this.connected;
}
+ /**
+ * @return a String representing the Casting Player device ID which is a concatenation of the
+ * device's IP address and port number.
+ */
@Override
public String getDeviceId() {
return this.deviceId;
@@ -88,11 +97,13 @@ public String getInstanceName() {
return this.instanceName;
}
+ /** @return an int, corresponding to the number of valid IP addresses for this Casting PLayer. */
@Override
public int getNumberIPs() {
return this.numberIPs;
}
+ /** @return a list of valid IP addresses for this Casting PLayer. */
@Override
public List getIpAddresses() {
return this.ipAddresses;
@@ -119,10 +130,20 @@ public int getDeviceType() {
}
@Override
- public boolean discoveredCastingPlayerHasSameSource(Object o) {
+ public String toString() {
+ return this.deviceId;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.deviceId.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MatterCastingPlayer that = (MatterCastingPlayer) o;
- return Objects.equals(deviceId, that.deviceId) && vendorId == that.vendorId;
+ return Objects.equals(this.deviceId, that.deviceId);
}
}
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterCastingPlayerDiscovery.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterCastingPlayerDiscovery.java
index 66ce86aa301000..bcd36708e7e77b 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterCastingPlayerDiscovery.java
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/core/MatterCastingPlayerDiscovery.java
@@ -16,36 +16,72 @@
*/
package com.matter.casting.core;
-import android.util.Log;
+import com.matter.casting.support.MatterError;
import java.util.List;
+/**
+ * MatterCastingPlayerDiscovery provides an API to control Matter Casting Player discovery over
+ * DNS-SD, and to collect discovery results. Discovery is centrally managed by the native C++ layer
+ * in the Matter SDK. This class exposes native functions to add and remove a
+ * CastingPlayerChangeListener, which contains the C++ to Java callbacks for when Casting Players
+ * are discovered, updated, or lost from the network. This class is a singleton.
+ */
public final class MatterCastingPlayerDiscovery implements CastingPlayerDiscovery {
private static final String TAG = MatterCastingPlayerDiscovery.class.getSimpleName();
private static MatterCastingPlayerDiscovery matterCastingPlayerDiscoveryInstance;
// Methods:
public static MatterCastingPlayerDiscovery getInstance() {
- Log.d(TAG, "MatterCastingPlayerDiscovery.getInstance() called");
if (matterCastingPlayerDiscoveryInstance == null) {
matterCastingPlayerDiscoveryInstance = new MatterCastingPlayerDiscovery();
}
return matterCastingPlayerDiscoveryInstance;
};
+ /**
+ * @return a list of Casting Players discovered during the current discovery session. This list is
+ * cleared when discovery stops.
+ */
@Override
public native List getCastingPlayers();
+ /**
+ * Starts Casting Players discovery or returns an error.
+ *
+ * @param discoveryTargetDeviceType the target device type to be discovered using DNS-SD. 35
+ * represents device type of Matter Casting Player.
+ * @return a specific MatterError if the the operation failed or NO_ERROR if succeeded.
+ */
@Override
- public native com.matter.casting.support.MatterError startDiscovery();
+ public native MatterError startDiscovery(int discoveryTargetDeviceType);
+ /**
+ * Stops Casting Players discovery or returns an error.
+ *
+ * @return a specific MatterError if the the operation failed or NO_ERROR if succeeded.
+ */
@Override
- public native com.matter.casting.support.MatterError stopDiscovery();
+ public native MatterError stopDiscovery();
+ /**
+ * Adds a CastingPlayerChangeListener instance to be used during discovery. The
+ * CastingPlayerChangeListener contains the C++ to Java callbacks for when Casting Players are
+ * discovered, updated, or lost from the network. Should be called prior to calling
+ * MatterCastingPlayerDiscovery.startDiscovery().
+ *
+ * @param listener an instance of the CastingPlayerChangeListener to be implemented by the APIs
+ * consumer.
+ * @return a specific MatterError if the the operation failed or NO_ERROR if succeeded.
+ */
@Override
- public native com.matter.casting.support.MatterError addCastingPlayerChangeListener(
- CastingPlayerChangeListener listener);
+ public native MatterError addCastingPlayerChangeListener(CastingPlayerChangeListener listener);
+ /**
+ * Removes CastingPlayerChangeListener from the native layer.
+ *
+ * @param listener the specific instance of CastingPlayerChangeListener to be removed.
+ * @return a specific MatterError if the the operation failed or NO_ERROR if succeeded.
+ */
@Override
- public native com.matter.casting.support.MatterError removeCastingPlayerChangeListener(
- CastingPlayerChangeListener listener);
+ public native MatterError removeCastingPlayerChangeListener(CastingPlayerChangeListener listener);
}
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingPlayerDiscovery-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingPlayerDiscovery-JNI.cpp
index c3b4e2dd0e3613..d585b3412abd93 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingPlayerDiscovery-JNI.cpp
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingPlayerDiscovery-JNI.cpp
@@ -41,7 +41,7 @@ namespace casting {
namespace core {
/**
- * @brief React to CastingPlayer discovery results with this sigleton
+ * @brief React to CastingPlayer discovery results with this singleton
*/
class DiscoveryDelegateImpl : public DiscoveryDelegate
{
@@ -59,11 +59,8 @@ class DiscoveryDelegateImpl : public DiscoveryDelegate
static DiscoveryDelegateImpl * GetInstance()
{
- ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::GetInstance() called");
if (DiscoveryDelegateImpl::discoveryDelegateImplSingletonInstance == nullptr)
{
- ChipLogProgress(AppServer,
- "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::GetInstance() creating new singleton instance");
DiscoveryDelegateImpl::discoveryDelegateImplSingletonInstance = new DiscoveryDelegateImpl();
}
return DiscoveryDelegateImpl::discoveryDelegateImplSingletonInstance;
@@ -71,91 +68,80 @@ class DiscoveryDelegateImpl : public DiscoveryDelegate
void HandleOnAdded(matter::casting::memory::Strong player) override
{
- ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() called with CastingPlayer:");
- player->LogDetail();
+ ChipLogProgress(AppServer,
+ "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() called with CastingPlayer, ID: %s",
+ player->GetId());
+
+ VerifyOrReturn(castingPlayerChangeListenerJavaObject != nullptr,
+ ChipLogError(AppServer,
+ "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Warning: Not set, "
+ "CastingPlayerChangeListener == nullptr"));
+ VerifyOrReturn(onAddedCallbackJavaMethodID != nullptr,
+ ChipLogError(AppServer,
+ "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Warning: Not set, "
+ "onAddedCallbackJavaMethodID == nullptr"));
- if (castingPlayerChangeListenerJavaObject == nullptr || onAddedCallbackJavaMethodID == nullptr)
- {
- ChipLogError(AppServer,
- "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Warning: Not specified, "
- "CastingPlayerChangeListener == nullptr");
- }
- else
- {
- JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
- jobject matterCastingPlayerJavaObject = support::createJCastingPlayer(player);
- if (matterCastingPlayerJavaObject == nullptr)
- {
- ChipLogError(AppServer,
- "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Warning: Could not create "
- "CastingPlayer jobject");
- }
- else
- {
- env->CallVoidMethod(castingPlayerChangeListenerJavaObject, onAddedCallbackJavaMethodID,
- matterCastingPlayerJavaObject);
- }
- }
+ jobject matterCastingPlayerJavaObject = support::createJCastingPlayer(player);
+ VerifyOrReturn(matterCastingPlayerJavaObject != nullptr,
+ ChipLogError(AppServer,
+ "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Warning: Could not create "
+ "CastingPlayer jobject"));
+
+ JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
+ env->CallVoidMethod(castingPlayerChangeListenerJavaObject, onAddedCallbackJavaMethodID, matterCastingPlayerJavaObject);
}
void HandleOnUpdated(matter::casting::memory::Strong player) override
{
ChipLogProgress(AppServer,
- "CastingPlayerDiscovery-JNI DiscoveryDelegateImpl::HandleOnUpdated() called with CastingPlayer:");
- player->LogDetail();
+ "CastingPlayerDiscovery-JNI DiscoveryDelegateImpl::HandleOnUpdated() called with CastingPlayer, ID: %s",
+ player->GetId());
+
+ VerifyOrReturn(castingPlayerChangeListenerJavaObject != nullptr,
+ ChipLogError(AppServer,
+ "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Warning: Not set, "
+ "CastingPlayerChangeListener == nullptr"));
+ VerifyOrReturn(onChangedCallbackJavaMethodID != nullptr,
+ ChipLogError(AppServer,
+ "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Warning: Not set, "
+ "onChangedCallbackJavaMethodID == nullptr"));
- if (castingPlayerChangeListenerJavaObject == nullptr || onChangedCallbackJavaMethodID == nullptr)
- {
- ChipLogError(AppServer,
- "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Warning: Not specified, "
- "CastingPlayerChangeListener == nullptr");
- }
- else
- {
- JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
- jobject matterCastingPlayerJavaObject = support::createJCastingPlayer(player);
- if (matterCastingPlayerJavaObject == nullptr)
- {
- ChipLogError(AppServer,
- "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Warning: Could not create "
- "CastingPlayer jobject");
- }
- else
- {
- env->CallVoidMethod(castingPlayerChangeListenerJavaObject, onChangedCallbackJavaMethodID,
- matterCastingPlayerJavaObject);
- }
- }
+ jobject matterCastingPlayerJavaObject = support::createJCastingPlayer(player);
+ VerifyOrReturn(matterCastingPlayerJavaObject != nullptr,
+ ChipLogError(AppServer,
+ "CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Warning: Could not "
+ "create CastingPlayer jobject"));
+
+ JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
+ env->CallVoidMethod(castingPlayerChangeListenerJavaObject, onChangedCallbackJavaMethodID, matterCastingPlayerJavaObject);
}
// TODO: In following PRs. Implement HandleOnRemoved after implemented in tv-casting-commom CastingPlayerDiscovery.h/cpp
// void HandleOnRemoved(matter::casting::memory::Strong player) override
// {
// ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI DiscoveryDelegateImpl::HandleOnRemoved() called with
- // CastingPlayer:"); player->LogDetail();
+ // CastingPlayer, ID: %s", player->GetId());
// }
};
// Initialize the static instance to nullptr
DiscoveryDelegateImpl * DiscoveryDelegateImpl::discoveryDelegateImplSingletonInstance = nullptr;
-JNI_METHOD(jobject, startDiscovery)(JNIEnv * env, jobject)
+JNI_METHOD(jobject, startDiscovery)(JNIEnv * env, jobject, jint discoveryTargetDeviceType)
{
chip::DeviceLayer::StackLock lock;
- ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI::startDiscovery() called");
- DiscoveryDelegateImpl * delegate = DiscoveryDelegateImpl::GetInstance();
- CastingPlayerDiscovery::GetInstance()->SetDelegate(delegate);
+ ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI::startDiscovery() called with discoveryTargetDeviceType: %lu",
+ (uint64_t) discoveryTargetDeviceType);
+ CastingPlayerDiscovery::GetInstance()->SetDelegate(DiscoveryDelegateImpl::GetInstance());
- // Start CastingPlayer discovery
- const uint64_t kTargetPlayerDeviceType = 35; // 35 represents device type of Matter Video Player
- CHIP_ERROR err = CastingPlayerDiscovery::GetInstance()->StartDiscovery(kTargetPlayerDeviceType);
+ // Start CastingPlayer discovery, 35 represents device type of Matter Casting Player
+ CHIP_ERROR err = CastingPlayerDiscovery::GetInstance()->StartDiscovery((uint64_t) discoveryTargetDeviceType);
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "CastingPlayerDiscovery-JNI startDiscovery() err: %" CHIP_ERROR_FORMAT, err.Format());
+ return support::createJMatterError(err);
}
- // TODO: Verify error returned?
- VerifyOrReturnValue(err == CHIP_NO_ERROR, support::createJMatterError(CHIP_ERROR_INCORRECT_STATE));
return support::createJMatterError(CHIP_NO_ERROR);
}
@@ -169,9 +155,9 @@ JNI_METHOD(jobject, stopDiscovery)(JNIEnv * env, jobject)
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "CastingPlayerDiscovery-JNI::StopDiscovery() err: %" CHIP_ERROR_FORMAT, err.Format());
+ return support::createJMatterError(err);
}
- VerifyOrReturnValue(err == CHIP_NO_ERROR, support::createJMatterError(CHIP_ERROR_INCORRECT_STATE));
return support::createJMatterError(CHIP_NO_ERROR);
}
@@ -181,8 +167,7 @@ JNI_METHOD(jobject, addCastingPlayerChangeListener)(JNIEnv * env, jobject, jobje
ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI::addCastingPlayerChangeListener() called");
VerifyOrReturnValue(castingPlayerChangeListenerJavaObject != nullptr, support::createJMatterError(CHIP_ERROR_INCORRECT_STATE));
- DiscoveryDelegateImpl * delegate = DiscoveryDelegateImpl::GetInstance();
- if (delegate->castingPlayerChangeListenerJavaObject != nullptr)
+ if (DiscoveryDelegateImpl::GetInstance()->castingPlayerChangeListenerJavaObject != nullptr)
{
ChipLogError(AppServer,
"CastingPlayerDiscovery-JNI::addCastingPlayerChangeListener() Warning: Call removeCastingPlayerChangeListener "
@@ -205,10 +190,11 @@ JNI_METHOD(jobject, addCastingPlayerChangeListener)(JNIEnv * env, jobject, jobje
// support::createJMatterError(CHIP_ERROR_INCORRECT_STATE));
// Set Java callbacks in the DiscoveryDelegateImpl Singleton
- delegate->castingPlayerChangeListenerJavaObject = env->NewGlobalRef(castingPlayerChangeListenerJavaObject);
- delegate->onAddedCallbackJavaMethodID = onAddedJavaMethodID;
- delegate->onChangedCallbackJavaMethodID = onChangedJavaMethodID;
- // delegate->onRemovedCallbackJavaMethodID = onRemovedJavaMethodID;
+ DiscoveryDelegateImpl::GetInstance()->castingPlayerChangeListenerJavaObject =
+ env->NewGlobalRef(castingPlayerChangeListenerJavaObject);
+ DiscoveryDelegateImpl::GetInstance()->onAddedCallbackJavaMethodID = onAddedJavaMethodID;
+ DiscoveryDelegateImpl::GetInstance()->onChangedCallbackJavaMethodID = onChangedJavaMethodID;
+ // DiscoveryDelegateImpl::GetInstance()->onRemovedCallbackJavaMethodID = onRemovedJavaMethodID;
return support::createJMatterError(CHIP_NO_ERROR);
}
@@ -218,24 +204,20 @@ JNI_METHOD(jobject, removeCastingPlayerChangeListener)(JNIEnv * env, jobject, jo
chip::DeviceLayer::StackLock lock;
ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI::removeCastingPlayerChangeListener() called");
- // Remove the Java callbacks in the DiscoveryDelegateImpl Singleton
- DiscoveryDelegateImpl * delegate = DiscoveryDelegateImpl::GetInstance();
-
// Check if the passed object is the same as the one added in addCastingPlayerChangeListener() JNI method
- jboolean isSameObject =
- env->IsSameObject(castingPlayerChangeListenerJavaObject, delegate->castingPlayerChangeListenerJavaObject);
+ jboolean isSameObject = env->IsSameObject(castingPlayerChangeListenerJavaObject,
+ DiscoveryDelegateImpl::GetInstance()->castingPlayerChangeListenerJavaObject);
if ((bool) isSameObject)
{
- ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI::removeCastingPlayerChangeListener() removing listener");
-
// Delete the global reference to the Java object
- env->DeleteGlobalRef(delegate->castingPlayerChangeListenerJavaObject);
- delegate->castingPlayerChangeListenerJavaObject = nullptr;
+ env->DeleteGlobalRef(DiscoveryDelegateImpl::GetInstance()->castingPlayerChangeListenerJavaObject);
+ // Remove the Java callbacks in the DiscoveryDelegateImpl Singleton
+ DiscoveryDelegateImpl::GetInstance()->castingPlayerChangeListenerJavaObject = nullptr;
// No explicit cleanup required
- delegate->onAddedCallbackJavaMethodID = nullptr;
- delegate->onChangedCallbackJavaMethodID = nullptr;
- // delegate->onRemovedCallbackJavaMethodID = nullptr;
+ DiscoveryDelegateImpl::GetInstance()->onAddedCallbackJavaMethodID = nullptr;
+ DiscoveryDelegateImpl::GetInstance()->onChangedCallbackJavaMethodID = nullptr;
+ // DiscoveryDelegateImpl::GetInstance()->onRemovedCallbackJavaMethodID = nullptr;
return support::createJMatterError(CHIP_NO_ERROR);
}
@@ -267,12 +249,7 @@ JNI_METHOD(jobject, getCastingPlayers)(JNIEnv * env, jobject)
if (matterCastingPlayerJavaObject != nullptr)
{
jboolean added = env->CallBooleanMethod(arrayList, addMethod, matterCastingPlayerJavaObject);
- if ((bool) added)
- {
- ChipLogProgress(AppServer, "CastingPlayerDiscovery-JNI::getCastingPlayers() added CastingPlayer with ID: %s",
- player->GetId());
- }
- else
+ if (!((bool) added))
{
ChipLogError(AppServer,
"CastingPlayerDiscovery-JNI::getCastingPlayers() Warning: Unable to add CastingPlayer with ID: %s",
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/CastingPlayerConverter-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/CastingPlayerConverter-JNI.cpp
index 04208bfbc7c97f..86d42a76fabc13 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/CastingPlayerConverter-JNI.cpp
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/CastingPlayerConverter-JNI.cpp
@@ -52,17 +52,7 @@ jobject createJCastingPlayer(matter::casting::memory::StrongIsConnected())
- {
- connected = true;
- }
- jboolean connectedJavaBoolean = static_cast(connected);
- jstring idJavaString = env->NewStringUTF(player->GetId());
- jstring deviceNameJavaString = env->NewStringUTF(player->GetDeviceName());
- jstring hostNameJavaString = env->NewStringUTF(player->GetHostName());
- jstring instanceNameJavaString = env->NewStringUTF(player->GetInstanceName());
- jint numIPsJavaInt = (jint) (player->GetNumIPs());
+ bool connected = player->IsConnected() ? true : false;
jobject ipAddressListJavaObject = nullptr;
const chip::Inet::IPAddress * ipAddresses = player->GetIPAddresses();
@@ -84,17 +74,14 @@ jobject createJCastingPlayer(matter::casting::memory::StrongGetPort());
- jint productIdJavaInt = (jint) (player->GetProductId());
- jint vendorIdJavaInt = (jint) (player->GetVendorId());
- jint deviceTypeJavaInt = (jint) (player->GetDeviceType());
-
// Create a new instance of the MatterCastingPlayer Java class
jobject matterCastingPlayerJavaObject = nullptr;
matterCastingPlayerJavaObject =
- env->NewObject(matterCastingPlayerJavaClass, constructor, connectedJavaBoolean, idJavaString, hostNameJavaString,
- deviceNameJavaString, instanceNameJavaString, numIPsJavaInt, ipAddressListJavaObject, portJavaInt,
- productIdJavaInt, vendorIdJavaInt, deviceTypeJavaInt);
+ env->NewObject(matterCastingPlayerJavaClass, constructor, static_cast(connected),
+ env->NewStringUTF(player->GetId()), env->NewStringUTF(player->GetHostName()),
+ env->NewStringUTF(player->GetDeviceName()), env->NewStringUTF(player->GetInstanceName()),
+ (jint) (player->GetNumIPs()), ipAddressListJavaObject, (jint) (player->GetPort()),
+ (jint) (player->GetProductId()), (jint) (player->GetVendorId()), (jint) (player->GetDeviceType()));
if (matterCastingPlayerJavaObject == nullptr)
{
ChipLogError(AppServer,
diff --git a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_discovery_example.xml b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_discovery_example.xml
index 57b59355ff5e1b..1c3eb13ce6c486 100644
--- a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_discovery_example.xml
+++ b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_discovery_example.xml
@@ -15,12 +15,14 @@
android:padding="10sp">