Create & Initialize Media Fragment
App should have camera, mic i.e RECORD_AUDIO, READ_PHONE_STATE permissions and also check if required files have been downloaded using below code.
DynamicSDKDownloadManager.getDynamicSDKDownloadManagerinstance().isRequiresSoFilesDownloaded()
else
DynamicSDKDownloadManager.getDynamicSDKDownloadManagerinstance().showRetryDialog(this)
before performing fragment transaction with media related activity
Joining Room with meeting id and pin : In this case pass JiomeetSdkManger.MEETING_ID, JioMeetSdkManager.MEETING_PIN, JioMeetSdkManager.GUEST_NAME, JioMeetSdkManager.MOBILE_NUMBER and JioMeetSdkManager.JOIN_MEETING_WITH_PIN as "true" while initializing the fragment.
Also Please send the following boolean values
JioMeetSdkManager.SHOW_PARTICIPANT_ICON as true/false
JioMeetSdkManager.SHOW_AUDIO_ONLY_MODE as true/false
JioMeetSdkManager.SHARE_DETAILS as true/false
JioMeetSdkManager.SHOW_HAND_RAISE as true/false
JioMeetSdkManager.IS_AUTOMATIC_RECORDING_ENABLED as true/false
JioMeetSdkManager.IS_PIP_WINDOW_REQUIRED as true/false
JioMeetSdkManager.SHOW_PARTICIPANT_LIST as true/false
Code Snippet
class MediaContainerActivity : AppCompatActivity(), JioMeetConnectionListener,
JioMeetScreenShareListener {
private var mediaProjection: MediaProjectionManager? = null
private var captureIntent: Intent? = null
private var isScreenSharing: Boolean = false
private var startShareClickTimestamp: Long = 0
lateinit var screenCaptureService: ScreenCapturerService
private var screenCaptureServiceBound = false
private var guestName: String? = null
private var isMicMute: Boolean = false
private var isCameraMuted: Boolean = false
private lateinit var mPreferenceHelper: PreferenceHelper
private lateinit var mediacontainerActivityBinding: MediacontainerActivityBinding
private val binding get() = mediacontainerActivityBinding
private val exposedAPIs = MediaFragment().APIsForClient()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val uiModeManager = getSystemService(UI_MODE_SERVICE) as UiModeManager
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
mediacontainerActivityBinding = MediacontainerActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
registerConnectionListener()
if (intent.extras != null) {
guestName = intent.getStringExtra(JioMeetSdkManager.GUEST_NAME)
}
this.mediaProjection =
getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
val MediaFragment = MediaFragment()
MediaFragment.arguments = intent.extras
//Please pass the appId and authToken shared by Jio. Without which, the videoCall will not start
MediaFragment.arguments?.putString(JioMeetSdkManager.APP_ID, "yourAppId")
MediaFragment.arguments?.putString(
JioMeetSdkManager.AUTH_TOKEN,
"yourAuthToken"
)
val fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.video_container, MediaFragment).commit()
}
override fun onStart() {
super.onStart()
val intent = Intent(this, ScreenCapturerService::class.java)
bindService(intent, screenCaptureServiceConnection, BIND_AUTO_CREATE)
}
override fun onStop() {
super.onStop()
if (!isScreenSharing) {
unbindService(screenCaptureServiceConnection)
screenCaptureServiceBound = false
}
}
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration?
) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
Log.d("PIP", "onPictureInPictureModeChanged called")
Log.d("PIP", "Lifecycle current state = " + lifecycle.currentState.name)
if (lifecycle.currentState == Lifecycle.State.CREATED) {
Log.d("PIP", "Close button or Drag and Drop of PIP window is clicked")
val intent = Intent(this, ScreenCapturerService::class.java)
bindService(intent, screenCaptureServiceConnection, BIND_AUTO_CREATE)
} else if (lifecycle.currentState == Lifecycle.State.STARTED) {
Log.d("PIP", "PIP window is maximized or user entered into PIP")
}
}
fun registerConnectionListener() {
JioMeetSdkManager.instance?.registerJioMeetConnectionListener(this)
JioMeetSdkManager.instance?.registerJioMeetScreenShareListener(this)
}
fun unRegisterConnectionListener() {
JioMeetSdkManager.instance?.unRegisterJioMeetConnectionListener()
JioMeetSdkManager.instance?.unRegisterJioMeetScreenShareListener()
}
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.video_container)
if (fragment != null && fragment.isAdded) {
(fragment as MediaFragment).onBackPressed()
} else {
super.onBackPressed()
}
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
val fragment = supportFragmentManager.findFragmentById(R.id.video_container)
return if (fragment != null && fragment.isAdded) {
(fragment as MediaFragment).onKeyDown(keyCode)
} else {
return super.onKeyDown(keyCode, event)
}
}
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
val fragment = supportFragmentManager.findFragmentById(R.id.video_container)
return if (fragment != null && fragment.isAdded) {
(fragment as MediaFragment).dispatchKeyEvent(event)
} else {
return super.dispatchKeyEvent(event)
}
}
override fun onDestroy() {
super.onDestroy()
unRegisterConnectionListener()
}
override fun getHistoryID(historyId: String?) {
}
override fun onLocalJoinedRoom(jwtToken: String?, historyId: String?) {
}
override fun onLocalLeftRoom() {
if (isScreenSharing) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
screenCaptureService.endForeground()
}
isScreenSharing = false
}
val joinRoomDetailsIntent = Intent(this, JioMeetActivity::class.java)
startActivity(joinRoomDetailsIntent)
finish()
}
override fun onErrorOccurred(errorMessage: String?) {
}
override fun onErrorFromSDK(errCode: Int) {
}
override fun onErrorCTAClicked() {
}
override fun onRemoteMicMuted(isMicMuted: Boolean) {
}
override fun onRemoteCameraMuted(isCameraMuted: Boolean) {
}
override fun onRemoteParticipantJoined(uid: Int) {
}
override fun onRemoteParticipantLeft(uid: Int) {
}
override fun onConnectionStateChanged(state: Int) {
}
override fun hostLockUnLockMeeting(status: Int, sdkParticipant: SdkParticipant) {
}
override fun showAlertToStartStopMic(
isMute: Boolean,
hostSdkParticipant: SdkParticipant,
targetHostUserId: String,
targetParticipantUri: String
) {
}
override fun showAlertToStartStopVideo(
isMute: Boolean,
hostSdkParticipant: SdkParticipant,
targetHostUserId: String,
targetParticipantUri: String?
) {
}
override fun onShareScreenSuccess() {
isScreenSharing = true
//enterInPiPMode()
}
override fun onShareScreenStop() {
isScreenSharing = false
}
override fun onParticipantListIconClicked() {
Toast.makeText(this, " call back onParticipantListIconClicked ", Toast.LENGTH_SHORT).show()
}
override fun forceMuteStatus(isForceMute: Boolean, sdkParticipant: SdkParticipant) {
}
override fun muteAllStatus(toMicMute: Boolean, sdkParticipant: SdkParticipant) {
}
override fun hostDisconnectAll(sdkParticipant: SdkParticipant) {
}
override fun hostDisconnectedParticipant(
sdkParticipant: SdkParticipant,
targetParticipantUri: String,
targetParticipantId: String
) {
}
override fun hostStartedWhiteBoard(status: Boolean, message: ConferenceMessage) {
}
override fun hostChangedParticipantAudienceStatus(
status: Boolean,
sdkParticipant: SdkParticipant,
targetHostUserId: String?,
targetParticipantUri: String?,
targetParticipantId: String?
) {
}
override fun participantRaiseHand(sdkParticipant: SdkParticipant, status: Boolean) {
}
override fun hostLoweredAllHands(sdkParticipant: SdkParticipant) {
}
override fun hostLoweredParticipantHand(
sdkParticipant: SdkParticipant,
targetParticipantId: String
) {
}
override fun onShareScreen() {
if (isScreenSharing) {
showStopShareScreenWarningDialog()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
screenCaptureService.startForeground()
}
} else {
startShareClickTimestamp = System.currentTimeMillis()
startActivityForResult(mediaProjection?.createScreenCaptureIntent(), 1)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 1) {
if (data != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
screenCaptureService.startForeground()
}
screenSharePermissionsResponse(requestCode, resultCode, data)
}
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}
fun screenSharePermissionsResponse(requestCode: Int, resultCode: Int, data: Intent) {
if (resultCode == RESULT_OK && requestCode == 1) {
isScreenSharing = true
this.captureIntent = data
val fragment = supportFragmentManager.findFragmentById(R.id.video_container)
if (fragment != null && fragment.isAdded) {
(fragment as MediaFragment).startScreenShare(
isScreenSharing,
captureIntent!!,
mediaProjection
)
launchHome()
}
}
}
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode)
val fragment = supportFragmentManager.findFragmentById(R.id.video_container)
if (fragment != null && fragment.isAdded) {
(fragment as MediaFragment).pictureInPictureModeChanged(isInPictureInPictureMode)
}
}
override fun onUserLeaveHint() {
super.onUserLeaveHint()
if (isScreenSharing) {
enterInPiPMode()
}
}
private fun enterInPiPMode() {
try {
val fragment = supportFragmentManager.findFragmentById(R.id.video_container)
if (fragment != null && fragment.isAdded) {
(fragment as MediaFragment).onUserLeaveHint()
}
val pm: PackageManager = packageManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && pm.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) && isPipPermissionEnabled()) {
val params = PictureInPictureParams.Builder()
.setAspectRatio(Rational(9, 16))
.build()
enterPictureInPictureMode(params)
}
} catch (e: Exception) {
}
}
private fun isPipPermissionEnabled(): Boolean {
val appOps = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (appOps != null) return appOps.checkOpNoThrow(
AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
Process.myUid(),
packageName
) == AppOpsManager.MODE_ALLOWED
}
return false
}
private fun showStopShareScreenWarningDialog() {
val dialog = AlertDialog.Builder(this)
dialog.setTitle(getString(R.string.share_screen_title))
dialog.setMessage(getString(R.string.stop_share_screen_title))
dialog.setPositiveButton(getString(R.string.stop_share_title)) { dialogInterface: DialogInterface, _: Int ->
val fragment = supportFragmentManager.findFragmentById(R.id.video_container)
if (fragment != null && fragment.isAdded) {
isScreenSharing = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
screenCaptureService.endForeground()
}
exposedAPIs.startScreenShare(isScreenSharing, captureIntent!!, mediaProjection)
}
dialogInterface.dismiss()
}
dialog.setNegativeButton("Close") { dialogInterface: DialogInterface, _: Int -> dialogInterface.dismiss() }
dialog.show()
}
private val screenCaptureServiceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
// We've bound to ScreenCapturerService, cast the IBinder and get ScreenCapturerService instance
val binder = service as ScreenCapturerService.LocalBinder
screenCaptureService = binder.service
screenCaptureServiceBound = true
}
override fun onServiceDisconnected(arg0: ComponentName) {
screenCaptureServiceBound = false
}
}
override fun onPause() {
super.onPause()
if (isScreenSharing) {
val fragment = supportFragmentManager.findFragmentById(R.id.video_container)
}
}
private fun launchHome() {
val startMain = Intent(Intent.ACTION_MAIN)
startMain.addCategory(Intent.CATEGORY_HOME)
startMain.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(startMain)
}
}
Host Rights
- You can assign host rights to a specific user, to give them admin control over the meeting room. For that, set the below boolean to true/ false for the specific user:
- JioMeetSdkManager.IS_HOST as whatever value exis
Note: JioMeet only supports one host per meeting.
Default Audio-Video configuration
By default, the user would have joined the call with Audio & video switched On. You can configure the audio-video status of the user before they join the call, like so:
- JioMeetSdkManager.NEED_CONFIGURABLE_AUDIO_VIDEO is true if you want to pre-set the video and audio status before joining the meeting.
- JioMeetSdkManager.CLIENT_MIC_STATUS as true if you want the audio to be on, else false [This will work if NEED_CONFIGURABLE_AUDIO_VIDEO is set as true]
- JioMeetSdkManager.CLIENT_CAMERA_STATUS as true if you want the video to be on. Else false [This will work if NEED_CONFIGURABLE_AUDIO_VIDEO is set as true]