In an earlier blog post we had explained how a public XMPP chat server can be used to transmit messages between two computers. In that post we had shown how we can build a chatbot listener in Python that waits for messages and when messages arrive, there was a some simple logic that allowed it to either ring an alarm ( sound a bell tone) or insert the data into an SQLite database.
This chatbot -- ChatIOT -- was tested by sending messages from a Xabber, a free XMPP chat client using two userids registered on a free, public XMPP server available at adastra.re. This post shows how to build a basic XMPP client for Android, from scratch, using Java and the Smack XMPP library from the Openfire opensource project.
Non-trivial Android app development is not for the faint hearted. If one has never developed an Android application in the past, it would be good idea to look through this post Building an Android App -- Getting Started.
Start Eclipse and create a new Android project with the following parameters :
Use the default options on the next couple of screens and then choose the template for Blank Activity
Click through the rest of screens until the project is created and is visible on the Package Explorer panel on the left of the Eclipse Screen.
Two files would have been opened in the Editor panel, but if not, open the file ChatIOT > res > layout > activity_main.xml Replace the contents of the file with the following code :
activity_main.xml
This will show many errors because many of the required resources, artifacts are still missing.
Next, open the file ChatIOT > res > values > strings.xml and replace the contents with this code
strings.xml
Create a new folder in ChatIOT > res and name it drawable. Inside this folder, create new, empty file called ChatIOT > res > drawable > pmbutton.xml. Replace the default contents of the file with the following code :
pmbutton.xml
Finally download this 9.png image file
This chatbot -- ChatIOT -- was tested by sending messages from a Xabber, a free XMPP chat client using two userids registered on a free, public XMPP server available at adastra.re. This post shows how to build a basic XMPP client for Android, from scratch, using Java and the Smack XMPP library from the Openfire opensource project.
Non-trivial Android app development is not for the faint hearted. If one has never developed an Android application in the past, it would be good idea to look through this post Building an Android App -- Getting Started.
Start Eclipse and create a new Android project with the following parameters :
Use the default options on the next couple of screens and then choose the template for Blank Activity
Click through the rest of screens until the project is created and is visible on the Package Explorer panel on the left of the Eclipse Screen.
Two files would have been opened in the Editor panel, but if not, open the file ChatIOT > res > layout > activity_main.xml Replace the contents of the file with the following code :
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/Heading1text"
android:layout_alignParentTop="true"
android:textColor="#104E8B"
android:layout_centerHorizontal="true"
android:textSize="30dp" />
<ImageButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_marginTop="15dp"
android:layout_marginBottom="30dp"
android:layout_centerHorizontal="true"
android:src="@drawable/iotlogo_v1" />
<Button
android:id="@+id/button1"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_below="@+id/imageButton"
android:onClick="startCon"
android:layout_marginBottom="10dp"
android:layout_centerHorizontal="true"
android:background="@drawable/pmbutton"
android:text="@string/button1text" />
<Button
android:id="@+id/button2"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_below="@+id/button1"
android:layout_marginBottom="10dp"
android:layout_centerHorizontal="true"
android:onClick="pushData"
android:background="@drawable/pmbutton"
android:text="@string/button2text" />
<Button
android:id="@+id/button3"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_below="@+id/button2"
android:layout_marginBottom="10dp"
android:layout_centerHorizontal="true"
android:onClick="stopCon"
android:background="@drawable/pmbutton"
android:text="@string/button3text" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/Heading2text"
android:textColor="#104E8B"
android:textSize="20dp"
android:layout_below="@+id/button3"
android:layout_centerHorizontal="true"
android:layout_marginBottom="40dp" />
</RelativeLayout>
This will show many errors because many of the required resources, artifacts are still missing.
Next, open the file ChatIOT > res > values > strings.xml and replace the contents with this code
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ChatIOT</string>
<string name="action_settings">Settings</string>
<string name="button1text">Connect</string>
<string name="button2text">Send</string>
<string name="button3text">Disconnect</string>
<string name="Heading2text">xmpp chat for IOT</string>
<string name="Heading1text">chatIOT</string>
</resources>
Create a new folder in ChatIOT > res and name it drawable. Inside this folder, create new, empty file called ChatIOT > res > drawable > pmbutton.xml. Replace the default contents of the file with the following code :
pmbutton.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" >
<shape android:shape="rectangle" >
<corners android:radius="3dip" />
<stroke android:width="1dip" android:color="#5e7974" />
<gradient android:angle="-90" android:startColor="#345953" android:endColor="#689a92" />
</shape>
</item>
<item android:state_focused="true">
<shape android:shape="rectangle" >
<corners android:radius="3dip" />
<stroke android:width="1dip" android:color="#5e7974" />
<solid android:color="#58857e"/>
</shape>
</item>
<item >
<shape android:shape="rectangle" >
<corners android:radius="3dip" />
<stroke android:width="1dip" android:color="#5e7974" />
<gradient android:angle="-90" android:startColor="#8dbab3" android:endColor="#58857e" />
</shape>
</item>
</selector>
Finally download this 9.png image file
and store it in the folder ChatIOT > res > drawable-hdpi with the name iotlogo_v1.9.png Make sure that all files have been saved, then right click on project ChatIOT and press Refresh. After this the layout should be free of errors, though there will be some warnings. The screen will now look like this :
Open the MainActivity.java file located in ChatIOT > src > com.yantrajaal.chatiot > MainActivity.java and replace the contents of file with the following code :
MainActivity.java
package com.yantrajaal.chatiot;
import java.io.IOException;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
// Smack libraries
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.chat.ChatManager;
import org.jivesoftware.smack.chat.Chat;
import org.jivesoftware.smack.chat.ChatMessageListener;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import java.util.Random; // required for Random Number Generation
public class MainActivity extends Activity {
String msg = "PM1139 : ";
XMPPTCPConnectionConfiguration configChatIOT = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword("uid2", "password2")
.setServiceName("adastra.re")
.setHost("adastra.re")
.setPort(5222)
.setResource("chatIOT")
.build();
AbstractXMPPConnection conxChatIOT = new XMPPTCPConnection(configChatIOT);
/** Called when the activity is first created. **/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SmackConfiguration.setDefaultPacketReplyTimeout(10000);
Log.d(msg, "The onCreate() event");
}
private class pmConnect extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void...dummy) {
try {
conxChatIOT.connect();
conxChatIOT.login();
} catch (SmackException | IOException | XMPPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/*
// this piece of code is kept just for the sake of completeness of Async Tasks
protected void onProgressUpdate(Void...progress) {
// setProgressPercent(progress[0]);
}
protected void onPostExecute(Void...result) {
//showDialog("Downloaded bytes");
}
*/
}
private class pmSend extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void...dummy) {
Random randomGenerator = new Random();
int pseudoSensorData;
// Assume we've created an XMPPConnection name "conxChatIOT"._
ChatManager chatmanager = ChatManager.getInstanceFor(conxChatIOT);
Chat ChatIOT = chatmanager.createChat("uid3@adastra.re", new ChatMessageListener() {
public void processMessage(Chat chat, Message message) {
System.out.println("Received message: " + message);
}
});
for(int i=0 ; i < 4 ; i++)
{
try {
if (i==0){
ChatIOT.sendMessage("Sound 2");
} else {
// this data needs to be generated from some Android physical sensor
// instead of using a random number generator
pseudoSensorData = randomGenerator.nextInt(100);
String payLoad = "Push " + String.valueOf(pseudoSensorData);
ChatIOT.sendMessage(payLoad);
}
} catch (NotConnectedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(5000); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
return null;
}
}
//Method to start the Connection
public void startCon(View view) {
Toast.makeText(this, "Connecting", Toast.LENGTH_LONG).show();
new pmConnect ().execute();
}
//Method to start the Connection
public void pushData(View view) {
Toast.makeText(this, "Push Data", Toast.LENGTH_LONG).show();
new pmSend ().execute();
}
//Method to Quit
public void stopCon(View View) {
Toast.makeText(this, "Disconnection", Toast.LENGTH_LONG).show();
conxChatIOT.disconnect();
}
}
This will immediately, throw lots and lots of errors because the Smack/XMPP libraries have not been loaded as yet. To get the libraries perform the following steps
1. Go to the Smack 4.1 Readme and Upgrade Guide and go to the part for Using Eclipses Android Development Tools (ADT) Ant Based Build
2. Download a python script getMavenArtifactsNG.py This is in Python 3. Hopefully you have that!
3. Create an artifacts.csv file with the text information given in the paragraph
4. Execute the command ./getMavenArtifactsNG.py -f artifacts.csv -p <path_to_Eclipse_Workspace_Directory>/ChatIOT which is the project directory. This will populate the libs and libs-sources directory with a zooful of jar files!
Refresh the project and this will remove all errors EXCEPT on the lines that refer to the ChatManager. For some reason, the script given above does not load the smack-IM libraries!
5. Go to the downloads section of the Smack library and download the smack-4.1.4.zip file. Unzip this file, locate ONE file smack-im-4.1.4.jar and copy it into ChatIOT/libs directory.
This should remove all compile time errors.
Finally, open the AndroidManifest.xml file located in the ChatIOT project folder and insert one line on permission to access the Internet :
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yantrajaal.chatiot"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Now if the MainActivity.java program is Run as an Android Application, it should show up on the Emulator like this :
To test the program we need to do the following tasks
- This test assumes that we have two registered userid at the xmpp server adastra.re. So create two IDs say uid2 and uid3. In principle you can choose any public XMPP server but this program has been tested at AdAstra.
- Set up the ChatIOT listener chatbot by following these instructions and and start the chatbot using the uid3 userid and its corresponding password.
- Start the ChatIOT app either in the Emulator or in a physical Android device
- Press the Connect button -- this will connect to the AdAstra server and login as uid2
- Press the Send button -- this will first send a message to the listener that contains the text "SOUND 2". This will cause an alarm sound. Next it will send three messages consisting of the word PUSH followed by a random number. These three random numbers would be stored in the SQLite database on the listener machine. There will be a 5 second gap between the messages
- The Send button can be pressed repeatedly.
- The Disconnect button will cause a logout.
- Finally for uid2 to be able to send a message to uid3, the two users must be in each others contact lists! Please use a standard IM client like Pidgin or Xabber to first establish this contact. Otherwise no message will ever be relayed.
- You may be wondering why we have used uid2, uid3 as users. Actually there is another user uid1 through which we can keep a check on when uid2 and uid3 are logged in and able to communicate.
In this program we are simply transmitting numbers generated at random. In a real IOT case, these numbers will be generated by physical sensors connected to the Android device. [ this is explained in a subsequent post, where we see how to sense and report illumination levels ]
Java programming on Eclipse is a treacherous business because more often than not the libraries cannot be located and loaded. With Android and Smack there is another level of complexity. Hopefully the steps given here will work. If there is a problem, you can always download the entire project from GitHub, with all libraries in place, and import the same into Eclipse.
Great information. Thanks for providing us such a useful information. Keep up the good work and continue providing us more quality information from time to time. Android Development
ReplyDeleteHi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog.
ReplyDeleteReally very informative post you shared here. Kindly keep blogging.
If anyone wants to become a Front end developer learn from Javascript Online Training from India .
or learn thru JavaScript Online Training from India.
Nowadays JavaScript has tons of job opportunities on various vertical industry. ES6 Training in Chennai
Among one of the finest pieces on the internet, freshening in its specificity.
ReplyDeleteNumber for Base Chat in Germany
First You got a great blog .I will be interested in more similar topics. i see you got really very useful topics, i will be always checking your blog thanks.
ReplyDeletemadalin stunt cars 2
Happy to read your blog and gained a lot of new information in detail. Thanks for sharing.
ReplyDeleteIELTS Coaching in Mulund
IELTS Training in Mulund West
IELTS Courses in Mulund
IELTS Coaching Centres in Mulund
IELTS Centres in Mulund East
Please refer below if you are looking for Online Job Support and Proxy support from India
ReplyDeleteJava Online Job Support and Proxy support from India | AWS Online Job Support and Proxy Support From India | Python Online Job Support and Proxy Support From India | Angular Online Job Support from India | Android Online Job Support and Proxy Support from India| SAP MM Online Job Support and Proxy support from India | ETL Testing Online Job Support and Proxy Support From India | SAP SD Online Job Support and Proxy Support From India
Thank you for excellent article.