package com.ushahidi.android.app;
import java.io.IOException;
import java.util.HashMap;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.util.Log;
import com.ushahidi.android.app.data.Database;
import com.ushahidi.android.app.net.MainHttpClient;
import com.ushahidi.android.app.util.ApiUtils;
/**
* Class is responsible for receiving connectivity change events and sending any
* off line incidents
*
* @author wtb
*/
public class OfflineIncidentSendReceiver extends BroadcastReceiver {
private static final String CLASS_TAG = OfflineIncidentSendReceiver.class.getCanonicalName();
private NotificationManager mNotificationManager;
private static final int OFFLINE_MESSAGES_SENT = 1;
/**
* When connectivity returns, send off line messages and notify user
*/
@Override
public void onReceive(Context context, Intent intent) {
Log.d(CLASS_TAG, "received connection state changed broadcast");
// Check if connectivity is being switch back on (could be a
// FAILOVER_CONNECTION event as well
// but I am going to ignore as no harm will come attempting to check)
if (!intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
Log.d(CLASS_TAG,
"High possibility connection is on, so try sending any off line incidents");
if (postToOnlineAllOfflineIncidents(context)) {
mNotificationManager = (NotificationManager)context
.getSystemService(Context.NOTIFICATION_SERVICE);
// creates notification to be displayed on the status bar
Notification notification = createNotfication(context);
// Notification expanding stuff
CharSequence contentTitle = context.getString(R.string.notification_expanded_title);
CharSequence contentText = context
.getString(R.string.notification_expanded_message);
Intent notificationIntent = new Intent(context, OfflineIncidentSendReceiver.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
// Send notification
mNotificationManager.notify(OFFLINE_MESSAGES_SENT, notification);
}
}
}
/**
* Try post all incidents stored in off line storage online
*/
private boolean postToOnlineAllOfflineIncidents(Context context) {
// Need to create own db handle instance as it can't be guaranteed the
// app handlr
// will be about
Database db = new Database(context);
db.open();
boolean someOfflineIncidentsSent = false;
final SharedPreferences settings = context.getSharedPreferences(Preferences.PREFS_NAME, 0);
StringBuilder urlBuilder = new StringBuilder(settings.getString("Domain", ""));
urlBuilder.append("/api");
Cursor cursor = db.fetchAllOfflineIncidents();
// only send offline reports if there are items in the database.
if (cursor.getCount() > 0) {
// double check to make sure there internet
if (!ApiUtils.isCheckinEnabled(context)) {
cursor.moveToFirst();
while (cursor.isAfterLast() == false) {
Log.d(CLASS_TAG,
"Sending message with title : "
+ cursor.getString(Database.ADD_INCIDENT_TITLE_INDEX));
try {
MainHttpClient.PostFileUpload(urlBuilder.toString(),
preparePostParams(cursor));
// if it fails without exception at this point there is
// problem
// with the message
db.deleteAddIncident(cursor.getInt(Database.ADD_INCIDENT_ID_INDEX));
someOfflineIncidentsSent = true;
} catch (IOException e) {
e.printStackTrace();
}
cursor.moveToNext();
}
}
}
cursor.close();
db.close();
return someOfflineIncidentsSent;
}
/**
* Create notification for status bar to inform the user at least one off
* line message were sent
*
* @return Notification
*/
private Notification createNotfication(Context context) {
CharSequence tickerText = context.getString(R.string.notification_status_bar_message);
long when = System.currentTimeMillis();
return new Notification(R.drawable.report_icon, tickerText, when);
}
/**
* Prepares a hash map of parameters representing an off line incident
* report so it can be posted to the Ushahidi server
*
* @param cursor - data to be added to the map
* @return HashMap<String, String>
*/
private HashMap<String, String> preparePostParams(Cursor cursor) {
HashMap<String, String> params = new HashMap<String, String>();
params.put(MainHttpClient.TASK, "report");
params.put(MainHttpClient.INCIDENT_TITLE,
cursor.getString(Database.ADD_INCIDENT_TITLE_INDEX));
params.put(MainHttpClient.INCIDENT_DESCRIPTION,
cursor.getString(Database.ADD_INCIDENT_DESC_INDEX));
params.put(MainHttpClient.INCIDENT_DATE,
cursor.getString(Database.ADD_INCIDENT_DATE_INDEX));
params.put(MainHttpClient.INCIDENT_HOUR,
cursor.getString(Database.ADD_INCIDENT_HOUR_INDEX));
params.put(MainHttpClient.INCIDENT_MINUTE,
cursor.getString(Database.ADD_INCIDENT_MINUTE_INDEX));
params.put(MainHttpClient.INCIDENT_AMPM,
cursor.getString(Database.ADD_INCIDENT_AMPM_INDEX));
params.put(MainHttpClient.INCIDENT_CATEGORY,
cursor.getString(Database.ADD_INCIDENT_CATEGORIES_INDEX));
params.put(MainHttpClient.LATITUDE,
cursor.getString(Database.INCIDENT_LOC_LATITUDE_INDEX));
params.put(MainHttpClient.LONGITUDE,
cursor.getString(Database.INCIDENT_LOC_LONGITUDE_INDEX));
params.put(MainHttpClient.LOCATION_NAME,
cursor.getString(Database.INCIDENT_LOC_NAME_INDEX));
params.put(MainHttpClient.PERSON_FIRST,
cursor.getString(Database.ADD_PERSON_FIRST_INDEX));
params.put(MainHttpClient.PERSON_LAST,
cursor.getString(Database.ADD_PERSON_LAST_INDEX));
params.put(MainHttpClient.PERSON_EMAIL,
cursor.getString(Database.ADD_PERSON_EMAIL_INDEX));
params.put(MainHttpClient.PHOTO,
cursor.getString(Database.ADD_INCIDENT_PHOTO_INDEX));
return params;
}
}