package apt.tutorial.two;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.util.Log;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import winterwell.jtwitter.Twitter;
import apt.tutorial.IPostListener;
import apt.tutorial.IPostMonitor;
public class Patchy extends Activity {
public static final String LATITUDE="apt.tutorial.latitude";
public static final String LONGITUDE="apt.tutorial.longitude";
public static final String STATUS_TEXT="apt.tutorial.statusText";
private EditText status=null;
private SharedPreferences prefs=null;
private Twitter client=null;
private List<TimelineEntry> timeline=new ArrayList<TimelineEntry>();
private TimelineAdapter adapter=null;
private IPostMonitor service=null;
private LocationManager locMgr=null;
private Pattern regexLocation=Pattern.compile("L\\:((\\-)?[0-9]+(\\.[0-9]+)?)\\,((\\-)?[0-9]+(\\.[0-9]+)?)");
private ServiceConnection svcConn=new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder binder) {
service=(IPostMonitor)binder;
try {
service.registerAccount(prefs.getString("user", null),
prefs.getString("password", null),
listener);
}
catch (Throwable t) {
Log.e("Patchy", "Exception in call to registerAccount()", t);
goBlooey(t);
}
}
public void onServiceDisconnected(ComponentName className) {
service=null;
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
status=(EditText)findViewById(R.id.status);
Button send=(Button)findViewById(R.id.send);
send.setOnClickListener(onSend);
prefs=PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(prefListener);
bindService(new Intent(this, PostMonitor.class), svcConn,
BIND_AUTO_CREATE);
adapter=new TimelineAdapter();
ListView list=(ListView)findViewById(R.id.timeline);
list.setAdapter(adapter);
list.setOnItemClickListener(onStatusClick);
clearNotification();
locMgr=(LocationManager)getSystemService(LOCATION_SERVICE);
locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10000, 10000.0f,
onLocationChange);
}
@Override
public void onNewIntent(Intent i) {
clearNotification();
}
@Override
public void onDestroy() {
super.onDestroy();
locMgr.removeUpdates(onLocationChange);
service.removeAccount(listener);
unbindService(svcConn);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(getApplication())
.inflate(R.menu.option, menu);
return(super.onCreateOptionsMenu(menu));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.prefs) {
startActivity(new Intent(this, EditPreferences.class));
return(true);
}
else if (item.getItemId()==R.id.location) {
insertLocation();
return(true);
}
else if (item.getItemId()==R.id.help) {
startActivity(new Intent(this, HelpPage.class));
return(true);
}
return(super.onOptionsItemSelected(item));
}
private void insertLocation() {
Location loc=locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc==null) {
Toast
.makeText(this, "No location available", Toast.LENGTH_SHORT)
.show();
}
else {
StringBuilder buf=new StringBuilder(status
.getText()
.toString());
buf.append(" L:");
buf.append(String.valueOf(loc.getLatitude()));
buf.append(",");
buf.append(String.valueOf(loc.getLongitude()));
status.setText(buf.toString());
}
}
private void clearNotification() {
NotificationManager mgr=
(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
mgr.cancel(PostMonitor.NOTIFICATION_ID);
}
synchronized private Twitter getClient() {
if (client==null) {
client=new Twitter(prefs.getString("user", ""),
prefs.getString("password", ""));
client.setAPIRootUrl("https://identi.ca/api");
}
return(client);
}
synchronized private void resetClient() {
client=null;
service.removeAccount(listener);
service.registerAccount(prefs.getString("user", ""),
prefs.getString("password", ""),
listener);
}
private void updateStatus() {
try {
getClient().updateStatus(status.getText().toString());
}
catch (Throwable t) {
Log.e("Patchy", "Exception in updateStatus()", t);
goBlooey(t);
}
}
private void goBlooey(Throwable t) {
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder
.setTitle("Exception!")
.setMessage(t.toString())
.setPositiveButton("OK", null)
.show();
}
private View.OnClickListener onSend=new View.OnClickListener() {
public void onClick(View v) {
updateStatus();
}
};
private SharedPreferences.OnSharedPreferenceChangeListener prefListener=
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences sharedPrefs,
String key) {
if (key.equals("user") || key.equals("password")) {
resetClient();
}
}
};
private IPostListener listener=new IPostListener() {
public void newFriendStatus(final String friend, final String status,
final String createdAt) {
runOnUiThread(new Runnable() {
public void run() {
adapter.insert(new TimelineEntry(friend,
createdAt,
status),
0);
}
});
}
};
private LocationListener onLocationChange=new LocationListener() {
public void onLocationChanged(Location location) {
// required for interface, not used
}
public void onProviderDisabled(String provider) {
// required for interface, not used
}
public void onProviderEnabled(String provider) {
// required for interface, not used
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
// required for interface, not used
}
};
private AdapterView.OnItemClickListener onStatusClick=
new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
TimelineEntry entry=timeline.get(position);
Matcher r=regexLocation.matcher(entry.status);
if (r.find()) {
double latitude=Double.valueOf(r.group(1));
double longitude=Double.valueOf(r.group(4));
Intent i=new Intent(Patchy.this, StatusMap.class);
i.putExtra(LATITUDE, latitude);
i.putExtra(LONGITUDE, longitude);
i.putExtra(STATUS_TEXT, entry.status);
startActivity(i);
}
}
};
class TimelineEntry {
String friend="";
String createdAt="";
String status="";
TimelineEntry(String friend, String createdAt,
String status) {
this.friend=friend;
this.createdAt=createdAt;
this.status=status;
}
}
class TimelineAdapter extends ArrayAdapter<TimelineEntry> {
TimelineAdapter() {
super(Patchy.this, R.layout.row, timeline);
}
public View getView(int position, View convertView,
ViewGroup parent) {
View row=convertView;
TimelineEntryWrapper wrapper=null;
if (row==null) {
LayoutInflater inflater=getLayoutInflater();
row=inflater.inflate(R.layout.row, parent, false);
wrapper=new TimelineEntryWrapper(row);
row.setTag(wrapper);
}
else {
wrapper=(TimelineEntryWrapper)row.getTag();
}
wrapper.populateFrom(timeline.get(position));
return(row);
}
}
class TimelineEntryWrapper {
private TextView friend=null;
private TextView createdAt=null;
private TextView status=null;
private View row=null;
TimelineEntryWrapper(View row) {
this.row=row;
}
void populateFrom(TimelineEntry s) {
getFriend().setText(s.friend);
getCreatedAt().setText(s.createdAt);
getStatus().setText(s.status);
}
TextView getFriend() {
if (friend==null) {
friend=(TextView)row.findViewById(R.id.friend);
}
return(friend);
}
TextView getCreatedAt() {
if (createdAt==null) {
createdAt=(TextView)row.findViewById(R.id.created_at);
}
return(createdAt);
}
TextView getStatus() {
if (status==null) {
status=(TextView)row.findViewById(R.id.status);
}
return(status);
}
}
}