Skip to content

Commit

Permalink
Fixed up the battery drain bug and cleaned up some code
Browse files Browse the repository at this point in the history
  • Loading branch information
unknown authored and unknown committed May 17, 2010
1 parent ff7fd14 commit 921879c
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 49 deletions.
80 changes: 80 additions & 0 deletions src/com/tokudu/demo/ConnectionLog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* $Id$
*/

package com.tokudu.demo;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.os.Environment;

public class ConnectionLog
{
private String mPath;
private Writer mWriter;

private static final SimpleDateFormat TIMESTAMP_FMT =
new SimpleDateFormat("[HH:mm:ss] ");

public ConnectionLog()
throws IOException
{
File sdcard = Environment.getExternalStorageDirectory();
File logDir = new File(sdcard, "tokudu/log/");
if (!logDir.exists()) {
logDir.mkdirs();
// do not allow media scan
new File(logDir, ".nomedia").createNewFile();
}

open(logDir.getAbsolutePath() + "/push.log");
}

public ConnectionLog(String basePath)
throws IOException
{
open(basePath);
}

protected void open(String basePath)
throws IOException
{
File f = new File(basePath + "-" + getTodayString());
mPath = f.getAbsolutePath();
mWriter = new BufferedWriter(new FileWriter(mPath), 2048);

println("Opened log.");
}

private static String getTodayString()
{
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd-hhmmss");
return df.format(new Date());
}

public String getPath()
{
return mPath;
}

public void println(String message)
throws IOException
{
mWriter.write(TIMESTAMP_FMT.format(new Date()));
mWriter.write(message);
mWriter.write('\n');
mWriter.flush();
}

public void close()
throws IOException
{
mWriter.close();
}
}
133 changes: 84 additions & 49 deletions src/com/tokudu/demo/PushService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.tokudu.demo;

import java.io.IOException;

import com.ibm.mqtt.IMqttClient;
import com.ibm.mqtt.MqttClient;
import com.ibm.mqtt.MqttException;
Expand Down Expand Up @@ -30,68 +32,72 @@
public class PushService extends Service
{
// this is the log tag
public static final String TAG = "DemoPushService";
public static final String TAG = "DemoPushService";

// the IP address, where your MQTT broker is running.
private static final String MQTT_HOST = "209.124.50.185";
private static final String MQTT_HOST = "209.124.50.185";
// the port at which the broker is running.
private static int MQTT_BROKER_PORT_NUM = 1883;
private static int MQTT_BROKER_PORT_NUM = 1883;
// Let's not use the MQTT persistence.
private static MqttPersistence MQTT_PERSISTENCE = null;
private static MqttPersistence MQTT_PERSISTENCE = null;
// We don't need to remember any state between the connections, so we use a clean start.
private static boolean MQTT_CLEAN_START = true;
// Let's set the internal keep alive for MQTT to 15 mins. I haven't tested this value much. It could probably be inreased.
private static short MQTT_KEEP_ALIVE = 60 * 15;
private static boolean MQTT_CLEAN_START = true;
// Let's set the internal keep alive for MQTT to 15 mins. I haven't tested this value much. It could probably be increased.
private static short MQTT_KEEP_ALIVE = 60 * 15;
// Set quality of services to 0 (at most once delivery), since we don't want push notifications
// arrive more than once. However, this means that some messages might get lost (delivery is not guaranteed)
private static int[] MQTT_QUALITIES_OF_SERVICE = { 0 } ;
private static int MQTT_QUALITY_OF_SERVICE = 0;
private static int[] MQTT_QUALITIES_OF_SERVICE = { 0 } ;
private static int MQTT_QUALITY_OF_SERVICE = 0;
// The broker should not retain any messages.
private static boolean MQTT_RETAINED_PUBLISH = false;
private static boolean MQTT_RETAINED_PUBLISH = false;

// MQTT client ID, which is given the broker. In this example, I also use this for the topic header.
// You can use this to run push notifications for multiple apps with one MQTT broker.
public static String MQTT_CLIENT_ID = "com.tokudu.demo";

// These are the actions for the service (name are descriptive enough)
private static final String ACTION_START = MQTT_CLIENT_ID + ".START";
private static final String ACTION_STOP = MQTT_CLIENT_ID + ".STOP";
private static final String ACTION_KEEPALIVE = MQTT_CLIENT_ID + ".KEEP_ALIVE";
private static final String ACTION_RECONNECT = MQTT_CLIENT_ID + ".RECONNECT";
public static String MQTT_CLIENT_ID = "com.tokudu.demo";

// Notification title
public static String NOTIF_TITLE = "Tokudu";
// Notification id
private static final int NOTIF_CONNECTED = 0;
// These are the actions for the service (name are descriptive enough)
private static final String ACTION_START = MQTT_CLIENT_ID + ".START";
private static final String ACTION_STOP = MQTT_CLIENT_ID + ".STOP";
private static final String ACTION_KEEPALIVE = MQTT_CLIENT_ID + ".KEEP_ALIVE";
private static final String ACTION_RECONNECT = MQTT_CLIENT_ID + ".RECONNECT";

// Connection log for the push service. Good for debugging.
private ConnectionLog mLog;

// Connectivity manager to determining, when the phone loses connection
private ConnectivityManager mConnMan;
private ConnectivityManager mConnMan;
// Notification manager to displaying arrived push notifications
private NotificationManager mNotifMan;
private NotificationManager mNotifMan;

// Whether or not the service has been started.
private boolean mStarted;
private boolean mStarted;

// This the application level keep-alive interval, that is used by the AlarmManager
// to keep the connection active, even when the device goes to sleep.
private static final long KEEP_ALIVE_INTERVAL = 1000 * 60 * 28;
private static final long KEEP_ALIVE_INTERVAL = 1000 * 60 * 28;

// Retry intervals, when the connection is lost.
private static final long INITIAL_RETRY_INTERVAL = 1000 * 10;
private static final long MAXIMUM_RETRY_INTERVAL = 1000 * 60 * 30;
private static final long INITIAL_RETRY_INTERVAL = 1000 * 10;
private static final long MAXIMUM_RETRY_INTERVAL = 1000 * 60 * 30;

// Preferences instance
private SharedPreferences mPrefs;
private SharedPreferences mPrefs;
// We store in the preferences, whether or not the service has been started
public static final String PREF_STARTED = "isStarted";
public static final String PREF_STARTED = "isStarted";
// We also store the deviceID (target)
public static final String PREF_DEVICE_ID = "deviceID";
public static final String PREF_DEVICE_ID = "deviceID";
// We store the last retry interval
public static final String PREF_RETRY = "retryInterval";
public static final String PREF_RETRY = "retryInterval";

// Notification title
public static String NOTIF_TITLE = "Tokudu";
// Notification id
private static final int NOTIF_CONNECTED = 0;

// This is the instance of an MQTT connection.
private MQTTConnection mConnection;
private MQTTConnection mConnection;
private long mStartTime;


// Static method to start the service
public static void actionStart(Context ctx) {
Expand Down Expand Up @@ -119,6 +125,14 @@ public void onCreate() {
super.onCreate();

log("Creating service");
mStartTime = System.currentTimeMillis();

try {
mLog = new ConnectionLog();
Log.i(TAG, "Opened log at " + mLog.getPath());
} catch (IOException e) {
Log.e(TAG, "Failed to open log", e);
}

// Get instances of preferences, connectivity manager and notification manager
mPrefs = getSharedPreferences(TAG, MODE_PRIVATE);
Expand Down Expand Up @@ -152,6 +166,11 @@ public void onDestroy() {
if (mStarted == true) {
stop();
}

try {
if (mLog != null)
mLog.close();
} catch (IOException e) {}
}

@Override
Expand All @@ -168,7 +187,9 @@ public void onStart(Intent intent, int startId) {
} else if (intent.getAction().equals(ACTION_KEEPALIVE) == true) {
keepAlive();
} else if (intent.getAction().equals(ACTION_RECONNECT) == true) {
reconnectIfNecessary();
if (isNetworkAvailable()) {
reconnectIfNecessary();
}
}
}

Expand All @@ -179,7 +200,22 @@ public IBinder onBind(Intent intent) {

// log helper function
private void log(String message) {
Log.i(TAG, message);
log(message, null);
}
private void log(String message, Throwable e) {
if (e != null) {
Log.e(TAG, message, e);

} else {
Log.i(TAG, message);
}

if (mLog != null)
{
try {
mLog.println(message);
} catch (IOException ex) {}
}
}

// Reads whether or not the service has been started from the preferences
Expand Down Expand Up @@ -244,8 +280,10 @@ private synchronized void connect() {
mConnection = new MQTTConnection(MQTT_HOST, deviceID);
} catch (MqttException e) {
// Schedule a reconnect, if we failed to connect
Log.e(TAG, "MQQTEXCEPTION" + (e.getMessage() == null? e.getMessage():" NULL"), e);
scheduleReconnect(System.currentTimeMillis());
log("MqttException: " + (e.getMessage() != null ? e.getMessage() : "NULL"));
if (isNetworkAvailable()) {
scheduleReconnect(mStartTime);
}
}
setStarted(true);
}
Expand All @@ -256,16 +294,13 @@ private synchronized void keepAlive() {
// Send a keep alive, if there is a connection.
if (mStarted == true && mConnection != null) {
mConnection.sendKeepAlive();
} else {
if (isNetworkAvailable()) {
reconnectIfNecessary();
}
}
} catch (MqttException e) {
log("MqttException: " + (e.getMessage() != null? e.getMessage(): "NULL"), e);

mConnection.disconnect();
mConnection = null;
scheduleReconnect(System.currentTimeMillis());
Log.e(TAG, "Failed to send a keepalive", e);
cancelReconnect();
}
}

Expand Down Expand Up @@ -353,11 +388,11 @@ public void onReceive(Context context, Intent intent) {
log("Connectivity changed: connected=" + hasConnectivity);

if (hasConnectivity) {
// If there connectivity, we reconnect if necessary
reconnectIfNecessary();
} else if (mConnection != null) {
// if there no connectivity, make sure MQTT connection is destroyed
mConnection.disconnect();
cancelReconnect();
mConnection = null;
}
}
Expand Down Expand Up @@ -397,7 +432,6 @@ private boolean isNetworkAvailable() {
// This inner class is a wrapper on top of MQTT client.
private class MQTTConnection implements MqttSimpleCallback {
IMqttClient mqttClient = null;
private long startTime;

// Creates a new connection given the broker address and initial topic
public MQTTConnection(String brokerHostName, String initTopic) throws MqttException {
Expand All @@ -417,7 +451,7 @@ public MQTTConnection(String brokerHostName, String initTopic) throws MqttExcept
log("Connection established to " + brokerHostName + " on topic " + initTopic);

// Save start time
startTime = System.currentTimeMillis();
mStartTime = System.currentTimeMillis();
// Star the keep-alives
startKeepAlives();
}
Expand All @@ -428,7 +462,7 @@ public void disconnect() {
stopKeepAlives();
mqttClient.disconnect();
} catch (MqttPersistenceException e) {
Log.e(TAG, "MQQTEXCEPTION" + (e.getMessage() == null? e.getMessage():" NULL"), e);
log("MqttException" + (e.getMessage() != null? e.getMessage():" NULL"), e);
}
}
/*
Expand All @@ -453,8 +487,8 @@ private void subscribeToTopic(String topicName) throws MqttException {
private void publishToTopic(String topicName, String message) throws MqttException {
if ((mqttClient == null) || (mqttClient.isConnected() == false)) {
// quick sanity check - don't try and publish if we don't have
// a connection
Log.e(TAG, "no connection publish");
// a connection
log("No connection to public to");
} else {
mqttClient.publish(topicName,
message.getBytes(),
Expand All @@ -472,7 +506,7 @@ public void connectionLost() throws Exception {
// null itself
mConnection = null;
if (isNetworkAvailable() == true) {
scheduleReconnect(startTime);
scheduleReconnect(mStartTime);
}
}

Expand All @@ -487,6 +521,7 @@ public void publishArrived(String topicName, byte[] payload, int qos, boolean re
}

public void sendKeepAlive() throws MqttException {
log("Sending keep alive");
// publish to a keep-alive topic
publishToTopic(MQTT_CLIENT_ID + "/keepalive", mPrefs.getString(PREF_DEVICE_ID, ""));
}
Expand Down

0 comments on commit 921879c

Please sign in to comment.