--- title: "Developer Notes (3.0.11)" slug: "developer-notes-android-3011" description: "Explore the new features in ScreenMeet SDK 3.0.11 for Android, including API changes, enhanced event handling, and improved video performance." updated: 2024-10-17T18:56:38Z published: 2024-10-17T18:56:38Z canonical: "docs.screenmeet.com/developer-notes-android-3011" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.screenmeet.com/llms.txt > Use this file to discover all available pages before exploring further. # Developer Notes (3.0.11) Version 3.0.11 of the ScreenMeet SDK for Android introduces several new features. They are discussed on this page. ## **API Changes** ### **SessionEventListener** Several methods in `SessionEventListener` have updated their signatures. The return type has changed from `Unit` to `Boolean`, which determines whether the SDK should handle the event or if the client application has consumed it. This primarily affects UI-related events. - `true`: Indicates that the event has been handled by the developer and should not be further dispatched by the SDK. - `false`: Indicates that the event was not handled and the SDK should process it. Developers can attach multiple `SessionEventListener` instances. An event is considered consumed if any of the listeners returns `true`. #### **Methods with Signature Changes** ```kotlin // Before fun onFeatureRequest(feature: Feature, decisionHandler: (granted: Boolean) -> Unit) // After fun onFeatureRequest(feature: Feature, decisionHandler: (granted: Boolean) -> Unit): Boolean // Before fun onFeatureRequestRejected(entitlement: Entitlement) // After fun onFeatureRequestRejected(entitlement: Entitlement): Boolean // Before fun onScreenShareRequest(participant: Participant) // After fun onScreenShareRequest(participant: Participant): Boolean ``` #### **New Method Added** ```kotlin fun onRemoteControlCommand(command: RemoteControlCommand): Boolean ``` #### Code Sample **Override Remote Control Events** Added the ability to override Remote Control events using the `SessionEventListener` method `onRemoteControlCommand`: ```kotlin private var areaNotClickableRemotely: Rect? = null val rect = Rect()   notClickableView.getGlobalVisibleRect(rect)   areaNotClickableRemotely = rect override fun onRemoteControlCommand(command: RemoteControlCommand): Boolean {   if (command is RemoteControlCommand.Mouse) {   // If the click occurs in a non-clickable area, return true.   // This indicates that the event has been handled and should not be // further dispatched.         return areaNotClickableRemotely?.contains(command.x, command.y) == true   }   return false   } ``` ### **ScreenMeet.Configuration** A new method has been added: ```kotlin fun preferredScreenCaptureFps(fps: Int): Configuration ``` #### Code Sample **Preferred Application Frame Capturing FPS** Exposed an API to specify the preferred application frame capturing FPS. This can help tune video stream performance and reduce CPU usage. The default FPS is `24`. ```kotlin val configuration = Configuration(apiKey)   configuration.preferredScreenCaptureFps(15) ``` ## **Other Enhancements** - **Mouse Scroll Support for Remote Control** Added support for mouse scroll events in Remote Control. - **Synchronized Frame Rendering** Introduced the ability to synchronize frame rendering between `SurfaceView`, `TextureView`, `GLSurfaceView`, and regular `View`. Previously, different `Surface` instances might overlap `View` elements during frame rendering. Setting a higher `zIndex` for the `View` than the `Surface` resolves this issue. ```kotlin view.z = 1f ``` - **Updated Sample App** Updated the Sample App with an example demonstrating how to handle a mismatch between the local `VideoTrack` preview and the remote stream. The key point is that `SurfaceViewRenderer` should be resized to match the video's aspect ratio. ```kotlin binding.renderer.init(      eglBase,      object : RendererCommon.RendererEvents {          override fun onFrameResolutionChanged(              videoWidth: Int,              videoHeight: Int,              rotation: Int          ) {              binding.renderer.post {                  binding.renderer.layoutParams = fitFrame(                      videoWidth,                      videoHeight,                      binding.root.width,                      binding.root.height                  )              }          }            override fun onFirstFrameRendered() {          }      }   ) private fun fitFrame(      videoWidth: Int,      videoHeight: Int,      containerWidth: Int,      containerHeight: Int   ): FrameLayout.LayoutParams {      val videoAspect = videoWidth.toFloat() / videoHeight      val containerAspect = containerWidth.toFloat() / containerHeight        val newWidth: Int      val newHeight: Int        if (videoAspect > containerAspect) {          newWidth = containerWidth          newHeight = (containerWidth / videoAspect).toInt()      } else {          newHeight = containerHeight          newWidth = (containerHeight * videoAspect).toInt()      }        val offsetX = (containerWidth - newWidth) / 2      val offsetY = (containerHeight - newHeight) / 2        return FrameLayout.LayoutParams(newWidth, newHeight).apply {          setMargins(offsetX, offsetY, 0, 0)      }   } ``` --- Thank you for using our SDK! If you have any questions or feedback, please reach out to our support team.