package org.bitseal.controllers; import java.util.ArrayList; import org.bitseal.core.AckProcessor; import org.bitseal.core.App; import org.bitseal.core.IncomingMessageProcessor; import org.bitseal.data.Message; import org.bitseal.data.Payload; import org.bitseal.database.MessageProvider; import org.bitseal.database.PayloadProvider; import org.bitseal.database.PayloadsTable; import org.bitseal.network.ServerCommunicator; import org.bitseal.services.NotificationsService; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.util.Log; /** * This class controls the operations necessary to check whether * any new messages are available from servers and to process any * new messages that are retrieved. * * @author Jonathan Coe */ public class CheckForMessagesController { /** Used when broadcasting Intents to the UI so that it can refresh the data it is displaying */ private static final String UI_NOTIFICATION = "uiNotification"; /** Stores the Unix timestamp of the last msg payload we processed. This can be used to tell us how far behind the network we are. */ private static final String LAST_PROCESSED_MSG_TIME = "lastProcessedMsgTime"; private static final String TAG = "CHECK_FOR_MESSAGES_CONTROLLER"; /** * Polls one or more servers to check whether any new messages are available. */ public void checkServerForMessages() { new ServerCommunicator().checkServerForNewMsgs(); } /** * Processes one or more msg payloads that have been sent to me * * @return An int representing the number of new messages successfully processed */ public int processIncomingMessages() { int newMessagesReceived = 0; // Search the database for the Payloads of any possible new msgs PayloadProvider payProv = PayloadProvider.get(App.getContext()); String[] columnNames = new String[]{PayloadsTable.COLUMN_TYPE, PayloadsTable.COLUMN_BELONGS_TO_ME, PayloadsTable.COLUMN_PROCESSING_COMPLETE}; String[] searchTerms = new String[]{Payload.OBJECT_TYPE_MSG, "0", "0"}; // Zero stands for false in the database ArrayList<Payload> msgsToProcess = payProv.searchPayloads(columnNames, searchTerms); // At this point we have selected all the msg payloads received by me which have not been processed yet. Now process them. ArrayList<Payload> processedMsgs = new ArrayList<Payload>(); for (Payload p : msgsToProcess) { Message decryptedMessage = new IncomingMessageProcessor().processReceivedMsg(p); if (decryptedMessage != null) // If the message was decrypted and authenticated successfully { newMessagesReceived ++; // Save the decrypted Message to the database MessageProvider.get(App.getContext()).addMessage(decryptedMessage); // Update the UI App.getContext().sendBroadcast(new Intent(UI_NOTIFICATION)); } processedMsgs.add(p); } // Update all the processed Payload records so that they won't be processed again for (Payload p : processedMsgs) { p.setProcessingComplete(true); payProv.updatePayload(p); } if (processedMsgs.size() > 0) { // If we have processed at least 1 message, use the time value of the last processed message to set a // variable that tells us how far behind the network we are Payload lastMsgPayload = processedMsgs.get(processedMsgs.size() - 1); long lastProcessedMsgTime = lastMsgPayload.getTime(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(App.getContext()); SharedPreferences.Editor editor = prefs.edit(); editor.putLong(LAST_PROCESSED_MSG_TIME, lastProcessedMsgTime); editor.commit(); Log.i(TAG, "Updated the 'last processed msg time' value stored in SharedPreferences to " + lastProcessedMsgTime); } if (newMessagesReceived > 0) { // Display a notification for any new message(s) we have received Context appContext = App.getContext(); Intent intent = new Intent(appContext, NotificationsService.class); intent.putExtra(NotificationsService.EXTRA_DISPLAY_NEW_MESSAGES_NOTIFICATION, newMessagesReceived); appContext.startService(intent); } return processedMsgs.size(); } /** * Attempts to send any acknowledgements that are scheduled to be * sent by me for messages that I have received * * @return - A boolean indicating whether or not all outstanding acknowledgements * were successfully processed */ public boolean sendAcknowledgments() { return new AckProcessor().sendAcknowledgments(); } }