<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Kaushik Ravikumar on Medium]]></title>
        <description><![CDATA[Stories by Kaushik Ravikumar on Medium]]></description>
        <link>https://medium.com/@kaushik.ravikumar1999?source=rss-2d6a5a28d910------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*4STAuGa157U8EcXyip2_aw.jpeg</url>
            <title>Stories by Kaushik Ravikumar on Medium</title>
            <link>https://medium.com/@kaushik.ravikumar1999?source=rss-2d6a5a28d910------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 12 Nov 2026 08:19:33 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@kaushik.ravikumar1999/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Build a Smart Parking Lot with Realtime Space Monitoring]]></title>
            <link>https://codeburst.io/build-a-smart-parking-lot-with-realtime-space-monitoring-897d05d717b9?source=rss-2d6a5a28d910------2</link>
            <guid isPermaLink="false">https://medium.com/p/897d05d717b9</guid>
            <category><![CDATA[internet-of-things]]></category>
            <category><![CDATA[soracom]]></category>
            <category><![CDATA[pubnub]]></category>
            <category><![CDATA[raspberry-pi]]></category>
            <category><![CDATA[smart-cities]]></category>
            <dc:creator><![CDATA[Kaushik Ravikumar]]></dc:creator>
            <pubDate>Wed, 08 Aug 2018 13:05:31 GMT</pubDate>
            <atom:updated>2018-08-08T13:05:31.091Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*C7Nav2yTXtReUuzU0pNzuA.png" /></figure><p>Never before have we lived in an era, where every “thing” could seamlessly be interconnected by the Internet. The idea of <strong>Internet of Things</strong> (IoT) has continually transformed our world by presenting innovative solutions to numerous problems using an <strong>Event Driven Pub/Sub Architecture</strong>. For example, to solve the exhausting problem of finding parking in crowded spaces, parking garages have installed live electronic dashboards showing which spots are available by subscribing to status updates published from individual sensors in a parking lot. Building such an IoT app can be challenging due to a number of hurdles.</p><p>One of these hurdles is hosting a server capable of handling messages sent between the mobile app and the sensor devices in realtime. Another is hosting a wifi network capable of supporting every single embedded sensor device in the smart parking lot.</p><p>By using <strong>PubNub</strong> and <strong>Soracom</strong> alongside each other, however, developers can quickly circumvent these challenges. With PubNub’s realtime platform, developers can easily <a href="https://www.pubnub.com/solutions/iot/">build complex IoT solutions</a> without worrying about tedious tasks such as hosting servers. Additionally, with <a href="https://soracom.io/en/services/air/cellular/">Soracom Air</a> and <a href="https://soracom.io/en/services/beam/">Soracom Beam</a>, developers can easily build IoT solutions that utilize LTE, instead of a restrictive WFI network.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FKySPa_D2ne0%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DKySPa_D2ne0&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FKySPa_D2ne0%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/b60c9d36e94f7eecf0364ad95e794511/href">https://medium.com/media/b60c9d36e94f7eecf0364ad95e794511/href</a></iframe><h3>Tutorial Overview</h3><p>In this tutorial, we will build a Smart Parking Simulation using Raspberry Pi and an ultrasonic sensor to detect whether a parking spot is occupied or vacant. We will use Soracom Air to send messages from the sensor to PubNub via cellular data. Then using PubNub’s Publish-Subscribe API, we will make live parking data instantly available to all the app’s mobile users. This is shown in the following diagram.</p><p><strong>For the full source code, </strong><a href="https://github.com/kaushikravikumar/Smart-Parking"><strong>click here</strong></a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/879/0*bb7jox-vE-_DksS1.png" /></figure><p>To build this demo, you will need:</p><ol><li>Raspberry Pi (Any Version)</li><li>Breadboard</li><li>HC-SR04 Ultrasonic Sensor</li><li>1 Female-female + 6 male-female jumper wires</li><li>1 <strong>1k Ω</strong> resistor and 1 <strong>2k Ω</strong> resistor</li><li>MicroSD card + MicroSD to SD Adapter</li><li>Huawei USB Stick Modem</li><li>Soracom Air Sim Card</li></ol><h3>Raspberry Pi Setup</h3><h3>1. Raspbian OS Installation</h3><p>If you haven’t already, make sure to install the <a href="https://www.raspberrypi.org/downloads/raspbian/">Raspbian OS</a> onto your Raspberry Pi. To do this, we will first install it locally on our computer. This will be of disk image format, so we will need to flash the disk before using it. You can use <a href="https://etcher.io/">Etcher</a> to flash the disk onto your microSD card Adapter.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/799/0*Bn9yw5Z3Bkyny8zV.png" /></figure><p>Once the Raspbian OS files are on our microSD card Adapter, we may remove the microSD card from the adapter and then insert it into the bottom slot of our Raspberry Pi. With the OS installed, you may now boot up the Raspberry Pi by plugging in a keyboard, mouse, monitor, and power source.</p><h3>2. Configure Sensor</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/628/0*l5PLlkKwFHPGRBv1.png" /></figure><ol><li>Plug 3 of our <strong>male-female jumper wires</strong> into the <strong>HC-SR04 ultrasonic sensor </strong>in the<strong> VCC, Echo, and GND slots. </strong>Plug one of our <strong>female-female jumper wires</strong> into the <strong>Trig</strong> slot of the sensor.</li><li>Plug the <strong>VCC</strong> <strong>wire</strong> into the <strong>positive rail</strong> of our breadboard and the <strong>GND</strong> <strong>wire</strong> into the <strong>negative rail</strong>.</li><li>Plug <strong>GPIO 5V</strong> on the Raspberry Pi to the <strong>positive rail</strong> of our breadboard and <strong>GPIO GND</strong> to the <strong>negative rail</strong>.</li><li>Plug the <strong>Trig wire</strong> into <strong>GPIO 23</strong>.</li><li>Plug the <strong>Echo wire</strong> into a <strong>blank rail</strong> on the breadboard.</li><li>Link another blank rail using a <strong>1k Ω resistor</strong>. (The reason, we need resistors is so we can lower the voltage output to ensure that our Raspberry Pi is not damaged by the sensor configuration)</li><li>Then link a blank rail using a <strong>2k Ω resistor </strong>to the negative rail of our breadboard leaving a space. If you do not have a 2k Ω resistor, you could create a series of 2 1k Ω resistors, as shown in the following picture.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0tC0Zx8A9aqT4Lp-.jpg" /></figure><p>8. In the space we have left, we will use a <strong>male-female jumper wire </strong>to link to <strong>GPIO 24</strong>.</p><p>Congrats, we have now completed the configuration of our ultrasonic sensor. If you find yourself stuck with the configuration of the sensor, check out this <a href="https://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi">tutorial</a> for a more detailed explanation. While you are building your circuit, remember that on the <a href="https://en.wikipedia.org/wiki/Breadboard">breadboard’s</a> blank rails current flows horizontally and on the breadboard’s positive and negative rails, current flows vertically. Next, we will set up PubNub and Soracom into our IoT app.</p><h3>PubNub Setup</h3><p>First, we will create our app in the <a href="http://admin.pubnub.com/">PubNub Admin Console</a> (<strong>It’s free</strong>). After creating the app in the console, you will see the publish and subscribe keys which we will use in the next step to connect PubNub and Soracom.</p><h3>Soracom Setup</h3><h3>Register SIM</h3><p>We will head on over to the <a href="https://console.soracom.io/">Soracom Admin Console</a>. Here we will click <strong>Register SIM</strong> and input the <strong>ICCID</strong> and <strong>PUK</strong> digits, which you can find on the back of your <strong>Soracom Air Sim Card</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*CFUXQvTUIO7UlM4B.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/596/0*8Ouk9l-tfEVjJVB7.png" /></figure><h3>USB Modem Configuration</h3><p>After registering our SIM card, we will remove the SIM chip (shown with the purple circle I’ve drawn around it in the image above). Then we will insert it into <strong>Huawei USB Stick Modem</strong>. Make sure that you have slid the SIM card all the way in, the right way facing up.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/314/0*7bnxjsmIJEy4HA5z.png" /></figure><p>In order to have our Raspberry Pi running on cellular data, we will simply plug the <a href="https://consumer.huawei.com/en/mobile-broadband/e3372/specs/">Huawei USB Stick Modem</a> into the USB port of the Raspberry Pi. A<strong> solid blue light</strong> (not blinking) shows that the modem is successfully picking up 3g data. If it is blinking it means it is still attempting to connect.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GJ6n7LU_jqKhwkno.jpg" /></figure><p>Once, we have a solid blue light, we must add our USB Stick Modem to the Raspberry Pi’s Network Manager. To do this first install the Network Manager onto the Raspberry Pi. In your Raspberry Pi’s terminal type the following.</p><pre>sudo apt-get update &amp;&amp; sudo apt-get install network-manager</pre><p>Then to connect our USB Stick Modem to our Soracom Account we must type the following command from our Raspberry Pi terminal. Substitute <strong>&lt;ENTER_USERNAME&gt;</strong> and <strong>&lt;ENTER_PASSWORD&gt;</strong> with your respective account credentials.</p><pre>sudo nmcli con add type gsm ifname &quot;*&quot; con-name soracom apn soracom.io user &lt;ENTER_USERNAME&gt; password &lt;ENTER_PASSWORD&gt;</pre><p>To make this configuration go into effect, we must reboot our Raspberry Pi.</p><pre>sudo reboot</pre><p>Now to ensure that your USB Modem is being recognized by your Raspberry Pi’s Network Manager type in:</p><pre>ifconfig</pre><p>You should see a ppp0 (your USB Modem) show up. Then type the following 3 terminal commands to ensure that you’ve downloaded Soracom’s ppp route metric script and that the script is run every time the USB modem is plugged in or restarted.</p><pre>sudo curl -o /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric <a href="https://soracom-files.s3.amazonaws.com/handson/90.set_ppp_route_metric">https://soracom-files.s3.amazonaws.com/handson/90.set_ppp_route_metric</a></pre><pre>sudo chmod +x /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric</pre><pre>sudo /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric ppp0 up</pre><p>Now, our USB Stick modem should be properly configured. If you’re still stuck on configuring the USB Stick Modem, make sure you read thoroughly over these <a href="https://github.com/soracom/handson/wiki/1.3.-USB-Dongle-configuration-tutorial-(SIM-pre-registered)">Soracom docs</a>.</p><h3>MQTT Setup</h3><p><strong>MQTT </strong>(Mosquitto) is the name of the protocol we will use in order to publish messages to our PubNub channel from the Raspberry Pi IoT App. In the Admin Console, we will open up the side navigation bar link titled Groups to <strong>add a new Group</strong>. We will call this new group, <strong>Beam-Soracom</strong>. Under basic settings for this new group, click on <strong>Soracom Beam</strong>. Here, we will create a <strong>MQTT Entry Point</strong>. Ensure that you have the following inputted when creating the MQTT Entry Point. You will need to specify the Destination Type as <strong>PubNub</strong>. Where you see <strong>Credentials Set</strong>, we will add our <a href="https://admin.pubnub.com/#/register">PubNub</a> credentials (<strong>Publish and Subscribe Key</strong>) to allow our Soracom device to publish messages to our PubNub channel.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/594/0*h9AYT6vWdRUBSoF6.png" /></figure><p>Then, we will select our Registered SIM card in the Admin Console and set its group to the one we just created, called <strong>Beam-Soracom</strong>. Ensure that you have clicked <strong>activate</strong> on our Registered SIM card, so that it is active and picking up data.</p><p>Now, we must install <strong>mosquitto-clients</strong> package onto our Raspberry Pi, so that we are able to use MQTT’s publish method. In the Raspberry Pi’s terminal run the following command.</p><pre>sudo apt-get update &amp;&amp; sudo apt-get install mosquitto-clients</pre><p>With mosquitto-clients installed, we may test our <strong>mosquitto_pub</strong> command, which we will use to publish a message to our PubNub channel. The format of our mosquitto_pub command will be as follows. After <strong>-t</strong> we will insert our channel name, <strong>parking_spot</strong>. And after <strong>-m</strong> we will insert a test message “test”. Pull up your Debug View on the PubNub Admin Console. Once you run the command below on the Raspberry Pi’s terminal, you should see that the message has successfully been published to our PubNub channel.</p><pre>mosquitto_pub -h beam.soracom.io -p 1883 -t parking_spot -m &quot;test&quot;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/410/0*MFMf7oJEU4RfWrCU.png" /></figure><p>Now our Soracom Air Device is able to successfully publish messages from our Raspberry Pi to our PubNub channel. With this set up, we are ready to start writing the code to publish from the ultrasonic sensor and subscribe from the Android mobile app.</p><h3>Publish — Ultrasonic Sensor Python Script</h3><p>We will write our python code in a script called <strong>sensor_publish.py</strong> (this script must be inside the Raspberry Pi!). Begin by importing some of the modules we’ll need at the top of the script. The <strong>RPI.GPIO </strong>module will allow us to obtain data from the sensors. The <strong>time </strong>module will allow us to periodically obtain readings from the sensor. <strong>Signal</strong> and <strong>sys</strong> will allow us to write our method that kills the script and stops reading the sensor data when the user uses the command ^C. <strong>Subprocess</strong> and <strong>json</strong> will allow us to parse our boolean into the appropriate JSON String format and send it to our PubNub channel.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e8459aefb19dcc2ca9f211298729b3f2/href">https://medium.com/media/e8459aefb19dcc2ca9f211298729b3f2/href</a></iframe><h3>Sensor Setup</h3><p>After importing our modules, we must ensure that our GPIO object is using Raspberry Pi Board Pin Numbers. We will do this with the following line.</p><pre>GPIO.setmode(GPIO.BCM)</pre><p>We must then assign values to our input and output pins. Our input pin is called <strong>ECHO</strong> and our output pin is called <strong>TRIG</strong>. ECHO is connected to pin 18 (<strong>GPIO 24</strong>) and TRIG is connected to pin 16 (<strong>GPIO 23</strong>), as you can verify on your Raspberry Pi setup. Also we must initialize our occupied variable which we will use to keep track of the last updated status of the parking spot. We will initialize it to False.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4c66962314e705a1ed063f0c2f7ccf26/href">https://medium.com/media/4c66962314e705a1ed063f0c2f7ccf26/href</a></iframe><p>Next, we will define our function that will set up our sensor. We’ll name this function setup_sensor(). Here we must define which pin is our input and which is our output. We will call this function later in our main function.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/68c4dcc0925442edf9a02a2721c16265/href">https://medium.com/media/68c4dcc0925442edf9a02a2721c16265/href</a></iframe><h3>Obtain Sensor Distance Reading</h3><p>We will use the function get_distance() to obtain the data of how far an object is from our sensor. This function will perform a calculation on how long the pulse signal took to go and come back from the object. Using the time it took, it will compute the distance from the sensor to the object.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/700db6a7e30903a6927c298016253df4/href">https://medium.com/media/700db6a7e30903a6927c298016253df4/href</a></iframe><h3>Publishing Parking Space Availability</h3><p>We will be publishing our parking space’s availability in the main function of our python script. This will be the function that is executed once the script is started. The main function must do the following actions in order.</p><ol><li>Set up the sensor</li><li>Perform an initial check on the availability of the parking space</li><li>Check to see if status has changed (every 5 seconds): If it has changed then publish message of new status. Store this status as the new last updated status.</li></ol><p>To set up the sensor we will call the function we defined earlier, setup_sensor(). Next it will do an initial check to see if the parking space is available or vacant. We will define method initial_check() to do this.</p><p>We will then have a loop that is executed every 5 seconds to check the new distance reading of the car. If the distance reading obtained by function get_distance() is greater than 7cm (the length of the parking space in my model), then we can infer that the parking space is vacant. The distance it is picking up is simply noise in this case. If it is less than 7cm, then we know that the parking space is being occupied by a car.</p><p>In order to minimize expenses and maximize efficiency, we will only update the status of the parking space if the sensor shows that the status has changed since the last reading. This is shown below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/183ef19d17efd6dff57da22e76361466/href">https://medium.com/media/183ef19d17efd6dff57da22e76361466/href</a></iframe><p>Our initial_check() function will assign our variable occupied to the current status of the parking space. We must publish this using the subprocess module we imported earlier. With this module, we are able to run terminal commands from a python script. Using the method Popen(), we simply pass an array of strings from the command as you would type it in a terminal. After <strong>-m</strong>, we want to pass the message encoded as a JSON String, with key “occupied” and value the variable occupied. We can do this by calling our helper method convertToJsonString() which takes a boolean and converts it into a JSON string message that we can send.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aa3e1f92a681ac74c40f008ddec42947/href">https://medium.com/media/aa3e1f92a681ac74c40f008ddec42947/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/447ecfbb4414005e5d97b89f53a6d708/href">https://medium.com/media/447ecfbb4414005e5d97b89f53a6d708/href</a></iframe><p>Finally, inside our loop that is executed every 5 seconds in our main function, we will have the following code. This will toggle the occupied boolean and then publish it to our <strong>parking_spot</strong> channel<strong>, </strong>if it is different from its last updated status.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fd4d5d33f697dbe7602955a3905de70e/href">https://medium.com/media/fd4d5d33f697dbe7602955a3905de70e/href</a></iframe><h3>Kill Script</h3><p>We must also ensure that our python script can be killed properly. We define close() as the function that’s called when a user kills the script with the command ^C. In here, we can clean up our sensor readings with the line GPIO.cleanup().</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b054c57c3bb5b8be1016a3f5d47ab3cc/href">https://medium.com/media/b054c57c3bb5b8be1016a3f5d47ab3cc/href</a></iframe><p>Congrats, we have now written a python script that publishes updates of the parking space’s status.</p><h3>Subscribe — Android Mobile App</h3><p>Now that our sensor is successfully publishing data to our PubNub channel, we must set up the mobile app so it is subscribed to the channel containing parking spot availability data.</p><p>We must first add the following gradle dependencies into our Module build.gradle file in order to utilize the <a href="https://www.pubnub.com/docs/android-java/pubnub-java-sdk">PubNub Android SDK.</a></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c4dd381ab5f1c0dbb7613b75f71525d/href">https://medium.com/media/2c4dd381ab5f1c0dbb7613b75f71525d/href</a></iframe><p>Next, we will add the following Android Manifest Permissions to allow our app to use the internet.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a557f436758b72f9c7be323b0beb6997/href">https://medium.com/media/a557f436758b72f9c7be323b0beb6997/href</a></iframe><p>For this mobile app, we will build one Activity, the <strong>MainActivity </strong>class. This Activity will contain a basic view consisting of 3 UI-Elements.</p><ul><li>TextView for stating availability</li><li>ImageView for car icon</li><li>ImageView for parking space icon</li></ul><p>We will use the TextView to state whether the parking space is available and we will have a simple animation showing the car icon inside of the parking space or outside of it. The parked car will have a Y position of 203f and the not parked car will have a Y position of 903f. In order to show whether the parking spot is vacant or occupied we will toggle its position between the two using an animation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*LZFv6rEElTja_ec6.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*J2QL4j-tRJl7rDKE.png" /></figure><p>First, we’ll declare the fields of our MainActivity class.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aa813cd05228d3de12ebf92e8bdf8d75/href">https://medium.com/media/aa813cd05228d3de12ebf92e8bdf8d75/href</a></iframe><p>Then, we will instantiate the UI elements with the method findViewById() inside our activity’s onCreate() method. We must ensure that the <strong>Main Activity layout file</strong> has the following UI elements included with the appropriate ID’s as specified below. The Id’s I’ve chosen are occupiedText, car, and parkingspot. To see my complete layout file, <a href="https://github.com/kaushikravikumar/Smart-Parking/blob/master/SmartParkingAndroid/app/src/main/res/layout/activity_main.xml">click here.</a></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7e7bb8e38cac9272ae060c7052fe87a9/href">https://medium.com/media/7e7bb8e38cac9272ae060c7052fe87a9/href</a></iframe><p>Now we must instantiate our PubNub instance, so we can make calls to the PubNub API from within our Android App. In order to do this, we will write the following code and pass the <strong>Subscribe Key</strong> and <strong>Publish Key</strong> that we generated when creating the app in the PubNub Admin Console.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/41340e276df8886fc0abe31e9fff2a96/href">https://medium.com/media/41340e276df8886fc0abe31e9fff2a96/href</a></iframe><p>Now, that we have instantiated our PubNub instance, we can subscribe to the channel our sensor is publishing parking availability data to, <strong>parking_spot</strong>. In order to do this, we will need to add a callback listener for when a message has been published to the channel. Then we must actually subscribe to the channel. This is shown below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/637c071c80a9362d47652f095515f216/href">https://medium.com/media/637c071c80a9362d47652f095515f216/href</a></iframe><p>We will then implement the logic of handling the message. We want to essentially toggle the availability of the parking spot in our mobile app UI by checking its current status of occupancy. Thus, we will check the message just published to our channel to see if the parking spot is now available or occupied. In the case that it is available, we will call our helper method carLeaveAnimation(). In the case that it is occupied, we will call our helper method carEnterAnimation(). Thus inside our message() method we have the following.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ce59a1618dcc0399fe8144ddd23cb51d/href">https://medium.com/media/ce59a1618dcc0399fe8144ddd23cb51d/href</a></iframe><p>In carEnterAnimation(), we simply set the textview to say occupied. We also call the animate() method on the car’s imageview and move its Y position into the parking space (to the Y-coordinate value stored in variable, parkedCar). In carLeaveAnimation(), we simply set the textview to say available and call the animate() method on the car’s imageview to move its Y position outside the parking space (to the Y-coordinate value, outsideCar).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1b95c3bedbcf70ffd24290c04ddd54a5/href">https://medium.com/media/1b95c3bedbcf70ffd24290c04ddd54a5/href</a></iframe><p>That’s it for our mobile app! Now it successfully receives updates from the sensor on the availability of our parking spot.</p><h3>Running App</h3><p>To start the sensor, simply enter the directory in which your script is located from the Raspberry Pi terminal. Then execute the following command.</p><pre>python sensor_publish.py</pre><p>You will see that your sensor has now been turned on and is checking the distance readings. Run the Android mobile app and you should see that the mobile app’s UI will update and display the status of the parking spot.</p><h3>Conclusion</h3><p>Congrats! We have now built a simple Smart Parking IoT app. <strong>For the full source code, </strong><a href="https://github.com/kaushikravikumar/Smart-Parking"><strong>click here</strong></a>. By integrating PubNub and Soracom, we have built an IoT app that uses LTE to send realtime messages from the Raspberry Pi. Instead of being restricted by a wifi network, our Smart Parking IoT app is extremely portable and perfect for use outdoors.</p><p>For more information on how to link your ultrasonic sensor to PubNub’s realtime data charting framework, <strong>Project EON</strong>, <a href="https://www.pubnub.com/blog-graphing-ultrasonic-sensor-realtime-data-raspberry-pi-soracom-pubnub/">check out this blog post on our website</a>.</p><p><em>Originally published at </em><a href="https://www.pubnub.com/blog/smart-parking-iot-simulation-with-realtime-space-monitoring/?utm_source=Syndication&amp;utm_medium=Medium&amp;utm_campaign=SYN-CY18-Q2-Medium-May-16"><em>www.pubnub.com</em></a><em>.</em></p><figure><a href="http://bit.ly/codeburst"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i3hPOj27LTt0ZPn5TQuhZg.png" /></a></figure><blockquote>✉️ <em>Subscribe to </em>CodeBurst’s<em> once-weekly </em><a href="http://bit.ly/codeburst-email"><strong><em>Email Blast</em></strong></a><strong><em>, </em></strong>🐦 <em>Follow </em>CodeBurst<em> on </em><a href="http://bit.ly/codeburst-twitter"><strong><em>Twitter</em></strong></a><em>, view </em>🗺️ <a href="http://bit.ly/2018-web-dev-roadmap"><strong><em>The 2018 Web Developer Roadmap</em></strong></a><em>, and </em>🕸️ <a href="http://bit.ly/learn-web-dev-codeburst"><strong><em>Learn Full Stack Web Development</em></strong></a><em>.</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=897d05d717b9" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/build-a-smart-parking-lot-with-realtime-space-monitoring-897d05d717b9">Build a Smart Parking Lot with Realtime Space Monitoring</a> was originally published in <a href="https://codeburst.io/">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Build Your Own HQ Trivia App for Android]]></title>
            <link>https://codeburst.io/how-to-build-your-own-hq-trivia-app-for-android-78ef47bfa0dd?source=rss-2d6a5a28d910------2</link>
            <guid isPermaLink="false">https://medium.com/p/78ef47bfa0dd</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Kaushik Ravikumar]]></dc:creator>
            <pubDate>Tue, 24 Jul 2018 15:50:50 GMT</pubDate>
            <atom:updated>2018-07-24T15:50:50.345Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YIbWm_rPzwZrfIe3XiHeJQ.png" /></figure><p>For many years, quiz/trivia games have been extremely popular, consistently charting at the top of app markets globally. Specifically, <a href="https://itunes.apple.com/us/app/hq-live-trivia-game-show/id1232278996?mt=8">HQ Trivia</a> was able to revolutionize this market, by making their game a viral social trend. It instantly became a norm to see friend groups and families coming together with their phones in a circle ready to tune in live to HQ Trivia. If you’re not familiar with HQ Trivia, it is a live game show app that allows players to compete with upwards of a million other players in a 10 question quiz for enticing monetary prizes.</p><p>Building such an app, however, includes huge technical challenges such as scaling up to a million users, displaying the questions to all of them synchronously, receiving all their responses in realtime, and incrementing answer counts and returning all this data back to all the players instantly. With PubNub, a realtime data stream network, developers can reduce this challenging task to a much more intuitive and simplified one.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FYvud7KK5QKY%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DYvud7KK5QKY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FYvud7KK5QKY%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/b601b1a6c2083a584249ac689f79552a/href">https://medium.com/media/b601b1a6c2083a584249ac689f79552a/href</a></iframe><h3>Tutorial Overview</h3><p><a href="https://github.com/kaushikravikumar/HQDemo"><strong>Full source code</strong></a><strong> for this tutorial is available here.</strong></p><p>In this tutorial, we will build a basic HQ demo app that has two interfaces. The first will be the <strong>Admin Interface</strong>, a web app, from which the Admin will publish the question live to all the game’s players eagerly waiting. After 10 seconds for the player to answer the question, it will then automatically publish answer results live for players to see. This interface that the admin interacts with is shown below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/0*F1rCO2rxy7yuiSF5.png" /></figure><p>The second will be the <strong>Player Interface</strong>, an Android app, from which the players will engage in the game playing experience. Here they will see a loading screen and the number of players currently playing the game, until a question is uploaded from the admin. Once uploaded, the player will see the question, the corresponding answer options, and a 10-second countdown timer. This experience is shown in the gif below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*1gmYD7SO-0p-o7Bo.gif" /></figure><h3>PubNub Setup</h3><p>In order to set up PubNub in our app, we will head over to the <a href="https://admin.pubnub.com/">PubNub Dashboard</a>, to create a new project called <strong>HQDemo</strong>. In this new project, we will navigate to the sidebar and click on Key Info. For our Key Set, we will <strong>enable Presence, PubNub Functions, and Access Manager</strong>. Then click on functions, in our sidebar. Here, we will create a module called <strong>processResults</strong> and within the module create 3 functions: <strong>getAnswers</strong>, <strong>submitAnswer</strong>, and <strong>grantAccess</strong>.</p><p>For getAnswers, we will set our event type to be <strong>On Request</strong>, since it will be called by a XMLHTTPRequest from the Admin Web App. For submitAnswer, the event type will be set to <strong>After Publish or Fire</strong>, since it will be invoked after a user publishes their answer. We will set its channel name to also be <strong>submitAnswer. </strong>Finally for grantAccess, we will set our event type to be <strong>OnRequest</strong>, since it is called from a XMLHTTPRequest from the Admin User. You will declare these settings in the panel to the left of the screen as shown.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/620/0*MCuZszvwk7o6qVKC.png" /></figure><p>Now, we have completed the initial setup of PubNub in our app.</p><h3>Admin App</h3><p>Our Admin App Development can be broken down into the following steps:</p><ol><li>Initial Setup of PubNub Javascript SDK</li><li>Build Admin App User Interface</li><li>Publish Question</li><li>Get Answer Counts</li><li>Publish Answer Results</li><li>Reset Answer Counts</li></ol><h3>Initial Setup of PubNub Javascript SDK</h3><p>In our admin app, we will simply add the following script tags into our <strong>index.html</strong> file in order to import our PubNub Javascript SDK and our Javascript file (<strong>index.js</strong>) that we will write our logic in.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/696f37d1c8eec41bb642751380bbf226/href">https://medium.com/media/696f37d1c8eec41bb642751380bbf226/href</a></iframe><p>Inside <strong>index.js</strong>, create the variables subscribe_key, publish_key, and secret_key at the top of a file. Initialize them with their appropriate values from the key set we created in the <a href="https://admin.pubnub.com/">PubNub Dashboard</a>. The admin will initialize their PubNub instance with the secret key, so that they have unlimited access to read/write to all the channels.</p><p>Now, we are finished with the initial setup of PubNub into our admin app.</p><h3>Build Admin App User Interface</h3><p>The Admin App will have a basic layout with 5 text fields: Question, Option A, Option B, Option C, and Option D. It will then have radio buttons to allow the admin to select which option is the correct answer. Finally, there will be a submit button. This simple layout can be created with the following code in <a href="https://github.com/kaushikravikumar/HQDemo/blob/master/admin_app/index.html"><strong>index.html</strong></a>.</p><p>In the action attribute of the form tag, we must specify the function that will be called once the submit button is pressed. We will do that by making the action javascript:publishQuestionAnswer(), where publishQuestionAnswer() is the function. Take note of the ID’s that you have specified for each UI element, since they will be used again in the javascript code to obtain the admin’s input.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d72c53e4fa41187d55d23274c8976702/href">https://medium.com/media/d72c53e4fa41187d55d23274c8976702/href</a></iframe><p>In order to improve the User Interface of the Admin Panel, feel free to add CSS to our HTML code. I have added the following inside of a style tag to make such improvements.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8e16da4119eec24cfdce96004f5a1987/href">https://medium.com/media/8e16da4119eec24cfdce96004f5a1987/href</a></iframe><h3>Publish Question</h3><p>Here, we will use PubNub’s Publish/Subscribe Model to have the admin publish the question to all of our game’s players. The channel <strong>question_post</strong> will hold messages with the question’s title and its answer options, encoded in JSON. The message structure for this channel is shown in the example below. <strong>We must use the same keys</strong> when publishing a message to the channel.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/225/0*DgMe61PP9L12k3pc.png" /></figure><p>Now, we’ll write our Javascript code in <strong>index.js</strong>. We need to write method publishQuestionAnswer() that we defined earlier in our HTML code as the method invoked when the user presses submit. In here, we want to initialize our PubNub instance, so that we can use PubNub in our Admin App. We will do this by adding the following code into the method. Here we are using the variables subscribe_key, publish_key, and secret_key, which we already gave values to.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3b8293c05404cad29a751efbe9c301c8/href">https://medium.com/media/3b8293c05404cad29a751efbe9c301c8/href</a></iframe><p>Next, we must use this PubNub instance we just initialized to publish the question to the <strong>question_post</strong> channel. We will use document.getElementById(&#39;ENTER UI ELEMENT ID&#39;).value, to obtain the specific values inputted into each text fields. We’ll then publish this data to our channel in the appropriate format we defined earlier.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/56db1866153a0f0f976d3f4a0a3691b8/href">https://medium.com/media/56db1866153a0f0f976d3f4a0a3691b8/href</a></iframe><h3>Get Answer Counts</h3><p>Now that our question message has been published to <strong>question_post</strong>, the admin account will allow the user 10 seconds to answer the question. We want to then consider up to 2 seconds latency between answers being sent in and results being published. Thus that adds up to a <strong>12 second delay</strong> between the question being published and the answer results being published.</p><p>In order to do this we will use the function setTimeout(), which holds two parameters. The first is the function to be executed after a certain amount of time and the second is the amount of time to wait in milliseconds.</p><pre>setTimeout(getResults, 12000);</pre><p>Now we want to write our getResults() function, which must make a request to our <strong>getAnswers</strong> PubNub Function.</p><p>Before we make this request, let’s write the code of our <strong>getAnswers</strong> Function.</p><p>We will model it as a REST API, so that it can perform different functions dependent on the route parameter which we will specify in the URL. We need 2 routes, one will be called getcount and the next one is reset. The route getcount will get the count of a specific option and the route reset will reset the count of a specific option to 0. Reset will be used after we display the answer results, since we want to reset every counter to prepare for the next question. Thus, we will write the code for reset in step 6.</p><p>With the following setup in our <strong>getAnswers</strong> Function, we declare our routes in an object called controllers. Then, we can define our functions for each route, using the following code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0d420f9a7140d7d6dd6cb913fd082921/href">https://medium.com/media/0d420f9a7140d7d6dd6cb913fd082921/href</a></iframe><p>In order to determine which route specific function to invoke we will have the following logic. Here, we check to see if there is a method and route defined and if so, we will return the corresponding function. If not, we will return a 404 error.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c3e42592f6760a8ab4947c67ee5cd0e8/href">https://medium.com/media/c3e42592f6760a8ab4947c67ee5cd0e8/href</a></iframe><p>Now, we must actually fill in the blanks of what is done in getcount. We must extract the request parameter that the admin user will pass. This will be one of <strong>“A”, “B”, “C”, or “D”</strong>. Then, we will use JavaScript’s template literals to make a string <strong>“optionA”, “optionB”, “optionC” or “optionD”</strong>. These are the keys of our Key-Value store for the counters of each option.</p><p>In the case that the request passed is one of the above accepted requests, our Function will get the count for that key and return it in jsonRes, else it will return a 400 error response.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aa3576f9e351fc27966eda28d62731eb/href">https://medium.com/media/aa3576f9e351fc27966eda28d62731eb/href</a></iframe><p>Going back to the admin app, we will make 4 separate requests to the <strong>getAnswers</strong> function we just created. Each of the requests will have a parameter with key <strong>“which”</strong> that determines which option we are looking to perform the PubNub function on. Thus, we will create a variable jsonReqOptions, that holds the parameter. We will also create a get_answers_url variable to hold the URL to this function.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c5a5a7d8c40939cd40e91ad754b0651e/href">https://medium.com/media/c5a5a7d8c40939cd40e91ad754b0651e/href</a></iframe><p>Before making each request, we must ensure that our jsonReqOptions variable’s value for which is the appropriate one for the request. Also, our URL must be the get_answers_url variable and the URL parameter of the route appended onto it.</p><p>In this case, since we are doing getcount first, it will be ?route=getcount that we append. Finally, as we defined in our PubNub function, the request must be of type POST. In order to make our 4 requests cleaner, we will add a helper method request(), which allows us to <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">“promisify</a>” our requests. Using the responses we get from each request, firstResponse, secondResponse, thirdResponse, and fourthResponse, we can extract the count of how many users answered each option.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dd80c37f82114700ba4432d3c02b84cd/href">https://medium.com/media/dd80c37f82114700ba4432d3c02b84cd/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7d3f1003b2d7ba0f75dd5bcf6a71b268/href">https://medium.com/media/7d3f1003b2d7ba0f75dd5bcf6a71b268/href</a></iframe><p>Now, that we have obtained the answer counts, we are almost ready to publish this data to the players. This takes us to our next step!</p><h3>Publish Answer Results</h3><p>The admin will publish answer results to the channel <strong>answer_post</strong> which players will be subscribed to, using PubNub’s Pub/Sub model. This channel will hold messages with counts for how many users answered each answer option and the correct answer option (either “optionA”, “optionB”, “optionC”, or “optionD”), all encoded in JSON. The message structure for both channels is shown below in the following example.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/222/0*fXcXr9N1JvNZdQaJ.png" /></figure><p>We have just obtained the answer counts through our PubNub function <strong>getAnswers</strong>, so now all we need is the correct answer, denoted by <strong>“correct”</strong> key. In order to determine the correct answer that the admin has chosen, we will simply use a series of if statements to determine which radio button was selected.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5e86f93abfc7fffadd843eee3c382548/href">https://medium.com/media/5e86f93abfc7fffadd843eee3c382548/href</a></iframe><p>Now, that we’ve determined the correct answer and stored it in our variable correctAnswer, we may publish a message to the <strong>answer_post</strong> channel. We will call a helper method publishAnswerResults() to do this, and pass the counts for each answer option: countA, countB, countC, countD. The last parameter is the correctAnswer, which we obtained the value for. The call will look like this.</p><pre>publishAnswerResults(countA, countB, countC, countD, correctAnswer);</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dffec850588fcdc9d0a2d8bd258a9b3c/href">https://medium.com/media/dffec850588fcdc9d0a2d8bd258a9b3c/href</a></iframe><h3>Reset Answer Counts</h3><p>In order to reset the answer counts, we must make requests to our <strong>getAnswers</strong> PubNub function and define our reset route function. It will act similarly to getcount and first verify that the request parameter passed is one of the accepted requests. In that case it will get the counter with the key option_string. It will then use the kvstore’s incrCounter() function and increment by the negative of the value, to set it to 0.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8aa18440644cb04c195f579b7124ce22/href">https://medium.com/media/8aa18440644cb04c195f579b7124ce22/href</a></iframe><p>After publishing the answer results, we have one final thing to do: reset the counts for each answer option. We will do this a second after answer data is published, to allow time for possible latency.</p><pre>setTimeout(resetCounters, 1000);</pre><p>In resetCounters(), we will simply do the same exact thing as we did with getcount, except the route should be reset instead, so we know the right part of our function is being called. Thus we append ?route=reset to get_answers_url. Additionally, we won’t be doing anything with the responses from these requests, since all we’re doing is resetting counters.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c246a064c4b5e99c67e60f61b84b78c7/href">https://medium.com/media/c246a064c4b5e99c67e60f61b84b78c7/href</a></iframe><p>Congrats, we have now completed the admin side of our HQ Demo App. The Admin Panel now publishes questions and answer results live to the channels. It also resets the counts for how many players answered each option. Now, we must work on the player app and solidify the interface from which the game players can submit their answers and engage in the game experience.</p><h3>Player App</h3><p>Our Player App Development can be broken down into the following steps:</p><ol><li>Initial Setup of PubNub Android SDK</li><li>Authentication with PAM</li><li>Player App UI Elements Setup</li><li>Loading Screen with Total Occupancy</li><li>Display Question with Countdown Timer</li><li>Submitting Player Answers</li><li>Display Answer Results</li></ol><h3>Initial Setup of PubNub Android SDK</h3><p>We will first complete the initial setup for the Android player app. We must add the following gradle dependencies into our Module build.gradle file in order to utilize the <a href="https://www.pubnub.com/docs/android-java/pubnub-java-sdk">PubNub SDK</a>, <a href="https://developer.android.com/training/volley/">Android Volley Library</a>, and <a href="https://github.com/PhilJay/MPAndroidChart">MPAndroidChart Library</a>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5af5dc937bf417eaa21945227fc02ef8/href">https://medium.com/media/5af5dc937bf417eaa21945227fc02ef8/href</a></iframe><p>We must then add the following line to our Project build.gradle file under allprojects and then repositories.</p><p>maven { url &#39;https://jitpack.io&#39; }</p><p>Finally, we will add the following Android Manifest Permissions to allow our app to use the internet.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bed506971dfd4c728f909e544323a938/href">https://medium.com/media/bed506971dfd4c728f909e544323a938/href</a></iframe><p>We will then make a <strong>Constants.java</strong> class that will declare all our important constants such as Subscribe Key and Publish Key. Enter the corresponding values into this file. <strong>Do not</strong> include the <strong>secret key</strong> on the player side!</p><h3>Authentication with PAM</h3><p>Our next step, will be to establish our Authentication requirements so that the game is secure from malicious users. Using <strong>PAM </strong>(PubNub Access Manager), this task becomes significantly easier. Our app must meet the following security requirements:</p><ul><li>Only the Admin can publish Questions and the Answer Results</li><li>Only the Admin can read answer submissions</li></ul><p>In the PubNub setup step, we enabled PAM into our PubNub app. With PAM, we are able to easily regulate access to all of our channels. Our rough outline for how PAM will work in our app is as follows:</p><ul><li>Our Admin will have the <strong>secret key</strong> so that they have read/write access to all channels.</li><li>Our players will sign up when they first open the app. When they have signed up, we will generate a random <strong>UUID</strong> (Universal Unique Identifier), corresponding to their account. This UUID will also be used as their <strong>Auth Key</strong>, which is a String used to allow the user certain access into specific PAM controlled channels.</li><li>Once the UUID is generated, a request will be made to our PubNub function, grantAccess, from the user’s device. The UUID will be passed as a parameter in this request. Inside the PubNub function, we will grant the following permissions to the user’s unique Auth Key (their UUID).</li><li>We will allow <strong>read only</strong> access to the question_post channel and the answer_post channel. This will allow users to read question postings and answer result postings (when available), but prevent them from maliciously writing to these channels.</li><li>Inside this function, we will also grant <strong>write only</strong> access to the submitAnswer channel. This will allow users to publish their own answers, but not read other users’ submissions to this channel.</li></ul><p>We will now write the <strong>SignupActivity</strong> from the player app to make the plan above possible. The SignupActivity will be the launcher activity, meaning that it is the activity launched first when the app is launched. To specify this, we must add the following code under the activity tag for SignupActivity in the AndroidManifest file.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5bde0398526bdef0b0f08f4719963f67/href">https://medium.com/media/5bde0398526bdef0b0f08f4719963f67/href</a></iframe><p>Our SignupActivity will have a very basic layout with a simple text field for both the username and password and then a submit button. Use either the drag and drop layout or the .xml file to create the following view for our SignupActivity.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/170/0*4baWkfdyGtT8Vtwz.png" /></figure><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/90138dc4f1154558d0453acf9bbe3ab6/href">https://medium.com/media/90138dc4f1154558d0453acf9bbe3ab6/href</a></iframe><p>For the sake of our demo, however, we will not use the username and password that the user enters but rather, we will simply randomly generate their UUID, once the user presses the submit button. This UUID will be stored locally on the device using SharedPreferences, a class offered by Android.</p><p>Thus, on the onClick method for the submit button, we must first generate a random UUID and store this locally onto the user’s device using SharedPreferences, under the key <strong>“uuid”</strong>. This is shown below in the following code. In order to create an onClick method, simply add the onClick android attribute to your button XML tag in the signupactivity’s layout.xml file. Then create a method with the exact same signature as the one defined in your xml file.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a363ed9af9179ba9abd0cd3106993fd8/href">https://medium.com/media/a363ed9af9179ba9abd0cd3106993fd8/href</a></iframe><p>Then in the same signUp() method, we will call our PubNub function grantAccess. Here, we use Android’s Volley Library to make a request to our <strong>grantAccess</strong> PubNub Function. In this request we pass a JSONObject, with “uuid” as the key and we pass the value to be what we just stored in our SharedPreferences instance. To get the value from our SharedPreferences, we can use the following line of code. pref.getString(&quot;uuid&quot;, null)</p><p>Here we are getting the string with key “uuid” and null as the default value, if there is no such value. In order to get the grantAccess URL, navigate over to the PubNub Functions code editor and click on the copy URL button. In the onResponse() callback, we will use a <a href="https://developer.android.com/guide/topics/ui/notifiers/toasts">Toast Message</a> to show the user that they have successfully been signed up and granted their user access permissions. They will then be redirected to the MainActivity where they can play the game. With the queue.add(), we can make the request to our PubNub function while passing our request parameters through a JSON Object. This is all shown in the code snippet below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8446c1508617996f559470f8977aa7d1/href">https://medium.com/media/8446c1508617996f559470f8977aa7d1/href</a></iframe><p>Now, we must write the code in our grantAccess PubNub function in the editor online. First, we must extract the UUID that has been passed as a parameter in the request.</p><pre>var uuid = JSON.parse(request.body).uuid;</pre><p>Using this value, we will add the following code to grant access to the user’s auth key (their UUID). We will make two grant() calls, as we defined earlier. One to allow read only access to the channels question_post and answer_post. And the second to allow write only access to submitAnswer. We will nest the second call inside the .then() of the first call, so that the second is executed once the first is completed successfully. In the case that there is an error we will send back a 500 Error response. In the case that the grants were completed successfully we will send back a 200 OK response. This is shown in the below code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e201ecb328f91c89fd8b7d5624cd88bf/href">https://medium.com/media/e201ecb328f91c89fd8b7d5624cd88bf/href</a></iframe><p>Finally, we will add the following code in the onCreate() method of our SignupActivity. This will check if the user has already signed up, or in other words, there is already a randomly generated UUID stored locally on the device. If so we will automatically redirect the user to the <strong>MainActivity</strong>, where the user can play the game. If not, the user will remain in the SignupActivity, so they can sign up. This is shown in the following code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/60cc87511184954b1d45902c6eb84856/href">https://medium.com/media/60cc87511184954b1d45902c6eb84856/href</a></iframe><p>Now, we have successfully completed the authorization with PAM security part of our app. Next, we will move on to the game functionality in the <strong>MainActivity</strong>.</p><h3>Player App UI Elements Setup</h3><p>In this step, we will first be writing our layout file for <strong>MainActivity</strong>, the central Activity file for the player’s game experience. The layout elements we’ll need for this activity are:</p><p><strong>Once User enters MainActivity</strong></p><ul><li>ProgressBar(Loading Spinner), TextView (label explaining what user is waiting for).</li><li>TextView (Number of Players)</li></ul><p><strong>Once Question is published by Admin</strong></p><ul><li>TextView (Question)</li><li>Button (option A), Button (optionB), Button (optionC), Button (optionD)</li><li>TextView (time left)</li></ul><p><strong>Once 10 seconds to answer the question is over</strong></p><ul><li>TextView (correct answer)</li><li>HorizontalBarChart (displays answer results)</li></ul><p>In the beginning we want only a loading spinner and the number of players to show, so the user knows that they are waiting for the question to be posted. These will be the only UI Elements in the Layout file that are visible. Everything else will be declared as gone, with the attribute android:visibility=&quot;gone&quot;. They will be programmatically set to visible in our MainActivity code, when the time is appropriate. The entire layout file is shown <a href="https://github.com/kaushikravikumar/HQDemo/blob/master/player_app/app/src/main/res/layout/activity_main.xml">here</a>.</p><p>Now, we’ll initialize the UI elements in code in the MainActivity class. We must start by declaring our class fields that we will need. The String optionChosen, will hold either “optionA”, “optionB”, “optionC”, “optionD” and is used to store the option that the user has currently chosen. After 10 seconds is over, this string will be published as a message to the channel submitAnswer. OPTION_A, OPTION_B, OPTION_C, and OPTION_D are constants used to store the string representation of each option. This is used to minimize coding errors from hardcoded strings. Finally, we will use our PubNub instance to subscribe to the <strong>question_post</strong> and <strong>answer_post</strong> channel and then publish to the <strong>submitAnswer</strong> channel.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fd2b1e30349e727f0f873f82f81f2707/href">https://medium.com/media/fd2b1e30349e727f0f873f82f81f2707/href</a></iframe><p>In onCreate(), which is called when MainActivity is created, we will first initialize all of our UI Elements by using the method findViewById() and passing the ID’s we set in the layout file as parameters.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2dfa258a4faddb6d98b79be845becbd1/href">https://medium.com/media/2dfa258a4faddb6d98b79be845becbd1/href</a></iframe><h3>Loading Screen with Total Occupancy</h3><p>Inside our method onCreate(), we will call initPubNub(). Through this method, we will be able to initialize the PubNub instance on the player’s app. We will pass the credentials that we already entered in our Constants.java class. We must set our auth key to the UUID that has been granted player specific access. After initializing the PubNub instance, we will call helper method updateUI(), which will help us display the total occupancy of players currently playing the game.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0bee8115cb09bd0e34576e2843964f67/href">https://medium.com/media/0bee8115cb09bd0e34576e2843964f67/href</a></iframe><p>At the end of initPubNub(), we are calling updateUI(), which will use the PubNub instance to call its hereNow() method, which will allow us to track how many users are currently subscribed to the <strong>question_post</strong> channel (how many users are playing the game at the moment). Inside the onResponse() callback method, we then use getTotalOccupancy(), to find this number and set the text of our TextView numPlayers to it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/764bedd8654165c2597581fc5c3fdc4e/href">https://medium.com/media/764bedd8654165c2597581fc5c3fdc4e/href</a></iframe><p>Now our player app displays a loading screen and the total number of occupants playing the game. However, it will not work properly yet, since our players are not subscribed to the channels. This takes us to our next step.</p><h3>Display Question with Countdown Timer</h3><p>Before displaying the question to the player, we must ensure that they are subscribed to the appropriate channels. Thus, we will add the following lines of code to updateUI() in order to subscribe to <strong>question_post</strong> and <strong>answer_post</strong>. We will also add a listener with a message() callback method for when a message is published to either channel. In the callback method, will use a simple if-else statement to determine which channel the message has been published to and act accordingly. We’ll also subscribe to both channels after adding the listener.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e2ed160f6ba574a7360bbbdef43d26d8/href">https://medium.com/media/e2ed160f6ba574a7360bbbdef43d26d8/href</a></iframe><p>Now to display the question to our players, we want to call our method showQuestion(), which will take a PNMessageResult object as a parameter. From this object, it will extract the question, and answer options. It will then set the question TextView to its appropriate text, the text of the buttons for each option to their appropriate text. Using method setVisibility(View.VISIBLE), it will make these UI Elements all visible. We must also make the loading spinner disappear by setting its visibility to gone, with setVisibility(View.GONE).</p><p>A 10 second timer will then be started where each second, the TextView showing time left will be updated. We will do this using the CountDownTimer class provided in Android. Instantiating this class takes two parameters: the total milliseconds of timer and the ticking interval in milliseconds. We will set the first to 10000 (10 seconds) and second to 1000(1 second), so it ticks every second for 10 seconds. Then once the timer is finished, callback method onFinish() will be invoked.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5ab75ba150aa859156d016079f770cc1/href">https://medium.com/media/5ab75ba150aa859156d016079f770cc1/href</a></iframe><p>Now, we have setup the players’ subscriptions, along with the listener that will display the question/answer options and a 10 second timer once the admin has published a question.</p><h3>Submitting Player Answers</h3><p>We will use PubNub Functions to handle our answer submissions. Each player’s device will use the PubNub fire() method to send a message, specifying which answer option they have chosen, to the channel <strong>submitAnswer</strong>. fire() is essentially the same as publish(), except it does not replicate the messages to servers across the world, but rather only to the servers in the geographical region of the app’s users. This is a good practice to minimize usage.</p><p>Using our PubNub function, <strong>submitAnswer</strong>, that has event type <strong>After Publish or Fire</strong>, we check which answer each user has chosen. Using the <a href="https://www.pubnub.com/docs/blocks/tutorials/kv-store">Key-Value Store</a> feature, we can then maintain counters for how many players answered each answer option. This is shown in the diagram below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/903/0*Jd9SHmUeZozqtjtm.png" /></figure><p>Before writing onFinish(), we will write our onClick methods for each answer option’s button. We want to set the background color of the button that is currently pressed to a shade of blue indicating that it is the currently selected answer option. We also want to set our variable optionChosen to the appropriate answer option string.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b1b07d647a33a4137679ab014befddb4/href">https://medium.com/media/b1b07d647a33a4137679ab014befddb4/href</a></iframe><p>Now in the onFinish() method of our CountDownTimer, we will call a method makeRequestToPubNubFunction() and make the answer option buttons’ visibilities gone, so that users cannot submit an answer after the 10 seconds are over. In makeRequestToPubNubFunction(), we simply send a JSON message with key <strong>“answer”</strong> and value as <strong>“optionA”, “optionB”, “optionC”, or “optionD”</strong>, as specified below. We will then use PubNub’s fire() method to send the user’s answer to the submitAnswer channel.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/289/0*SlTiJE3Z_USfoIXV.png" /></figure><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8f78fe417635462f20346aebc326ab53/href">https://medium.com/media/8f78fe417635462f20346aebc326ab53/href</a></iframe><p>Now, we want to write our <strong>After Publish or Fire</strong> PubNub function <strong>submitAnswer</strong>, which is called when the player’s device fires a message to the submitAnswer channel. We will simply obtain the user’s answer, through simple JSON parsing. Then we will increment our counters, <strong>“optionA”, “optionB”, “optionC”, and “optionD”</strong> appropriately using the kvstore’s incrCounter() function.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2b44dc6f6f31e5e090e102df69578ef4/href">https://medium.com/media/2b44dc6f6f31e5e090e102df69578ef4/href</a></iframe><p>Now, we’ve successfully made a fire() call to the <strong>submitAnswer</strong> PubNub Function from each player device and written the function so it increments the counter of the answer option each user has chosen.</p><h3>Display Answer Results</h3><p>First, we will display the correct answer, using our method showCorrectAnswer(), if a message has been published to our <strong>answer_post</strong> channel. This method takes in a parameter of a PNMessageResult object. Thus, we will make the following call in the message() callback, in the else case that the message is from channel <strong>answer_post</strong>.</p><pre>showCorrectAnswer(message);</pre><p>This method first checks whether the optionChosen is null. If so, the user did not enter an answer, it will tell the user they ran out of time. If the user’s optionChosen string matches correct, it will congratulate them. Otherwise it will apologize for their loss. Then it will state what the correct answer was. This text must then be made visible and set as the text for our TextView answer.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d0bceafcdae1357bcc3d5d0167a2ecc7/href">https://medium.com/media/d0bceafcdae1357bcc3d5d0167a2ecc7/href</a></iframe><p>Next, we want to display the statistics of how many users answered each option. We must first obtain the data from the <strong>answer_post</strong> channel message.</p><p>Thus right after our showCorrectAnswer(message) call, we will the following call.</p><pre>showAnswerResults(message)</pre><p>This method will first extract the counts for how many players answered each option. To do this, it will get the value for the keys <strong>“optionA”, “optionB”, “optionC”, and “optionD”</strong> in an <strong>answer_post</strong> channel message. It will then add the counts in reverse order, since MPAndroidChart’s <strong>BarEntry</strong> class operates as a stack. Then we will also add the options’ texts to the chart’s xAxis, so we can see the label of the option by its bar on the chart. We must then make our answerResultsChart view visible, so users can see it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b4f305bbd498609e6920ef9e7eef33fc/href">https://medium.com/media/b4f305bbd498609e6920ef9e7eef33fc/href</a></iframe><p>Now, we have shown our answer results to our players, who are subscribed to the <strong>answer_post</strong> channel. We have successfully completed all the steps of our Player App!</p><h3>Further Optimizations</h3><p>If you wish to further develop this demo, one good practice would be to change the ttl during the granting access portion of our app code. Using 0 is not a recommended security practice, since this means that access is granted permanently. A better practice would be to have the access token expire in a set amount of time and if a user is not able to obtain access, since their token has expired, to refresh their token. For sake of simplicity in our demo we used 0.</p><p>Additionally, you could work on expanding the demo so that it allows users to engage in a 10 question quiz experience, instead of just one.</p><h3>Conclusion</h3><p>Congrats! We have now successfully built our functional HQ Demo App on the admin side and the player side. If you are testing your app, ensure that the module for your PubNub Functions is running. Click here for the <a href="https://github.com/kaushikravikumar/HQDemo">full source code</a>.</p><p><em>Originally published at </em><a href="https://www.pubnub.com/blog/build-your-own-hq-trivia-app-for-android/?utm_source=Syndication&amp;utm_medium=Medium&amp;utm_campaign=SYN-CY18-Q2-Medium-May-16"><em>www.pubnub.com</em></a><em>.</em></p><figure><a href="http://bit.ly/codeburst"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i3hPOj27LTt0ZPn5TQuhZg.png" /></a></figure><blockquote>✉️ <em>Subscribe to </em>CodeBurst’s<em> once-weekly </em><a href="http://bit.ly/codeburst-email"><strong><em>Email Blast</em></strong></a><strong><em>, </em></strong>🐦 <em>Follow </em>CodeBurst<em> on </em><a href="http://bit.ly/codeburst-twitter"><strong><em>Twitter</em></strong></a><em>, view </em>🗺️ <a href="http://bit.ly/2018-web-dev-roadmap"><strong><em>The 2018 Web Developer Roadmap</em></strong></a><em>, and </em>🕸️ <a href="http://bit.ly/learn-web-dev-codeburst"><strong><em>Learn Full Stack Web Development</em></strong></a><em>.</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=78ef47bfa0dd" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/how-to-build-your-own-hq-trivia-app-for-android-78ef47bfa0dd">How to Build Your Own HQ Trivia App for Android</a> was originally published in <a href="https://codeburst.io/">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build Your Own Uber/Lyft App with Geolocation Tracking for Android Devices]]></title>
            <link>https://codeburst.io/build-your-own-uber-lyft-app-with-geolocation-tracking-for-android-devices-641ad5635f24?source=rss-2d6a5a28d910------2</link>
            <guid isPermaLink="false">https://medium.com/p/641ad5635f24</guid>
            <category><![CDATA[uber]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Kaushik Ravikumar]]></dc:creator>
            <pubDate>Thu, 05 Jul 2018 13:34:17 GMT</pubDate>
            <atom:updated>2018-07-05T13:34:17.277Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*yOLra8pnVs-ZiAWd.png" /></figure><p>Tracking the realtime location of another device is the basis of many popular mobile, location-focused apps, specifically in the ride sharing industry for leaders like Lyft and Uber. Building this functionality is challenging and can be tedious, but we’ll simplify it with an easy publish/subscribe model between the drivers and passengers, powered by PubNub.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FkQ6EzqoQu5A%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DkQ6EzqoQu5A&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FkQ6EzqoQu5A%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/1387c1139dfde8b371a1b04cc3b1e5b0/href">https://medium.com/media/1387c1139dfde8b371a1b04cc3b1e5b0/href</a></iframe><h3>Tutorial Overview</h3><p><a href="https://github.com/kaushikravikumar/RealtimeTaxiAndroidDemo"><strong>Full source code</strong></a><strong> for this tutorial is available here.</strong></p><p>In this tutorial, we’ll show you how to implement this common use case in an Android application. The sample app we will build first asks the user if they are the driver or the passenger. If a user is a driver, their current location will be published to a channel, updated every 5 seconds (in this sample), or however many times your app requires.</p><p>If a user is a passenger, they will subscribe to the same channel to receive updates on the current location of their driver. This publish/subscribe model is displayed in the visual below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/825/0*qfPNnuAhSzdVQjGR.png" /></figure><h3>Google Maps API and PubNub Setup</h3><p>We first need to write our Gradle dependencies to use the <a href="https://www.pubnub.com/docs/android-java/pubnub-java-sdk">PubNub Android SDK</a> and Google Play Services for the map functionality. We also will implement com.fasterxml.jacksonlibraries, in order to complete some basic JSON parsing of PubNub messages.</p><p>In the build.gradle file for the app module under dependencies, input the codeblock of command below to ensure that we have what we need. Be sure that Google Play Services is installed from the Android SDK Manager on the tools portion of the menu, so we may implement the necessary libraries.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f374715606c761525e3508b301bcb658/href">https://medium.com/media/f374715606c761525e3508b301bcb658/href</a></iframe><p>Now that we have the necessary dependencies, let’s make sure that we have the necessary permissions in our Android Manifest file. With the permission to access network state and establish internet connection, the user can now make the connection to the PubNub API. We will use the location permission later, when we request for the driver’s location.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6576032ebc36b88d58fce077ecb65864/href">https://medium.com/media/6576032ebc36b88d58fce077ecb65864/href</a></iframe><p>In order to set up PubNub in your Android app, you will need to create a PubNub app in the <a href="https://dashboard.pubnub.com/signup/">PubNub Admin Dashboard</a><strong> (it’s free)</strong>. Upon creating the app, you will be assigned a subscribe key and publish key. In the following part, we will use these credentials in our MainActivity class to establish the connection.</p><p>Now, we must set up our Google Maps API key, so that we can use it in our application. In order to do this head over to <a href="https://console.cloud.google.com/apis/">Google’s Developer API console</a>. Here, we will create a new project and then generate an API key. Now that we have our API key, we can write the following code to set up our Google Maps API and configure it with our generated API key.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a61abf6ddd460d9d88145ceb1f113055/href">https://medium.com/media/a61abf6ddd460d9d88145ceb1f113055/href</a></iframe><h3>Main Activity</h3><p>The MainActivity class will have three important functionalities:</p><ol><li>Directing our user to their respective interface, depending on whether they are a driver or passenger.</li><li>Establishing a connection to PubNub for all users of the app</li><li>Checking location access permissions</li></ol><p>First, we want to separate our users into our drivers and passengers and provide them with their respective user interface. We will do this by creating a DriverActivity class and a PassengerActivity class, which we will discuss in detail in parts 2 and parts 3.</p><p>In MainActivity we will make a simple button-based interface which prompts the user to let the app know their role as a driver or passenger. Using Android’s Intent class, we can transition from the MainActivity class into the DriverActivity class or from the MainActivity class into the PassengerActivity class, depending on which button is pressed.</p><p>The interface will appear as:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*shRLLuGX4fCXOCcL.png" /></figure><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/935ac42dc0754394d5987aeca149ca23/href">https://medium.com/media/935ac42dc0754394d5987aeca149ca23/href</a></iframe><p>Next, using our PubNub credentials from the <a href="https://dashboard.pubnub.com/signup">Admin Dashboard</a>, we will create a PNConfiguration instance, which allows us to create a PubNub instance connecting our app and PubNub. This PubNub instance in the MainActivity class will be public and static so it is accessible from both the DriverActivity and the PassengerActivity. We will call the below method in our onCreate() method of the Main Activity, so that PubNub is properly initialized for all of our app’s users. This is all shown in the following code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2f894cd80b592b29673a3efe692a17e5/href">https://medium.com/media/2f894cd80b592b29673a3efe692a17e5/href</a></iframe><p>Finally, we must ensure that our user has enabled their location services for our app. This can be done with the following code. If our user does not grant permission to access fine location or coarse location, our app will request this permission.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9ca43b9c1178169dc4d4edb05c94a43f/href">https://medium.com/media/9ca43b9c1178169dc4d4edb05c94a43f/href</a></iframe><h3>Driver Activity</h3><p>The sole function of the DriverActivity class is to obtain the driver’s location and publish this data at a certain time interval to the PubNub channel.</p><p>First, let’s look at how to make a location request. We will use the FusedLocationProviderClient class from the Google Location API in order to request location updates from the driver. We will also use the LocationRequest class in order to specify important parameters of our location request, such as the priority, smallest displacement, and time interval.</p><p>For our sample, we will use a time interval of 5000 milliseconds, so that the location is updated every 5 seconds and a smallest displacement of 10 meters to ensure that the location is only being updated if there is a change of at least 10 meters. Finally, we want the location request to use the mobile device’s GPS, for high accuracy location tracking. This high accuracy is important in enabling the passenger to see a detailed display of their driver (shown as car icon) moving across the map to the destination.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/27b6f7ff1a7b9961296a93a102c699dc/href">https://medium.com/media/27b6f7ff1a7b9961296a93a102c699dc/href</a></iframe><p>Now that we have defined our location request parameters, we will pass this LocationRequest object into our FusedLocationProviderClient object’s request for location updates.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/51a86871b9363f0fb7cfcb1953020794/href">https://medium.com/media/51a86871b9363f0fb7cfcb1953020794/href</a></iframe><p>Using the location we get from our request, we must convert it into a LinkedHashMap so that it fits the desired format of a location message in the PubNub channel. The LinkedHashMap will have two keys “lat” and “lng” and the corresponding values for these keys, both as Strings.</p><p>Now with our message in the format of a LinkedHashMap, we are able to publish it to the PubNub channel. This is shown in the following code. Notice that we must use MainActivity.pubnubto obtain the PubNub instance that we earlier in the onCreate method of the Main Activity. We do not want to establish multiple connections by initializing PubNub again. Instead, we just use the one we already created in the MainActivity class.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d28a53b6b987c0a0d1c2e124fc67cbd1/href">https://medium.com/media/d28a53b6b987c0a0d1c2e124fc67cbd1/href</a></iframe><h3>Passenger Activity</h3><p>In our PassengerActivity class, we want to create a MapView to show the location of the driver being updated. In order to add the MapView UI element to our Passenger Activity we must include the following code in our corresponding layout.xml file for this activity.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f5388b2f91082eab161a063d6739b180/href">https://medium.com/media/f5388b2f91082eab161a063d6739b180/href</a></iframe><p>Then, instantiate the MapFragment object using the ID we define in the layout file. In our sample code, we used “map” as the ID. We will also set up our onMapReady method by having PassengerActivity implement onMapReadyCallback. Then we will pass PassengerActivity.this as a parameter into our MapFragment object’s getMapAsync method. This allows us to setup our onMapReady callback method for our MapFragment object.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/82c0cbb4b06c429776adb387909ed2f4/href">https://medium.com/media/82c0cbb4b06c429776adb387909ed2f4/href</a></iframe><p>Now, we want to subscribe to the driver location channel so we receive updates on the driver’s current location. This must be done once the map is ready, so we will include this code in our callback method. Additionally, we must add a listener with a SubscribeCallback, so our app knows how to act upon receiving a message.</p><p>As specified in the PubNub Android docs, we must carry this out in the order where we first add the listener and then subscribe the PubNub instance to the channel. Once we receive a message, we want to convert the JSON output into a LinkedHashMap, which we can easily parse to obtain the longitude and latitude. In order to convert the JSON output into a LinkedHashMap, we must import the JsonUtil class, which contains the method fromJson() that allows us to do this. This class is shown in the full source code. Once we have the driver’s location, we must update the UI by calling our method updateUI() and passing the new location as the parameter.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9ed3d92a7ce3cb1d1565d14618689e37/href">https://medium.com/media/9ed3d92a7ce3cb1d1565d14618689e37/href</a></iframe><p>Our updateUI method has two cases it will encounter.</p><p>The first case is that there does not already exist a marker for the driver and in this case, we will instantiate the Marker object and set its position to the first tracked location of the driver. We must also zoom in on the map in order to maintain a street view of the driver’s car.</p><p>The second case is that there already exists a marker for the driver and in this case, we do not have to re-instantiate the Marker object. Rather, we simply move the location of the marker across the map to its new location. We do this by calling the method animateCar(). We must also ensure that we move the camera of the MapView to the new location, if it is out of the bounds of the camera. Thus, the driver’s marker will always be in the bounds of the MapView. This is shown in the following code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cef0943159e417af33e3c54532637dda/href">https://medium.com/media/cef0943159e417af33e3c54532637dda/href</a></iframe><p>In our animateCar method, we must move our car marker to its new location, in a smooth line shaped manner. The animation must last 5 seconds, because our app receives updates on the driver’s location every 5 seconds. This way every time the animation is over, it will have the new location update to start the next animation. That way, we minimize the lag in the animation of the car.</p><p>We will also utilize the LatLngInterpolator interface below. This allows us to implement the method interpolate(), which returns a new LatLng coordinate that’s a fraction of the way to the final newLocation. This fraction is determined with the method getAnimatedFraction(). We will call this method from a ValueAnimator instance, which we get obtain from the onAnimationUpdate() callback method. This fraction will increase at a steady rate so that by 5 seconds, it is 1 (all the way to the new location). This animating of the car is shown in the following code snippets.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ea4c411e30c6e76fb966dd9d6030c96e/href">https://medium.com/media/ea4c411e30c6e76fb966dd9d6030c96e/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ceebe92456ca72aad4ecfdf41838161d/href">https://medium.com/media/ceebe92456ca72aad4ecfdf41838161d/href</a></iframe><h3>Further Improvements</h3><p>If you wish to further develop this sample, one feature to add would be having the marker turn as the car turns. This feature would require us to add one key-value pair to our message structure. We would need to include the key “bearing” and the value. Then we would simply rotate the marker depending on the driver’s bearing.</p><h3>Congrats!</h3><p>Now that we have created the MainActivity, DriverActivity, and PassengerActivity, we have successfully built the publish/subscribe model necessary to create a simple Lyft/Uber Android demo. Click here for the <a href="https://github.com/kaushikravikumar/RealtimeTaxiAndroidDemo">full source code</a>.</p><figure><a href="http://bit.ly/codeburst"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i3hPOj27LTt0ZPn5TQuhZg.png" /></a></figure><blockquote>✉️ <em>Subscribe to </em>CodeBurst’s<em> once-weekly </em><a href="http://bit.ly/codeburst-email"><strong><em>Email Blast</em></strong></a><strong><em>, </em></strong>🐦 <em>Follow </em>CodeBurst<em> on </em><a href="http://bit.ly/codeburst-twitter"><strong><em>Twitter</em></strong></a><em>, view </em>🗺️ <a href="http://bit.ly/2018-web-dev-roadmap"><strong><em>The 2018 Web Developer Roadmap</em></strong></a><em>, and </em>🕸️ <a href="http://bit.ly/learn-web-dev-codeburst"><strong><em>Learn Full Stack Web Development</em></strong></a><em>.</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=641ad5635f24" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/build-your-own-uber-lyft-app-with-geolocation-tracking-for-android-devices-641ad5635f24">Build Your Own Uber/Lyft App with Geolocation Tracking for Android Devices</a> was originally published in <a href="https://codeburst.io/">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build a Google Home App with PubNub Functions]]></title>
            <link>https://medium.com/hackernoon/build-a-google-home-app-with-pubnub-functions-10188479699d?source=rss-2d6a5a28d910------2</link>
            <guid isPermaLink="false">https://medium.com/p/10188479699d</guid>
            <category><![CDATA[pubnub-function]]></category>
            <category><![CDATA[google-home]]></category>
            <category><![CDATA[google-home-pubnub]]></category>
            <category><![CDATA[aws-lambda]]></category>
            <category><![CDATA[google-home-app]]></category>
            <dc:creator><![CDATA[Kaushik Ravikumar]]></dc:creator>
            <pubDate>Sat, 30 Jun 2018 23:16:35 GMT</pubDate>
            <atom:updated>2018-06-30T23:16:35.228Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*QZp6dfcYICJ_h02i.png" /></figure><p>Artificial intelligence powered voice apps have become a key player in the recent smart home movement. With Google’s Dialogflow, developers can quickly create conversational apps that facilitate tasks for users. What Dialogflow does not provide, however, is an easily implementable server that allows developers to perform certain functions with user data.</p><p>In this demo, we will utilize PubNub Functions alongside Dialogflow in order to create a sample app that plays the right music for a user, based on their current mood. Dialogflow does not provide any means of analyzing the sentiment of a user’s speech input, but through PubNub Functions and our <a href="https://www.pubnub.com/docs/blocks-catalog/amazon-comprehend">Amazon Comprehend BLOCK</a>, developers can easily analyze the sentiment of a user’s speech input and carry out a certain action depending on that result.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FTLmrhj5Z70A%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DTLmrhj5Z70A&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FTLmrhj5Z70A%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/956383de4a4149236780cd926d198bcb/href">https://medium.com/media/956383de4a4149236780cd926d198bcb/href</a></iframe><h3>Tutorial Overview</h3><p>Once our demo app MoodTunes is activated, it will ask the user “Hey, what’s up?” The user will reply with a sentence or two describing their overall mood. The app will then obtain the user’s speech input and analyze it to determine the mood of the user using the Comprehend BLOCK.</p><p>Finally, it will categorize the mood as either really positive, slightly positive, slightly negative, or really negative. The following diagram displays the structure of the app and a test response.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/904/0*bG0JRGEclqbqACkp.png" /></figure><h3>Initial Setup</h3><p>Our first step will be to create a new <strong>agent</strong> on the <a href="https://console.dialogflow.com/">Dialogflow Console</a>. The agent is the term for your app, since it helps a user carry out a certain action.</p><p>Let’s name our agent <strong>Mood Tunes</strong>.</p><p>This new agent will have two intents by default: <strong>Default Fallback Intent</strong> and <strong>Default Welcome Intent</strong>. Think of an intent as a specific part of the whole conversation that is triggered when the user says a certain phrase. The Default Welcome Intent is triggered when the user invokes your app by saying “Talk to (Agent Name)” and the Default Fallback Intent is triggered when the user says something that the app does not understand or is not trained to respond to.</p><p>For our demo, we will only be using two intents: Default Welcome Intent and another intent we will create called <strong>Get_Emotion. </strong>In our Default Welcome Intent, we will add a standard text response “Hey what’s up?”, which will prompt the user to describe how they’re feeling in a sentence or two.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/771/0*9mmTt2jEFjHjGe5g.png" /></figure><p>This new speech will trigger our new intent Get_Emotion. In order to create a new intent, click on the plus button on the side navigation bar of your console. We want our user to be able to say any sort of sentence with no specific pattern to trigger our Get_Emotion intent. Thus, we must specify this in our Training Phrases section of the intent. We will do this by clicking on the <strong>” icon</strong> to change it to an <strong>@ icon </strong>and then typing <strong>@sys.any:any.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/820/0*W1nfCmitZ5tVz4Wb.png" /></figure><p>Finally, we must scroll down to the fulfillment section and click on the toggle button to <strong>enable webhook calls</strong> for the Get_Emotion intent. The webhook call is what will allow us to establish the connection between our Dialogflow app and our PubNub functions server, so that our function can be activated after the user describes how they’re feeling.</p><p>Now we will head over to the <a href="https://admin.pubnub.com/">PubNub Admin Dashboard</a>, to create a new project called MoodTunes. In this new project, we will navigate to the side bar and click on functions. Here, we will create a module called <strong>Music Player</strong> and within the module create an <strong>onRequest </strong>function, which we call <strong>playmusic</strong>. Click on the copy URL button to copy the path of the function. We will then paste this URL in our Dialogflow app’s fulfillment tab, under Webhook where it says URL.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/389/0*WfrQAUnp54tGjjse.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*78osgFSzd2Ijhqbr.png" /></figure><p>Now we have successfully set up our Dialogflow App and its connection through webhook to our PubNub Function. In the remainder of this tutorial, we will write our app’s JavaScript code in the PubNub functions editor.</p><h3>PubNub Function</h3><p>We can break down our PubNub function into three parts.</p><ol><li>Receiving the webhook request from Dialogflow</li><li>Processing data from request</li><li>Forming response to send to Dialogflow</li></ol><p>In our PubNub function, we have two parameters, request and response. The request from Dialogflow will be in the form of JSON and it contains the user’s speech input which we must extract. The structure of the JSON request is in the following form according to Google’s documentation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/856/0*wmzVEdc5V6IsHeNR.png" /></figure><p>To obtain the queryText value from this request, we must first parse its body so that it is in proper JSON format. We will do this using JSON.parse(). Now that it is in proper JSON format, we may extract the queryResult value and then the queryText value. This is shown in the following line.</p><pre>var text = JSON.parse(request.body).queryResult.queryText;</pre><p>Now, that we have a reference to the user’s speech input, the next step is to process this data. We will do this by passing it into our Amazon Comprehend BLOCK. To add the block into your project, click the plus button and you will be prompted to add a function to your module. We will name our function <strong>Amazon Comprehend</strong> and set the event type to <strong>onRequest</strong>. Then set the URL path to <strong>amazoncomprehend</strong>. The default Amazon Comprehend BLOCK code is for a Before Publish handler. However, we want our block to be a OnRequest handler, so copy and paste this <a href="https://github.com/kaushikravikumar/MoodTunes/blob/master/amazoncomprehend-function.js">code</a> into your editor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/631/0*iiA_lqlvu8QzOMbu.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1012/0*0WpRgU0kK6yVI4a-.png" /></figure><p>Next, we will make an AWS account, if you don’t have one already. We need to obtain the following credentials: Comprehend <strong>access key</strong> and <strong>secret key </strong>(<a href="https://docs.aws.amazon.com/comprehend/latest/dg/comprehend-api-permissions-ref.html">find out how here</a>). Once we have these credentials, we will enter them into PubNub’s <strong>My Secrets</strong> Key Value Store. You can find this on the left side of your module view in a large button labeled “My Secrets.” The key for the access key must be <strong>AWS_access_key</strong> and the key for the secret key must be <strong>AWS_secret_key</strong>. Then enter the corresponding values and click <strong>Save</strong>, so you know your credentials are correct in your vault reference in the function code.</p><p>With our Amazon Comprehend Function set up, we must now make a HTTP request to it using the <strong>xhr module</strong>, provided by PubNub functions. With the xhr.fetch method, we can make a HTTP request to a specified URL, while also passing an object that defines the type, body parameters, and header parameters. Obtain the URL from the copy URL button on the Amazon Comprehend function and store it in a variable, amazon_url. Our amazon_request_options, in the code below, defines the necessary parameters for the HTTP request.</p><p>We pass the text we want to analyze in the key, speechInput. We must also specify inside a field named comprehend, the keys language and location. The language is simply the language that the text is in (en for English) and the location is the name of key in the request which holds the text to analyze (in our case speechInput). Also we must specify the type of the request which is POST, as the value of the method key. Passing both the amazon_url and amazon_request_options objects into the xhr.fetch method, we use a promise to obtain the JSON response to the HTTP request, once it is ready.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/719b27d13c014eb57bc89de75787c426/href">https://medium.com/media/719b27d13c014eb57bc89de75787c426/href</a></iframe><p>Now that we have our response stored in the variable sentiment_response, we must now parse it so we can obtain the measure for how positive the user’s speech input was. The JSON response’s body should contain a field sentiment, which will contain key SentimentScore, which will contain a key Positive. You can see this if you use the console to log the response’s body. Thus, in order to obtain this numeric value from 0 to 1 that shows how positive the user’s speech input was, we must use the following line of code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/24baa56f0867f9e63d1566bf3408a5f9/href">https://medium.com/media/24baa56f0867f9e63d1566bf3408a5f9/href</a></iframe><p>Next, we will use this value and if-else logic to choose which song to play for the user. As explained earlier, if positive_measure is greater than 0.75, we will play our really positive song. In the case that it is between 0.5 and 0.75, we will play our slightly positive song. If it is between 0.25 and 0.5, we will play our slightly negative song and it it is less than 0.25, we play our really negative song. The respective songs are all hosted in my GitHub project under the URLs shown in the code snippet below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2eb0c745589fd81f4f5a2114d606c7c4/href">https://medium.com/media/2eb0c745589fd81f4f5a2114d606c7c4/href</a></iframe><p>With our analysis of the user’s speech input done, we are ready for the final step of our app, which is forming the response to send to Dialogflow. In this response, we need to pass the URL that will play the right song on the Google Home device. As specified in Google’s Documentation, this response must resemble the following format.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/501/0*yL6ZMIsxPj4z2Daw.png" /></figure><p>In our case, the key expectUserResponse should have value false, since the playing of music is the end of a user’s conversation with our app. Additionally, we will have our simpleResponse, let the user know that their music is being played. We will also include a mediaResponse field, which will contain a mediaObjects array, with keys name, description, and contentUrl.</p><p>The keys name and description, will be for the music player view that shows up when a user uses our app on a google assistant device with a display. The contentUrl will be the URL of our song to play (we will set this to our variable song_url which we set before). Inside richResponse, we must include a suggestions array, according to Google’s documentation. Since it is not pertinent to our app, however, we will make it an empty array. This JSON response must be a string, since response.send only accepts strings, so we will use the method JSON.stringify. This is all shown in the following code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/770839bd728db540630f2da3ffcf80f1/href">https://medium.com/media/770839bd728db540630f2da3ffcf80f1/href</a></iframe><h3>Congrats!</h3><p>Now that we’ve obtained the user’s speech input through the Dialogflow webhook request, analyzed it for sentiment using PubNub function’s Amazon Comprehend BLOCK, and formed a response playing a song matching the user’s mood, we have completed MoodTunes.</p><p>If you are testing your app, ensure that you have started your functions module, so the server side code is running live and deployed. In order to test your app on a Google Home device, ensure that you have completed these <a href="https://developers.google.com/actions/smarthome/testing-deploying">steps</a>. Click here for the <a href="https://github.com/kaushikravikumar/MoodTunes">full source code</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=10188479699d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/build-a-google-home-app-with-pubnub-functions-10188479699d">Build a Google Home App with PubNub Functions</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>