This is an example implementation of the SDK in an Android App. The App will have a login flow and will enable / disable In Apps to only show them to users that are logged in.

First we need to set the PulsateAuthData. If possible set this data in the Application onCreate() callback.

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()

        val authData = PulsateAuthData(
            appToken,
            appSecret,
        )

        PulsateFactory.getInstance(authData)
    }
}

In our Login Screen we will check if the user is logged in or not and navigate to the proper screen.

class LoginFragment : Fragment() {
  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val pulsateManager = PulsateFactory.getInstance()
        
        // We want to show some type of loading indicator and block the login screen while we check if the user is logged in
        showSpinner()
        val isUserLoggedIn = mLoginViewModel.isUserLoggedIn()
        if (isUserLoggedIn) {
            // If the user is logged in we want to enable in app notifications and navigate to the main screen
            navigateToMainScreen()
        } else {
            // If the user is not logged in we hide the loading indicator and unblock the login screen
            hideSpinner()
            setupLoginScreen()
        }
    }
}

We do not want to start the Pulsate session on the Login Screen, because the Pulsate session is an async call that does network calls in the background and on success it will try to attach an In App to the Login Screen which will soon be destroyed. Attaching the In App to a screen that will shortly be destroyed can possibly cause the In App to not render at all. In the Main Screen we will be starting the session and ask the SDK to show any In Apps that might be waiting to render.

class MainFragment : Fragment() {
  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val pulsateManager = PulsateFactory.getInstance()

        pulsateManager.startPulsateSessionForAlias(
           retailAlias / businessAlias,
            object : IPulsateRequestListener {
                override fun onSuccess() {
                    pulsateManager.setInAppNotificationEnabled(true)
                    pulsateManager.showLastInAppNotification(true)
                    pulsateManager.setPushNotificationEnabled(true)
                    pulsateManager.setUserAuthorized(true)
                    pulsateManager.showLastUnauthorizedMessage()
                }

                override fun onError(e: Throwable?) {
                    e?.printStackTrace()
                }
            },
        )
    }
}

This will start a Pulsate session, enable In Apps if they are disabled for any reason and show any In Apps that are waiting to be shown. We do not want to call "setInAppNotificationEnabled(inAppNotification" multiple times with different values, because these are async database calls and can result in a race condition where either the wrong value is set or the In Apps are in the middle of rendering and we suddenly block them from showing.

Once the user leaves our App we still want him to receive push notifications, but don't want him to see any In Apps until he logs in again and is on the Main Screen. To achieve this we can setup the DefaultLifecycleObserver in our Application class.

class MyApp : Application() {
    val mMyLifecycleManager: MyLifecycleManager? = null

    override fun onCreate() {
        super.onCreate()
        
        mMyLifecycleManager = MyLifecycleManager()
       
        val authData = PulsateAuthData(
            appToken,
            appSecret,
        )

        PulsateFactory.getInstance(authData)
    }
}
class MyLifecycleManager constructor() : DefaultLifecycleObserver {
    init {
        // Handler required to prevent some devices from crashing in some rare cases
        Handler(Looper.getMainLooper()).post {
            ProcessLifecycleOwner.get().lifecycle.addObserver(this)
        }
    }
    
    override fun onStop(owner: LifecycleOwner) {
        val pulsateManager = PulsateFactory.getInstance()
        pulsateManager.setInAppNotificationEnabled(false)
        // We want the user to still receive pushes
        pulsateManager.setPushNotificationEnabled(true)
        pulsateManager.setUserAuthorized(false)
    }
}

This implementation will allow Pulsate to still be active in the background and trigger geofences / beacons / pushes / manage sessions and you will only show In Apps to logged in users. If needed you can also disable push notifications by just adding pulsateManager.setPushNotificationEnabled(true) and pulsateManager.setPushNotificationEnabled(false).

Flow Diagram