Skip to content

Commit 2ca30ac

Browse files
Android - implement ChipDnssdStopBrowse (#32801)
* Android - implement ChipDnssdStopBrowse in the core SDK Fixing style issues cleanup log statement * Addressed comments by bzbarsky-apple and sharadb-amazon * Addressed comments by bzbarsky-apple now using browseIdentifier to stop DNS-SD browse * Addressed comments by sharadb-amazon - debug logging
1 parent 49d6e34 commit 2ca30ac

File tree

7 files changed

+119
-59
lines changed

7 files changed

+119
-59
lines changed

examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java

+21-34
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,14 @@
3838
import java.util.ArrayList;
3939
import java.util.List;
4040
import java.util.Optional;
41-
import java.util.concurrent.Executors;
42-
import java.util.concurrent.ScheduledExecutorService;
43-
import java.util.concurrent.ScheduledFuture;
4441

4542
public class DiscoveryExampleFragment extends Fragment {
4643
private static final String TAG = DiscoveryExampleFragment.class.getSimpleName();
4744
// 35 represents device type of Matter Casting Player
4845
private static final Long DISCOVERY_TARGET_DEVICE_TYPE = 35L;
4946
private static final int DISCOVERY_RUNTIME_SEC = 15;
5047
private TextView matterDiscoveryMessageTextView;
51-
private static final ScheduledExecutorService executorService =
52-
Executors.newSingleThreadScheduledExecutor();
53-
private ScheduledFuture scheduledFutureTask;
48+
private TextView matterDiscoveryErrorMessageTextView;
5449
private static final List<CastingPlayer> castingPlayerList = new ArrayList<>();
5550
private static ArrayAdapter<CastingPlayer> arrayAdapter;
5651

@@ -164,15 +159,17 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
164159
matterDiscoveryMessageTextView.setText(
165160
getString(R.string.matter_discovery_message_initializing_text));
166161

162+
matterDiscoveryErrorMessageTextView =
163+
getActivity().findViewById(R.id.matterDiscoveryErrorTextView);
164+
matterDiscoveryErrorMessageTextView.setText(
165+
getString(R.string.matter_discovery_error_message_initial));
166+
167167
arrayAdapter = new CastingPlayerArrayAdapter(getActivity(), castingPlayerList);
168168
final ListView list = getActivity().findViewById(R.id.castingPlayerList);
169169
list.setAdapter(arrayAdapter);
170170

171171
Log.d(TAG, "onViewCreated() creating callbacks");
172172

173-
// TODO: In following PRs. Enable startDiscoveryButton and stopDiscoveryButton when
174-
// stopDiscovery is implemented in the core Matter SDK DNS-SD API. Enable in
175-
// fragment_matter_discovery_example.xml
176173
Button startDiscoveryButton = getView().findViewById(R.id.startDiscoveryButton);
177174
startDiscoveryButton.setOnClickListener(
178175
v -> {
@@ -188,8 +185,6 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
188185
v -> {
189186
Log.i(TAG, "onViewCreated() stopDiscoveryButton button clicked. Calling stopDiscovery()");
190187
stopDiscovery();
191-
Log.i(TAG, "onViewCreated() stopDiscoveryButton button clicked. Canceling future task");
192-
scheduledFutureTask.cancel(true);
193188
});
194189

195190
Button clearDiscoveryResultsButton = getView().findViewById(R.id.clearDiscoveryResultsButton);
@@ -198,6 +193,8 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
198193
Log.i(
199194
TAG, "onViewCreated() clearDiscoveryResultsButton button clicked. Clearing results");
200195
arrayAdapter.clear();
196+
matterDiscoveryErrorMessageTextView.setText(
197+
getString(R.string.matter_discovery_error_message_initial));
201198
});
202199
}
203200

@@ -219,11 +216,7 @@ public void onResume() {
219216
public void onPause() {
220217
super.onPause();
221218
Log.i(TAG, "onPause() called");
222-
// stopDiscovery();
223-
// Don't crash the app
224-
if (scheduledFutureTask != null) {
225-
scheduledFutureTask.cancel(true);
226-
}
219+
stopDiscovery();
227220
}
228221

229222
/** Interface for notifying the host. */
@@ -235,6 +228,8 @@ public interface Callback {
235228

236229
private boolean startDiscovery() {
237230
Log.i(TAG, "startDiscovery() called");
231+
matterDiscoveryErrorMessageTextView.setText(
232+
getString(R.string.matter_discovery_error_message_initial));
238233

239234
arrayAdapter.clear();
240235

@@ -244,13 +239,17 @@ private boolean startDiscovery() {
244239
matterCastingPlayerDiscovery.addCastingPlayerChangeListener(castingPlayerChangeListener);
245240
if (err.hasError()) {
246241
Log.e(TAG, "startDiscovery() addCastingPlayerChangeListener() called, err Add: " + err);
242+
matterDiscoveryErrorMessageTextView.setText(
243+
getString(R.string.matter_discovery_error_message_stop_before_starting) + err);
247244
return false;
248245
}
249246
// Start discovery
250247
Log.i(TAG, "startDiscovery() calling CastingPlayerDiscovery.startDiscovery()");
251248
err = matterCastingPlayerDiscovery.startDiscovery(DISCOVERY_TARGET_DEVICE_TYPE);
252249
if (err.hasError()) {
253250
Log.e(TAG, "startDiscovery() startDiscovery() called, err Start: " + err);
251+
matterDiscoveryErrorMessageTextView.setText(
252+
getString(R.string.matter_discovery_error_message_start_error) + err);
254253
return false;
255254
}
256255

@@ -259,37 +258,23 @@ private boolean startDiscovery() {
259258
matterDiscoveryMessageTextView.setText(
260259
getString(R.string.matter_discovery_message_discovering_text));
261260

262-
// TODO: In following PRs. Enable this to auto-stop discovery after stopDiscovery is
263-
// implemented in the core Matter SDK DNS-SD API.
264-
// Schedule a service to stop discovery and remove the CastingPlayerChangeListener
265-
// Safe to call if discovery is not running
266-
// scheduledFutureTask =
267-
// executorService.schedule(
268-
// () -> {
269-
// Log.i(
270-
// TAG,
271-
// "startDiscovery() executorService "
272-
// + DISCOVERY_RUNTIME_SEC
273-
// + " seconds timer expired. Auto-calling stopDiscovery()");
274-
// stopDiscovery();
275-
// },
276-
// DISCOVERY_RUNTIME_SEC,
277-
// TimeUnit.SECONDS);
278-
279261
return true;
280262
}
281263

282264
private void stopDiscovery() {
283265
Log.i(TAG, "stopDiscovery() called");
266+
matterDiscoveryErrorMessageTextView.setText(
267+
getString(R.string.matter_discovery_error_message_initial));
284268

285269
// Stop discovery
286270
MatterError err = matterCastingPlayerDiscovery.stopDiscovery();
287271
if (err.hasError()) {
288272
Log.e(
289273
TAG,
290274
"stopDiscovery() MatterCastingPlayerDiscovery.stopDiscovery() called, err Stop: " + err);
275+
matterDiscoveryErrorMessageTextView.setText(
276+
getString(R.string.matter_discovery_error_message_stop_error) + err);
291277
} else {
292-
// TODO: In following PRs. Implement stop discovery in the Android core API.
293278
Log.d(TAG, "stopDiscovery() MatterCastingPlayerDiscovery.stopDiscovery() success");
294279
}
295280

@@ -309,6 +294,8 @@ private void stopDiscovery() {
309294
TAG,
310295
"stopDiscovery() matterCastingPlayerDiscovery.removeCastingPlayerChangeListener() called, err Remove: "
311296
+ err);
297+
matterDiscoveryErrorMessageTextView.setText(
298+
getString(R.string.matter_discovery_error_message_stop_error) + err);
312299
}
313300
}
314301
}

examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/CastingPlayerDiscovery-JNI.cpp

+17-11
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,17 @@ class DiscoveryDelegateImpl : public DiscoveryDelegate
7373

7474
VerifyOrReturn(castingPlayerChangeListenerJavaObject.HasValidObjectRef(),
7575
ChipLogError(AppServer,
76-
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Warning: Not set, "
76+
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Not set, "
7777
"CastingPlayerChangeListener == nullptr"));
7878
VerifyOrReturn(onAddedCallbackJavaMethodID != nullptr,
7979
ChipLogError(AppServer,
80-
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Warning: Not set, "
80+
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Not set, "
8181
"onAddedCallbackJavaMethodID == nullptr"));
8282

8383
jobject matterCastingPlayerJavaObject = support::convertCastingPlayerFromCppToJava(player);
8484
VerifyOrReturn(matterCastingPlayerJavaObject != nullptr,
8585
ChipLogError(AppServer,
86-
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Warning: Could not create "
86+
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnAdded() Could not create "
8787
"CastingPlayer jobject"));
8888

8989
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
@@ -100,17 +100,17 @@ class DiscoveryDelegateImpl : public DiscoveryDelegate
100100

101101
VerifyOrReturn(castingPlayerChangeListenerJavaObject.HasValidObjectRef(),
102102
ChipLogError(AppServer,
103-
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Warning: Not set, "
103+
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Not set, "
104104
"CastingPlayerChangeListener == nullptr"));
105105
VerifyOrReturn(onChangedCallbackJavaMethodID != nullptr,
106106
ChipLogError(AppServer,
107-
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Warning: Not set, "
107+
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Not set, "
108108
"onChangedCallbackJavaMethodID == nullptr"));
109109

110110
jobject matterCastingPlayerJavaObject = support::convertCastingPlayerFromCppToJava(player);
111111
VerifyOrReturn(matterCastingPlayerJavaObject != nullptr,
112112
ChipLogError(AppServer,
113-
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Warning: Could not "
113+
"CastingPlayerDiscovery-JNI::DiscoveryDelegateImpl::HandleOnUpdated() Could not "
114114
"create CastingPlayer jobject"));
115115

116116
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
@@ -191,7 +191,7 @@ JNI_METHOD(jobject, addCastingPlayerChangeListener)(JNIEnv * env, jobject, jobje
191191
if (DiscoveryDelegateImpl::GetInstance()->castingPlayerChangeListenerJavaObject.HasValidObjectRef())
192192
{
193193
ChipLogError(AppServer,
194-
"CastingPlayerDiscovery-JNI::addCastingPlayerChangeListener() Warning: Call removeCastingPlayerChangeListener "
194+
"CastingPlayerDiscovery-JNI::addCastingPlayerChangeListener() Call removeCastingPlayerChangeListener "
195195
"before adding a new one");
196196
return support::convertMatterErrorFromCppToJava(CHIP_ERROR_INCORRECT_STATE);
197197
}
@@ -246,11 +246,18 @@ JNI_METHOD(jobject, removeCastingPlayerChangeListener)(JNIEnv * env, jobject, jo
246246

247247
return support::convertMatterErrorFromCppToJava(CHIP_NO_ERROR);
248248
}
249+
else if (DiscoveryDelegateImpl::GetInstance()->castingPlayerChangeListenerJavaObject.ObjectRef() == nullptr)
250+
{
251+
ChipLogError(
252+
AppServer,
253+
"CastingPlayerDiscovery-JNI::removeCastingPlayerChangeListener() Cannot remove listener. No listener was added");
254+
return support::convertMatterErrorFromCppToJava(CHIP_NO_ERROR);
255+
}
249256
else
250257
{
251258
ChipLogError(AppServer,
252-
"CastingPlayerDiscovery-JNI::removeCastingPlayerChangeListener() Warning: Cannot remove listener. Received a "
253-
"different CastingPlayerChangeListener object");
259+
"CastingPlayerDiscovery-JNI::removeCastingPlayerChangeListener() Cannot remove listener. Received a different "
260+
"CastingPlayerChangeListener object");
254261
return support::convertMatterErrorFromCppToJava(CHIP_ERROR_INCORRECT_STATE);
255262
}
256263
}
@@ -276,8 +283,7 @@ JNI_METHOD(jobject, getCastingPlayers)(JNIEnv * env, jobject)
276283
jboolean added = env->CallBooleanMethod(arrayList, addMethod, matterCastingPlayerJavaObject);
277284
if (!((bool) added))
278285
{
279-
ChipLogError(AppServer,
280-
"CastingPlayerDiscovery-JNI::getCastingPlayers() Warning: Unable to add CastingPlayer with ID: %s",
286+
ChipLogError(AppServer, "CastingPlayerDiscovery-JNI::getCastingPlayers() Unable to add CastingPlayer with ID: %s",
281287
player->GetId());
282288
}
283289
}

examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_discovery_example.xml

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools"
44
android:layout_width="match_parent"
55
android:layout_height="match_parent"
@@ -15,14 +15,14 @@
1515
android:padding="10sp">
1616

1717
<Button
18-
android:enabled="false"
18+
android:enabled="true"
1919
android:id="@+id/startDiscoveryButton"
2020
android:layout_width="match_parent"
2121
android:layout_height="wrap_content"
2222
android:text="@string/matter_start_discovery_button_text" />
2323

2424
<Button
25-
android:enabled="false"
25+
android:enabled="true"
2626
android:id="@+id/stopDiscoveryButton"
2727
android:layout_width="match_parent"
2828
android:layout_height="wrap_content"
@@ -49,5 +49,13 @@
4949
android:fadeScrollbars = "false" />
5050
</LinearLayout>
5151

52+
<TextView
53+
android:id="@+id/matterDiscoveryErrorTextView"
54+
android:layout_width="match_parent"
55+
android:layout_height = "wrap_content"
56+
android:text="string/matter_discovery_error_default_text"
57+
android:textAlignment="center"
58+
android:textAppearance="@style/TextAppearance.AppCompat.Small"
59+
android:layout_alignParentBottom="true"/>
5260

53-
</FrameLayout>
61+
</RelativeLayout>

examples/tv-casting-app/android/App/app/src/main/res/values/strings.xml

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@
3131
<string name="matter_stop_discovery_button_text">Stop Discovery"</string>
3232
<string name="matter_clear_results_button_text">Clear Results"</string>
3333
<string name="matter_discovery_message_initializing_text">Initializing</string>
34-
<string name="matter_discovery_message_discovering_text">Casting Players on-network:</string>
34+
<string name="matter_discovery_message_discovering_text">Discovering Casting Players on-network:</string>
3535
<string name="matter_discovery_message_stopped_text">Discovery Stopped</string>
36+
<string name="matter_discovery_error_message_initial">No errors to report</string>
37+
<string name="matter_discovery_error_message_start_error">Start discovery error. -</string>
38+
<string name="matter_discovery_error_message_stop_before_starting">Start discovery error. Discovery ongoing, stop before starting. -</string>
39+
<string name="matter_discovery_error_message_stop_error">Stop discovery error. -</string>
3640
<string name="matter_connection_next_button_text">Next</string>
3741
<string name="matter_action_selector_text">Select an action</string>
3842
<string name="matter_select_content_launcher_launch_url_button_text">Content Launcher Launch URL</string>

src/platform/android/DnssdImpl.cpp

+23-2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ JniGlobalReference sBrowserObject;
4444
JniGlobalReference sMdnsCallbackObject;
4545
jmethodID sResolveMethod = nullptr;
4646
jmethodID sBrowseMethod = nullptr;
47+
jmethodID sStopBrowseMethod = nullptr;
4748
jmethodID sGetTextEntryKeysMethod = nullptr;
4849
jmethodID sGetTextEntryDataMethod = nullptr;
4950
jclass sMdnsCallbackClass = nullptr;
@@ -203,13 +204,31 @@ CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, Ine
203204
return CHIP_JNI_ERROR_EXCEPTION_THROWN;
204205
}
205206

206-
*browseIdentifier = reinterpret_cast<intptr_t>(nullptr);
207+
auto sdCtx = chip::Platform::New<BrowseContext>(callback);
208+
*browseIdentifier = reinterpret_cast<intptr_t>(sdCtx);
209+
207210
return CHIP_NO_ERROR;
208211
}
209212

210213
CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier)
211214
{
212-
return CHIP_ERROR_NOT_IMPLEMENTED;
215+
VerifyOrReturnError(sBrowserObject.HasValidObjectRef() && sStopBrowseMethod != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
216+
217+
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
218+
auto ctx = reinterpret_cast<BrowseContext *>(browseIdentifier);
219+
220+
env->CallVoidMethod(sBrowserObject.ObjectRef(), sStopBrowseMethod, reinterpret_cast<jlong>(ctx->callback));
221+
222+
if (env->ExceptionCheck())
223+
{
224+
ChipLogError(Discovery, "Java exception in ChipDnssdStopBrowse");
225+
env->ExceptionDescribe();
226+
env->ExceptionClear();
227+
return CHIP_JNI_ERROR_EXCEPTION_THROWN;
228+
}
229+
chip::Platform::Delete(ctx);
230+
231+
return CHIP_NO_ERROR;
213232
}
214233

215234
template <size_t N>
@@ -306,6 +325,8 @@ void InitializeWithObjects(jobject resolverObject, jobject browserObject, jobjec
306325

307326
sBrowseMethod = env->GetMethodID(browserClass, "browse", "(Ljava/lang/String;JJLchip/platform/ChipMdnsCallback;)V");
308327

328+
sStopBrowseMethod = env->GetMethodID(browserClass, "stopDiscover", "(J)V");
329+
309330
if (sResolveMethod == nullptr)
310331
{
311332
ChipLogError(Discovery, "Failed to access Resolver 'resolve' method");

src/platform/android/DnssdImpl.h

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#pragma once
1919

2020
#include <jni.h>
21+
#include <lib/dnssd/platform/Dnssd.h>
2122

2223
namespace chip {
2324
namespace Dnssd {
@@ -37,5 +38,12 @@ void HandleResolve(jstring instanceName, jstring serviceType, jstring hostName,
3738

3839
void HandleBrowse(jobjectArray instanceName, jstring serviceType, jlong callbackHandle, jlong contextHandle);
3940

41+
struct BrowseContext
42+
{
43+
DnssdBrowseCallback callback;
44+
45+
BrowseContext(DnssdBrowseCallback cb) { callback = cb; };
46+
};
47+
4048
} // namespace Dnssd
4149
} // namespace chip

0 commit comments

Comments
 (0)