/* LogMyNight - Android app for logging night activities. Copyright (c) 2010 Michael Greifeneder <mikegr@gmx.net> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package at.madexperts.logmynight; import static java.lang.Math.abs; import static java.lang.Math.pow; import static java.lang.Math.sqrt; import java.util.ArrayList; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; import android.app.Dialog; import android.app.ListActivity; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.graphics.drawable.Drawable; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; public class MainActivity extends ListActivity { private final static String TAG = MainActivity.class.getName(); SQLiteDatabase db; AutoCompleteTextView auto; LocationHelper locationHelper; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); db = new DatabaseHelper(this).getWritableDatabase(); locationHelper = new LocationHelper(this, db); setContentView(R.layout.main); DatabaseHelper.debug(db, "drinks"); DatabaseHelper.debug(db, "drinklog"); setUpButtonBar(); setUpLocation(); updateList(); } private void setUpButtonBar() { updateTabView(findViewById(R.id.buttonBar1), "Rechnung", R.drawable.check_32, HistoryActivity.class); updateTabView(findViewById(R.id.buttonBar2), "Aufrisse", R.drawable.people_32, GalleryActivity.class); updateTabView(findViewById(R.id.buttonBar3), "Locations", R.drawable.icon_anti_small, MapsActivity.class); } View updateTabView(View tab, String name, int imageId, final Class activity) { ImageView image = (ImageView) tab.findViewById(R.id.tabImage); Drawable d = getResources().getDrawable(imageId); d.setBounds(0, 0, 32, 32); image.setImageDrawable(d); TextView text = (TextView) tab.findViewById(R.id.tabText); text.setText(name); tab.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Intent i = new Intent(MainActivity.this, activity); startActivity(i); } }); return tab; } private void setUpLocation() { auto = (AutoCompleteTextView) findViewById(R.id.mainLocationAutoCompleteTextView); auto.setThreshold(0); auto.setOnFocusChangeListener(new View.OnFocusChangeListener() { public void onFocusChange(View v, boolean hasFocus) { Log.d(TAG, "onFocusChange"); updateLocationAdapter(); } }); //Set to current location updateLocationViewAndSettings(); auto.setOnEditorActionListener(new AutoCompleteTextView.OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (event != null) { Log.d(TAG, "keyCode: " + event.getKeyCode()); } Log.d(TAG, "actionId: " + actionId); Log.d(TAG, "ENTER: " + KeyEvent.KEYCODE_ENTER); updateLocationAdapter(); Location location = locationHelper.getLocation(); double tmplat = 0; double tmplon = 0; if (location != null) { tmplat = location.getLatitude(); tmplon = location.getLongitude(); } final double lat = tmplat; final double lon = tmplon; final String name = auto.getText().toString(); final Integer id = getLocationId(name); Log.d(TAG, "Id of entered Location: " + id); if ((id == null) || (id != null && ! hasLocationData(id))) { Log.d(TAG, "Open dialog"); View view = getLayoutInflater().inflate(R.layout.yesnodialog, null); final Dialog dlg = new Dialog(MainActivity.this); Button yes = (Button) view.findViewById(R.id.yesNoDialogYesButton); yes.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { dlg.dismiss(); if (id == null) { long newId = insertLocation(name, lat, lon); updateCurrentLocation(newId); } else { updateLocation(id, name, lat, lon); updateCurrentLocation(id); } } }); Button no = (Button) view.findViewById(R.id.yesNoDialogNoButton); no.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { dlg.dismiss(); if (id == null) { long newId = insertLocation(name); updateCurrentLocation(newId); } //else do nothing } }); dlg.setTitle("Sind Sie am aktuellen Ort?"); dlg.setContentView(view); Log.d(TAG, "Show dialog"); dlg.show(); } else { // id not null + has location data already updateCurrentLocation(id); Log.d(TAG, "Lat: " + lat + ";Long:" + lon); } return false; } }); registerLocationChange(); } private void updateLocationViewAndSettings() { updateLocationViewAndSettings(locationHelper.getLocation()); } private void updateLocationViewAndSettings(Location loc) { Log.d(TAG, "setting location"); String location = locationHelper.getNearestLocation(loc); if (location != null) { Log.d(TAG, "Found closed location: " + location); auto.setText(location); updateCurrentLocation(getLocationId(location)); } } private void registerLocationChange() { final LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE); String provider = locationHelper.getBestProvider(lm); Log.d(TAG, "Request update from location provider: " + provider); lm.requestLocationUpdates(provider, 5*60*1000, 50, new LocationListener() { public void onStatusChanged(String provider, int status, Bundle extras) { } public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } public void onLocationChanged(Location location) { updateLocationViewAndSettings(location); } }); } private void updateLocationAdapter() { auto.setAdapter(locationHelper.getSortedNameAdapter()); } @Override public boolean onCreateOptionsMenu(Menu menu) { new MenuInflater(this).inflate(R.menu.mainmenu, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.historyMenuItem: openHistory(); return true; case R.id.galleryMenuItem: openGallery(); return true; case R.id.locationMenuItem: openLocations(); return true; } // TODO Auto-generated method stub return super.onOptionsItemSelected(item); } private void updateCurrentLocation(long id) { SharedPreferences prefs = getSharedPreferences("default", MODE_PRIVATE); prefs.edit().putLong("location", id); } private Long insertLocation(String name) { ContentValues cv = new ContentValues(); cv.put("name", name); return db.insert("location", null, cv); // table, nullColumnHack, values) execSQL("INSERT INTO location (_id, name, latitude, longitude) VALUES (null, ?, null, null)", new String[] {name}); } private Long insertLocation(String name, double latitude, double longitude) { ContentValues cv = new ContentValues(); cv.put("name", name); cv.put("latitude", latitude); cv.put("longitude", longitude); return db.insert("location", null, cv); } private void updateLocation(long id, String name, double lat, double lon) { db.execSQL("UPDATE location SET name = ?, latitude = ?, longitude = ? WHERE _id = ?", new String[] {name, Double.toString(lat), Double.toString(lon), Long.toString(id)}); } private Integer getLocationId(String name){ Cursor c = db.rawQuery("SELECT _id FROM location WHERE lower(name) = lower(?)", new String[] {name}); if (c.moveToFirst()) { if (c.isNull(0)) { return null; } return c.getInt(0); } return null; } private boolean hasLocationData(int id) { Cursor c = db.rawQuery("SELECT latitude, longitude FROM location WHERE _id = ?", new String[] {Integer.toString(id)}); if (c.moveToFirst()) { if (c.isNull(0) || c.isNull(1)) { return false; } return true; } return false; } private void openGallery() { Intent intent = new Intent(this, GalleryActivity.class); startActivity(intent); } private void openLocations() { Intent intent = new Intent(this, MapsActivity.class); startActivity(intent); } private void openHistory() { Intent intent = new Intent(this, HistoryActivity.class); startActivity(intent); } public void updateList() { //SELECT d._id, d.name as name, COUNT(l._id) as counter FROM drinks d LEFT OUTER JOIN drinklog l ON d._id = l.drink_id GROUP BY d._id, d.name; Cursor allCursor = db.rawQuery( "SELECT d._id as _id, d.name as name, d.category as category, COUNT(l._id) as counter " + "FROM drinks d " + "LEFT OUTER JOIN drinklog l ON d._id = l.drink_id " + "GROUP BY d._id, d.name", null); //SELECT d._id, d.name as name, COUNT(l._id) as counter FROM drinks d LEFT OUTER JOIN drinklog l ON d._id = l.drink_id GROUP BY d._id, d.name ORDER BY COUNT(l._id) DESC LIMIT 10; Cursor favouriteCursor = db.rawQuery( "SELECT d._id as _id, d.name as name, d.category as category, COUNT(l._id) as counter " + "FROM drinks d " + "LEFT OUTER JOIN drinklog l ON d._id = l.drink_id " + "GROUP BY d._id, d.name " + "ORDER BY COUNT(l._id) DESC LIMIT 3" , null); //SELECT d._id, d.name as name, COUNT(l._id) as counter FROM drinks d LEFT OUTER JOIN drinklog l ON d._id = l.drink_id GROUP BY d._id, d.name HAVING MAX(l.log_time) = (SELECT MAX(log_time) FROM drinklog); Cursor lastCursor = db.rawQuery( "SELECT d._id as _id, d.name as name, d.category as category, COUNT(l._id) as counter " + "FROM drinks d LEFT OUTER JOIN drinklog l ON d._id = l.drink_id " + "GROUP BY d._id, d.name " + "HAVING MAX(l.log_time) = (SELECT MAX(log_time) FROM drinklog)", null); SectionedAdapter adapter=new SectionedAdapter() { protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent) { Log.d(TAG, "Caption: " + caption + " for " + index); View result = convertView; if (result ==null) { result = getLayoutInflater().inflate(R.layout.sectionheader, parent, false); TextView textView = (TextView) result.findViewById(R.id.sectionHeader); textView.setText(caption); } return(result); } @Override public long getItemId(int position) { long value = super.getItemId(position); Log.d(TAG, "itemId=" + value); return value; } }; adapter.addSection("Last", new GradientAdapter(this, "Last", lastCursor)); adapter.addSection("Favourites", new GradientAdapter(this, "Favourites", favouriteCursor)); adapter.addSection("All drinks", new GradientAdapter(this, "All drinks", allCursor)); setListAdapter(adapter); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); updateList(); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Log.d(TAG, "Clicked: position:" + position + ", id:" + id); Intent i = new Intent(this, LogActivity.class); i.putExtra("drink", (int) id); startActivityForResult(i, 0); } @Override protected void onDestroy() { db.close(); super.onDestroy(); } class GradientAdapter extends I18NSimpleCursorAdapter { private String header; public GradientAdapter(Context ctx, String header, Cursor cursor) { super(ctx, R.layout.row, cursor, new String[] {"name", "counter", "category"}, new int[] {R.id.rowText, R.id.rowCounter, R.id.rowImage}, new int[ ] {0}); this.header = header; } @Override public View getView(int position, View convertView, ViewGroup parent) { Log.d(TAG, "Requested in Gradient " + header + ":"+ position); View view = super.getView(position, convertView, parent); //setBackgroundResource(R.drawable.entry); view.setBackgroundResource(R.drawable.entry); ImageView imageView = (ImageView) view.findViewById(R.id.rowImage); Cursor cursor = getCursor(); int category = cursor.getInt(cursor.getColumnIndex("category")); imageView.setImageResource(Utilities.getIcon(category)); return view; } public String getHeader() { return header; } } }