0

I am implementing Twilio Chat SDK where I do add members in a private Channel. The flow goes like this that First I check whether is there a channel in my list or not. If it exists then I join it. And if there is no channel in my list I First create it and then join and it and then add member with it's unique name. When I run my application the Client is created and after the channel process is done it crashes with the following error:

com.twilio.chat.ListenerException: Exception thrown by a listener. Your application might have a problem in listener implementation. Listeners must never throw uncaught exceptions. See 'Caused by:' below for more details.
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
        at com.twilio.chat.internal.RethrowingForwarder$RethrowingProxy.invoke(RethrowingForwarder.java:123)
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
        at $Proxy17.onError(Unknown Source)
        at com.twilio.chat.internal.StatusListenerForwarder$2.run(StatusListenerForwarder.java:46)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8167)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.twilio.chat.Members.addByIdentity(java.lang.String, com.twilio.chat.StatusListener)' on a null object reference
        at com.zofeur.customer.views.fragments.SupportFragment.addMemberInChannel(SupportFragment.kt:259)
        at com.zofeur.customer.views.fragments.SupportFragment.access$addMemberInChannel(SupportFragment.kt:22)
        at com.zofeur.customer.views.fragments.SupportFragment$joinChannel$1.onError(SupportFragment.kt:249)

I have been looking for several solutions but unable to do so.

Below is the code for my Fragment:

Support Fragment:

private fun createChannel(channelUniqueName: String) {
    mViewModel.chatClient?.channels?.getChannel(channelUniqueName,
        object : CallbackListener<Channel>() {
            override fun onSuccess(channel: Channel?) {
                if (channel != null) {
                    mViewModel.channel = channel
                    joinChannel(channel)

                }
            }

            override fun onError(errorInfo: ErrorInfo?) {
                super.onError(errorInfo)
                if (errorInfo?.code == Constants.ERROR_CHANNEL_NOT_FOUND) {
                    mViewModel.chatClient?.channels?.channelBuilder()
                        ?.withUniqueName(channelUniqueName)
                        ?.withType(Channel.ChannelType.PRIVATE)
                        ?.build(object : CallbackListener<Channel>() {
                            override fun onSuccess(channel: Channel?) {
                                requireContext().T("Channel Created $channel")
                                if (channel != null) {
                                    mViewModel.channel = channel
                                    joinChannel(channel)
                                }
                            }

                        })
                } else {
                    requireContext().T("Channel not created" + errorInfo.toString())

                }
            }
        })

}

private fun joinChannel(channel: Channel) {
    channel.join(object : StatusListener() {
        override fun onSuccess() {
            requireContext().T("Channel Joined" + channel.uniqueName)
            addMemberInChannel(channel, identity)
        }

        override fun onError(errorInfo: ErrorInfo) {
            if (errorInfo.code == Constants.ERROR_MEMBER_ALREADY_EXISTS) {
                // already join member
                addMemberInChannel(channel, identity)
            } else {
                requireContext().T("Error joining channel$errorInfo")
            }
        }
    })
}

private fun addMemberInChannel(channel: Channel, identity: String) {
    if (mViewModel.channel.createdBy == mViewModel.chatClient.myIdentity) {
        channel.members.addByIdentity(identity, object : StatusListener() {
            override fun onSuccess() {
                requireContext().T("Member added successfully" + channel.uniqueName)
            }

            override fun onError(errorInfo: ErrorInfo?) {
                super.onError(errorInfo)
                requireContext().T("Channel member added error" + errorInfo.toString())
            }
        })

    } else {
        requireContext().T("You cannot add member, You don't have rights.")
    }
}

Any sort of help would be very helpful. Thanks in advance.

Afaq Khan
  • 212
  • 2
  • 9

1 Answers1

3

Hi I was facing the same issue When I debugged a deep longer I found out that when you create a channel it has 3 States:

  1. SynchronizationStatus_STARTED
  2. SynchronizationStatus_CHANNELS_COMPLETED
  3. SyncronizationStatus_COMPLETED

You need to perform any channel related operation after the client SyncronizationStatus_COMPLETED Hope it works thanks just like that

client.addListener(object :ChatClientListener{
    override fun onClientSynchronization(p0: 
   ChatClient.SynchronizationStatus?) {
                                if (p0 == ChatClient.SynchronizationStatus.COMPLETED) {
                                    // Client is now ready for business, start working
                                    mViewModel.chatClient = client
                                   
                                }
                            }
    }
Abdul Wahab
  • 411
  • 6
  • 15
  • Correct, you need to synchronize your channel first, as [described in the documentation](https://media.twiliocdn.com/sdk/android/chat/releases/7.0.0/docs/classcom_1_1twilio_1_1chat_1_1Channel.html). Synchronize your client after creation as well, so that other accessors like `channels` would work correctly. "Get members object that allows access to member roster in the channel. You need to synchronize the channel before you can call this method unless you just joined the channel, in which case it synchronizes automatically." – berkus Aug 02 '21 at 09:16
  • Please upvote me answer i will be very thankfully to you – Abdul Wahab Aug 02 '21 at 11:30