Skip to content

Custom Onboarding

Add Launch screen activity to your manifest file

The LaunchScreenActivity should be added to the AndroidManifest.xml file in an activity xml tag. It is required to specify also the "action_handler" meta-data tag.

1
2
3
4
5
6
7
8
        <activity
            android:name="com.sap.cloud.mobile.onboarding.launchscreen.LaunchScreenActivity"
            android:label="@string/app_name"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar">
            <meta-data
                android:name="action_handler"
                android:value="<your_package_name>.WelcomeScreenActionHandlerImpl" />
        </activity>

Start the LaunchScreenActivity

The LaunchScreenActivity can be started with standard startActivityResult method of the Activity and you can configure it via the LaunchScreenSettings class. For example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
        Intent i = new Intent(getIntent());
        i.setComponent(new ComponentName(
                getPackageName(),
                "com.sap.cloud.mobile.onboarding.launchscreen.LaunchScreenActivity"));
        LaunchScreenSettings settings = new LaunchScreenSettings();
        settings.setLaunchScreenHeadline("Project Companion \n for Managers");
        settings.setLaunchScreenImages(new int[]{R.drawable.img1, R.drawable.img2, 0});
        settings.setLaunchScreenTitles(new String[]{"title1", "title2", "title3"});
        settings.setLaunchScreenDescriptions(new String[]{"short_desc1", "short_desc2", "long_desc3"});
        settings.setLaunchScreenAnimationInterval(4000);
        settings.setWelcomeScreenType(OnboardingType.STANDARD_ONBOARDING);
        settings.setDemoAvailable(true);
        settings.saveToIntent(i);

        startActivityForResult(i, LAUNCH_SCREEN);
In case of the welcome screen, the most important setting to be set is the WelcomeScreenType. The supported types are documented via the OnboardingType enumeration:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * The enumeration containing the supported welcome screen types. The welcome screen types specifies which user interface elements are visible and enabled on the {@link LaunchScreenActivity} welcome screen
 * and which onboarding functionalities are supported on it.
 */
public enum OnboardingType {
    /**
     * Standard onboarding implemented by app developer. The user interface displays a primary
     * action button which starts this onboarding process.
     */
    STANDARD_ONBOARDING,
    /**
     * The welcome's user interface displays a primary action button, which starts an activation screen.
     * The user interface of the activation displays only an information message,
     * not allowing the user to execute the onboarding directly from the welcome/activation screen.
     */
    ACTIVATION_MAIL_ONBOARDING,
    /**
     * The welcome's user interface displays a primary action button, which starts an activation
     * screen.
     * The user interface of the activation supports both the QR code based onboarding and the discovery service based onboarding and the user should choose one of these onboarding
     * options on the activation.
     */
    BARCODE_OR_DISCOVERY_SERVICE_ONBOARDING,
    /**
     * The welcome's user interface displays a primary action button, which starts an activation
     * screen.
     * The user interface of the activation displays - in addition to the primary action button -
     * also an edit box where the user should specify the email address used for
     * the discovery service based onboarding process.
     */
    DISCOVERY_SERVICE_ONBOARDING,
    /**
     * The welcome's user interface displays a primary action button, which starts an activation screen.
     * The user interface displays the primary action button which starts the QR code based onboarding.
     */
    BARCODE_ONBOARDING;
}

If you would like to use a custom onboarding process, then you should set the type of the welcome screen/launch screen to OnboardingType.STANDARD_ONBOARDING as shown in the example above. In this case you have to implement of the startStandardOnboarding method of the WelcomeScreenActionHandler interface in your action handler implementation class.

In addition, via the setDemoAvailable method you can specify if the demo mode is supported (that is the "Try the demo" button is visible on the welcome screen/launch screen). If you enable demo mode, then you have to implement of the startDemoMode method of the WelcomeScreenActionHandler interface in your action handler implementation class as well.

Implementation of the callback method for custom onboarding

If you need custom onboarding process you have to implement of the startStandardOnboarding method of the WelcomeScreenActionHandler interface in your action handler implementation class.

The implementation of this method will be executed on a dedicated background thread of the caller activity, more precisely the background thread of the headless fragment of the caller activity. This fragment is handed over to the method as parameter. You can access the caller activity via the getActivity() method of this fragment. Please note that the result of the getActivity call might be null value if there is no active activity in the background, for example due to an ongoing change orientation process.

First: the callback method waits for response synchronously, so if you need asynchronous communication, then you have to wait on this thread until the async response arrives. You are allowed block the thread because you are on a dedicated background thread.

As a consequence, you have to be prepared to handle the interrupted flag of the thread. For example: if the user taps on the back button, or if the system destroys the caller fragment, then this thread will be interrupted. If the execution of your callback method was successfully interrupted, that is the normal processing was not completed, then you should throw InterruptedException from your implementation in order to indicate that the processing was cancelled. For example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    @Override
    public void startStandardOnboarding(Fragment fragment) throws InterruptedException {
        Log.i(TAG, "createStandardOnboarding");
        Intent i = new Intent();
        i.setComponent(new ComponentName(
                fragment.getActivity().getPackageName(),
                "<your_package>.LoginActivity"));
        fragment.getActivity().startActivityForResult(i, 1000);

        //do NOT return here until the onboarding is not finished
        //you have to wait for the result via blocking the thread
        synchronized (SYNC) {
            while (!responseAvailable) {
                SYNC.wait();
            }
        }
    }

On the other, you are also allowed to start new activity on top of the caller activity. Please note that in this case the caller fragment might be destroyed, that is you are not allowed to use the fragment parameter after this point. In addition, the response of the new activity will be called on the caller fragment/activity and therefore you have to implement one more callback method named onActivityResult. For example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    @Override
    public boolean onActivityResult(Fragment fragment, int requestCode, int resultCode, Intent data) {

        if (requestCode == 1000) {
            if (resultCode == Activity.RESULT_OK) {
                Intent intent = new Intent();
                intent.putExtra("DEMO", false);
                fragment.getActivity().setResult(Activity.RESULT_OK, intent);
                fragment.getActivity().finish();
                synchronized (SYNC) {
                    responseAvailable = true;
                    SYNC.notify();
                }
                return false;
            } else {
                synchronized (SYNC) {
                    responseAvailable = true;
                    SYNC.notify();
                }
                return true;
            }
        }
        return true;

    }
The onActivityResult will get a caller fragment again. Please note that this caller instance might be difference from the one you received from the startStandardOnboarding.