Apply Shimmer Effect for Progress in Open Event Attendee Application

The open event attendee is an android app which allows users to discover events happening around the world using the Open Event Platform. It consumes the APIs of the open event server to get a list of available events and can get detailed information about them.

Shimmer effect was created by Facebook to indicate a loading status, so instead of using ProgressBar or the usual loader use Shimmer for a better design and user interface. They also open-sourced a library called Shimmer both for Android and iOS so that every developer could use it for free.

  • Add Shimmer library
  • Create a placeholder for shimmer
  • Apply the effect with live data
  • Conclusion
  • Resources

Let’s analyze every step in detail.

Add Shimmer Library 

Add Shimmer Library to build.gradle :

// Cards Shimmer Animation
implementation 'com.facebook.shimmer:shimmer:0.5.0'

Create reasouces

Add shimmer background color to colors.xml:

<color name="shimmer_background">#dddddd</color>

Create a placeholder layout:

<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/layout_margin_medium"
    app:cardBackgroundColor="@android:color/white"
    app:cardCornerRadius="@dimen/card_corner_radius"
    app:cardElevation="@dimen/layout_margin_none"
    android:foreground="?android:attr/selectableItemBackground"
    android:background="@android:color/white">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/layout_margin_large"
        android:layout_gravity="center"
        android:orientation="vertical">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="@dimen/item_image_view_160dp"
            android:scaleType="centerCrop"
            android:background="@color/shimmer_background"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_marginTop="@dimen/layout_margin_medium"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <View
                android:layout_width="@dimen/card_width_45dp"
                android:layout_height="@dimen/item_image_view"
                android:background="@color/shimmer_background"
                android:layout_marginEnd="@dimen/padding_large"
                android:layout_marginRight="@dimen/padding_large"
                android:gravity="center_horizontal"
                android:orientation="vertical"
                android:layout_marginTop="@dimen/padding_medium">
            </View>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:paddingBottom="@dimen/padding_large"
                android:paddingTop="@dimen/padding_medium">

                <View
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/view_height_25dp"
                    android:layout_marginBottom="@dimen/layout_margin_small"
                    android:background="@color/shimmer_background"/>

                <View
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/view_height_25dp"
                    android:background="@color/shimmer_background"/>

            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</androidx.cardview.widget.CardView>

Add shimmer in your fragment/activity layout resources file:

<com.facebook.shimmer.ShimmerFrameLayout
        android:id="@+id/shimmer_view_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="15dp"
        android:orientation="vertical"
        shimmer:duration="800">

        <!-- Adding 7 rows of placeholders -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <include layout="@layout/data_placeholder_layout" />
            <include layout="@layout/data_placeholder_layout" />
            <include layout="@layout/data_placeholder_layout" />
            <include layout="@layout/data_placeholder_layout" />
            <include layout="@layout/data_placeholder_layout" />
            <include layout="@layout/data_placeholder_layout" />
            <include layout="@layout/data_placeholder_layout" />
        </LinearLayout>

    </com.facebook.shimmer.ShimmerFrameLayout>

Apply Shimmer with LiveData

Declare live data variable in view model:

private val mutableShowShimmer = MediatorLiveData<Boolean>()
val showShimmer: MediatorLiveData<Boolean> = mutableShowShimmer

Handle progress in the view model:

compositeDisposable += eventPagedList
            .subscribeOn(Schedulers.io())
            .doOnSubscribe {
                mutableShowShimmer.value = true
            }.finally {
     mutableShowShimmer.value = false
}

Handle shimmer with observing the live data in fragment/activity:

eventsResultsViewModel.showShimmer
            .nonNull()
            .observe(viewLifecycleOwner, Observer {
                if (it) {
                    rootView.shimmer_view_container.startShimmer()
                } else {
                    rootView.shimmer_view_container.stopShimmer()
                }
                rootView.shimmer_view_container.isVisible = it
            })

GIF

Resources

Show shimmer progress in Android: https://medium.com/mindorks/android-design-shimmer-effect-fa7f74c68a93

Tags

Eventyay, open-event, Shimmer, Facebook, MVVM, Fossasia, GSoC, Android, Kotlin

Continue Reading Apply Shimmer Effect for Progress in Open Event Attendee Application

Integration of SUSI AI to Facebook

It’s easy to create your own SUSI AI Facebook messenger bot. You can read the official documentation by Facebook to get started.

Messenger bots use a web server to send and receive messages. You also need to have the bot be authenticated to speak with the web server and be approved by Facebook before getting public.

If any problems faced, visit the susi_fbbot repository which hosts the code for SUSI Facebook Messenger bot.

We will be using Node js technology to develop the FB bot. First, let’s see on how to request an answer from the SUSI API.

To call Susi API and fetch an answer from it for a query (‘hi’ in this case). Let’s first visit http://api.asksusi.com/susi/chat.json?q=hi from the browser. We will get a JSON object as follows:

The answer can be found as the value of the key named expression. In this case, it is “Hallo!”.

To fetch the answer through coding, we can use this code snippet in Node js:

// including request module
var request = require(‘request’);

// setting options to make a successful call to Susi API.
var options = {
            method: 'GET',
            url: 'http://api.asksusi.com/susi/chat.json',
            qs: 
            {
                timezoneOffset: '-330',
                q: 'hi'
            }
        };

// A request to the Susi bot
request(options, function (error, response, body) {
    if (error)
        throw new Error(error);
    // answer fetched from susi
    ans = (JSON.parse(body)).answers[0].actions[0].expression;
}

The properties required for the call are set up through a JSON object (i.e. options). Pass the options object to our request function as its 1st parameter. The response from the API will be stored in ‘body’ variable. We need to parse this body, to be able to access the properties of that body object. Hence, fetching the answer from Susi API.

Now let’s dive into the code of receiving and messaging back to the user on Facebook:

  • A generic function to send a message to the user.
// the first argument is the sender id and the second is the text to send.
function sendTextMessage(sender, text) {
    var messageData = { text:text };
    
    // making a post request to facebook graph API to send message.
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token:token},
        method: 'POST',
        json: {
            recipient: {id:sender},
            message: messageData,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending messages: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
}
  • According to step 9, in the below instructions we need to include this code snippet too:
// for facebook verification
app.get('/webhook/', function (req, res) {
    if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        res.send(req.query['hub.challenge']);
    }
    res.send('Error, wrong token');
});
  • When user messages to our bot, we need to extract the text of the message from the request body. Then we need to extract the reply from the SUSI API and send it back to the user.
// when a message from a user is received.
app.post('/webhook/', function (req, res) {
    var messaging_events = req.body.entry[0].messaging
    for (var i = 0; i < messaging_events.length; i++) {
        // fetching the current event
        var event = req.body.entry[0].messaging[i];

        // fetching the sender id
        var sender = event.sender.id;
        
        // if the event is a message event
        if (event.message && event.message.text) {
            var text = event.message.text;

            // Construct the query for susi
            var queryUrl = 'http://api.susi.ai/susi/chat.json?q='+encodeURI(text);
            var message = '';

            // Wait until done then reply
            request({
                url: queryUrl,
                json: true
            }, function (error, response, body) {
                if (!error && response.statusCode === 200) {
              // fetch the answer from the response body and save it in message variable.
                    // send the reply
                    sendTextMessage(sender, message);
                } 
                
            // if, due some reasons the answer couldn’t be fetched
            else {
                    message = 'Oops, Looks like Susi is taking a break, She will be back soon';
                    sendTextMessage(sender, message);
                }
            });
        }
        if (event.postback) {
            var text = JSON.stringify(event.postback);
            sendTextMessage(sender, "Postback received: "+text.substring(0, 200), token);
            continue;
        }
    }
    res.sendStatus(200)
})

Upload the code developed to a repository.

Let’s follow the below steps, to achieve a working fb messenger bot:

  1. Create a Facebook page here.

    Creating a FB Page
    New FB Page

    1. Create a new Heroku app here.

    New Heroku App

    1. Connect the Heroku app to the repository hosting our code.

    Connect to Github

    4. Deploy on the development branch. If you intend to contribute, it is recommended to Enable Automatic Deploys.

    Branch Deployment

    Successful Deployment

    5. Create or configure a Facebook App or Page here.

    New FB App

    6. Get started with Messenger tab in the created app.


    7.
    In the Page Access Token select the FB page that you created and generate the token and save it somewhere for future use.

    Token Generation

    8. Now, go to the Heroku app, select the settings tab and add the environment variable as shown, where the key is FB_PAGE_ACCESS_TOKEN and value is the token generated in the previous step.

    9. Create a web hook on the facebook app dashboard. The Callback URL should be https://<your_app_name>.herokuapp.com/webhook/ and rest should be as shown in the image below.

    App Complete

    10. Go to Terminal and type in this command to trigger the Facebook app to send messages. Remember to use the token you requested earlier.
    “`
    curl -X POST “https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=<PAGE_ACCESS_TOKEN>”
    “`

    11. Go to the Facebook page created and locate ‘Message Now’ or go to https://m.me/PAGE_USERNAME

    12. Enjoy chatting with Susi.

    Resources

Continue Reading Integration of SUSI AI to Facebook