quickblox-android-sdk: Problems when subscribing to push notifications. (SubscribeService)

Environment details

  • Any Android API
  • Any Quickblox SDK (Currently 3.3.5)

Did this work before?

  • No, this is happening regularly every release.

Expected behavior

  • The app should not crash when subscribing to push notifications

Actual behavior

  • The app crashes when subscribing to push notifications

Logs

Steps to reproduce the behavior

  • I was unable to reproduce the problem no matter which android version/quickblox sdk version for Decorators and ToStringHelper and Quickblox core
  • SubscribeService.subscibeToPushes(…) crashes on Android O devices.

Quickblox Usage in app

Project structure:

projectstruct

  • messaging package contains the abstraction of instant messaging in our app.
  • quickblox package is the Quickblox implementation of the instant messaging.
  • InstantMessaging is the main class. You can call any of the other interfaces from within this class:
    MessagesDispatcher getMessagesDispatcher();

    DialogsReceiver getDialogsReceiver();

    NotificationsDispatcher getNotificationsDispatcher();

    Authenticator getAuthenticator();

    ConnectionManager getConnectionManager();
  • There’s only one instance of InstantMessaging and it’s a field in the Application class.

Initializing quickblox

  • Calling this onCreate of Application, if the user is logged in to the app:
   public void initialiseInstantMessaging(final EmptyCallback callback) {
        instantMessaging = new QuickBloxInstantMessaging(this);
        try {
            instantMessaging.initialize(new EmptyCallback() {
                @Override
                public void onSuccess() {
                    callback.onSuccess();
                }

                @Override
                public void onFailure() {

                }
            });
        } catch (Exception e) {
            Log.d(TAG, e.toString());
        }
    }

-> InstantMessagin.initialize excecutes this task:

    /**
     * Initialization task. It's done in an {@link AsyncTask because, by default, the
     * Quickblox initialization is done on the UI thread. Blocking  UI until it's finished.
     */
     private class initTask extends AsyncTask<EmptyCallback, Void, EmptyCallback> {
        @Override
        protected EmptyCallback doInBackground(EmptyCallback... params) {
            authenticateApi();
            initApi();
            return params[0];
        }

        @Override
        protected void onPostExecute(final EmptyCallback callback) {
            super.onPostExecute(callback);
            quickbloxConnectionManager.addConnectionListener();
            updateChatEnabled();
            quickbloxAuthenticator.login(credentials.getUsername(), credentials.getPassword(), new EmptyCallback() {
                @Override
                public void onSuccess() {
                    callback.onSuccess();
                }

                @Override
                public void onFailure() {
                    reconnectApi(new EmptyCallback() {
                        @Override
                        public void onSuccess() {
                            callback.onSuccess();
                        }

                        @Override
                        public void onFailure() {

                        }
                    });
                }
            });
        }
    }

-> authenticateApi() :

    /**
     * Authenticates {@link QuickBloxInstantMessaging with the appropriate
     * credentials depending on current product flavor.
     */
    @Override
    public void authenticateApi() {
        if (!BuildConfig.DEBUG_ENABLED) {
            QBSettings.getInstance().setStoringMehanism(StoringMechanism.UNSECURED);
            QBSettings.getInstance().setEndpoints(API_DOMAIN, CHAT_DOMAIN, ServiceZone.PRODUCTION);
            QBSettings.getInstance().init(context, APP_ID, AUTH_KEY, AUTH_SECRET);
            QBSettings.getInstance().setAccountKey(ACCOUNT_KEY);
            QBSettings.getInstance().setEnablePushNotification(true);
            QBSettings.getInstance().setSubscribePushStrategy(SubscribePushStrategy.ALWAYS);
        } else {
            QBSettings.getInstance().setStoringMehanism(StoringMechanism.UNSECURED);
            QBSettings.getInstance().setEndpoints(API_DOMAIN, CHAT_DOMAIN, ServiceZone.PRODUCTION);
            QBSettings.getInstance().init(context, DEV_APP_ID, DEV_AUTH_KEY, DEV_AUTH_SECRET);
            QBSettings.getInstance().setAccountKey(DEV_ACCOUNT_KEY);
            QBSettings.getInstance().setEnablePushNotification(true);
            QBSettings.getInstance().setSubscribePushStrategy(SubscribePushStrategy.ALWAYS);
        }
    }

-> initApi():

    /**
     * Initializes the APIs configurations.
     */
    @Override
    public void initApi() {
        QBChatService.setDebugEnabled(true);
        QBChatService.setDefaultAutoSendPresenceInterval(15);
        QBChatService.ConfigurationBuilder builder = new QBChatService.ConfigurationBuilder();
        builder.setAutojoinEnabled(true);
        builder.setSocketTimeout(200);
        builder.setKeepAlive(true);
        builder.setReconnectionAllowed(true);
        builder.setUseTls(true);
        QBChatService.setConfigurationBuilder(builder);
    }

Using the InstantMessaging instance:

  • From the Application class:
    public InstantMessaging getInstantMessagingApi() throws NotLoggedInException {
        if (instantMessaging == null || !instantMessaging.getAuthenticator().isLoggedIn()) {
            throw new NotLoggedInException("User isn't logged in, can't init Instant Messaging");
        }
        return instantMessaging;
    }

Subscribing to pushes

  • When the user successfully logs in to quickblox, the QuickbloxConnectionManager subscribes to push notifications.
 /**
     * Authenticates the current user with Quickblox and logs in.
     */
    @Override
    public void login(String username, String password, final EmptyCallback callback) {
        final QBUser qUser = new QBUser(username, Base64Helper.encode(password));
        QBAuth.createSession(qUser).performAsync(new QBEntityCallback<QBSession>() {
            @Override
            public void onSuccess(QBSession qbSession, Bundle bundle) {
                qUser.setId(qbSession.getUserId());
                QBChatService.getInstance().login(qUser, new QBEntityCallback() {
                    @Override
                    public void onSuccess(Object o, Bundle bundle) {
                        getInstantMessaging().getConnectionManager().initManagersListeners();
                        getInstantMessaging().getConnectionManager().subscribeToPushNotifications();
/// code..

-> Subscribe to push notifications::

 /**
     * Subscribes the user to offline push notifications.
     */
    @Override
    public void subscribeToPushNotifications() {
        try {
            if (getInstantMessaging().getAuthenticator().isLoggedIn()) {
                SubscribeService.subscribeToPushes(context, true);
                QBPushManager.getInstance().addListener(new QBPushManager.QBSubscribeListener() {
                    @Override
                    public void onSubscriptionCreated() {
                        Log.d(TAG, "Subscribed to push notifications");
                    }

                    @Override
                    public void onSubscriptionError(Exception e, int i) {
                        Log.d(TAG, "Failed to subscribe to push notifications: " + e.toString());
                    }

                    @Override
                    public void onSubscriptionDeleted(boolean b) {
                        Log.d(TAG, "Subscription deleted to push notifications");
                    }
                });
            }
        } catch (Exception e) {
            Log.d(TAG, e.toString());
        }
    }

-> Check if the user is logged in:


    /**
     * Checks if the current user is logged in.
     *
     * @return true if the user is logged in.
     */
    @Override
    public boolean isLoggedIn() {
        try {
            return QBChatService.getInstance() != null && QBChatService.getInstance().isLoggedIn();
        } catch (Exception e) {
            return false;
        }
    }

Android Oreo problems

  • Calling startService() throws an IllegalStateException on Android Oreo devices.
  • Quickblox calls this method when SubscribeService.subscribeToPushes(..) is called:
 Intent intent = new Intent(context, SubscribeService.class);
            intent.putExtra("extraSubscribe", true);
            context.startService(intent);

EDIT:

  • Small note, the README in quickblox android releases github says 3.4.0 however 3.4.0 doesn’t compile but 3.4 does.
  • Added a new crash stack trace that happened just recently.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 18 (7 by maintainers)

Most upvoted comments

I am also facing the same issue where my targeted version of the app is Android API level 28. I’m using Quick Blox SDK version 3.8.1.

Does anyone found any solution?