diff --git a/examples/tv-casting-app/APIs.md b/examples/tv-casting-app/APIs.md
index 12f5fdf30ebc1b..1bbb189e7179d7 100644
--- a/examples/tv-casting-app/APIs.md
+++ b/examples/tv-casting-app/APIs.md
@@ -688,7 +688,7 @@ func startDiscovery() {
 }
 ```
 
-Note: You will need to connect with a Casting Player as described below to see
+Note: You will need to connect with a Casting Player as described below to se
 the list of Endpoints that they support. Refer to the
 [Connection](#connect-to-a-casting-player) section for details on how to
 discover available endpoints supported by a Casting Player.
@@ -696,7 +696,8 @@ discover available endpoints supported by a Casting Player.
 ### Connect to a Casting Player
 
 _{Complete Connection examples: [Linux](linux/simple-app-helper.cpp) |
-[iOS](darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift)}_
+[Android](android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java)
+| [iOS](darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift)}_
 
 Each `CastingPlayer` object created during
 [Discovery](#discover-casting-players) contains information such as
@@ -830,7 +831,7 @@ func connect(selectedCastingPlayer: MCCastingPlayer?) {
 ### Select an Endpoint on the Casting Player
 
 _{Complete Endpoint selection examples: [Linux](linux/simple-app-helper.cpp) |
-[Android](android/App/app/src/main/java/com/matter/casting/ContentLauncherLaunchURLExampleFragment.java)
+[Android](android/App/app/src/main/java/com/matter/casting/EndpointSelectorExample.java)
 |
 [iOS](darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift)}_
 
@@ -863,7 +864,7 @@ On Android, it can select an `Endpoint` as shown below.
 ```java
 private static final Integer SAMPLE_ENDPOINT_VID = 65521;
 
-private Endpoint selectEndpoint()
+private Endpoint selectFirstEndpointByVID()
 {
     Endpoint endpoint = null;
     if(selectedCastingPlayer != null)
@@ -905,18 +906,25 @@ Once the Casting Client has selected an `Endpoint`, it is ready to
 [issue commands](#issuing-commands) to it, [read](#read-operations) current
 playback state, and [subscribe](#subscriptions) to playback events.
 
-On Linux refer to the following platform specific files:
+Refer to the following platform specific files, to find the list of clusters,
+commands and attributes, with their request/response types available for use
+with the Matter TV Casting library.
+
+For Linux, refer to the following files:
 
-1. For a list of clusters, commands and attributes supported by the Matter TV
-   Casting library:
+1. For a list of supported clusters, commands and attributes:
    [tv-casting-common/clusters/Clusters.h](tv-casting-common/clusters/Clusters.h)
 2. For the IDs and request / response types to use with these APIs:
    [/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h](/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h)
 
-On iOS refer to the following platform specific files:
+For Android, refer to the following files:
+
+1. For a list of supported clusters, commands and attributes:
+   [/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java](/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java)
 
-1. For a list of clusters, commands and attributes supported by the Matter TV
-   Casting library:
+On iOS, refer to the following files:
+
+1. For a list of supported clusters, commands and attribute:
    [darwin/MatterTvCastingBridge/MatterTvCastingBridge/zap-generated/MCClusterObjects.h](darwin/MatterTvCastingBridge/MatterTvCastingBridge/zap-generated/MCClusterObjects.h)
 2. For the IDs and request / response types to use with the commands:
    [darwin/MatterTvCastingBridge/MatterTvCastingBridge/zap-generated/MCCommandObjects.h](darwin/MatterTvCastingBridge/MatterTvCastingBridge/zap-generated/MCCommandObjects.h)
@@ -929,6 +937,8 @@ On iOS refer to the following platform specific files:
 ### Issuing Commands
 
 _{Complete Command invocation examples: [Linux](linux/simple-app-helper.cpp) |
+[Android](android/App/app/src/main/java/com/matter/casting/ContentLauncherLaunchURLExampleFragment.java)
+|
 [iOS](darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift)}_
 
 The Casting Client can get a reference to an `Endpoint` on a `CastingPlayer`,
@@ -975,6 +985,51 @@ void InvokeContentLauncherLaunchURL(matter::casting::memory::Strong<matter::cast
 }
 ```
 
+On Android, given an `Endpoint`, it can send a `LaunchURL` command (part of the
+Content Launcher cluster) by calling the `launchURL` API on a
+`ChipClusters.ContentLauncherCluster` object.
+
+```java
+// get ChipClusters.ContentLauncherCluster from the endpoint
+ChipClusters.ContentLauncherCluster cluster =
+    endpoint.getCluster(ChipClusters.ContentLauncherCluster.class);
+if (cluster == null) {
+    Log.e(TAG, "Could not get ContentLauncherCluster for endpoint with ID: " + endpoint.getId());
+    return;
+}
+
+// call launchURL on the cluster object while passing in a
+// ChipClusters.ContentLauncherCluster.LauncherResponseCallback and request parameters
+cluster.launchURL(
+    new ChipClusters.ContentLauncherCluster.LauncherResponseCallback() {
+    @Override
+    public void onSuccess(Integer status, Optional<String> data) {
+        Log.d(TAG, "LaunchURL success. Status: " + status + ", Data: " + data);
+        new Handler(Looper.getMainLooper())
+            .post(
+                () -> {
+                TextView launcherResult = getView().findViewById(R.id.launcherResult);
+                launcherResult.setText(
+                    "LaunchURL result\nStatus: " + status + ", Data: " + data);
+                });
+    }
+
+    @Override
+    public void onError(Exception error) {
+        Log.e(TAG, "LaunchURL failure " + error);
+        new Handler(Looper.getMainLooper())
+            .post(
+                () -> {
+                TextView launcherResult = getView().findViewById(R.id.launcherResult);
+                launcherResult.setText("LaunchURL result\nError: " + error);
+                });
+    }
+    },
+    contentUrl,
+    Optional.of(contentDisplayString),
+    Optional.empty());
+```
+
 On iOS, given an `MCEndpoint` endpoint, it can send a `LaunchURL` command (part
 of the Content Launcher cluster) by calling the `invoke` API on a
 `MCContentLauncherClusterLaunchURLCommand`
@@ -1033,6 +1088,8 @@ timedInvokeTimeoutMs: 5000) // time out after 5000ms
 ### Read Operations
 
 _{Complete Attribute Read examples: [Linux](linux/simple-app-helper.cpp) |
+[Android](android/App/app/src/main/java/com/matter/casting/ApplicationBasicReadVendorIDExampleFragment.java)
+|
 [iOS](darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift)}_
 
 The `CastingClient` may read an Attribute from the `Endpoint` on the
@@ -1080,6 +1137,45 @@ void ReadApplicationBasicVendorID(matter::casting::memory::Strong<matter::castin
 }
 ```
 
+On Android, given an `Endpoint`, the `VendorID` can be read, by calling
+`readVendorIDAttribute` on the `ChipClusters.ApplicationBasicCluster` object.
+
+```java
+// get ChipClusters.ApplicationBasic from the endpoint
+ChipClusters.ApplicationBasicCluster cluster = endpoint.getCluster(ChipClusters.ApplicationBasicCluster.class);
+if (cluster == null) {
+    Log.e(TAG, "Could not get ApplicationBasicCluster for endpoint with ID: " + endpoint.getId());
+    return;
+}
+
+// call readVendorIDAttribute on the cluster object while passing in a
+// ChipClusters.IntegerAttributeCallback
+cluster.readVendorIDAttribute(new ChipClusters.IntegerAttributeCallback() {
+    @Override
+    public void onSuccess(int value) {
+        Log.d(TAG, "ReadVendorID success. Value: " + value);
+        new Handler(Looper.getMainLooper())
+                .post(
+                        () -> {
+                            TextView vendorIdResult = getView().findViewById(R.id.vendorIdResult);
+                            vendorIdResult.setText(
+                                    "Read VendorID result\nValue: " + value );
+                        });
+    }
+
+    @Override
+    public void onError(Exception error) {
+        Log.e(TAG, "ReadVendorID failure " + error);
+        new Handler(Looper.getMainLooper())
+                .post(
+                        () -> {
+                            TextView vendorIdResult = getView().findViewById(R.id.vendorIdResult);
+                            vendorIdResult.setText("Read VendorID result\nError: " + error);
+                        });
+    }
+});
+```
+
 On iOS, given a `MCEndpoint`, the `VendorID` can be read similarly, by calling
 the `read` API on the `MCApplicationBasicClusterVendorIDAttribute`
 
@@ -1138,6 +1234,9 @@ vendorIDAttribute!.read(nil) { context, before, after, err in
 ### Subscriptions
 
 _{Complete Attribute subscription examples: [Linux](linux/simple-app-helper.cpp)
+|
+[Android](android/App/app/src/main/java/com/matter/casting/MediaPlaybackSubscribeToCurrentStateExampleFragment.java)
+|
 |[iOS](darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift)}_
 
 A Casting Client may subscribe to an attribute on an `Endpoint` of the
@@ -1187,6 +1286,49 @@ void SubscribeToMediaPlaybackCurrentState(matter::casting::memory::Strong<matter
 }
 ```
 
+On Android, given an `Endpoint`, `CurrentState` can be subscribe to by calling
+`subscribeCurrentStateAttribute` on a `ChipClusters.MediaPlaybackCluster`
+object.
+
+```java
+                    // get ChipClusters.MediaPlaybackCluster from the endpoint
+                    ChipClusters.MediaPlaybackCluster cluster =
+                            endpoint.getCluster(ChipClusters.MediaPlaybackCluster.class);
+                    if (cluster == null) {
+                        Log.e(
+                                TAG,
+                                "Could not get ApplicationBasicCluster for endpoint with ID: " + endpoint.getId());
+                        return;
+                    }
+
+                    // call subscribeCurrentStateAttribute on the cluster object while passing in a
+                    // ChipClusters.IntegerAttributeCallback and [0, 1] for min and max interval params
+                    cluster.subscribeCurrentStateAttribute(new ChipClusters.IntegerAttributeCallback() {
+                        @Override
+                        public void onSuccess(int value) {
+                            Log.d(TAG, "Read success on subscription. Value: " + value + " @ " + new Date());
+                            new Handler(Looper.getMainLooper())
+                                    .post(
+                                            () -> {
+                                                TextView currentStateResult = getView().findViewById(R.id.currentStateResult);
+                                                currentStateResult.setText(
+                                                        "Current State result\nValue: " + value );
+                                            });
+                        }
+
+                        @Override
+                        public void onError(Exception error) {
+                            Log.e(TAG, "Read failure on subscription: " + error);
+                            new Handler(Looper.getMainLooper())
+                                    .post(
+                                            () -> {
+                                                TextView currentStateResult = getView().findViewById(R.id.currentStateResult);
+                                                currentStateResult.setText("Current State result\nError: " + error);
+                                            });
+                        }
+                    }, 0, 1);
+```
+
 On iOS, given a `MCEndpoint`, `CurrentState` can be subscribed to by calling the
 `subscribe` API on the it can subscribe to the `CurrentState` (part of the Media
 Playback Basic cluster) by calling the `Subscribe` API on the
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MainActivity.java b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MainActivity.java
index 6e54ff61b01c7e..cb04518f5c6259 100644
--- a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MainActivity.java
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MainActivity.java
@@ -11,10 +11,12 @@
 import com.chip.casting.TvCastingApp;
 import com.chip.casting.util.GlobalCastingConstants;
 import com.matter.casting.ActionSelectorFragment;
+import com.matter.casting.ApplicationBasicReadVendorIDExampleFragment;
 import com.matter.casting.ConnectionExampleFragment;
 import com.matter.casting.ContentLauncherLaunchURLExampleFragment;
 import com.matter.casting.DiscoveryExampleFragment;
 import com.matter.casting.InitializationExample;
+import com.matter.casting.MediaPlaybackSubscribeToCurrentStateExampleFragment;
 import com.matter.casting.PreferencesConfigurationManager;
 import com.matter.casting.core.CastingPlayer;
 import java.util.Random;
@@ -85,6 +87,18 @@ public void handleContentLauncherLaunchURLSelected(CastingPlayer selectedCasting
     showFragment(ContentLauncherLaunchURLExampleFragment.newInstance(selectedCastingPlayer));
   }
 
+  @Override
+  public void handleApplicationBasicReadVendorIDSelected(CastingPlayer selectedCastingPlayer) {
+    showFragment(ApplicationBasicReadVendorIDExampleFragment.newInstance(selectedCastingPlayer));
+  }
+
+  @Override
+  public void handleMediaPlaybackSubscribeToCurrentStateSelected(
+      CastingPlayer selectedCastingPlayer) {
+    showFragment(
+        MediaPlaybackSubscribeToCurrentStateExampleFragment.newInstance(selectedCastingPlayer));
+  }
+
   @Override
   public void handleContentLauncherSelected() {
     showFragment(ContentLauncherFragment.newInstance(tvCastingApp));
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/util/GlobalCastingConstants.java b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/util/GlobalCastingConstants.java
index d063cc7e6f78c5..483f1efedb1b46 100644
--- a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/util/GlobalCastingConstants.java
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/util/GlobalCastingConstants.java
@@ -6,5 +6,6 @@ public class GlobalCastingConstants {
   public static final int SetupPasscode = 20202021;
   public static final int Discriminator = 0xF00;
   public static final boolean ChipCastingSimplified =
-      false; // set this flag to true to demo simplified casting APIs
+      true; // set to true, to demo the simplified casting APIs. Otherwise, the older deprecated
+  // APIs are invoked
 }
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ActionSelectorFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ActionSelectorFragment.java
index 2906ad186d6054..cb5d2170e96d6d 100644
--- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ActionSelectorFragment.java
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ActionSelectorFragment.java
@@ -33,6 +33,8 @@ public class ActionSelectorFragment extends Fragment {
   private final CastingPlayer selectedCastingPlayer;
 
   private View.OnClickListener selectContentLauncherButtonClickListener;
+  private View.OnClickListener selectApplicationBasicButtonClickListener;
+  private View.OnClickListener selectMediaPlaybackButtonClickListener;
   private View.OnClickListener disconnectButtonClickListener;
 
   public ActionSelectorFragment(CastingPlayer selectedCastingPlayer) {
@@ -64,6 +66,16 @@ public View onCreateView(
           Log.d(TAG, "handle() called on selectContentLauncherButtonClickListener");
           callback.handleContentLauncherLaunchURLSelected(selectedCastingPlayer);
         };
+    this.selectApplicationBasicButtonClickListener =
+        v -> {
+          Log.d(TAG, "handle() called on selectApplicationBasicButtonClickListener");
+          callback.handleApplicationBasicReadVendorIDSelected(selectedCastingPlayer);
+        };
+    this.selectMediaPlaybackButtonClickListener =
+        v -> {
+          Log.d(TAG, "handle() called on selectMediaPlaybackButtonClickListener");
+          callback.handleMediaPlaybackSubscribeToCurrentStateSelected(selectedCastingPlayer);
+        };
 
     this.disconnectButtonClickListener =
         v -> {
@@ -82,6 +94,12 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
     getView()
         .findViewById(R.id.selectContentLauncherLaunchURLButton)
         .setOnClickListener(selectContentLauncherButtonClickListener);
+    getView()
+        .findViewById(R.id.selectApplicationBasicReadVendorIDButton)
+        .setOnClickListener(selectApplicationBasicButtonClickListener);
+    getView()
+        .findViewById(R.id.selectMediaPlaybackSubscribeToCurrentStateButton)
+        .setOnClickListener(selectMediaPlaybackButtonClickListener);
 
     getView().findViewById(R.id.disconnectButton).setOnClickListener(disconnectButtonClickListener);
   }
@@ -91,6 +109,12 @@ public interface Callback {
     /** Notifies listener to trigger transition on selection of Content Launcher cluster */
     void handleContentLauncherLaunchURLSelected(CastingPlayer selectedCastingPlayer);
 
+    /** Notifies listener to trigger transition on selection of Application Basic cluster */
+    void handleApplicationBasicReadVendorIDSelected(CastingPlayer selectedCastingPlayer);
+
+    /** Notifies listener to trigger transition on selection of Media PLayback cluster */
+    void handleMediaPlaybackSubscribeToCurrentStateSelected(CastingPlayer selectedCastingPlayer);
+
     /** Notifies listener to trigger transition on click of the Disconnect button */
     void handleDisconnect();
   }
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ApplicationBasicReadVendorIDExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ApplicationBasicReadVendorIDExampleFragment.java
new file mode 100644
index 00000000000000..878c18019f4d09
--- /dev/null
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ApplicationBasicReadVendorIDExampleFragment.java
@@ -0,0 +1,125 @@
+/*
+ *   Copyright (c) 2024 Project CHIP Authors
+ *   All rights reserved.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+package com.matter.casting;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import chip.devicecontroller.ChipClusters;
+import com.R;
+import com.matter.casting.core.CastingPlayer;
+import com.matter.casting.core.Endpoint;
+
+/**
+ * A {@link Fragment} to read the VendorID (from ApplicationBasic cluster) using the TV Casting App.
+ */
+public class ApplicationBasicReadVendorIDExampleFragment extends Fragment {
+  private static final String TAG =
+      ApplicationBasicReadVendorIDExampleFragment.class.getSimpleName();
+
+  private final CastingPlayer selectedCastingPlayer;
+
+  private View.OnClickListener readButtonClickListener;
+
+  public ApplicationBasicReadVendorIDExampleFragment(CastingPlayer selectedCastingPlayer) {
+    this.selectedCastingPlayer = selectedCastingPlayer;
+  }
+
+  /**
+   * Use this factory method to create a new instance of this fragment using the provided
+   * parameters.
+   *
+   * @param selectedCastingPlayer CastingPlayer that the casting app connected to
+   * @return A new instance of fragment ApplicationBasicReadVendorIDExampleFragment.
+   */
+  public static ApplicationBasicReadVendorIDExampleFragment newInstance(
+      CastingPlayer selectedCastingPlayer) {
+    return new ApplicationBasicReadVendorIDExampleFragment(selectedCastingPlayer);
+  }
+
+  @Override
+  public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+  }
+
+  @Override
+  public View onCreateView(
+      LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+    this.readButtonClickListener =
+        v -> {
+          Endpoint endpoint =
+              EndpointSelectorExample.selectFirstEndpointByVID(selectedCastingPlayer);
+          if (endpoint == null) {
+            Log.e(TAG, "No Endpoint with sample vendorID found on CastingPlayer");
+            return;
+          }
+
+          // get ChipClusters.ApplicationBasic from the endpoint
+          ChipClusters.ApplicationBasicCluster cluster =
+              endpoint.getCluster(ChipClusters.ApplicationBasicCluster.class);
+          if (cluster == null) {
+            Log.e(
+                TAG,
+                "Could not get ApplicationBasicCluster for endpoint with ID: " + endpoint.getId());
+            return;
+          }
+
+          // call readVendorIDAttribute on the cluster object while passing in a
+          // ChipClusters.IntegerAttributeCallback
+          cluster.readVendorIDAttribute(
+              new ChipClusters.IntegerAttributeCallback() {
+                @Override
+                public void onSuccess(int value) {
+                  Log.d(TAG, "ReadVendorID success. Value: " + value);
+                  new Handler(Looper.getMainLooper())
+                      .post(
+                          () -> {
+                            TextView vendorIdResult = getView().findViewById(R.id.vendorIdResult);
+                            vendorIdResult.setText("Read VendorID result\nValue: " + value);
+                          });
+                }
+
+                @Override
+                public void onError(Exception error) {
+                  Log.e(TAG, "ReadVendorID failure " + error);
+                  new Handler(Looper.getMainLooper())
+                      .post(
+                          () -> {
+                            TextView vendorIdResult = getView().findViewById(R.id.vendorIdResult);
+                            vendorIdResult.setText("Read VendorID result\nError: " + error);
+                          });
+                }
+              });
+        };
+    return inflater.inflate(
+        R.layout.fragment_matter_application_basic_read_vendor_id, container, false);
+  }
+
+  @Override
+  public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+    super.onViewCreated(view, savedInstanceState);
+    Log.d(TAG, "ApplicationBasicReadVendorIDExampleFragment.onViewCreated called");
+    getView().findViewById(R.id.readVendorIdButton).setOnClickListener(readButtonClickListener);
+  }
+}
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 c1bde0f9bb0323..ddf41b349d6890 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
@@ -17,18 +17,23 @@
 package com.matter.casting;
 
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.TextView;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
+import chip.devicecontroller.ChipClusters;
 import com.R;
 import com.matter.casting.core.CastingPlayer;
 import com.matter.casting.core.Endpoint;
-import java.util.List;
+import java.util.Optional;
 
-/** A {@link Fragment} to send Content Launcher LaunchURL command from the TV Casting App. */
+/** A {@link Fragment} to send Content Launcher LaunchURL command using the TV Casting App. */
 public class ContentLauncherLaunchURLExampleFragment extends Fragment {
   private static final String TAG = ContentLauncherLaunchURLExampleFragment.class.getSimpleName();
   private static final Integer SAMPLE_ENDPOINT_VID = 65521;
@@ -63,19 +68,61 @@ public View onCreateView(
       LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     this.launchUrlButtonClickListener =
         v -> {
-          Endpoint endpoint = selectEndpoint();
+          Endpoint endpoint =
+              EndpointSelectorExample.selectFirstEndpointByVID(selectedCastingPlayer);
           if (endpoint == null) {
+            Log.e(TAG, "No Endpoint with sample vendorID found on CastingPlayer");
+            return;
+          }
+
+          EditText contentUrlEditText = getView().findViewById(R.id.contentUrlEditText);
+          String contentUrl = contentUrlEditText.getText().toString();
+          EditText contentDisplayStringEditText =
+              getView().findViewById(R.id.contentDisplayStringEditText);
+          String contentDisplayString = contentDisplayStringEditText.getText().toString();
+
+          // get ChipClusters.ContentLauncherCluster from the endpoint
+          ChipClusters.ContentLauncherCluster cluster =
+              endpoint.getCluster(ChipClusters.ContentLauncherCluster.class);
+          if (cluster == null) {
             Log.e(
                 TAG,
-                "No Endpoint with chosen vendorID: "
-                    + SAMPLE_ENDPOINT_VID
-                    + " found on CastingPlayer");
+                "Could not get ContentLauncherCluster for endpoint with ID: " + endpoint.getId());
             return;
           }
 
-          // TODO: add command invocation API call
+          // call launchURL on the cluster object while passing in a
+          // ChipClusters.ContentLauncherCluster.LauncherResponseCallback and request parameters
+          cluster.launchURL(
+              new ChipClusters.ContentLauncherCluster.LauncherResponseCallback() {
+                @Override
+                public void onSuccess(Integer status, Optional<String> data) {
+                  Log.d(TAG, "LaunchURL success. Status: " + status + ", Data: " + data);
+                  new Handler(Looper.getMainLooper())
+                      .post(
+                          () -> {
+                            TextView launcherResult = getView().findViewById(R.id.launcherResult);
+                            launcherResult.setText(
+                                "LaunchURL result\nStatus: " + status + ", Data: " + data);
+                          });
+                }
+
+                @Override
+                public void onError(Exception error) {
+                  Log.e(TAG, "LaunchURL failure " + error);
+                  new Handler(Looper.getMainLooper())
+                      .post(
+                          () -> {
+                            TextView launcherResult = getView().findViewById(R.id.launcherResult);
+                            launcherResult.setText("LaunchURL result\nError: " + error);
+                          });
+                }
+              },
+              contentUrl,
+              Optional.of(contentDisplayString),
+              Optional.empty());
         };
-    return inflater.inflate(R.layout.fragment_content_launcher, container, false);
+    return inflater.inflate(R.layout.fragment_matter_content_launcher_launch_url, container, false);
   }
 
   @Override
@@ -84,22 +131,4 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
     Log.d(TAG, "ContentLauncherLaunchURLExampleFragment.onViewCreated called");
     getView().findViewById(R.id.launchUrlButton).setOnClickListener(launchUrlButtonClickListener);
   }
-
-  private Endpoint selectEndpoint() {
-    Endpoint endpoint = null;
-    if (selectedCastingPlayer != null) {
-      List<Endpoint> endpoints = selectedCastingPlayer.getEndpoints();
-      if (endpoints == null) {
-        Log.e(TAG, "No Endpoints found on CastingPlayer");
-      } else {
-        endpoint =
-            endpoints
-                .stream()
-                .filter(e -> SAMPLE_ENDPOINT_VID.equals(e.getVendorId()))
-                .findFirst()
-                .get();
-      }
-    }
-    return endpoint;
-  }
 }
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/EndpointSelectorExample.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/EndpointSelectorExample.java
new file mode 100644
index 00000000000000..c2932c59117c64
--- /dev/null
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/EndpointSelectorExample.java
@@ -0,0 +1,34 @@
+package com.matter.casting;
+
+import android.util.Log;
+import com.matter.casting.core.CastingPlayer;
+import com.matter.casting.core.Endpoint;
+import java.util.List;
+
+/** A utility that selects an endpoint based on some criterion */
+public class EndpointSelectorExample {
+  private static final String TAG = EndpointSelectorExample.class.getSimpleName();
+  private static final Integer SAMPLE_ENDPOINT_VID = 65521;
+
+  /**
+   * Returns the first Endpoint in the list of Endpoints associated with the selectedCastingPlayer
+   * whose VendorID matches the EndpointSelectorExample.SAMPLE_ENDPOINT_VID
+   */
+  public static Endpoint selectFirstEndpointByVID(CastingPlayer selectedCastingPlayer) {
+    Endpoint endpoint = null;
+    if (selectedCastingPlayer != null) {
+      List<Endpoint> endpoints = selectedCastingPlayer.getEndpoints();
+      if (endpoints == null) {
+        Log.e(TAG, "No Endpoints found on CastingPlayer");
+      } else {
+        endpoint =
+            endpoints
+                .stream()
+                .filter(e -> SAMPLE_ENDPOINT_VID.equals(e.getVendorId()))
+                .findFirst()
+                .get();
+      }
+    }
+    return endpoint;
+  }
+}
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/MediaPlaybackSubscribeToCurrentStateExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/MediaPlaybackSubscribeToCurrentStateExampleFragment.java
new file mode 100644
index 00000000000000..77f5129b6b9e4d
--- /dev/null
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/MediaPlaybackSubscribeToCurrentStateExampleFragment.java
@@ -0,0 +1,148 @@
+/*
+ *   Copyright (c) 2024 Project CHIP Authors
+ *   All rights reserved.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+package com.matter.casting;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import chip.devicecontroller.ChipClusters;
+import com.R;
+import com.matter.casting.core.CastingApp;
+import com.matter.casting.core.CastingPlayer;
+import com.matter.casting.core.Endpoint;
+import java.util.Date;
+
+/**
+ * A {@link Fragment} to subscribe to CurrentState (from MediaPLayback cluster) using the TV Casting
+ * App.
+ */
+public class MediaPlaybackSubscribeToCurrentStateExampleFragment extends Fragment {
+  private static final String TAG =
+      MediaPlaybackSubscribeToCurrentStateExampleFragment.class.getSimpleName();
+
+  private final CastingPlayer selectedCastingPlayer;
+
+  private View.OnClickListener subscribeButtonClickListener;
+  private View.OnClickListener shutdownSubscriptionsButtonClickListener;
+
+  public MediaPlaybackSubscribeToCurrentStateExampleFragment(CastingPlayer selectedCastingPlayer) {
+    this.selectedCastingPlayer = selectedCastingPlayer;
+  }
+
+  /**
+   * Use this factory method to create a new instance of this fragment using the provided
+   * parameters.
+   *
+   * @param selectedCastingPlayer CastingPlayer that the casting app connected to
+   * @return A new instance of fragment MediaPlaybackSubscribeToCurrentStateExampleFragment.
+   */
+  public static MediaPlaybackSubscribeToCurrentStateExampleFragment newInstance(
+      CastingPlayer selectedCastingPlayer) {
+    return new MediaPlaybackSubscribeToCurrentStateExampleFragment(selectedCastingPlayer);
+  }
+
+  @Override
+  public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+  }
+
+  @Override
+  public View onCreateView(
+      LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+    Endpoint endpoint = EndpointSelectorExample.selectFirstEndpointByVID(selectedCastingPlayer);
+    if (endpoint == null) {
+      Log.e(TAG, "No Endpoint with sample vendorID found on CastingPlayer");
+      return inflater.inflate(
+          R.layout.fragment_matter_media_playback_subscribe_current_state, container, false);
+    }
+
+    this.subscribeButtonClickListener =
+        v -> {
+          // get ChipClusters.MediaPlaybackCluster from the endpoint
+          ChipClusters.MediaPlaybackCluster cluster =
+              endpoint.getCluster(ChipClusters.MediaPlaybackCluster.class);
+          if (cluster == null) {
+            Log.e(
+                TAG,
+                "Could not get ApplicationBasicCluster for endpoint with ID: " + endpoint.getId());
+            return;
+          }
+
+          // call subscribeCurrentStateAttribute on the cluster object while passing in a
+          // ChipClusters.IntegerAttributeCallback and [0, 1] for min and max interval params
+          cluster.subscribeCurrentStateAttribute(
+              new ChipClusters.IntegerAttributeCallback() {
+                @Override
+                public void onSuccess(int value) {
+                  Log.d(TAG, "Read success on subscription. Value: " + value + " @ " + new Date());
+                  new Handler(Looper.getMainLooper())
+                      .post(
+                          () -> {
+                            TextView currentStateResult =
+                                getView().findViewById(R.id.currentStateResult);
+                            currentStateResult.setText("Current State result\nValue: " + value);
+                          });
+                }
+
+                @Override
+                public void onError(Exception error) {
+                  Log.e(TAG, "Read failure on subscription: " + error);
+                  new Handler(Looper.getMainLooper())
+                      .post(
+                          () -> {
+                            TextView currentStateResult =
+                                getView().findViewById(R.id.currentStateResult);
+                            currentStateResult.setText("Current State result\nError: " + error);
+                          });
+                }
+              },
+              0,
+              1);
+        };
+
+    this.shutdownSubscriptionsButtonClickListener =
+        new View.OnClickListener() {
+          @Override
+          public void onClick(View v) {
+            Log.d(TAG, "Shutting down subscriptions");
+            CastingApp.getInstance().shutdownAllSubscriptions();
+          }
+        };
+
+    return inflater.inflate(
+        R.layout.fragment_matter_media_playback_subscribe_current_state, container, false);
+  }
+
+  @Override
+  public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+    super.onViewCreated(view, savedInstanceState);
+    Log.d(TAG, "MediaPlaybackSubscribeToCurrentStateExampleFragment.onViewCreated called");
+    getView()
+        .findViewById(R.id.subscribeToCurrentStateButton)
+        .setOnClickListener(subscribeButtonClickListener);
+    getView()
+        .findViewById(R.id.shutdownSubscriptionsButton)
+        .setOnClickListener(shutdownSubscriptionsButtonClickListener);
+  }
+}
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<DeviceTypeStruct> getDeviceTypeList();
 
+  /** Get an instance of a cluster based on its Class */
+  <T extends ChipClusters.BaseChipCluster> T getCluster(Class<T> 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 b9dd564d6ff95f..86d0eb016958a7 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,12 +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_MS = 5000;
   protected long _cppEndpoint;
 
   @Override
@@ -36,6 +47,27 @@ public class MatterEndpoint implements Endpoint {
   @Override
   public native List<DeviceTypeStruct> getDeviceTypeList();
 
+  @Override
+  public <T extends ChipClusters.BaseChipCluster> T getCluster(Class<T> clusterClass) {
+    try {
+      Constructor<T> 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;
+    }
+  }
+
   @Override
   public native CastingPlayer getCastingPlayer();
 
@@ -56,4 +88,32 @@ public boolean equals(Object o) {
   public int hashCode() {
     return Objects.hash(getId());
   }
+
+  private Long getDeviceProxy() {
+    CompletableFuture<Long> deviceProxyFuture = new CompletableFuture<>();
+    getDeviceProxy(
+        new MatterCallback<Long>() {
+          @Override
+          public void handle(Long deviceProxy) {
+            deviceProxyFuture.complete(deviceProxy);
+          }
+        },
+        new MatterCallback<MatterError>() {
+          @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<Long> successCallback, MatterCallback<MatterError> failureCallback);
 }
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterEndpoint-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterEndpoint-JNI.cpp
index 2e28b873599a9a..e0c41ebc92d260 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterEndpoint-JNI.cpp
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterEndpoint-JNI.cpp
@@ -19,7 +19,6 @@
 #include "MatterEndpoint-JNI.h"
 
 #include "../JNIDACProvider.h"
-#include "../support/Converters-JNI.h"
 #include "../support/MatterCallback-JNI.h"
 #include "../support/RotatingDeviceIdUniqueIdProvider-JNI.h"
 #include "clusters/Clusters.h"           // from tv-casting-common
@@ -86,6 +85,30 @@ JNI_METHOD(jobject, getCastingPlayer)
     return support::convertCastingPlayerFromCppToJava(std::shared_ptr<CastingPlayer>(endpoint->GetCastingPlayer()));
 }
 
+JNI_METHOD(void, getDeviceProxy)
+(JNIEnv * env, jobject thiz, jobject jSuccessCallback, jobject jFailureCallback)
+{
+    chip::DeviceLayer::StackLock lock;
+    ChipLogProgress(AppServer, "MatterEndpoint-JNI::getDeviceProxy() called");
+    Endpoint * endpoint = support::convertEndpointFromJavaToCpp(thiz);
+    VerifyOrReturn(endpoint != nullptr, ChipLogError(AppServer, "MatterEndpoint-JNI::getDeviceProxy() endpoint == nullptr"));
+
+    ReturnOnFailure(MatterEndpointJNIMgr().mGetDeviceProxySuccessHandler.SetUp(env, jSuccessCallback));
+    ReturnOnFailure(MatterEndpointJNIMgr().mGetDeviceProxyFailureHandler.SetUp(env, jFailureCallback));
+
+    endpoint->GetCastingPlayer()->FindOrEstablishSession(
+        nullptr,
+        [](void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) {
+            ChipLogProgress(AppServer, "MatterEndpointJNI FindOrEstablishSession success");
+            OperationalDeviceProxy * device = new OperationalDeviceProxy(&exchangeMgr, sessionHandle); // TODO: delete *device
+            MatterEndpointJNIMgr().mGetDeviceProxySuccessHandler.Handle(device);
+        },
+        [](void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error) {
+            ChipLogError(AppServer, "MatterEndpointJNI FindOrEstablishSession failure %" CHIP_ERROR_FORMAT, error.Format());
+            MatterEndpointJNIMgr().mGetDeviceProxyFailureHandler.Handle(error);
+        });
+}
+
 }; // namespace core
 }; // namespace casting
 }; // namespace matter
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterEndpoint-JNI.h b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterEndpoint-JNI.h
index f9534435ab1903..2c65ca448b6f29 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterEndpoint-JNI.h
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterEndpoint-JNI.h
@@ -18,8 +18,11 @@
 
 #pragma once
 
+#include "../support/Converters-JNI.h"
+#include "../support/MatterCallback-JNI.h"
 #include "core/Endpoint.h" // from tv-casting-common
 
+#include <app/DeviceProxy.h>
 #include <jni.h>
 #include <lib/support/JniReferences.h>
 #include <lib/support/JniTypeWrappers.h>
@@ -30,6 +33,15 @@ namespace core {
 
 class MatterEndpointJNI
 {
+public:
+    MatterEndpointJNI() :
+        mGetDeviceProxySuccessHandler([](chip::DeviceProxy * device) -> jobject {
+            return support::convertLongFromCppToJava(reinterpret_cast<jlong>(device));
+        })
+    {}
+    support::MatterCallbackJNI<chip::DeviceProxy *> mGetDeviceProxySuccessHandler;
+    support::MatterFailureCallbackJNI mGetDeviceProxyFailureHandler;
+
 private:
     friend MatterEndpointJNI & MatterEndpointJNIMgr();
     static MatterEndpointJNI sInstance;
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp
index 9798f2b48b9359..aa5ef2b25f0096 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp
@@ -25,6 +25,30 @@ namespace support {
 
 using namespace chip;
 
+jobject convertLongFromCppToJava(jlong value)
+{
+    ChipLogProgress(AppServer, "convertLongFromCppToJava called");
+    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
+    VerifyOrReturnValue(env != nullptr, nullptr, ChipLogError(AppServer, "Could not get JNIEnv for current thread"));
+
+    jclass responseTypeClass = env->FindClass("java/lang/Long");
+    if (responseTypeClass == nullptr)
+    {
+        ChipLogError(AppServer, "ConvertToJObject: Class for Response Type not found!");
+        env->ExceptionClear();
+        return nullptr;
+    }
+
+    jmethodID constructor = env->GetMethodID(responseTypeClass, "<init>", "(J)V");
+    if (constructor == nullptr)
+    {
+        ChipLogError(AppServer, "Failed to access Long constructor");
+        env->ExceptionClear();
+        return nullptr;
+    }
+    return env->NewObject(responseTypeClass, constructor, value);
+}
+
 jobject convertMatterErrorFromCppToJava(CHIP_ERROR inErr)
 {
     ChipLogProgress(AppServer, "convertMatterErrorFromCppToJava() called");
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.h b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.h
index ecc3a95d15bd74..aa96af0668f5d4 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.h
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.h
@@ -29,6 +29,8 @@ namespace matter {
 namespace casting {
 namespace support {
 
+jobject convertLongFromCppToJava(jlong value);
+
 jobject convertMatterErrorFromCppToJava(CHIP_ERROR inErr);
 
 /**
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/MatterCallback-JNI.h b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/MatterCallback-JNI.h
index 3c56c426359d5c..82894e075ea912 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/MatterCallback-JNI.h
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/MatterCallback-JNI.h
@@ -43,6 +43,7 @@ class MatterCallbackJNI
         ChipLogProgress(AppServer, "MatterCallbackJNI::SetUp called");
         VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NO_ENV, ChipLogError(AppServer, "JNIEnv was null!"));
 
+        mCallbackObject.Reset();
         ReturnErrorOnFailure(mCallbackObject.Init(inCallback));
 
         jclass mClazz = env->GetObjectClass(mCallbackObject.ObjectRef());
@@ -53,7 +54,7 @@ class MatterCallbackJNI
         VerifyOrReturnError(mSuperClazz != nullptr, CHIP_JNI_ERROR_TYPE_NOT_FOUND,
                             ChipLogError(AppServer, "Failed to get callback's parent's Java class"));
 
-        mMethod = env->GetMethodID(mClazz, "handleInternal", mMethodSignature);
+        mMethod = env->GetMethodID(mSuperClazz, "handleInternal", mMethodSignature);
         VerifyOrReturnError(
             mMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND,
             ChipLogError(AppServer, "Failed to access 'handleInternal' method with signature %s", mMethodSignature));
diff --git a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_action_selector.xml b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_action_selector.xml
index ae61681a0bbf2f..1969c5eeb13212 100644
--- a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_action_selector.xml
+++ b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_action_selector.xml
@@ -27,6 +27,24 @@
             android:layout_marginRight="10sp"
             android:layout_below="@id/action_selector_heading" />
 
+        <Button
+            android:id="@+id/selectApplicationBasicReadVendorIDButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/matter_select_application_basic_read_vendor_id_button_text"
+            android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+            android:layout_marginRight="10sp"
+            android:layout_below="@id/selectContentLauncherLaunchURLButton" />
+
+        <Button
+            android:id="@+id/selectMediaPlaybackSubscribeToCurrentStateButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/matter_select_media_playback_subscribe_to_current_state_button_text"
+            android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+            android:layout_marginRight="10sp"
+            android:layout_below="@id/selectApplicationBasicReadVendorIDButton" />
+
         <Button
             android:id="@+id/disconnectButton"
             android:layout_width="wrap_content"
diff --git a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_application_basic_read_vendor_id.xml b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_application_basic_read_vendor_id.xml
new file mode 100644
index 00000000000000..65dbdee15410b9
--- /dev/null
+++ b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_application_basic_read_vendor_id.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".matter.casting.ApplicationBasicReadVendorIDExampleFragment">
+
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:padding="10sp">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/matter_application_basic_fragment_title"
+            android:textAppearance="@style/TextAppearance.AppCompat.Display2" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/vendor_id_attribute_title"
+            android:textAppearance="@style/TextAppearance.AppCompat.Large" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <Button
+                android:id="@+id/readVendorIdButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/read_vendor_id_button_text"
+                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                android:layout_marginRight="10sp" />
+
+            <TextView
+                android:id="@+id/vendorIdResult"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
+        </LinearLayout>
+
+    </LinearLayout>
+</FrameLayout>
diff --git a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_content_launcher_launch_url.xml b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_content_launcher_launch_url.xml
index eb09a5e4c47858..0b88474e6a4ba3 100644
--- a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_content_launcher_launch_url.xml
+++ b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_content_launcher_launch_url.xml
@@ -67,7 +67,7 @@
         <LinearLayout
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:orientation="horizontal">
+            android:orientation="vertical">
 
             <Button
                 android:id="@+id/launchUrlButton"
@@ -78,8 +78,8 @@
                 android:layout_marginRight="10sp" />
 
             <TextView
-                android:id="@+id/launchUrlStatus"
-                android:layout_width="200dp"
+                android:id="@+id/launcherResult"
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
         </LinearLayout>
diff --git a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_media_playback_subscribe_current_state.xml b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_media_playback_subscribe_current_state.xml
new file mode 100644
index 00000000000000..91f821e47faebb
--- /dev/null
+++ b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_media_playback_subscribe_current_state.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".matter.casting.MediaPlaybackSubscribeToCurrentStateExampleFragment">
+
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:padding="10sp">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/matter_media_playback_fragment_title"
+            android:textAppearance="@style/TextAppearance.AppCompat.Display2" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/current_state_attribute_title"
+            android:textAppearance="@style/TextAppearance.AppCompat.Large" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <Button
+                android:id="@+id/subscribeToCurrentStateButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/subscribe_to_current_state_button_text"
+                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                android:layout_marginRight="10sp" />
+
+            <TextView
+                android:id="@+id/currentStateResult"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
+        </LinearLayout>
+
+        <Button
+            android:id="@+id/shutdownSubscriptionsButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/matter_shutdown_subscriptions_text"
+            android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+            android:layout_marginRight="10sp"
+            android:layout_alignParentBottom="true" />
+
+    </LinearLayout>
+</FrameLayout>
diff --git a/examples/tv-casting-app/android/App/app/src/main/res/values/strings.xml b/examples/tv-casting-app/android/App/app/src/main/res/values/strings.xml
index d0cc982e220666..4485b6a31ab788 100644
--- a/examples/tv-casting-app/android/App/app/src/main/res/values/strings.xml
+++ b/examples/tv-casting-app/android/App/app/src/main/res/values/strings.xml
@@ -41,4 +41,12 @@
     <string name="matter_action_selector_text">Select an action</string>
     <string name="matter_select_content_launcher_launch_url_button_text">Content Launcher Launch URL</string>
     <string name="matter_disconnect_text">Disconnect from Casting Player</string>
+    <string name="matter_application_basic_fragment_title">Application Basic</string>
+    <string name="vendor_id_attribute_title">VendorID attribute</string>
+    <string name="read_vendor_id_button_text">Read</string>
+    <string name="matter_media_playback_fragment_title">Media Playback</string>
+    <string name="current_state_attribute_title">Current State</string>
+    <string name="matter_select_application_basic_read_vendor_id_button_text">Application Basic Read Vendor ID</string>
+    <string name="matter_select_media_playback_subscribe_to_current_state_button_text">Media Playback Subscribe to Current State</string>
+    <string name="matter_shutdown_subscriptions_text">Shutdown subscriptions</string>
 </resources>
\ No newline at end of file
diff --git a/examples/tv-casting-app/android/README.md b/examples/tv-casting-app/android/README.md
index c2a7622036bc8a..b620c1ac5cbdf4 100644
--- a/examples/tv-casting-app/android/README.md
+++ b/examples/tv-casting-app/android/README.md
@@ -70,6 +70,18 @@ Complete the following steps to prepare the Matter build:
     source scripts/bootstrap.sh
     ```
 
+3. The build will produce libraries: AndroidPlatform.jar, CHIPAppServer.jar,
+   CHIPInteractionModel.jar and TVCastingApp.jar in [App/app/libs](App/app/libs)
+   and libTvCastingApp.so and libc++\_shared.so in
+   [App/app/libs/jniLibs/](App/app/libs/jniLibs/) consumed by any casting app to
+   leverage the [casting APIs](../APIs.md), like the sample android
+   tv-casting-app. If building for your own casting app, make sure your client's
+   specific values are set for `CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID` and
+   `CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID` in the
+   [CHIPProjectAppConfig.h](tv-casting-common/include/CHIPProjectAppConfig.h)
+   file, before the build. Other values like the
+   `CHIP_DEVICE_CONFIG_DEVICE_NAME` may be optionally updated as well.
+
 ## Building & Installing the app
 
 This is the simplest option. In the command line, run the following command from