├── .gitignore
├── AndroidManifest.xml
├── README.md
├── proguard.cfg
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── layout
│ └── main.xml
└── values
│ └── strings.xml
└── src
└── org
└── example
└── mqtt
└── MQTTActivity.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | android-mqtt-demo
2 | =================
3 |
4 | Android MQTT Client - Demo
5 |
6 | This is a simple client to demonstrate the use of fusesource/mqtt-client library on Android.
7 |
8 | Once you have cloned the repo, you can build the project in eclipse with Android SDK.
9 |
10 | To Build the project in eclipse:
11 |
12 | 1) Select: File -> New -> Android Project
13 |
14 | 2) Give the project a name
15 |
16 | 3) Select: Create project from existing source
17 |
18 | 4) Browse to the location where you cloned the repo
19 |
20 | 5) Click Finish
21 |
22 | Once the project is created you will need to add the mqtt-client lib dependency.
23 |
24 | This can be done by cloning the fusesource/mqtt-client repo and building the project.
25 | Then add the mqtt-client uber jar to the build path.
--------------------------------------------------------------------------------
/proguard.cfg:
--------------------------------------------------------------------------------
1 | -optimizationpasses 5
2 | -dontusemixedcaseclassnames
3 | -dontskipnonpubliclibraryclasses
4 | -dontpreverify
5 | -verbose
6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7 |
8 | -keep public class * extends android.app.Activity
9 | -keep public class * extends android.app.Application
10 | -keep public class * extends android.app.Service
11 | -keep public class * extends android.content.BroadcastReceiver
12 | -keep public class * extends android.content.ContentProvider
13 | -keep public class * extends android.app.backup.BackupAgentHelper
14 | -keep public class * extends android.preference.Preference
15 | -keep public class com.android.vending.licensing.ILicensingService
16 |
17 | -keepclasseswithmembernames class * {
18 | native ;
19 | }
20 |
21 | -keepclasseswithmembers class * {
22 | public (android.content.Context, android.util.AttributeSet);
23 | }
24 |
25 | -keepclasseswithmembers class * {
26 | public (android.content.Context, android.util.AttributeSet, int);
27 | }
28 |
29 | -keepclassmembers class * extends android.app.Activity {
30 | public void *(android.view.View);
31 | }
32 |
33 | -keepclassmembers enum * {
34 | public static **[] values();
35 | public static ** valueOf(java.lang.String);
36 | }
37 |
38 | -keep class * implements android.os.Parcelable {
39 | public static final android.os.Parcelable$Creator *;
40 | }
41 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=Google Inc.:Google APIs:10
12 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jsherman1/android-mqtt-demo/f9768d94f04e2642c4b08357357e36b1199374e3/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jsherman1/android-mqtt-demo/f9768d94f04e2642c4b08357357e36b1199374e3/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jsherman1/android-mqtt-demo/f9768d94f04e2642c4b08357357e36b1199374e3/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
21 |
22 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
46 |
47 |
48 |
49 |
53 |
54 |
60 |
61 |
66 |
67 |
68 |
69 |
73 |
74 |
80 |
81 |
87 |
88 |
89 |
90 |
95 |
96 |
102 |
103 |
108 |
109 |
110 |
111 |
118 |
119 |
124 |
125 |
132 |
133 |
140 |
141 |
147 |
148 |
154 |
155 |
161 |
162 |
163 |
164 |
165 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Android MQTT Test Client
4 |
--------------------------------------------------------------------------------
/src/org/example/mqtt/MQTTActivity.java:
--------------------------------------------------------------------------------
1 | package org.example.mqtt;
2 |
3 | import java.net.URISyntaxException;
4 |
5 | import org.fusesource.mqtt.client.Callback;
6 | import org.fusesource.mqtt.client.FutureConnection;
7 | import org.fusesource.mqtt.client.MQTT;
8 | import org.fusesource.mqtt.client.Message;
9 | import org.fusesource.mqtt.client.QoS;
10 | import org.fusesource.mqtt.client.Topic;
11 |
12 | import org.example.mqtt.R;
13 |
14 | import android.app.Activity;
15 | import android.app.ProgressDialog;
16 | import android.content.pm.ActivityInfo;
17 | import android.os.Bundle;
18 | import android.util.Log;
19 | import android.view.View;
20 | import android.view.View.OnClickListener;
21 | import android.widget.Button;
22 | import android.widget.EditText;
23 | import android.widget.Toast;
24 |
25 | public class MQTTActivity extends Activity implements OnClickListener{
26 |
27 | private final String TAG = "MQTTClient";
28 |
29 | EditText addressET = null;
30 | EditText destinationET = null;
31 | EditText messageET = null;
32 | EditText receiveET = null;
33 | EditText userNameET = null;
34 | EditText passwordET = null;
35 |
36 | Button connectButton = null;
37 | Button disconnectButton = null;
38 | Button sendButton = null;
39 |
40 | private ProgressDialog progressDialog = null;
41 |
42 | String sAddress = null;
43 | String sUserName = null;
44 | String sPassword = null;
45 | String sDestination = null;
46 | String sMessage = null;
47 |
48 | MQTT mqtt = null;
49 |
50 | FutureConnection connection = null;
51 |
52 | /** Called when the activity is first created. */
53 | @Override
54 | public void onCreate(Bundle savedInstanceState) {
55 | super.onCreate(savedInstanceState);
56 | setContentView(R.layout.main);
57 |
58 | setupView();
59 | }
60 |
61 | @Override
62 | public void onPause()
63 | {
64 | super.onPause();
65 |
66 | disconnect();
67 | }
68 |
69 | public void setupView()
70 | {
71 | // lock the screen in portrait mode
72 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
73 |
74 | addressET = (EditText)findViewById(R.id.addressEditText);
75 | addressET.setHint("tcp://192.168.1.15:1883");
76 | userNameET = (EditText)findViewById(R.id.userNameEditText);
77 | passwordET = (EditText)findViewById(R.id.passwordEditText);
78 | destinationET = (EditText)findViewById(R.id.destinationEditText);
79 | messageET = (EditText)findViewById(R.id.messageEditText);
80 | receiveET = (EditText)findViewById(R.id.receiveEditText);
81 |
82 | connectButton = (Button)findViewById(R.id.connectButton);
83 | connectButton.setOnClickListener(this);
84 |
85 | disconnectButton = (Button)findViewById(R.id.disconnectButton);
86 | disconnectButton.setOnClickListener(this);
87 |
88 | sendButton = (Button)findViewById(R.id.sendButton);
89 | sendButton.setOnClickListener(this);
90 | }
91 |
92 | public void onClick(View v) {
93 | if(v == connectButton)
94 | {
95 | sAddress = addressET.getText().toString().trim();
96 | sUserName = userNameET.getText().toString().trim();
97 | sPassword = passwordET.getText().toString().trim();
98 |
99 | if(sAddress.equals(""))
100 | {
101 | toast("Address must be provided");
102 | }
103 | else
104 | {
105 | connect();
106 | }
107 | }
108 |
109 | if(v == disconnectButton)
110 | {
111 | disconnect();
112 | }
113 |
114 | if(v == sendButton)
115 | {
116 | sDestination = destinationET.getText().toString().trim();
117 | sMessage = messageET.getText().toString().trim();
118 |
119 | // allow empty messages
120 | if(sDestination.equals(""))
121 | {
122 | toast("Destination must be provided");
123 | }
124 | else
125 | {
126 | send();
127 | }
128 | }
129 | }
130 |
131 | // callback used for Future
132 | Callback onui(final Callback original) {
133 | return new Callback() {
134 | public void onSuccess(final T value) {
135 | runOnUiThread(new Runnable(){
136 | public void run() {
137 | original.onSuccess(value);
138 | }
139 | });
140 | }
141 | public void onFailure(final Throwable error) {
142 | runOnUiThread(new Runnable(){
143 | public void run() {
144 | original.onFailure(error);
145 | }
146 | });
147 | }
148 | };
149 | }
150 |
151 | private void connect()
152 | {
153 | mqtt = new MQTT();
154 | mqtt.setClientId("android-mqtt-example");
155 |
156 | try
157 | {
158 | mqtt.setHost(sAddress);
159 | Log.d(TAG, "Address set: " + sAddress);
160 | }
161 | catch(URISyntaxException urise)
162 | {
163 | Log.e(TAG, "URISyntaxException connecting to " + sAddress + " - " + urise);
164 | }
165 |
166 | if(sUserName != null && !sUserName.equals(""))
167 | {
168 | mqtt.setUserName(sUserName);
169 | Log.d(TAG, "UserName set: [" + sUserName + "]");
170 | }
171 |
172 | if(sPassword != null && !sPassword.equals(""))
173 | {
174 | mqtt.setPassword(sPassword);
175 | Log.d(TAG, "Password set: [" + sPassword + "]");
176 | }
177 |
178 | connection = mqtt.futureConnection();
179 | progressDialog = ProgressDialog.show(this, "",
180 | "Connecting...", true);
181 | connection.connect().then(onui(new Callback(){
182 | public void onSuccess(Void value) {
183 | connectButton.setEnabled(false);
184 | progressDialog.dismiss();
185 | toast("Connected");
186 | }
187 | public void onFailure(Throwable e) {
188 | toast("Problem connecting to host");
189 | Log.e(TAG, "Exception connecting to " + sAddress + " - " + e);
190 | progressDialog.dismiss();
191 | }
192 | }));
193 |
194 | }
195 |
196 | private void disconnect()
197 | {
198 | connectButton.setEnabled(true);
199 | try
200 | {
201 | if(connection != null && connection.isConnected())
202 | {
203 | connection.disconnect().then(onui(new Callback(){
204 | public void onSuccess(Void value) {
205 | connectButton.setEnabled(true);
206 | toast("Disconnected");
207 | }
208 | public void onFailure(Throwable e) {
209 | toast("Problem disconnecting");
210 | Log.e(TAG, "Exception disconnecting from " + sAddress + " - " + e);
211 | }
212 | }));
213 | }
214 | else
215 | {
216 | toast("Not Connected");
217 | }
218 | }
219 | catch(Exception e)
220 | {
221 | Log.e(TAG, "Exception " + e);
222 | }
223 | }
224 |
225 | private void send()
226 | {
227 | if(connection != null)
228 | {
229 | // automatically connect if no longer connected
230 | if(!connection.isConnected())
231 | {
232 | connect();
233 | }
234 |
235 | Topic[] topics = {new Topic(sDestination, QoS.AT_LEAST_ONCE)};
236 | connection.subscribe(topics).then(onui(new Callback() {
237 | public void onSuccess(byte[] subscription) {
238 |
239 | Log.d(TAG, "Destination: " + sDestination);
240 | Log.d(TAG, "Message: " + sMessage);
241 |
242 | // publish message
243 | connection.publish(sDestination, sMessage.getBytes(), QoS.AT_LEAST_ONCE, false);
244 | destinationET.setText("");
245 | messageET.setText("");
246 | toast("Message sent");
247 |
248 | // receive message
249 | connection.receive().then(onui(new Callback() {
250 | public void onSuccess(Message message) {
251 | String receivedMesageTopic = message.getTopic();
252 | byte[] payload = message.getPayload();
253 | String messagePayLoad = new String(payload);
254 | message.ack();
255 | connection.unsubscribe(new String[]{sDestination});
256 | receiveET.setText(receivedMesageTopic + ":" + messagePayLoad);
257 | }
258 |
259 | public void onFailure(Throwable e) {
260 | Log.e(TAG, "Exception receiving message: " + e);
261 | }
262 | }));
263 |
264 | }
265 |
266 | public void onFailure(Throwable e) {
267 | Log.e(TAG, "Exception sending message: " + e);
268 | }
269 | }));
270 | }
271 | else
272 | {
273 | toast("No connection has been made, please create the connection");
274 | }
275 | }
276 |
277 | private void toast(String message)
278 | {
279 | Toast.makeText(this, message, Toast.LENGTH_LONG).show();
280 | }
281 | }
--------------------------------------------------------------------------------