Android stuck in timeout exception

Hello

I am testing sending chats when the device has a really slow connection, I have set my device Network type to EDGE, and Signal Strength to Poor, when I send a message through the SDK, I quickly switch my data/ WIFI off, and wait for the timeout to be reached (15 seconds).

I then switch my data back on and try re-init the SDK and join the group to send messages but I always receive the timeout exception when trying to rejoin. My guess this is OkHttp cache that is set to clear after a time?

Is there any way that I can bypass the timeout exception when the device connects back to network?

Here is my flow for Checking Network and trying to join after displaying a Disconnected Dialog:

Activity.java

ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {

        }

        @Override
        public void onLost(Network network) {
            viewModel.removeChatListeners();
            showOfflineDialog();
        }
    };

    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        connectivityManager.registerDefaultNetworkCallback(networkCallback);
    } else {
        NetworkRequest request = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
        connectivityManager.registerNetworkCallback(request, networkCallback);
    }

Display offline Dialog:

private void showOfflineDialog() {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    Fragment prev = getSupportFragmentManager().findFragmentByTag(DialogConstants.OFFLINE_DIALOG);
    if (prev != null) {
        ft.remove(prev);
    }
    ft.addToBackStack(null);
    DialogFragment dialogFragment = OfflineDialog.newInstance(this);
    dialogFragment.show(ft, DialogConstants.OFFLINE_DIALOG);
}

When Dialog ok button is clicked:

@Override
public void onOkClicked() {
    dataBinding.activityChatReconnectInclude.setVisibility(View.VISIBLE);
    viewModel.initializeCometChat();
}

ViewModel re-initialize cometChat SDK. N.B I am initializing this at app startup too, but this seems to be the only workaround to eventually get the messages going through after a few minutes:

public void initializeCometChat() {
    AppSettings appSettings = new AppSettings.AppSettingsBuilder().setRegion("eu").build();
    CometChat.init(ContextProvider.getInstance().getApplication(), ContextProvider.getInstance().getContext().getResources().getString(R.string.comet_chat_app_id), appSettings, new CometChat.CallbackListener<String>() {
        @Override
        public void onSuccess(String successMessage) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    joinChat();
                }});

        }

        @Override
        public void onError(CometChatException e) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    Crashlytics.logException(e);
                }});
        }
    });
}

And join chat:

public void joinChat() {
    CometChat.joinGroup(chatMetaData.getCaseNumber(), CometChatConstants.GROUP_TYPE_PUBLIC, "", new CometChat.CallbackListener<Group>() {
        @Override
        public void onSuccess(Group joinedGroup) {
            joinedChat.setValue(true);
        }

        @Override
        public void onError(CometChatException e) {
            if (e.getCode().equals("ERR_ALREADY_JOINED")) {
                joinedChat.setValue(true);
                shouldFetchPreviousMessages.setValue(true);
            }else if(e.getCode().equalsIgnoreCase("ERROR_INTERNET_UNAVAILABLE") || e.getMessage().equalsIgnoreCase("timeout")) {
                noInternetConnection.setValue(true);
            } else {
                Crashlytics.logException(e);
                joinedChat.setValue(false);
            }

        }
    });
}

Please see my stack trace attached

Hello @Brandon

Can you please tell us a little more about your use case and what exactly you are trying to achieve with CometChat so that we can understand the problem better and help you out with a solution at the earliest.
A couple of things i would like to point out based on the code snippets provided:

  1. You only need to init CometChat once per session of the app. We suggest you add the init() code to the onCreate() method of the Application class. You do not need to reinitialise CometChat.

  2. You do not need to join a particular group every time. If you have joined the group once, you should be able to receive messages for the same group in future app sessions as well. In case you wish to stop receiving messages for a particular group, you need to use the leavGroup() method provided by the SDK.

Please provide us wit some more information regarding your use case so that we can help you better
Thanks

1 Like

Hi @aditya.gokula

The app I am working on is for users to be able to chat to Nurses in order to receive scripts and sick notes remotely, in some cases theses are emergency situations. The Android app uses CometChat SDK along with a Desktop client application which uses the CometChat SDK we have written that the nurses use. We initiate a group chat between the Android app user and the Desktop client nurse user because the nurse has functionality to add users with different roles to be able to view the chat without interacting or chatting

As I mentioned previously, I am calling init() in my Application’s onCreate() method, however, when the “timeout” exception is thrown after the device loses connection in my ChatActivity, the only way for the SDK to “wake up” and start sending messages again (basically any method I call on the SDK throws a timeout after the first timeout exception is thrown) is to call the init() method again. If I don’t do this, the timeout exception is thrown infinity times nomatter what method on the SDK I call.

This is why I asked if it may be your underlying OkHttp cache within the SDK that is not being cleared after connectivity is resumed on the device? I even enabled wifi with full signal, but the timeout exception is still returned.

To re-produce the issue, use an Emulator, switch off WIFI and set your Network Type to Edge and Signal strength to Poor. As soon as you send a message through the sdk, switch your Network off in the notification bar. Wait 15 seconds or more, then turn your network back on. The timeout exception is thrown for any SDK method. Joining a group, logging in, sending a message etc.

Thanks

Hello @Brandon,

Thank you for the detailed description. However, you do not need to init the SDK again or join the groups again. The reconnection mechanism is already present in the SDK and works as expected.
I will get this checked at my end and let you know what i find.
in the meanwhile, can you please confirm if the same issue is encountered while testing on a physical device too. I am saying this as we tried to test our reconnection login on emulators and while doing so did find some differences between the emulators and physical devices when it comes to network connection and reconnection

Thanks

2 Likes

Hi @aditya.gokula

Seems that reconnection works OK on an actual device :ok_hand:

Thanks for the help!

Cheers :beers:

2 Likes

Good to know. Cheers. :slightly_smiling_face:

1 Like