How to make SUSI kik bot

To make SUSI kik bot first you have to configure a bot. To configure bot go to https://dev.kik.com/ and make your bot by scanning code from your kik mobile app.You have to answer following questions from botsworth and make your bot.   After logging in to your dashboard get your api key by going to configuration menu on top. After your bot is setup follow given steps to create your first susi kik bot. Steps: Install Node.js from the link below on your computer if you haven’t installed it already. https://nodejs.org/en/ Create a folder with any name and open shell and change your current directory to the new folder you created. Type npm init in command line and enter details like name, version and entry point. Create a file with the same name that you wrote in entry point in above given step. i.e index.js and it should be in same folder you created. Type following commands in command line  npm install --save @kikinteractive/kik. After @kikinteractive/kik is installed type npm install --save http after http is installed type npm install --save request when all the modules are installed check your package.json these modules will be included within dependencies portion. Your package.json file should look like this. { "name": "susi_kikbot", "version": "1.0.0", "description": "susi kik bot", "main": "index.js", "scripts": { "test": "node tests/sample.js" }, "license": "MIT", "dependencies": { "@kikinteractive/kik": "^2.0.11", "request": "^2.75.0" } } Copy following code into file you created i.e index.js and add your bot name to it in place of username. var http = require('http'); var Bot = require('@kikinteractive/kik'); var request = require('request') var answer; var bot = new Bot({ username: '<your-bot-name>', apiKey: process.env.API_KEY, baseUrl: process.env.HEROKU_URL }); bot.updateBotConfiguration(); bot.onTextMessage((message) => { request('http://api.asksusi.com/susi/chat.json?q=' + encodeURI(query), function(error, response, body) { if (!error && response.statusCode == 200) { answer = JSON.parse(body).answers[0].actions[0].expression; } else { answer = "Oops, Looks like Susi is taking a break, She will be back soon"; } }); message.reply(answer) }); http.createServer(bot.incoming()).listen(process.env.PORT || 5000) Before deploying our bot to heroku so that it can be active we have to make a github repository for chatbot to make github repository follow these steps.In shell change current directory to folder we created above and  write git init git add . git commit -m”initial” git remote add origin <URL for remote repository> git remote -v git push -u origin master You will get URL for remote repository by making repository on your github and copying this link of your repository. To deploy your bot to heroku you need an account on Heroku and after making an account make an app.   Deploy app using github deployment method. Select Automatic deployment method. Go to settings of your app and config variables and paste your API key for bot to this and name it as API_KEY and get your heroku app url and make a variable for it named HEROKU_URL. Your susi bot is ready now test it by massaging it. If you want to learn more about kik API then refer to https://dev.kik.com/#/docs/messaging…

Continue ReadingHow to make SUSI kik bot

SUSI AI Bots with Microsoft’s Bot Framework

The Bot Framework is used to build intelligent chatbots and it supports .NET, Node.js, and REST. To learn about building bots using bot framework go to  https://docs.microsoft.com/en-us/bot-framework/bot-builder-overview-getstarted . Now to build SUSI AI bot for different platforms like facebook, telegram, kik, skype follow below given steps. Install Node.js from the link below on your computer if you haven’t installed it already. https://nodejs.org/en/ Create a folder with any name and open a shell and change your current directory to the new folder you created. Type npm init in shell and enter details like name, version and entry point. Create a file with the same name that you wrote in entry point in above given step. i.e index.js and it should be in same folder you created. Type following commands in command line  npm install --save restify.After restify is installed type npm install --save botbuilder   after botbuilder is installed type npm install --save request when all the modules are installed check your package.json modules will be included within dependencies portion. Your package.json file should look like this. { "name": "skype-bot", "version": "1.0.0", "description": "SUSI AI Skype Bot", "main": "app.js", "scripts": {   "test": "echo \"Error: no test specified\" && exit 1",   "start": "node app.js" }, "author": "", "license": "ISC", "dependencies": {   "botbuilder": "^3.8.1",   "request": "^2.81.0",   "restify": "^4.3.0" } } Copy following code into file you created i.e index.js var restify = require('restify'); var builder = require('botbuilder'); var request = require('request'); // Setup Restify Server var server = restify.createServer(); server.listen(process.env.port || process.env.PORT || 8080, function() {    console.log('%s listening to %s', server.name, server.url); }); // Create chat bot var connector = new builder.ChatConnector({  appId: process.env.appId,  appPassword: process.env.appPassword }); var bot = new builder.UniversalBot(connector); server.post('/api/messages', connector.listen()); //When bot is added by user bot.on('contactRelationUpdate', function(message) {    if (message.action === 'add') {        var name = message.user ? message.user.name : null;        var reply = new builder.Message()            .address(message.address)            .text("Hello %s... Thanks for adding me. You can talk to SUSI now.", name || 'there');        bot.send(reply);    } }); //getting response from SUSI API upon receiving messages from User bot.dialog('/', function(session) {    var options = {        method: 'GET',        url: 'http://api.asksusi.com/susi/chat.json',        qs: {            timezoneOffset: '-330',            q: session.message.text        }    }; //sending request to SUSI API for response    request(options, function(error, response, body) {        if (error) throw new Error(error);        var ans = (JSON.parse(body)).answers[0].actions[0].expression;        //responding back to user        session.send(ans);    }) }); You have to replace appID and appPassword with your own ID and Password which you can get by below given steps. Sign in/Sign up to this https://dev.botframework.com/. After signing in go to My Bots option at the top of the page and Create/Register your bot. Enter details of your bot and click on “Create Microsoft App ID and password”.  Leave messaging endpoint for now after getting app ID and password we will write messaging endpoint. Copy your APP ID and Password and save them for later use. Paste your App ID in box given for ID on bot registration page. Now we have to create messaging endpoint to listen for requests. Make a github repository and push…

Continue ReadingSUSI AI Bots with Microsoft’s Bot Framework

Deploy SUSI.AI to a Messenger

Integration of SUSI AI to messenger platform has become a vital step as to enhance the popularity of this chatbot and to target a large base of users. For example - Viber claims that it has a user base of 800 million. So just integrating SUSI AI to Viber can increase its user base exponentially. This integration also proves to be a big boon, if the chat bot learns with the number and variations in the questions being asked. Like in the case of the web chat client (Susi AI). This blog post will walk you through on how to deploy SUSI.AI to a messenger platform (Viber and Line messengers are used as an example in this post). We will be using Node.js and REST API technology in our example integrations. The repository of deployment of Susi AI to Viber can be found at susi_viberbot, and to Line messenger at susi_linebot. The SUSI AI Viberbot can be followed from here and Linebot by scanning this QR code. The diagram below will give you an overview on what flow is followed to deploy SUSI AI chatbot to various messenger platforms. Fig: Integration of Susi AI to chat messengers. Let’s walk through each of the steps mentioned in the above diagram. To get familiar with SUSI.AI chatbot. We have an API from where we fetch answers. To get a reply for the query ‘hi’, we can visit the API link with the query ‘hi’ appended to it (http://api.susi.ai/susi/chat.json?q=hi). You can chat with SUSI AI here. To set up a private SUSI AI chatbot account. A account must be set up in the messenger platform, so that the user can message in that account to get a reply by the chatbot. Steps to set up the chatbot account is dependent on the messenger platform. To set up a webhook url. The message sent to the chatbot account, must somehow connect to the chatbot. This message can be fed as a query to the chatbot, so that accordingly chatbot can think of a reply. To achieve this we need a url referred to as the webhook url. The messages sent by the user, to the SUSI AI chatbot account on the messenger, can then be redirected to this url. (Heroku platform allows 5 apps to be hosted on its platform for free, so you can check this documentation on how to host a node js app there.) Now we need to think on how to handle these messages. To host code on our webhook url As said earlier, we will be using Node js technology. Generally, the messages from our SUSI AI chatbot account on the messenger will travel as requests to our webhook url. These come as POST requests to our url. To handle that we can use this piece of code: app.post('/', function(request, response) { response.writeHead(200); // first step here, getting the message string from the request body // second step, calling the chatbot to get the reply to this message //…

Continue ReadingDeploy SUSI.AI to a Messenger

Using react-url-query in SUSI Chat

For SUSI Web Chat, I needed a query parameter which can be passed to the components directly to activate the SUSI dreams in my textarea using just the URL which is not easy when one is using react-router. React URL Query is a package for managing state through query parameters in the URL in React. It integrates well with React Router and Redux and provides additional tools specifically targeted at serializing and deserializing state in URL query parameters. So for example, if one wants to pass some parameters to populate in your component directly through the URL, you can use react-url-query. Eg. http://chat.susi.ai/?dream=fossasia will populate fossasia in our textarea section without actually typing the term textarea. So this in the URL, Will produce this in the textarea, To achieve this. the following steps are required: First we proceed with installing the packages (Dependencies  - history) npm install history --save npm install react-url-query --save   We then instantiate a history in our component where we want to listen to the parameters like the following code. Our class ChatApp is where we want to pass the params. ChatApp.react.js import history from '../history'; //Import the history object from the History package. // force an update if the URL changes inside the componentDidMount function componentDidMount() { history.listen(() => this.forceUpdate()); }  Next, we define the props of the parameters in our Message Section. For that we need the following props- urlPropsQueryConfig - this is where we define our URLConfig Static proptypes - the query param to which we want to pass the value, so for me it’s dream. The defaultProps when no such value is being passed to our param should be left a blank. And then we finally assign the props. This is then passed to the Message Composer Section from where we receive the value passed. MessageSection.react.js // Adding the UrlConfig const urlPropsQueryConfig = { dream: { type: UrlQueryParamTypes.string } }; // Defining the query param inside our ClassName static propTypes = { dream: PropTypes.string } // Setting the default param static defaultProps = { dream: '' } //Assigning the props inside the render() function const { dream } = this.props; //Passing the dream to the MessageComposer Section <MessageComposer threadID={this.state.thread.id} theme={this.state.darkTheme} dream={dream} /> //Exporting our Class export default addUrlProps({ urlPropsQueryConfig })(ClassName); Next we update the Message Composer section by the props we had passed. For this we first check if the props are null, we don’t populate it in our textarea if it is, otherwise we populate the textarea with the value ‘dream + props.dream’ so the value passed in the URL will be prepend by a word dream to enable the ‘dream value’ in our textarea. The full file is available at MessageComposer.js //Add Check to the constructor constructor(props) { super(props); this.state = {text: ''}; if(props.dream!==''){ //Setting the text as received ‘dream dreamPassed’ this.state= {text: 'dream '+ props.dream} } } // Populate the textarea <textarea name="message" value={this.state.text} onChange={this._onChange.bind(this)} onKeyDown={this._onKeyDown.bind(this)} ref={(textarea)=> { this.nameInput = textarea; }} placeholder="Type a message..." /> // Add props to…

Continue ReadingUsing react-url-query in SUSI Chat

Using SUSI as your dictionary

SUSI can be taught to give responses from APIs as well. I made use of an API called Datamuse which is a premier search engine for English words, indexing 10 million unique words and phrases in more than 1000 dictionaries and glossaries. 1. First, we head towards creating our dream pad for creating rules for the skill. To do this we need to create a dream at dream.susi.ai and give it a name, say dictionary. 2. After that one needs to go to the API and check the response generated. 3. Going through the docs of the API, one can create various queries to produce informative responses as follows - Word with a similar meaning. define *| Meaning of *| one word for * !console: $word$ { "url":"https://api.datamuse.com/words?ml=$1$", "path":"$.[0]" } eol Word related to something that start with a given letter. word related to * that start with the letter * !console: $word$ { "url":"https://api.datamuse.com/words?ml=$1$&sp=$2$*", "path":"$.[0]" } eol Word that sound like a given word.. word that sound like *|sounding like * !console: $word$ { "url":"https://api.datamuse.com/words?sl=$1$", "path":"$.[0]" } eol Words that are spelled similarly to a given word. words that are spelled similarly to *| similar spelling to *| spelling of * !console: $word$ { "url":"https://api.datamuse.com/words?sp=$1$", "path":"$.[0]" } eol Word that rhyme with a given word. rhyme *| word rhyming with * !console: $word$ { "url":"https://api.datamuse.com/words?rel_rhy=$1$", "path":"$.[0]" } eol Adjectives that are often used to describe a given word. adjective to describe *|show adjective for *|adjective for * !console: $word$ { "url":"https://api.datamuse.com/words?rel_jjb=$1$", "path":"$.[0]" } eol Suggestions for a given word. suggestions for *| show words like *| similar words to * | words like * !console: $word$ { "url":"https://api.datamuse.com/sug?s=$1$", "path":"$.[0]" } eol This is a sample query response for define * To create more dictionary skills go to http://dream.susi.ai/p/dictionary and add skills from the API. To contribute by adding more skills, send a pull request to the susi_skill_data.  To test the skills, you can go to chat.susi.ai

Continue ReadingUsing SUSI as your dictionary

20 Amazing Things SUSI can do for You

SUSI.AI has a collection of varied skills in numerous fields such as knowledge, entertainment, problem solving, small-talk, assistants etc. Here’s a list of top skills which SUSI possesses. Knowledge Based Ask SUSI to describe anything. Sample Queries - describe * Ask SUSI the distance between any two cities. Sample queries - distance between * and *|What is distance between * and * ?| What is distance between * and *          Ask SUSI about your site’s rank. Sample Query - site rank of *                 Ask SUSI to know the location of any place. Sample Queries - where is *          Ask SUSI the time in any city.  Sample Query - current time in *          Ask SUSI the weather information of any city. Sample Queries - temperature in * , hashtags * *, mentions * *, weather in *, Tell me about humidity in *|What is humidity in *|Humidity in *|* Humidity, Tell me tomorrow's weather in *|Weather forecast of *          Ask SUSI to wiki about anything. Sample Query - wiki *              Ask SUSI about any word, words etc. Sample Queries - define *| Meaning of *| one word for *, word related to * that start with the letter *, word that sound like *|sounding like *, words that are spelled similarly to *| similar spelling to *| spelling of *, rhyme *| word rhyming with *, adjective to describe *|show adjective for *|adjective for *, suggestions for *| show words like *| similar words to * | words like * Ask SUSI about a day in the calendar. Sample Queries - Date * ?, Day * ?, Day on year * month * date *?          Ask to convert a currency to USD for you.  Sample Queries -  convert * to USD          Problem Solving Based Ask SUSI to solve a problem for you in Mathematics.   Sample Queries - compute *| Compute *| Calculate *| calculate *          Entertainment Based Ask SUSI to draw a card for you. Sample Query - draw a card          Ask SUSI to toss a coin for you. Sample Query - flip a coin          Ask SUSI to tell you a Big Bang Theory Joke. Sample Query - * big bang theory| tell me about big bang theory|geek jokes|geek joke|big bang theory * Ask SUSI to generate a meme for you.  Sample Query - get me a meme                   Ask SUSI to give you a recipe.  Sample Queries - * cook *, cook *|how to cook *|recipe for   Ask SUSI to tell you a random joke. Sample Queries - tell me a joke|recite me a joke|entertain me Ask SUSI to give you a random gif. Sample Query - random gif          Assistants Ask SUSI to translate something for you Sample Queries - What is * in french|french for * , What is * in german|german for *, What is * in spanish|spanish for *,  What is * in hindi|hindi for * Ask SUSI to search anything for you. Sample…

Continue Reading20 Amazing Things SUSI can do for You

Using Flux to embed SUSI’s API Service in a Chat System.

To embed SUSI’s API Service in a chat-like system, I needed a view which could populate the content dynamically and maintain the state of the Application at the same time. Flux follows a unidirectional data flow path and I used this feature to the advantage of the Chat Application to maintain the real time state of the Chat View. A Flowchart model of Flux looks like   src: https://github.com/facebook/flux Flux uses a dispatcher service to render its views, thus making the data flow in a unidirectional path. When a user reacts with a React view (here through the TextArea in the chat system), the view propagates an action through the dispatcher service, to the various stores that hold the application’s data and finally update the views that are affected. Here’s another flowchart model from the website which helps one understand the model in a better way. For the current Chat Application, I used a single Message Store which contained all the event listeners to detect any change in the view. For example, when I send a “Hey” to SUSI, an action is called to Dispatch this message to the Message Store with an ActionType  “CREATE_MESSAGE”. This store then renders the message in the Message Section View. Here is an example snippet from the Actions.js file which performs an action of type CREATE_MESSAGE and dispatches the messages to the MessageStore.js. export function createMessage(text, currentThreadID) { let message = ChatMessageUtils.getCreatedMessageData(text, currentThreadID); ChatAppDispatcher.dispatch({ type: ActionTypes.CREATE_MESSAGE, message }); ChatWebAPIUtils.createMessage(message); }; The response from the message is generated as soon as another ActionType named “CREATE_SUSI_MESSAGE” is dispatched to the store, thereby rendering the SUSI’s response generated in the view. The file ChatConstants.js which declares all the ActionTypes. import keyMirror from 'keymirror'; export default { ActionTypes: keyMirror({ CREATE_MESSAGE: null, RECEIVE_RAW_CREATED_MESSAGE: null, CREATE_SUSI_MESSAGE: null, RECEIVE_SUSI_MESSAGE: null, RECEIVE_RAW_MESSAGES: null }) }; To get the message up on the view, I have used the following utils to call the API, render the messages to the view and call the different actions. Here’s a code snippet from ChatMessageUtils.js export function createMessage(message) { ChatExampleDataServer.postMessage(message, createdMessage => { Actions.receiveCreatedMessage(createdMessage, message.id); }); ChatExampleDataServer.postSUSIMessage(message, createdMessage => { Actions.createSUSIMessage(createdMessage, message.threadID); }); }; To know more about the project join us on Gitter at gitter.im/fossasia/susi_webchat, or to contribute go to https://github.com/fossasia/chat.susi.ai/. A demo application can be found running at http://chat.susi.ai. Resources - To know more about Flux you can visit the following websites. Docs and In-Depth Overview http://facebook.github.io/flux/docs/in-depth-overview.html#content Video Tutorials - http://facebook.github.io/flux/docs/videos.html#content

Continue ReadingUsing Flux to embed SUSI’s API Service in a Chat System.

Using Picasso library in SUSI Android

SUSI is an artificial intelligence for chatbots which have the ability to reply in most intuitive way through different types of answers such as images, charts, maps and text. Hence for the image displays in the SUSI Android client we need an image loading library which can help us to cache the images in the app. There are a few options available which include Glide and Picasso. Both of these libraries are open sourced. After some research we finally came up to use Picasso as it provides more additional features in comparison to Glide. Picasso is an image downloading library. It is an open source library. It is published and maintained by Square. It allows the developer to display an image from the external URL of the image. It provides caching of image in just a few lines of code. Previously without this library it was very difficult to download and display the image and required a lot more lines of code. But with the help of Picasso this task is reduced to just a few lines of code. How to use Picasso? To use Picasso in our project we must add the dependency of the library in build.gradle file. dependencies {   ...   compile "com.squareup.picasso:picasso:2.4.0"   ... } Let us define an imageView in which we want to load the image with the help of Picasso Library. <ImageView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:id="@+id/imageView"    android:layout_alignParentTop="true"    android:layout_centerHorizontal="true"> </ImageView> Now we are all set to download the image with the help of Picasso library in the following way:- //Initialize ImageView ImageView imageView = (ImageView) findViewById(R.id.imageView); //Loading image from below url into imageView Picasso.with(this)   .load("IMAGE URL")   .into(imageView); Picasso also provide the function for setting placeholders and error images to be shown if there is any problem in the downloading of the image. Picasso.with(this)    .load("YOUR IMAGE URL HERE")    .placeholder(R.drawable.ic_placeholder)    .error(R.drawable.ic_error_fallback)             .into(imageView); Now let us see the implementation of Picasso in Susi Android In the Susi app we are storing the link of images coming from response in the imageList. if (imageList == null || imageList.size() == 0) {   holder.linkPreviewImageView.setVisibility(View.GONE); } else {   Picasso.with(context).load(imageList.get(0))           .fit().centerCrop()           .into(holder.linkPreviewImageView); } Here we are passing the activity context to the Picasso library. We can use additional features like fit() and centerCrop() method the way we are using in the Susi app. These methods are fit the image at the center of the imageView. Screenshots from the Susi App Picasso Library also provides some additional functions as well like:- Picasso.with(this)     .load("YOUR IMAGE URL HERE")             .placeholder(R.drawable.ic_placeholder)   // optional             .error(R.drawable.ic_error_fallback)      // optional             .resize(250, 200)                        // optional             .rotate(90)                             // optional             .into(imageView); You can find more about Picasso from this link.

Continue ReadingUsing Picasso library in SUSI Android

Implementing DuckDuckGo Api in SUSI Android

As we know that Susi is an open source intelligent chatbot, it must be able to reply with user’s query on any topic. Therefore we have implemented DuckDuckGo API in Susi Android(https://github.com/fossasia/susi_android) which will help us to generate search result for the query asked by the user.   DuckDuckGo is an API which provides instant search results. This basically works as a search engine having information about various things. The most important thing about DuckDuckGo is that it is non tracking. It does not track its users and show results based on their search history. Thus the search results remain uniform across all the clients irrespective of their search history. The information inside the API is fed from more than 120 different independent sources. This is what makes it different from other search engines. The response in the form of answers include different types of links, description, categories, and definition about various stuffs. For more details about the Api please check this link.   API endpoints: http://api.duckduckgo.com/?q=DuckDuckGo&format=json This is one of the links generated to test the api. Here we can see different parameters, the parameter q is the query parameter where we write our question/query to get the response from the API. The format here defines the format in which we want the response to be. Here in this case we are obtaining the response in the form of JSON which can be parsed to obtain the desired result in the client. The response obtained by the following query is as follow:- {     "DefinitionSource":"",   "Heading":"DuckDuckGo",   "ImageWidth":340,   "RelatedTopics":[        {           "Result":"<a href=\"https://duckduckgo.com/Names_Database\">Names Database</a> - The Names Database is a partially defunct social network, owned and operated by Classmates.com, a wholly owned subsidiary of United Online. The site does not appear to be significantly updated since 2008, and has many broken links and display issues.",         "Icon":{              "URL":"",            "Height":"",            "Width":""         },         "FirstURL":"https://duckduckgo.com/Names_Database",         "Text":"Names Database - The Names Database is a partially defunct social network, owned and operated by Classmates.com, a wholly owned subsidiary of United Online. The site does not appear to be significantly updated since 2008, and has many broken links and display issues."      } }   Implementation in Susi android In Susi Android we are using Retrofit library by Square for API calling. Retrofit is one of the best libraries present for the network calling. It helps the developer to migrate from the old way of using AsyncTask in the Android app which creates a lot of mess and ugly code. For the implementation in Susi Android, we have made a WebSearchClient class that stores the base address for the API calling. public class WebSearchClient {   public static final String BASE_URL = "http://api.duckduckgo.com";   private static Retrofit retrofit = null;   public static Retrofit getClient() {       if (retrofit==null) {           retrofit = new Retrofit.Builder()                   .baseUrl(BASE_URL)                   .addConverterFactory(GsonConverterFactory.create())                   .build();       }       return retrofit;   } } To get the response we call the API with get method passing the query and format parameter in the following way. public interface WebSearchService {   @GET("/?format=json&pretty=1")   Call<WebSearch> getresult(@Query("q")…

Continue ReadingImplementing DuckDuckGo Api in SUSI Android

Custom Views in Susi Android App

Android provides us with the ability to have different views for your App. These views help in the formation of the UI element of the application. These includes imageView, textView and layouts such as LinearLayout and FrameLayout etc. The view hierarchy of Android looks something like this. The problem with these views is that we cannot modify them according to our own need inside the application. This is what we faced during the making of chat bubble layout for Susi Android App (https://github.com/fossasia/susi_android). We wanted to implement the chat bubble similar to Whatsapp that resizes and position the time textView according to size of the response coming from the server ie something like this as shown in the screenshot. Therefore we finally came up the solution of using Custom views inside the app that allowed us to modify the view the way we wanted.   So now lets us understand how we can make custom views by extending existing views So first question that comes in our mind is why are we extending existing views if we want to make our own. The reason behind this is that extending an existing view provides us with ability to have all the features that are there in an existing view. On top of that we can add our own functionality into it. Now see below how we can implement it. It's time for some actual code. As we can see in the code below that here we made our own custom class called ValueSelector. This class is extending the existing layout which is RelativeLayout. The first constructor used in the above class which takes context as the parameter is used to create an instance of the view programmatically. The second constructor used which takes context and AttributeSet as parameters is used to inflate the view from the XML. While the third constructor is used to define the base classes. public class ValueSelector extends RelativeLayout {    View rootView;    TextView valueTextView;    View minusButton;    View plusButton;    public ValueSelector(Context context) {        super(context);        init(context);    }    public ValueSelector(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    private void init(Context context) {        //do setup work here    } The init method used here is to inflate the views and to get the reference of all the child view. private void init(Context context) {    rootView = inflate(context, R.layout.value_selector, this);    valueTextView = (TextView) rootView.findViewById(R.id.valueTextView);    minusButton = rootView.findViewById(R.id.minusButton);    plusButton = rootView.findViewById(R.id.plusButton);    minusButton.setOnClickListener(new View.OnClickListener() {        @Override        public void onClick(View v) {            decrementValue(); //we'll define this method later        }    });    plusButton.setOnClickListener(new View.OnClickListener() {        @Override        public void onClick(View v) {            incrementValue(); //we'll define this method later        }    }); } Let's now see the implementation of CustomViews in Susi Android.   public class ChatBubbleLayout extends FrameLayout {   public ChatBubbleLayout(Context context) {       super(context);   }   public ChatBubbleLayout(Context context, AttributeSet attrs) {       super(context, attrs);   }   public ChatBubbleLayout(Context context, AttributeSet attrs, int defStyleAttr) {       super(context, attrs, defStyleAttr);   }   @TargetApi(21)   public ChatBubbleLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {       super(context, attrs, defStyleAttr, defStyleRes);   }   @Override   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)…

Continue ReadingCustom Views in Susi Android App