Blame | Last modification | View Log | Download | RSS feed
package org.vt.ece4564.latmb;import java.util.ArrayList;import java.util.Calendar;import java.util.GregorianCalendar;import java.util.List;import org.jboss.netty.channel.Channel;import org.vt.ece4564.latmb.LATMBProtocol.Message;import org.vt.ece4564.latmb.LATMBProtocol.Message.Builder;import org.vt.ece4564.latmb.LATMBProtocol.Position;import org.vt.ece4564.latmb.LATMBProtocol.TrackingMessage;import org.vt.ece4564.latmb.LATMBProtocol.DateTime;import android.app.Activity;import android.content.Intent;import android.content.SharedPreferences;import android.location.Location;import android.location.LocationListener;import android.location.LocationManager;import android.location.LocationProvider;import android.os.Bundle;import android.os.Handler;import android.preference.PreferenceManager;import android.util.Log;import android.view.Menu;import android.view.MenuInflater;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MessageBoardActivity extends Activity implements OnClickListener,LocationListener, NetworkMessageHandler<TrackingMessage> {private static final String TAG = MessageBoardActivity.class.getName();private EditText newEntry_;private Button submit_;private TextView status_;private ViewGroup messageContainer_;private String server_;private int port_;private String username_;private String chatroom_;private boolean useGPS_;private boolean gpsAcquired_ = false;private boolean gpsChanged_ = false;private Handler handler_ = new Handler();private Boolean connected_ = false;private long reconnectInterval_ = 5000;private boolean autoReconnect_ = false;private double latitude_ = 0;private double longitude_ = 0;private double radius_ = 0;private LocationManager locationManager_;private ClientHandler<LATMBProtocol.TrackingMessage> msgHandler_;// List of messages stored locallyprivate static List<LATMBMessage> storedMessages_ = new ArrayList<LATMBMessage>();@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Create the menuMenuInflater inflater = getMenuInflater();inflater.inflate(R.menu.messagemenu, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle item selectionswitch (item.getItemId()) {case R.id.menuPreferences:startActivity(new Intent(this, PreferenceActivity.class));return true;case R.id.menuDisconnect:disconnectFromServer();return true;case R.id.menuChangeChatroom:finish();return true;case R.id.menuRefresh:storedMessages_.clear();getInitialMessages();return true;default:return super.onOptionsItemSelected(item);}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.messageboard);newEntry_ = (EditText) findViewById(R.id.editMessage);submit_ = (Button) findViewById(R.id.buttonSubmit);status_ = (TextView) findViewById(R.id.textStatus);messageContainer_ = (ViewGroup) findViewById(R.id.messageList);Intent i = getIntent();server_ = i.getStringExtra("server");port_ = Integer.parseInt(i.getStringExtra("port"));username_ = i.getStringExtra("username");chatroom_ = i.getStringExtra("chatroom");useGPS_ = i.getBooleanExtra("gps", false);radius_ = i.getDoubleExtra("radius", 1);submit_.setOnClickListener(this);locationManager_ = (LocationManager) getSystemService(LOCATION_SERVICE);}@Overrideprotected void onPause() {super.onPause();// Stop the GPS updater if location is usedif (useGPS_) {locationManager_.removeUpdates(this);}stopAutoReconnect();disconnectFromServer();}@Overrideprotected void onResume() {super.onResume();// Start the GPS updater if location is usedif (useGPS_) {locationManager_.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);}startAutoReconnect();}@Overridepublic void onClick(View arg0) {// Send message if client is connected to server and location is acquired (only if gps is used)if ((connected_ && !useGPS_) || (connected_ && gpsAcquired_)) {SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);String text = newEntry_.getText().toString();Calendar c = Calendar.getInstance();DateTime timestamp = DateTime.newBuilder().setYear(c.get(Calendar.YEAR)).setMonth(c.get(Calendar.MONTH)).setDay(c.get(Calendar.DAY_OF_MONTH)).setHour(c.get(Calendar.HOUR_OF_DAY)).setMinute(c.get(Calendar.MINUTE)).setSecond(c.get(Calendar.SECOND)).build();// Get the expiration time from saved preferencesint exp_days = Integer.parseInt(sharedPrefs.getString("pref_MessageExpiration_Days", "1"));int exp_months = Integer.parseInt(sharedPrefs.getString("pref_MessageExpiration_Months", "0"));int exp_hours = Integer.parseInt(sharedPrefs.getString("pref_MessageExpiration_Hours", "0"));int exp_minutes = Integer.parseInt(sharedPrefs.getString("pref_MessageExpiration_Minutes", "0"));c.add(Calendar.DAY_OF_MONTH, exp_days);c.add(Calendar.MONTH, exp_months);c.add(Calendar.HOUR_OF_DAY, exp_hours);c.add(Calendar.MINUTE, exp_minutes);DateTime expiration = DateTime.newBuilder().setYear(c.get(Calendar.YEAR)).setMonth(c.get(Calendar.MONTH)).setDay(c.get(Calendar.DAY_OF_MONTH)).setHour(c.get(Calendar.HOUR_OF_DAY)).setMinute(c.get(Calendar.MINUTE)).setSecond(c.get(Calendar.SECOND)).build();Builder message = Message.newBuilder().setMessage(text).setTimestamp(timestamp).setExpiration(expiration);if (!username_.isEmpty()) {message.setUsername(username_);}if (!useGPS_) {message.setChatroom(chatroom_);} else {Position pos = Position.newBuilder().setLatitude(latitude_).setLongitude(longitude_).setAccuracy(0).build();message.setRadius(radius_);message.setCoordinates(pos);}TrackingMessage msg = TrackingMessage.newBuilder()// Type 1 == New Message.setId(0).setType(1).addMessage(message).build();// Send the message to the servermsgHandler_.send(msg);newEntry_.setText("");}}private boolean connectToServer(String server, int port) {try {synchronized (connected_) {if (connected_)return true;updateStatus("Connecting to server...");msgHandler_ = LATMBClient.connect(server, port);msgHandler_.setListener(this);connected_ = true;// Remove all currently saved messagesstoredMessages_.clear();if (!useGPS_) {getInitialMessages();}// Start the thread to check for expired messagesstartUpdaterThread();updateStatus("Connected to server [" + server + ":" + port + "]");}return true;} catch (Exception e) {Log.e(TAG, "Unable to connect to server", e);return false;}}private class ConnectWorker implements Runnable {public void run() {doConnect();}public void doConnect() {try {while (autoReconnect_ && !connectToServer(server_, port_)) {updateStatus("Attempting to reconnect to server...");Thread.currentThread().sleep(reconnectInterval_);}} catch (Exception e) {doConnect();}}}private void startAutoReconnect() {autoReconnect_ = true;ConnectWorker w = new ConnectWorker();Thread t = new Thread(w);t.start();}private void stopAutoReconnect() {autoReconnect_ = false;}private void disconnectFromServer() {synchronized (connected_) {connected_ = false;msgHandler_.disconnect();}}private void updateStatus(final String status) {handler_.post(new Runnable() {@Overridepublic void run() {status_.setText(status);}});}private void startUpdaterThread() {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true) {try {// If a new GPS coordinate is set, pull new list of messagesif (gpsChanged_ && gpsAcquired_) {storedMessages_.clear();getInitialMessages();gpsChanged_ = false;}// Refresh the displayupdateMessageUI();Thread.currentThread().sleep(5000);} catch (Exception e) {e.printStackTrace();}}}});t.start();}private void getInitialMessages() {Runnable r = new Runnable() {@Overridepublic void run() {if (connected_) {Calendar c = Calendar.getInstance();DateTime timestamp = DateTime.newBuilder().setYear(c.get(Calendar.YEAR)).setMonth(c.get(Calendar.MONTH)).setDay(c.get(Calendar.DAY_OF_MONTH)).setHour(c.get(Calendar.HOUR_OF_DAY)).setMinute(c.get(Calendar.MINUTE)).setSecond(c.get(Calendar.SECOND)).build();Builder message = Message.newBuilder().setMessage("").setTimestamp(timestamp).setExpiration(timestamp);if (!username_.isEmpty()) {message.setUsername(username_);}if (!useGPS_) {message.setChatroom(chatroom_);} else {Position pos = Position.newBuilder().setLatitude(latitude_).setLongitude(longitude_).setAccuracy(0).build();message.setRadius(radius_);message.setCoordinates(pos);}TrackingMessage msg = TrackingMessage.newBuilder()// Type 0 == Initial Message.setId(0).setType(0).addMessage(message).build();msgHandler_.send(msg);}}};handler_.post(r);}@Overridepublic void onLocationChanged(Location location) {latitude_ = location.getLatitude();longitude_ = location.getLongitude();if (latitude_ != 0 && longitude_ != 0) {gpsChanged_ = true;gpsAcquired_ = true;}}@Overridepublic void onProviderDisabled(String arg0) {updateStatus("GPS is disabled");Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);startActivity(intent);}@Overridepublic void onProviderEnabled(String arg0) {updateStatus("GPS is enabled");}@Overridepublic void onStatusChanged(String provider, int status, Bundle bundle) {switch (status) {case LocationProvider.OUT_OF_SERVICE:Toast.makeText(this, "GPS Status Changed: Out of Service", Toast.LENGTH_SHORT).show();break;case LocationProvider.TEMPORARILY_UNAVAILABLE:Toast.makeText(this, "GPS Status Changed: Temporarily Unavailable", Toast.LENGTH_SHORT).show();break;case LocationProvider.AVAILABLE:Toast.makeText(this, "GPS Status Changed: Available", Toast.LENGTH_SHORT).show();break;}}@Overridepublic void received(final TrackingMessage msg) {Runnable r = new Runnable() {@Overridepublic void run() {// Create a LATMBMessage from the TrackingMessage and store itList<Message> messages = msg.getMessageList();for (int i = 0; i < messages.size(); i++) {Message message = messages.get(i);DateTime timestamp = message.getTimestamp();DateTime expiration = message.getExpiration();LATMBMessage newEntry = new LATMBMessage();newEntry.setMessage(message.getMessage());Calendar time = new GregorianCalendar();time.set(timestamp.getYear(), timestamp.getMonth(), timestamp.getDay(),timestamp.getHour(), timestamp.getMinute(), timestamp.getSecond());newEntry.setTimestamp(time);Calendar exp = new GregorianCalendar();exp.set(expiration.getYear(), expiration.getMonth(), expiration.getDay(),expiration.getHour(), expiration.getMinute(), expiration.getSecond());newEntry.setExpiration(exp);if (message.hasUsername()) {newEntry.setUsername(message.getUsername());} else {newEntry.setUsername("Anonymous");}if (message.hasChatroom()) {newEntry.setChatroom(message.getChatroom());}if (message.hasCoordinates()) {Position coord = message.getCoordinates();newEntry.setLatitude(coord.getLatitude());newEntry.setLongitude(coord.getLongitude());}if (message.hasRadius()) {newEntry.setRadius(message.getRadius());}storedMessages_.add(newEntry);}}};handler_.post(r);updateMessageUI();}// Updates the GUI to show stored entriespublic void updateMessageUI() {Runnable r = new Runnable() {@Overridepublic void run() {if (connected_) {// Show the current chatroom or the current GPS coordinatesif (!useGPS_) {updateStatus("Current chatroom: " + chatroom_);} else {if (!gpsAcquired_) {updateStatus("Waiting for location...");} else {updateStatus("Using location (" + latitude_ + "," + longitude_ + ")");}}}removeExpiredMessages();messageContainer_.removeAllViews();// Print each messagefor (LATMBMessage message : storedMessages_) {Calendar time = message.getTimestamp();String msg = String.format("%d/%d/%d @ %d:%d:%d ~ %s\n>> %s",time.get(Calendar.DAY_OF_MONTH), time.get(Calendar.MONTH),time.get(Calendar.YEAR), time.get(Calendar.HOUR_OF_DAY),time.get(Calendar.MINUTE), time.get(Calendar.SECOND),message.getUsername(), message.getMessage());TextView v = new TextView(MessageBoardActivity.this);v.setText(msg);messageContainer_.addView(v);}}};handler_.post(r);}// Removes all stored expired messagespublic void removeExpiredMessages() {Runnable r = new Runnable() {@Overridepublic void run() {List<LATMBMessage> toRemove = new ArrayList<LATMBMessage>();for (LATMBMessage message : storedMessages_) {Calendar c = Calendar.getInstance();if (c.after(message.getExpiration())) {toRemove.add(message);}}for (LATMBMessage message : toRemove) {storedMessages_.remove(message);}}};handler_.post(r);}@Overridepublic void channelException(Throwable e) {updateStatus("Exception occured connecting to server");connected_ = false;}@Overridepublic void channelClosed(Channel c) {updateStatus("Connection to server closed");connected_ = false;}}