0,0 → 1,542 |
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 locally |
private static List<LATMBMessage> storedMessages_ = new ArrayList<LATMBMessage>(); |
|
@Override |
public boolean onCreateOptionsMenu(Menu menu) { |
// Create the menu |
MenuInflater inflater = getMenuInflater(); |
inflater.inflate(R.menu.messagemenu, menu); |
return true; |
} |
|
@Override |
public boolean onOptionsItemSelected(MenuItem item) { |
// Handle item selection |
switch (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); |
} |
} |
|
@Override |
protected 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); |
} |
|
@Override |
protected void onPause() { |
super.onPause(); |
|
// Stop the GPS updater if location is used |
if (useGPS_) { |
locationManager_.removeUpdates(this); |
} |
stopAutoReconnect(); |
disconnectFromServer(); |
} |
|
@Override |
protected void onResume() { |
super.onResume(); |
|
// Start the GPS updater if location is used |
if (useGPS_) { |
locationManager_.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); |
} |
startAutoReconnect(); |
} |
|
@Override |
public 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 preferences |
int 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 server |
msgHandler_.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 messages |
storedMessages_.clear(); |
|
if (!useGPS_) { |
getInitialMessages(); |
} |
// Start the thread to check for expired messages |
startUpdaterThread(); |
|
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() { |
|
@Override |
public void run() { |
status_.setText(status); |
} |
}); |
} |
|
private void startUpdaterThread() { |
Thread t = new Thread(new Runnable() { |
|
@Override |
public void run() { |
while (true) { |
try { |
// If a new GPS coordinate is set, pull new list of messages |
if (gpsChanged_ && gpsAcquired_) { |
storedMessages_.clear(); |
getInitialMessages(); |
gpsChanged_ = false; |
} |
// Refresh the display |
updateMessageUI(); |
Thread.currentThread().sleep(5000); |
} catch (Exception e) { |
e.printStackTrace(); |
} |
} |
} |
}); |
t.start(); |
} |
|
private void getInitialMessages() { |
Runnable r = new Runnable() { |
|
@Override |
public 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); |
} |
|
@Override |
public void onLocationChanged(Location location) { |
latitude_ = location.getLatitude(); |
longitude_ = location.getLongitude(); |
if (latitude_ != 0 && longitude_ != 0) { |
gpsChanged_ = true; |
gpsAcquired_ = true; |
} |
} |
|
@Override |
public void onProviderDisabled(String arg0) { |
updateStatus("GPS is disabled"); |
Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); |
startActivity(intent); |
} |
|
@Override |
public void onProviderEnabled(String arg0) { |
updateStatus("GPS is enabled"); |
} |
|
@Override |
public 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; |
} |
|
} |
|
|
@Override |
public void received(final TrackingMessage msg) { |
Runnable r = new Runnable() { |
|
@Override |
public void run() { |
|
// Create a LATMBMessage from the TrackingMessage and store it |
List<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 entries |
public void updateMessageUI() { |
Runnable r = new Runnable() { |
|
@Override |
public void run() { |
if (connected_) { |
// Show the current chatroom or the current GPS coordinates |
if (!useGPS_) { |
updateStatus("Current chatroom: " + chatroom_); |
} else { |
if (!gpsAcquired_) { |
updateStatus("Waiting for location..."); |
} else { |
updateStatus("Using location (" + latitude_ + "," + longitude_ + ")"); |
} |
} |
} |
|
removeExpiredMessages(); |
|
messageContainer_.removeAllViews(); |
|
// Print each message |
for (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 messages |
public void removeExpiredMessages() { |
Runnable r = new Runnable() { |
|
@Override |
public 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); |
} |
|
@Override |
public void channelException(Throwable e) { |
updateStatus("Exception occured connecting to server"); |
connected_ = false; |
} |
|
@Override |
public void channelClosed(Channel c) { |
updateStatus("Connection to server closed"); |
connected_ = false; |
} |
|
} |