Skip to content

Commit 7cb2672

Browse files
Al Stockdill-ManderGerrit Code Review @ Eclipse.org
authored andcommitted
Merge "Fix Bug 443367 - [feature] mqtt service provide a callback interface to let user setup their own notification callback to notify message arrived during app is dead" into develop
2 parents 3a5c7df + c0af8d9 commit 7cb2672

9 files changed

Lines changed: 414 additions & 34 deletions

File tree

org.eclipse.paho.android.service/org.eclipse.paho.android.service.sample/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<uses-permission android:name="android.permission.INTERNET" />
1313
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
1414
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
15+
<uses-permission android:name="android.permission.GET_TASKS" />
1516

1617
<application
1718
android:allowBackup="true"

org.eclipse.paho.android.service/org.eclipse.paho.android.service.sample/src/org/eclipse/paho/android/service/sample/ClientConnections.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ private void connectAction(Bundle data) {
305305
}
306306
}
307307
client.setCallback(new MqttCallbackHandler(this, clientHandle));
308+
309+
//setServiceNotificationCallback
310+
client.setServiceNotificationCallback(MyMqttServiceNtfCallback.class);
311+
308312
connection.addConnectionOptions(conOpt);
309313
Connections.getInstance(this).addConnection(connection);
310314
if (doConnect) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*******************************************************************************
2+
* Copyright (c) 1999, 2014 IBM Corp.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v1.0
6+
* and Eclipse Distribution License v1.0 which accompany this distribution.
7+
*
8+
* The Eclipse Public License is available at
9+
* http://www.eclipse.org/legal/epl-v10.html
10+
* and the Eclipse Distribution License is available at
11+
* http://www.eclipse.org/org/documents/edl-v10.php.
12+
*/
13+
package org.eclipse.paho.android.service.sample;
14+
15+
import org.eclipse.paho.android.service.MqttService;
16+
import org.eclipse.paho.android.service.MqttServiceNotificationCallback;
17+
import org.eclipse.paho.client.mqttv3.MqttMessage;
18+
19+
import android.app.Notification;
20+
import android.app.NotificationManager;
21+
import android.content.Context;
22+
import android.support.v4.app.NotificationCompat;
23+
import android.util.Log;
24+
25+
26+
public class MyMqttServiceNtfCallback implements MqttServiceNotificationCallback {
27+
28+
@Override
29+
public void notify(MqttService service,String topic,MqttMessage message) {
30+
31+
NotificationCompat.Builder b=new NotificationCompat.Builder(service)
32+
.setContentTitle("message["+topic+"]")
33+
.setContentText(new String(message.getPayload()))
34+
.setSmallIcon(R.drawable.ic_launcher)
35+
.setAutoCancel(true);
36+
37+
Notification n=b.build();
38+
39+
NotificationManager nm = (NotificationManager)service.getSystemService(Context.NOTIFICATION_SERVICE);
40+
nm.notify(103245, n);
41+
}
42+
43+
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2014 IBM Corp.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v1.0
6+
* and Eclipse Distribution License v1.0 which accompany this distribution.
7+
*
8+
* The Eclipse Public License is available at
9+
* http://www.eclipse.org/legal/epl-v10.html
10+
* and the Eclipse Distribution License is available at
11+
* http://www.eclipse.org/org/documents/edl-v10.php.
12+
*/
13+
package org.eclipse.paho.android.service;
14+
15+
import android.content.ContentValues;
16+
import android.content.Context;
17+
import android.database.Cursor;
18+
import android.database.SQLException;
19+
import android.database.sqlite.SQLiteDatabase;
20+
import android.database.sqlite.SQLiteOpenHelper;
21+
22+
public class DatabaseServiceNotificationCallbackStore implements
23+
ServiceNotificationCallbackStore {
24+
25+
// TAG used for indentify trace data etc.
26+
private static String TAG = "DatabaseServiceNotificationCallbackStore";
27+
28+
29+
private static final String SERVICE_NTFCALLBACK_TABLE_NAME = "MqttServiceNTFCallbackTable";
30+
31+
// the database
32+
private SQLiteDatabase db = null;
33+
34+
// a SQLiteOpenHelper specific for this database
35+
private MQTTDatabaseHelper mqttDb = null;
36+
37+
// a place to send trace data
38+
private MqttTraceHandler traceHandler = null;
39+
40+
public DatabaseServiceNotificationCallbackStore(MqttService service, Context context) {
41+
this.traceHandler = (MqttTraceHandler) service;
42+
43+
// Open message database
44+
mqttDb = new MQTTDatabaseHelper(traceHandler, context);
45+
46+
// Android documentation suggests that this perhaps
47+
// could/should be done in another thread, but as the
48+
// database is only one table, I doubt it matters...
49+
traceHandler.traceDebug(TAG, "DatabaseMessageStore<init> complete");
50+
}
51+
52+
@Override
53+
public String getAppServiceNTFCallbackClass(String appPackageName) {
54+
55+
db = mqttDb.getWritableDatabase();
56+
57+
String[] cols = new String[2];
58+
cols[0] = "apppack";
59+
cols[1]="ntfcls";
60+
Cursor c = db.query(SERVICE_NTFCALLBACK_TABLE_NAME, cols,
61+
"apppack='" + appPackageName + "'",
62+
null, null, null, null);
63+
String ntfCallbackcls=null;
64+
if (c.moveToFirst()) {
65+
ntfCallbackcls = c.getString(1);
66+
}
67+
c.close();
68+
69+
return ntfCallbackcls;
70+
}
71+
72+
@Override
73+
public boolean setAppServiceNTFCallbackClass(String appPackageName,
74+
String NTFCallback) {
75+
76+
db = mqttDb.getWritableDatabase();
77+
78+
ContentValues values = new ContentValues();
79+
values.put("ntfcls", NTFCallback);
80+
81+
//check if the appPackageName key exists
82+
String oldNTFCallback=getAppServiceNTFCallbackClass(appPackageName);
83+
84+
try {
85+
//if exists, let's update it
86+
if (oldNTFCallback!=null) {
87+
if(!oldNTFCallback.equals(NTFCallback)) {
88+
db.update(SERVICE_NTFCALLBACK_TABLE_NAME, values, "apppack=?",new String[]{appPackageName});
89+
}
90+
}
91+
//if not, let's insert it
92+
else {
93+
values.put("apppack", appPackageName);
94+
db.insertOrThrow(SERVICE_NTFCALLBACK_TABLE_NAME, null, values);
95+
}
96+
return true;
97+
} catch (SQLException e) {
98+
traceHandler.traceException(TAG, "onUpgrade", e);
99+
}
100+
101+
return false;
102+
}
103+
104+
private static class MQTTDatabaseHelper extends SQLiteOpenHelper {
105+
// TAG used for indentify trace data etc.
106+
private static String TAG = "MQTTDatabaseHelper";
107+
108+
private static final String DATABASE_NAME = "mqttAndroidServiceNTFCallback.db";
109+
110+
// database version, used to recognise when we need to upgrade
111+
// (delete and recreate)
112+
private static final int DATABASE_VERSION = 1;
113+
114+
// a place to send trace data
115+
private MqttTraceHandler traceHandler = null;
116+
117+
/**
118+
* Constructor.
119+
*
120+
* @param traceHandler
121+
* @param context
122+
*/
123+
public MQTTDatabaseHelper(MqttTraceHandler traceHandler, Context context) {
124+
super(context, DATABASE_NAME, null, DATABASE_VERSION);
125+
this.traceHandler = traceHandler;
126+
}
127+
128+
@Override
129+
public void onCreate(SQLiteDatabase database) {
130+
String createArrivedTableStatement = "CREATE TABLE "
131+
+ SERVICE_NTFCALLBACK_TABLE_NAME + "("
132+
+" apppack TEXT PRIMARY KEY,"
133+
+" ntfcls TEXT"
134+
+ ");";
135+
traceHandler.traceDebug(TAG, "onCreate {"
136+
+ createArrivedTableStatement + "}");
137+
try {
138+
database.execSQL(createArrivedTableStatement);
139+
traceHandler.traceDebug(TAG, "created the table");
140+
} catch (SQLException e) {
141+
traceHandler.traceException(TAG, "onCreate", e);
142+
throw e;
143+
}
144+
}
145+
146+
@Override
147+
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
148+
traceHandler.traceDebug(TAG, "onUpgrade");
149+
try {
150+
db.execSQL("DROP TABLE IF EXISTS " + SERVICE_NTFCALLBACK_TABLE_NAME);
151+
} catch (SQLException e) {
152+
traceHandler.traceException(TAG, "onUpgrade", e);
153+
throw e;
154+
}
155+
onCreate(db);
156+
traceHandler.traceDebug(TAG, "onUpgrade complete");
157+
}
158+
}
159+
160+
@Override
161+
public void close() {
162+
this.db.close();
163+
164+
}
165+
}

org.eclipse.paho.android.service/org.eclipse.paho.android.service/src/org/eclipse/paho/android/service/MqttAndroidClient.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ public void onServiceDisconnected(ComponentName name) {
144144
// The MqttCallback provided by the application
145145
private MqttCallback callback;
146146
private MqttTraceHandler traceCallback;
147+
private String serviceNTFCallbackCls;
147148

148149
//The acknowledgment that a message has been processed by the application
149150
private Ack messageAck;
@@ -260,7 +261,7 @@ public String getServerURI() {
260261
@Override
261262
public void close() {
262263
if (clientHandle == null) {
263-
clientHandle = mqttService.getClient(serverURI, clientId, String.valueOf(myContext.hashCode()),persistence);
264+
clientHandle = mqttService.getClient(serverURI, clientId, myContext.getApplicationInfo().packageName,persistence);
264265
}
265266
mqttService.close(clientHandle);
266267
}
@@ -408,11 +409,19 @@ private void registerReceiver(BroadcastReceiver receiver) {
408409
*/
409410
private void doConnect() {
410411
if (clientHandle == null) {
411-
clientHandle = mqttService.getClient(serverURI, clientId,String.valueOf(myContext.hashCode()),
412+
clientHandle = mqttService.getClient(serverURI, clientId,myContext.getApplicationInfo().packageName,
412413
persistence);
413414
}
414415
mqttService.setTraceEnabled(traceEnabled);
415416
mqttService.setTraceCallbackId(clientHandle);
417+
mqttService.setAppRunning(true);
418+
//store the app package name and service notification callback class
419+
if (this.serviceNTFCallbackCls!=null) {
420+
ServiceNotificationCallbackStore store=mqttService.getServiceNTFCallbackStore();
421+
if(store!=null) {
422+
store.setAppServiceNTFCallbackClass(mqttService.getApplicationInfo().packageName, serviceNTFCallbackCls);
423+
}
424+
}
416425

417426
String activityToken = storeToken(connectToken);
418427
try {
@@ -1039,6 +1048,16 @@ public void setCallback(MqttCallback callback) {
10391048
this.callback = callback;
10401049

10411050
}
1051+
1052+
/**
1053+
* Using this API, the end user can setup customized notification callback for MqttService
1054+
* This callback is only used when the applications is dead and the service is restarted
1055+
* @param callback is the Class which implements org.eclipse.paho.android.service.MqttServiceNotificationCallback
1056+
*/
1057+
public <T extends MqttServiceNotificationCallback> void setServiceNotificationCallback(Class<T> callback) {
1058+
this.serviceNTFCallbackCls=callback.getName();
1059+
Log.i("MqttAndroidClient","MqttService Notification Callback Class="+this.serviceNTFCallbackCls);
1060+
}
10421061

10431062
/**
10441063
* identify the callback to be invoked when making tracing calls back into

org.eclipse.paho.android.service/org.eclipse.paho.android.service/src/org/eclipse/paho/android/service/MqttConnection.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ public void deliveryComplete(IMqttDeliveryToken messageToken) {
840840
service.callbackToActivity(clientHandle, Status.OK, resultBundle);
841841
}
842842

843-
// this notification will have kept the connection alive but send the previously sechudled ping anyw
843+
// this notification will have kept the connection alive but send the previously sechudled ping anyway
844844
}
845845

846846
/**
@@ -860,13 +860,28 @@ public void messageArrived(String topic, MqttMessage message)
860860

861861
String messageId = service.messageStore.storeArrived(clientHandle,
862862
topic, message);
863+
864+
/**
865+
* if app is running, let's callback to activity if app is dead, let's
866+
* use service callback
867+
*/
868+
Log.i("MqttConnection","Get a message="+new String(message.getPayload()));
869+
//only if app running, call back to Activity
870+
if (service.isAppRunning()) {
863871
Bundle resultBundle = messageToBundle(messageId, topic, message);
864872
resultBundle.putString(MqttServiceConstants.CALLBACK_ACTION,
865873
MqttServiceConstants.MESSAGE_ARRIVED_ACTION);
866874
resultBundle.putString(MqttServiceConstants.CALLBACK_MESSAGE_ID,
867875
messageId);
868876
service.callbackToActivity(clientHandle, Status.OK, resultBundle);
869-
877+
}
878+
else {
879+
//otherwise, service will callback the service NTF callback
880+
Log.i("MqttConnection",
881+
"Notify message=" + new String(message.getPayload()));
882+
service.callbackToNotification(topic, message);
883+
}
884+
870885
}
871886

872887
/**

0 commit comments

Comments
 (0)