diff --git a/OsmAnd/res/layout/set_time_of_parking.xml b/OsmAnd/res/layout/parking_set_time_limit.xml similarity index 55% rename from OsmAnd/res/layout/set_time_of_parking.xml rename to OsmAnd/res/layout/parking_set_time_limit.xml index 2008836829..3088730631 100644 --- a/OsmAnd/res/layout/set_time_of_parking.xml +++ b/OsmAnd/res/layout/parking_set_time_limit.xml @@ -5,8 +5,15 @@ android:orientation="vertical" > + + \ No newline at end of file diff --git a/OsmAnd/res/layout/choose_type_of_parking.xml b/OsmAnd/res/layout/parking_set_type.xml similarity index 100% rename from OsmAnd/res/layout/choose_type_of_parking.xml rename to OsmAnd/res/layout/parking_set_type.xml diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index e928712179..9033c48472 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -9,6 +9,7 @@ 1. All your modified/created strings are in the top of the file (to make easier find what's translated). PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy --> + Add a notification to Calendar application Time-limited parking Time-unlimited parking The position of your parked car. %1$s diff --git a/OsmAnd/src/net/osmand/plus/parkingpoint/CalendarEvent.java b/OsmAnd/src/net/osmand/plus/parkingpoint/CalendarEvent.java new file mode 100644 index 0000000000..74f0cb7089 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/parkingpoint/CalendarEvent.java @@ -0,0 +1,369 @@ +package net.osmand.plus.parkingpoint; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map.Entry; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.util.Log; + +public class CalendarEvent +{ + private int calendarID = -1; + static String contentProvider; + static Uri remindersUri; + static Uri eventsUri; + static Uri calendars; + static String eventsTable; + static long EVENT_DURATION = 3600000; + static long REMINDER_TIME = 0; + + public Context context = null; + + /** + * @param a + * Constructor + */ + public CalendarEvent(Context c) + { + int sdk; + + try + { + sdk = new Integer(Build.VERSION.SDK_INT).intValue(); + } + catch(Exception e) + { + sdk = 9; + } + + this.context = c; + if(sdk >= 8) + { + //2.2 or higher + eventsTable = "view_events"; + contentProvider = "com.android.calendar"; + } + else + { + //anything older + eventsTable = "Events"; + contentProvider = "calendar"; + } + + remindersUri = Uri.parse(String.format("content://%s/reminders",contentProvider)); + eventsUri = Uri.parse(String.format("content://%s/events",contentProvider)); + calendars = Uri.parse(String.format("content://%s/calendars",contentProvider)); + } + + + /** + * @param strTitle + * as the Title of the event + * @param strDescription + * as the description of the event + * @param startTime + * as the time in millis the event begins + */ + public long insertEvent(String strTitle, String strDescription, long startTime, long endTime) throws Exception + { + if (calendarID != -1) + { + // Source: http://sgap.springnote.com/pages/5150959 + + ContentValues event = new ContentValues(); + event.put(EventColumns.ID, calendarID); + event.put(EventColumns.TITLE, strTitle); + event.put(EventColumns.DESC, strDescription); + event.put(EventColumns.START, startTime); + event.put(EventColumns.END, endTime); + event.put(EventColumns.ALLDAY, "0"); + event.put(EventColumns.STATUS, "1"); + event.put(EventColumns.VIS, "0"); + event.put(EventColumns.TRANS, "0"); + event.put(EventColumns.ALARM, "1"); + return Long.parseLong(context.getContentResolver().insert(eventsUri, event).getLastPathSegment()); + + } + return -1; + //throw exception + + } + + public long insertEvent(HashMap args) + { + //Convert to use ContentValues? + if (calendarID != -1) + { // Source: http://sgap.springnote.com/pages/5150959 + ContentValues event = new ContentValues(); + event.put(EventColumns.ID, calendarID); + + event.putAll(HashMapToContentValues(args)); + event.put(EventColumns.ALLDAY, "0"); + event.put(EventColumns.STATUS, "1"); + event.put(EventColumns.VIS, "0"); + event.put(EventColumns.TRANS, "0"); + event.put(EventColumns.ALARM, "1"); + + return Long.parseLong(context.getContentResolver().insert(eventsUri, event).getLastPathSegment()); + } + //throw exception + return -1; + + } + + public void addReminder(long eventID) + { + try + { + if (contains(eventID)) + { + ContentValues values = new ContentValues(); + + values.put("event_id", eventID); + values.put("method", 1); + values.put("minutes", REMINDER_TIME); + context.getContentResolver().insert(remindersUri, values); + + Log.d("Calendar Event", "Reminder Added for event " + eventID); + + } + else + Log.d("Calendar Event", "Reminder Not Added"); + } + catch(Exception e) + { + + } + + } + + public void updateReminder(long eventID, int minutes) + { + + Uri updateReminderUri = Uri.withAppendedPath(remindersUri, String.valueOf(eventID)); + ContentValues values = new ContentValues(); + values.put(ReminderColumns.ID, eventID); + values.put(ReminderColumns.METHOD, 1); + values.put(ReminderColumns.TIME, minutes); + + context.getContentResolver().update(updateReminderUri, values, null, null); + Log.d("Calendar Event", "Alarm Updated"); + } + + public void deleteReminder(long eventID) + { + + Uri reminderUri = Uri.withAppendedPath(remindersUri, String.valueOf(eventID)); + context.getContentResolver().delete(reminderUri, null, null); + Log.d("Calendar Event", "Reminder deleted"); + } + + public boolean containsAlarm(long eventID) + { + String selection = ReminderColumns.ID + "=" + eventID; + String[] projection = new String[] { ReminderColumns.METHOD }; + Cursor cursor = context.getContentResolver().query(remindersUri, projection, selection, null, null); + + if (cursor.getCount() > 0) + { + cursor.close(); + Log.d("Calendar Event", "Contains Reminder"); + return true; + } + if(cursor != null) + cursor.close(); + Log.d("Calendar Event", "Does not contain a reminder for " + eventID); + return false; + } + + /** + * Removes the eventID passed Returns the number of rows removed + * + * @param iEventID + * as the eventID to remove + */ + public int removeEvent(long iEventID) + { + Log.d("studentspet", "removing event.. " + iEventID); + if (calendarID != -1 && iEventID != -1) + { + if (this.contains(iEventID)) + { + Uri deleteEventUri = Uri.withAppendedPath(eventsUri, String.valueOf(iEventID)); + return context.getContentResolver().delete(deleteEventUri, null, null); + } + } + return -1; + } + + /** + * Returns boolean specifying if the passed EventID is in the Calendar + * + * @param iEventID + */ + public boolean contains(long iEventID) + { + if (calendarID != -1) + { + //Wrong table name for android 2.2 + String[] projection = new String[] { EventColumns.TITLE, CalendarColumns.ID }; + Cursor managedCursor = context.getContentResolver().query(eventsUri, projection, eventsTable+"._id=" + iEventID, null, null); + while (managedCursor.moveToNext()) + { + managedCursor.close(); + return true; + } + if(managedCursor != null) + managedCursor.close(); + } + + + return false; + } + + /** + * Returns the number of rows updated + * + * @param iEventID + * as the eventID to update + * @param whereArgs + * as the Set arguments see Where class + */ + public int updateEvent(long iEventID, HashMap args) + { + if (calendarID != -1) + { + if (contains(iEventID)) + { + Uri updateEventUri = Uri.withAppendedPath(eventsUri, String.valueOf(iEventID)); + return context.getContentResolver().update(updateEventUri, HashMapToContentValues(args), null, null); + } + + } + + return -1; + + } + + private ContentValues HashMapToContentValues(HashMap hm) + { + ContentValues cv = new ContentValues(); + for (Entry kvp : hm.entrySet()) + { + cv.put(kvp.getKey(), kvp.getValue()); + } + + return cv; + + } + + /** + * @return ArrayList as list of calendars available + */ + //needs rewritten + public ArrayList getCalendars() + { + ArrayList calendarList = new ArrayList(); + String[] projection = new String[] { CalendarColumns.ID, CalendarColumns.NAME, CalendarColumns.DISPLAYNAME}; + Cursor managedCursor = context.getContentResolver().query(calendars, projection, null, null, null); + + if (managedCursor.getCount() > 0) + { + int nameColumn = managedCursor.getColumnIndex(CalendarColumns.NAME); + int displayNameColumn = managedCursor.getColumnIndex(CalendarColumns.DISPLAYNAME); + int idColumn = managedCursor.getColumnIndex(CalendarColumns.ID); + while (managedCursor.moveToNext()) + { + if (!managedCursor.isNull(nameColumn)) + calendarList.add(new CalendarListItem(managedCursor.getString(nameColumn), managedCursor.getLong(idColumn))); + else + calendarList.add(new CalendarListItem(managedCursor.getString(displayNameColumn), managedCursor.getLong(idColumn))); + } + } + if(managedCursor != null) + managedCursor.close(); + + return calendarList; + + } + + /** + * + * @return calendarID as selected calendar's id + */ + public long getSelectedCalendar() + { + return calendarID; + } + + /** + * @param newCalendarID + * as new calendar + */ + public void setSelectedCalendar(int newCalendarID) + { + calendarID = newCalendarID; + } + + class CalendarException extends Exception + { + private static final long serialVersionUID = 0; + + public CalendarException(String desc) + { + super(desc); + } + } + + + + + public static class CalendarListItem + { + + String name; + long id; + + public CalendarListItem(String calendarName, long calendarID) + { + this.name = calendarName; + this.id = calendarID; + } + } + + public static class EventColumns + { + public static final String ID = "calendar_id"; + public static final String TITLE = "title"; + public static final String DESC = "description"; + public static final String START = "dtstart"; + public static final String END = "dtend"; + public static final String ALLDAY = "allDay"; + public static final String STATUS = "eventStatus"; + public static final String VIS = "visibility"; + public static final String TRANS = "transparency"; + public static final String ALARM = "hasAlarm"; + } + + public static class ReminderColumns + { + public static final String ID = "event_id"; + public static final String METHOD = "method"; + public static final String TIME = "minutes"; + } + + public static class CalendarColumns + { + public static final String ID = "_id"; + public static final String TITLE = "title"; + public static final String NAME = "name"; + public static final String DISPLAYNAME = "displayName"; + } + + +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionLayer.java b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionLayer.java index 3800c1e724..7086e29dbe 100644 --- a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionLayer.java +++ b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionLayer.java @@ -16,10 +16,7 @@ import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.TextInfoControl; -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; import android.content.Context; -import android.content.DialogInterface; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -187,33 +184,12 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL return view.getContext().getString(R.string.osmand_parking_position_name); } - public void setParkingPoint(LatLon point) { + public void setParkingPointOnLayer(LatLon point) { this.parkingPoint = point; if (view != null && view.getLayers().contains(ParkingPositionLayer.this)) { view.refreshMap(); } } - - /** - * Method creates confirmation dialog for deletion of a parking location - */ - public void showDeleteDialog() { - Builder confirm = new AlertDialog.Builder(map); - confirm.setTitle("Delete parking location"); - confirm.setMessage("Do you want to remove the location of the parked car?"); - confirm.setCancelable(true); - confirm.setPositiveButton(R.string.default_buttons_yes, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - settings.clearParkingPosition(); -// TODO Remove the event from Calendar app - view.refreshMap(); - } - }); - confirm.setNegativeButton(R.string.default_buttons_cancel, null); - confirm.show(); - } /** * @param latitude diff --git a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java index e7d35f53b1..1e07d30705 100644 --- a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java +++ b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java @@ -14,8 +14,8 @@ import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.Intent; -import android.text.format.Time; import android.view.View; +import android.widget.CheckBox; import android.widget.ImageButton; import android.widget.TimePicker; @@ -85,12 +85,8 @@ public class ParkingPositionPlugin extends OsmandPlugin { boolean isChecked, DialogInterface dialog) { if (resId == R.string.context_menu_item_add_parking_point) { showAddParkingDialog(mapActivity, latitude, longitude); - // settings.setParkingPosition(latitude, longitude); - // if - // (mapActivity.getMapView().getLayers().contains(parkingLayer)) - // parkingLayer.setParkingPoint(settings.getParkingPosition()); } else if ((resId == R.string.context_menu_item_delete_parking_point)) { - parkingLayer.showDeleteDialog(); + showDeleteDialog(mapActivity); } } }; @@ -103,33 +99,27 @@ public class ParkingPositionPlugin extends OsmandPlugin { } /** - * Method creates confirmation dialog for deletion of a parking location + * Method dialog for adding of a parking location */ - public void showAddParkingDialog(final MapActivity mapActivity, - final double latitude, final double longitude) { - final View addParking = mapActivity.getLayoutInflater().inflate(R.layout.choose_type_of_parking, null); + private void showAddParkingDialog(final MapActivity mapActivity, final double latitude, final double longitude) { + final View addParking = mapActivity.getLayoutInflater().inflate(R.layout.parking_set_type, null); Builder choose = new AlertDialog.Builder(mapActivity); choose.setView(addParking); choose.setTitle("Choose the type of parking"); - final AlertDialog create = choose.create(); - ImageButton limitButton = (ImageButton) addParking - .findViewById(R.id.parking_lim_button); + ImageButton limitButton = (ImageButton) addParking.findViewById(R.id.parking_lim_button); limitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - create.cancel(); setParkingPosition(mapActivity, latitude, longitude, true); showChooseParkingTypeDialog(mapActivity); } }); - ImageButton noLimitButton = (ImageButton) addParking - .findViewById(R.id.parking_no_lim_button); + ImageButton noLimitButton = (ImageButton) addParking.findViewById(R.id.parking_no_lim_button); noLimitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - create.cancel(); setParkingPosition(mapActivity, latitude, longitude, false); } }); @@ -138,46 +128,79 @@ public class ParkingPositionPlugin extends OsmandPlugin { } + + /** + * Method creates confirmation dialog for deletion of a parking location + */ + private void showDeleteDialog(final MapActivity mapActivity) { + Builder confirm = new AlertDialog.Builder(mapActivity); + confirm.setTitle("Delete parking location"); + confirm.setMessage("Do you want to remove the location of the parked car?"); + confirm.setCancelable(true); + confirm.setPositiveButton(R.string.default_buttons_yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + settings.clearParkingPosition(); + deleteCalendarEvent(); + } + }); + confirm.setNegativeButton(R.string.default_buttons_cancel, null); + confirm.show(); + } + private void showChooseParkingTypeDialog(final MapActivity mapActivity) { - final View setTimeParking = mapActivity.getLayoutInflater().inflate(R.layout.set_time_of_parking, null); + final View setTimeParking = mapActivity.getLayoutInflater().inflate(R.layout.parking_set_time_limit, null); Builder setTime = new AlertDialog.Builder(mapActivity); setTime.setView(setTimeParking); setTime.setTitle("Set the time limit of parking"); setTime.setNegativeButton(R.string.default_buttons_cancel, null); setTime.setPositiveButton(R.string.default_buttons_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - TimePicker timePicker = (TimePicker) setTimeParking.findViewById(R.id.parkingTimePicker); - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.HOUR, timePicker.getCurrentHour()); - cal.set(Calendar.MINUTE, timePicker.getCurrentMinute()); - settings.setParkingTime(cal.getTimeInMillis()); - addCalendarEvent(setTimeParking); - } - }); + @Override + public void onClick(DialogInterface dialog, int which) { + TimePicker timePicker = (TimePicker) setTimeParking.findViewById(R.id.parking_time_picker); + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.HOUR, timePicker.getCurrentHour()); + cal.set(Calendar.MINUTE, timePicker.getCurrentMinute()); + settings.setParkingTime(cal.getTimeInMillis()); + CheckBox addCalendarEvent = (CheckBox)setTimeParking.findViewById(R.id.check_event_in_calendar); + if (addCalendarEvent.isChecked()) + addCalendarEvent(setTimeParking); + } + }); setTime.create(); setTime.show(); } - private void addCalendarEvent(View view) { - Calendar cal = Calendar.getInstance(); + private void addCalendarEvent(View view) { Intent intent = new Intent(Intent.ACTION_EDIT); intent.setType("vnd.android.cursor.item/event"); intent.putExtra("calendar_id", 1); intent.putExtra("beginTime", settings.getParkingTime()); intent.putExtra("allDay", false); - intent.putExtra("endTime", cal.getTimeInMillis()+60*60*1000); + intent.putExtra("endTime", settings.getParkingTime()+60*60*1000); intent.putExtra("title", "Pickup the car from parking"); intent.putExtra("name", "parkingEvent"); -// opens Calendar app. TODO Is that needed? view.getContext().startActivity(intent); } + + private void deleteCalendarEvent() { +// TODO delete calendar event +// Uri calendars = Uri.parse(String.format("content://%s/calendars", "com.android.calendar")); +// String[] projection = new String[] { CalendarColumns.ID, CalendarColumns.NAME, CalendarColumns.DISPLAYNAME}; +// TODO next line throws SecurityException +// Cursor managedCursor = view.getContext().getContentResolver().query(calendars, projection, null, null, null); + } private void setParkingPosition(final MapActivity mapActivity, final double latitude, final double longitude, boolean isLimited) { +// to set a new parking position first the event for old parking (in case of a time-limit parking) should be deleted! + deleteCalendarEvent(); settings.setParkingPosition(latitude, longitude); settings.setParkingType(isLimited); if (mapActivity.getMapView().getLayers().contains(parkingLayer)) { - parkingLayer.setParkingPoint(settings.getParkingPosition()); + parkingLayer.setParkingPointOnLayer(settings.getParkingPosition()); } } + + }