Video is not visible afer joining meeting

Hi There,

We are facing issue with video preview, when we join meeting first time in app, everything works fine but when we close meeting and join same or another meeting again, there is no video preview there, I have checked in logs, i can see video preview is enabled but i cannot see any video on screen.

here is screenshot from app.

as you can see in screenshot, there is no camera priew

to exit meeting, we have added code as below
inMeetingService?.leaveCurrentMeeting(true)

we have made custom screen for meetings. and below is code for this screen.


class MyMeetingActivity: MeetingActivity(), OnGestureListener {


    private var inMeetingService: InMeetingService? = null

    companion object {

        private const val TAG = "MyMeetingActivity"

        var isRunning = false

        fun start(context: Context) {
            val intent = Intent(context, MyMeetingActivity::class.java)
            context.startActivity(intent)
        }
    }

    override fun isAlwaysFullScreen(): Boolean {
        return false
    }

    override fun isSensorOrientationEnabled(): Boolean {
        return false
    }


    private lateinit var btnAudio: ImageView
    private lateinit var btnVideo: ImageView
    private lateinit var btnParticipants: ImageView
    private lateinit var btnChat: ImageView
    private lateinit var btnLeave: ImageView
    
    private lateinit var zoomSdk: ZoomSDK

    private lateinit var context: Context

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        context = this

        zoomSdk = ZoomSDK.getInstance()

        if (!zoomSdk.isInitialized) {
            finish()
            return
        }

        if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                this@MyMeetingActivity,
                arrayOf(Manifest.permission.CAMERA),
                1001
            )
        }

        inMeetingService = zoomSdk.inMeetingService

        btnAudio = findViewById(R.id.btnAudio)
        btnVideo = findViewById(R.id.btnVideo)
        btnChat = findViewById(R.id.btnChat)
        btnParticipants = findViewById(R.id.btnParticipants)
        btnLeave = findViewById(R.id.btnLeaveZoomMeeting)

        initListeners()

    }

    override fun getLayout(): Int {
        return R.layout.activity_meeting
    }

    override fun onResume() {
        super.onResume()
        updateButtonsStatus()

        // disable animation
        overridePendingTransition(0, 0)

    }


    private fun initListeners() {


        btnLeave.setOnClickListener {
            inMeetingService?.leaveCurrentMeeting(true)
            Log.e(TAG,"Leave meeting")
            finish()
        }

        btnAudio.setOnClickListener {
            val audioController = zoomSdk.inMeetingService.inMeetingAudioController
            val result = audioController.muteMyAudio(!audioController.isMyAudioMuted)

            Log.e(TAG,"Audio > ${result.name} / ${result.ordinal} / ${result.declaringClass.simpleName}")

            if (audioController.isMyAudioMuted) {
                btnAudio.setImageResource(R.drawable.ic_mic_focus)
            }else {
                btnAudio.setImageResource(R.drawable.ic_mic_mute_focus)
            }
        }

        btnVideo.setOnClickListener {
            val videoController = zoomSdk.inMeetingService.inMeetingVideoController
//            videoController.switchToNextCamera()
            val result = videoController.muteMyVideo(!videoController.isMyVideoMuted)

            Log.e(TAG,"Video > ${result.name} / ${result.ordinal} / ${result.declaringClass.simpleName}")

            if (videoController.isMyVideoMuted) {
                btnVideo.setImageResource(R.drawable.ic_videocam_on_focus)
            }else {
                btnVideo.setImageResource(R.drawable.ic_videocam_off_focus)
            }

        }

        btnChat.setOnClickListener {
            MyMessage.showToast(context,"This function is not ready yet!")
            return@setOnClickListener
        }

        btnParticipants.setOnClickListener {
            MyMessage.showToast(context,"This function is not ready yet!")

            return@setOnClickListener
        }

        zoomSdk.meetingService.addListener { meetingStatus, i, i1 ->
            Log.e(TAG,"meetingService ${meetingStatus.name}")


            if (meetingStatus == MeetingStatus.MEETING_STATUS_INMEETING) {
                updateButtonsStatus()
                val videoController = zoomSdk.inMeetingService.inMeetingVideoController

                Log.e(TAG,"videoController > ${videoController.selectedCameraId} / ${videoController.isMyVideoMuted}")
                Log.d(TAG,"videoController > ${videoController.cameraDeviceList.size}")
                for (camera in videoController.cameraDeviceList) {
                    Log.d(TAG,"Camera >>> ${camera.deviceId} / ${camera.isSelectedDevice} ${camera.deviceName}")
                }


            }
        }
        zoomSdk.inMeetingService.addListener(object : InMeetingServiceListener {
            override fun onMeetingNeedPasswordOrDisplayName(
                b: Boolean,
                b1: Boolean,
                inMeetingEventHandler: InMeetingEventHandler
            ) {
            }

            override fun onWebinarNeedRegister() {

            }
            override fun onJoinWebinarNeedUserNameAndEmail(inMeetingEventHandler: InMeetingEventHandler) {}
            override fun onMeetingNeedColseOtherMeeting(p0: InMeetingEventHandler?) {}
            override fun onMeetingFail(i: Int, i1: Int) {}
            override fun onMeetingLeaveComplete(l: Long) {
                Log.e(TAG,"onMeetingLeaveComplete > $l")
            }

            override fun onMeetingUserJoin(list: List<Long>) {

                Log.e(TAG,"onMeetingUserJoin > ${list.size}")

                val service = zoomSdk.inMeetingService
                for (id in list) {
                    Log.d(TAG,"Participant > $id")
                    try {
                        val info = service.getUserInfoById(id)
                        Log.e(TAG,"User > ${info.userName} / ${info.inMeetingUserRole} / ${info.avatarPath} ")
                    }catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
            override fun onMeetingUserLeave(list: List<Long>) {
                Log.e(TAG,"onMeetingUserLeave > ${list.size}")
                val service = zoomSdk.inMeetingService
                for (id in list) {
                    Log.d(TAG,"Participant > $id")
                    try {
                        val info = service.getUserInfoById(id)
                        Log.e(TAG,"User > ${info.userName} / ${info.inMeetingUserRole} / ${info.avatarPath} ")
                    }catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
            override fun onMeetingUserUpdated(l: Long) {}
            override fun onMeetingHostChanged(l: Long) {}
            override fun onMeetingCoHostChanged(l: Long) {}
            override fun onActiveVideoUserChanged(l: Long) {}
            override fun onActiveSpeakerVideoUserChanged(l: Long) {}
            override fun onSpotlightVideoChanged(b: Boolean) {}
            override fun onUserVideoStatusChanged(p0: Long) {}
            override fun onUserNetworkQualityChanged(l: Long) {}
            override fun onMicrophoneStatusError(mobileRTCMicrophoneError: MobileRTCMicrophoneError) {
                Log.e(TAG,"onMicrophoneStatusError >> ${mobileRTCMicrophoneError.name}")
            }
            override fun onUserAudioStatusChanged(p0: Long) {}
            override fun onHostAskUnMute(l: Long) {}
            override fun onHostAskStartVideo(l: Long) {}
            override fun onUserAudioTypeChanged(l: Long) {}
            override fun onMyAudioSourceTypeChanged(i: Int) {
                Log.e(TAG,"onMyAudioSourceTypeChanged >> $i")
            }
            override fun onLowOrRaiseHandStatusChanged(l: Long, b: Boolean) {}
            override fun onMeetingSecureKeyNotification(p0: ByteArray?) {}
            override fun onChatMessageReceived(inMeetingChatMessage: InMeetingChatMessage) {}
            override fun onSilentModeChanged(b: Boolean) {
                updateButtonsStatus()
            }

            override fun onFreeMeetingReminder(b: Boolean, b1: Boolean, b2: Boolean) {}
            override fun onMeetingActiveVideo(l: Long) {}
            override fun onSinkAttendeeChatPriviledgeChanged(i: Int) {}
            override fun onSinkAllowAttendeeChatNotification(i: Int) {}
            override fun onUserNameChanged(l: Long, s: String) {}
        })


    }


    private fun updateButtonsStatus() {
        val enabled = inMeetingService?.isMeetingConnected ?: false

        Log.e(TAG,"updateButtonsStatus $enabled")

        btnAudio.isEnabled = enabled
        btnVideo.isEnabled = enabled
        btnChat.isEnabled = enabled
        btnParticipants.isEnabled = enabled

        val videoController = zoomSdk.inMeetingService.inMeetingVideoController
        if (videoController.isMyVideoMuted) {
            btnVideo.setImageResource(R.drawable.ic_videocam_on)
        }else {
            btnVideo.setImageResource(R.drawable.ic_videocam_off)
        }

        val audioController = zoomSdk.inMeetingService.inMeetingAudioController
        if (audioController.isMyAudioMuted) {
            btnAudio.setImageResource(R.drawable.ic_mic)
        }else {
            btnAudio.setImageResource(R.drawable.ic_mic_mute)
        }
    }

    override fun onContentChanged() {
        super.onContentChanged()
        disableFullScreenMode()
    }

    private fun disableFullScreenMode() {
        window.setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN.inv(),
            WindowManager.LayoutParams.FLAG_FULLSCREEN
        )
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onMessageEvent(myEvent: MyEvent) {
        Log.e(TAG, "Event >> ${myEvent.event} / ${myEvent.msg}")
        if (myEvent.event == Events.GESTURE) {
            myEvent.motionEvent?.let {
                onGesture(it)
            }
        }
    }

    override fun onStart() {
        super.onStart()
        isRunning = true
        EventBus.getDefault().register(this)
    }

    override fun onStop() {
        super.onStop()
        isRunning = false
        EventBus.getDefault().unregister(this)
    }

    private var currentSelection: ImageView? = null
    private var cursor = 0

    override fun onGesture(gesture: Gesture): Boolean {

        return when(gesture) {
            Gesture.TAP -> {
                currentSelection?.performClick()
               true
            }
            Gesture.SWIPE_BACKWARD -> {
                if (cursor > 0) {
                    cursor -= 1
                }
                showSelectedButton()
                return true
            }
            Gesture.SWIPE_FORWARD -> {
                if (cursor < 4) {
                    cursor += 1
                }
                showSelectedButton()
                return true
            }
            Gesture.SWIPE_DOWN -> {
                btnLeave.performClick()
                return true
            }
            Gesture.TAP_AND_HOLD -> {
                GestureService.stopGestureService(this)
                return true
            }
            else -> {
                false
            }
        }
    }

    private fun showSelectedButton() {

        Log.e(TAG,"Swipe > $ $cursor")

        currentSelection?.let {
            when (it.id) {
                btnAudio.id -> {
                    val audioController = zoomSdk.inMeetingService.inMeetingAudioController
                    if (audioController.isMyAudioMuted) {
                        btnAudio.setImageResource(R.drawable.ic_mic)
                    }else {
                        btnAudio.setImageResource(R.drawable.ic_mic_mute)
                    }
                }
                btnVideo.id ->{
                    val videoController = zoomSdk.inMeetingService.inMeetingVideoController

                    if (videoController.isMyVideoMuted) {
                        btnVideo.setImageResource(R.drawable.ic_videocam_on)
                    }else {
                        btnVideo.setImageResource(R.drawable.ic_videocam_off)
                    }
                }
                btnChat.id -> {
                    btnChat.setImageResource(R.drawable.ic_chat)
                }
                btnParticipants.id -> {
                    btnParticipants.setImageResource(R.drawable.ic_group)
                }
                btnLeave.id -> {
                    btnLeave.setImageResource(R.drawable.ic_exit)
                }
            }
        }

        currentSelection = when(cursor) {
            0 -> {
                val audioController = zoomSdk.inMeetingService.inMeetingAudioController
                if (audioController.isMyAudioMuted) {
                    btnAudio.setImageResource(R.drawable.ic_mic_focus)
                }else {
                    btnAudio.setImageResource(R.drawable.ic_mic_mute_focus)
                }
                btnAudio
            }
            1 -> {
                val videoController = zoomSdk.inMeetingService.inMeetingVideoController
                if (videoController.isMyVideoMuted) {
                    btnVideo.setImageResource(R.drawable.ic_videocam_on_focus)
                }else {
                    btnVideo.setImageResource(R.drawable.ic_videocam_off_focus)
                }
                btnVideo
            }
            2 -> {
                btnChat.setImageResource(R.drawable.ic_chat_focus)
                btnChat
            }
            3 -> {
                btnParticipants.setImageResource(R.drawable.ic_group_focus)
                btnParticipants
            }
            else -> {
                btnLeave.setImageResource(R.drawable.ic_exit_focus)
                btnLeave
            }
        }


    }

}

also i’m sharing encrypted logs from app for reference.
here are logs

please check and let me know about this issue.
thanks.

Hi @jovy,

Please note that I have moved this over to the #meeting-sdk:android category. :slightly_smiling_face:

Can you please provide a code snippet showing how you are joining the meeting and how you are enabling the video preview?

Thanks!

hi @jon.zoom

following is code to join meeting,

        val meetingService: MeetingService = instance.meetingService ?: return 0

        jmo.no_audio = false
        jmo.no_video = false

        val jmp = JoinMeetingParams()
        jmp.displayName = displayName
        jmp.meetingNo = id
        jmp.password = password

        return meetingService.joinMeetingWithParams(context, jmp, jmo)

When meeting is started, we are opening following activity which extends MeetingActivity.
here we have updated ui only and other code is as per sdk, for code in meeting activity please refer first message by me.

below is design code for reference

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/buttons"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#443F51B5"
        android:padding="@dimen/space_l"
        android:gravity="center"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/btnAudio"
            android:background="@drawable/bg_circle"
            android:padding="@dimen/space_s"
            android:src="@drawable/ic_mic"
            android:layout_width="@dimen/meeting_option"
            android:layout_height="@dimen/meeting_option"
            android:layout_marginHorizontal="10dp"/>

        <ImageView
            android:id="@+id/btnVideo"
            android:padding="@dimen/space_s"
            android:src="@drawable/ic_videocam_on"
            android:background="@drawable/bg_circle"
            android:layout_width="@dimen/meeting_option"
            android:layout_height="@dimen/meeting_option"
            android:layout_marginHorizontal="10dp" />

        <ImageView
            android:id="@+id/btnChat"
            android:textColor="@color/black"
            android:src="@drawable/ic_chat"
            android:background="@drawable/bg_circle"
            android:padding="@dimen/space_s"
            android:layout_width="@dimen/meeting_option"
            android:layout_height="@dimen/meeting_option"
            android:layout_marginHorizontal="10dp"/>

        <ImageView
            android:id="@+id/btnParticipants"
            android:textColor="@color/black"
            android:src="@drawable/ic_group"
            android:background="@drawable/bg_circle"
            android:padding="@dimen/space_s"
            android:layout_width="@dimen/meeting_option"
            android:layout_height="@dimen/meeting_option"
            android:layout_marginHorizontal="10dp"/>

        <ImageView
            android:id="@+id/btnLeaveZoomMeeting"
            android:textColor="@color/black"
            android:background="@drawable/bg_circle"
            android:padding="@dimen/space_s"
            android:src="@drawable/ic_exit"
            android:layout_width="@dimen/meeting_option"
            android:layout_height="@dimen/meeting_option"
            android:layout_marginHorizontal="10dp" />

    </LinearLayout>
    
    <include
        android:id="@+id/meetingContent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/buttons"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="1"
        layout="@layout/zm_conf_main_screen" />

    <TextView
        android:id="@+id/tvTitle"
        android:layout_margin="@dimen/space_l"
        android:text="@string/app_name"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:textSize="@dimen/text_h"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/users"
        android:layout_marginEnd="@dimen/space_l"
        android:drawablePadding="@dimen/space_m"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toTopOf="@id/buttons"
        android:textSize="@dimen/text_m"
        android:text="@string/_1_members"
        android:visibility="gone"
        style="@style/ZMTextView.Normal.OnDark"
        android:gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:drawableStartCompat="@drawable/ic_group"
        app:drawableTint="@color/white" />

 
</androidx.constraintlayout.widget.ConstraintLayout>

As you can see, we are including zm_conf_main_screen in ui, which is used to show meeting screen inside our custom UI

and below is design screen for this

and when we end meeting we call
inMeetingService?.leaveCurrentMeeting(true)

actually it works when we start meeting first time, but when we leave and join same meeting again, we are able to join but video preview is not there

Hi @jovy,

Thanks for the additional information. When you say that you are opening your MeetingActivity, does that mean you are manually starting that Activity in your project? If that’s the case, instead you should be adding the following resource to your app’s config.xml file so that the SDK can start the Activity at the right time:

<string name="zm_config_conf_activity">my.packge.name.MyMeetingActivity</string> (be sure to replace the value with your package name + MeetingActivity name).

Thanks!

Hi @jon.zoom

I have created config.xml file and added
<string name="zm_config_conf_activity">sg.mirobotic.zoom.zoom.MyMeetingActivity</string>

but after that when i join meeting, MyMeetingActivity is not starting automatically

Hi @jovy,

Since you mentioned previously that you were manually starting your MyMeetingActivity instance, were you also enabling custom UI mode? If custom UI mode is enabled, the SDK will not display any UI unless you tell it to.

Thanks!

hi @jon.zoom ,

I have enbled custom screen at SDK initiolization as below,

zoom.meetingSettingsHelper.isCustomizedMeetingUIEnabled = true

also in config.xml, I have added
<string name="zm_config_conf_activity">sg.mirobotic.zoom.zoom.MyMeetingActivity</string>

and in last i have added MyMeetingActivity into manifest.xml as below

   <activity
            android:name=".zoom.MyMeetingActivity"
            android:configChanges="screenSize"
            android:theme="@style/ZMTheme.SubWindow"
            android:screenOrientation="landscape"/>

after all these changes, When i start meeting, its still not starting MyMeetingActivity screen automatically.

please let me know if i’m missing something here.

Thanks

Hi @jovy,

When you enable custom UI mode, you cannot use an instance of MeetingActivity. Custom UI mode means that you are going to define your own UI and the SDK will not show its own. Is this what you are looking to do? If so, you should use a regular Activity instead.

Thanks!

hi @jon.zoom

to create custom ui, we need to extend meeting activity and show ui on top of it as mentioned here
also, I dont have idea on without using it how we can show the meeting screen.
also after setting custom screen, its not starting MyMeetingActivity automatically

Hi @jovy,

Creating a custom meeting UI and extending the MeetingActivity instance used by the SDK are not the same thing. The article you’re linking to mentions the custom UI mode as an alternative. It is not a step in extending the MeetingActivity.

When you create a custom meeting UI, it means that you are explicitly telling the SDK not to start a MeetingActivity instance. As a direct result of this, you assume full responsibility for maintaining the appearance and behavior of the meeting UI. Is this what you are looking to accomplish?

Thanks!

Thanks @jon.zoom , this solves issue with video

You’re welcome, that’s great to hear!