implement event reminders
This commit is contained in:
parent
ad7a08eaeb
commit
4e294d89d8
|
@ -60,6 +60,8 @@
|
|||
android:resource="@xml/widget_info"/>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".NotificationPublisher"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
@ -107,12 +107,12 @@ public class CalendarImpl implements DBHelper.DBOperationsListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void eventInserted() {
|
||||
public void eventInserted(Event event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventUpdated() {
|
||||
public void eventUpdated(Event event) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
private static DBOperationsListener mCallback;
|
||||
|
||||
private static final String DB_NAME = "events.db";
|
||||
private static final int DB_VERSION = 1;
|
||||
private static final int DB_VERSION = 2;
|
||||
|
||||
private static final String TABLE_NAME = "events";
|
||||
private static final String COL_ID = "id";
|
||||
|
@ -24,6 +24,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
private static final String COL_END_TS = "end_ts";
|
||||
private static final String COL_TITLE = "title";
|
||||
private static final String COL_DESCRIPTION = "description";
|
||||
private static final String COL_REMINDER_MINUTES = "reminder_minutes";
|
||||
|
||||
public static DBHelper newInstance(Context context, DBOperationsListener callback) {
|
||||
mCallback = callback;
|
||||
|
@ -42,19 +43,25 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
COL_START_TS + " INTEGER," +
|
||||
COL_END_TS + " INTEGER," +
|
||||
COL_TITLE + " TEXT," +
|
||||
COL_DESCRIPTION + " TEXT" +
|
||||
COL_DESCRIPTION + " TEXT," +
|
||||
COL_REMINDER_MINUTES + " INTEGER" +
|
||||
")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
if (oldVersion == 1) {
|
||||
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + COL_REMINDER_MINUTES + " INTEGER DEFAULT -1");
|
||||
}
|
||||
}
|
||||
|
||||
public void insert(Event event) {
|
||||
final ContentValues values = fillContentValues(event);
|
||||
mDb.insert(TABLE_NAME, null, values);
|
||||
mCallback.eventInserted();
|
||||
long id = mDb.insert(TABLE_NAME, null, values);
|
||||
event.setId((int) id);
|
||||
|
||||
if (mCallback != null)
|
||||
mCallback.eventInserted(event);
|
||||
}
|
||||
|
||||
public void update(Event event) {
|
||||
|
@ -62,7 +69,9 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
final String selection = COL_ID + " = ?";
|
||||
final String[] selectionArgs = {String.valueOf(event.getId())};
|
||||
mDb.update(TABLE_NAME, values, selection, selectionArgs);
|
||||
mCallback.eventUpdated();
|
||||
|
||||
if (mCallback != null)
|
||||
mCallback.eventUpdated(event);
|
||||
}
|
||||
|
||||
private ContentValues fillContentValues(Event event) {
|
||||
|
@ -71,24 +80,20 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
values.put(COL_END_TS, event.getEndTS());
|
||||
values.put(COL_TITLE, event.getTitle());
|
||||
values.put(COL_DESCRIPTION, event.getDescription());
|
||||
values.put(COL_REMINDER_MINUTES, event.getReminderMinutes());
|
||||
return values;
|
||||
}
|
||||
|
||||
public void deleteEvent(int id) {
|
||||
final String selection = COL_ID + " = ?";
|
||||
final String[] selectionArgs = {String.valueOf(id)};
|
||||
mDb.delete(TABLE_NAME, selection, selectionArgs);
|
||||
mCallback.eventsDeleted(1);
|
||||
}
|
||||
|
||||
public void deleteEvents(String[] ids) {
|
||||
final String selection = COL_ID + " IN (?)";
|
||||
mDb.delete(TABLE_NAME, selection, ids);
|
||||
mCallback.eventsDeleted(ids.length);
|
||||
|
||||
if (mCallback != null)
|
||||
mCallback.eventsDeleted(ids.length);
|
||||
}
|
||||
|
||||
public void getEvents(int fromTS, int toTS) {
|
||||
final String[] projection = {COL_ID, COL_START_TS, COL_END_TS, COL_TITLE, COL_DESCRIPTION};
|
||||
final String[] projection = {COL_ID, COL_START_TS, COL_END_TS, COL_TITLE, COL_DESCRIPTION, COL_REMINDER_MINUTES};
|
||||
List<Event> events = new ArrayList<>();
|
||||
final String selection = COL_START_TS + " <= ? AND " + COL_END_TS + " >= ?";
|
||||
final String[] selectionArgs = {String.valueOf(toTS), String.valueOf(fromTS)};
|
||||
|
@ -101,18 +106,40 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||
final int endTS = cursor.getInt(cursor.getColumnIndex(COL_END_TS));
|
||||
final String title = cursor.getString(cursor.getColumnIndex(COL_TITLE));
|
||||
final String description = cursor.getString(cursor.getColumnIndex(COL_DESCRIPTION));
|
||||
events.add(new Event(id, startTS, endTS, title, description));
|
||||
final int reminderMinutes = cursor.getInt(cursor.getColumnIndex(COL_REMINDER_MINUTES));
|
||||
events.add(new Event(id, startTS, endTS, title, description, reminderMinutes));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
mCallback.gotEvents(events);
|
||||
|
||||
if (mCallback != null)
|
||||
mCallback.gotEvents(events);
|
||||
}
|
||||
|
||||
public Event getEvent(int id) {
|
||||
final String[] projection = {COL_START_TS, COL_END_TS, COL_TITLE, COL_DESCRIPTION, COL_REMINDER_MINUTES};
|
||||
final String selection = COL_ID + " = ?";
|
||||
final String[] selectionArgs = {String.valueOf(id)};
|
||||
final Cursor cursor = mDb.query(TABLE_NAME, projection, selection, selectionArgs, null, null, null);
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToFirst()) {
|
||||
final int startTS = cursor.getInt(cursor.getColumnIndex(COL_START_TS));
|
||||
final int endTS = cursor.getInt(cursor.getColumnIndex(COL_END_TS));
|
||||
final String title = cursor.getString(cursor.getColumnIndex(COL_TITLE));
|
||||
final String description = cursor.getString(cursor.getColumnIndex(COL_DESCRIPTION));
|
||||
final int reminderMinutes = cursor.getInt(cursor.getColumnIndex(COL_REMINDER_MINUTES));
|
||||
cursor.close();
|
||||
return new Event(id, startTS, endTS, title, description, reminderMinutes);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public interface DBOperationsListener {
|
||||
void eventInserted();
|
||||
void eventInserted(Event event);
|
||||
|
||||
void eventUpdated();
|
||||
void eventUpdated(Event event);
|
||||
|
||||
void eventsDeleted(int cnt);
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package com.simplemobiletools.calendar;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.simplemobiletools.calendar.activities.EventActivity;
|
||||
import com.simplemobiletools.calendar.models.Event;
|
||||
|
||||
public class NotificationPublisher extends BroadcastReceiver {
|
||||
public static String EVENT_ID = "event_id";
|
||||
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
int id = intent.getIntExtra(EVENT_ID, -1);
|
||||
if (id == -1)
|
||||
return;
|
||||
|
||||
final Event event = DBHelper.newInstance(context, null).getEvent(id);
|
||||
if (event == null || event.getReminderMinutes() == -1)
|
||||
return;
|
||||
|
||||
final PendingIntent pendingIntent = getPendingIntent(context, event);
|
||||
final String startTime = Formatter.getTime(event.getStartTS());
|
||||
final String endTime = Formatter.getTime(event.getEndTS());
|
||||
final String title = event.getTitle();
|
||||
final Notification notification = getNotification(context, pendingIntent, startTime + " - " + endTime + " " + title);
|
||||
notificationManager.notify(id, notification);
|
||||
}
|
||||
|
||||
private PendingIntent getPendingIntent(Context context, Event event) {
|
||||
final Intent intent = new Intent(context, EventActivity.class);
|
||||
intent.putExtra(Constants.EVENT, event);
|
||||
return PendingIntent.getActivity(context, 0, intent, 0);
|
||||
}
|
||||
|
||||
private Notification getNotification(Context context, PendingIntent pendingIntent, String content) {
|
||||
final Notification.Builder builder = new Notification.Builder(context);
|
||||
builder.setContentTitle(context.getResources().getString(R.string.app_name));
|
||||
builder.setContentText(content);
|
||||
builder.setSmallIcon(R.mipmap.calendar);
|
||||
builder.setContentIntent(pendingIntent);
|
||||
builder.setAutoCancel(true);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -189,12 +189,12 @@ public class DayActivity extends AppCompatActivity
|
|||
}
|
||||
|
||||
@Override
|
||||
public void eventInserted() {
|
||||
public void eventInserted(Event event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventUpdated() {
|
||||
public void eventUpdated(Event event) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
package com.simplemobiletools.calendar.activities;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.TimePickerDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.AppCompatSpinner;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.DatePicker;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
@ -18,6 +23,7 @@ import android.widget.TimePicker;
|
|||
import com.simplemobiletools.calendar.Constants;
|
||||
import com.simplemobiletools.calendar.DBHelper;
|
||||
import com.simplemobiletools.calendar.Formatter;
|
||||
import com.simplemobiletools.calendar.NotificationPublisher;
|
||||
import com.simplemobiletools.calendar.R;
|
||||
import com.simplemobiletools.calendar.Utils;
|
||||
import com.simplemobiletools.calendar.models.Event;
|
||||
|
@ -39,11 +45,13 @@ public class EventActivity extends AppCompatActivity implements DBHelper.DBOpera
|
|||
@BindView(R.id.event_end_time) TextView mEndTime;
|
||||
@BindView(R.id.event_title) EditText mTitleET;
|
||||
@BindView(R.id.event_description) EditText mDescriptionET;
|
||||
@BindView(R.id.event_reminder_other) EditText mReminderOtherET;
|
||||
@BindView(R.id.event_reminder) AppCompatSpinner mReminder;
|
||||
|
||||
private static DateTime mEventStartDateTime;
|
||||
private static DateTime mEventEndDateTime;
|
||||
private static Event mEvent;
|
||||
private static boolean mWasReminderInit;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -55,6 +63,7 @@ public class EventActivity extends AppCompatActivity implements DBHelper.DBOpera
|
|||
if (intent == null)
|
||||
return;
|
||||
|
||||
mWasReminderInit = false;
|
||||
final Event event = (Event) intent.getSerializableExtra(Constants.EVENT);
|
||||
if (event != null) {
|
||||
mEvent = event;
|
||||
|
@ -72,6 +81,7 @@ public class EventActivity extends AppCompatActivity implements DBHelper.DBOpera
|
|||
updateStartTime();
|
||||
updateEndDate();
|
||||
updateEndTime();
|
||||
setupReminder();
|
||||
}
|
||||
|
||||
private void setupEditEvent() {
|
||||
|
@ -93,9 +103,42 @@ public class EventActivity extends AppCompatActivity implements DBHelper.DBOpera
|
|||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
|
||||
}
|
||||
|
||||
private void showKeyboard(EditText et) {
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(et, InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
|
||||
private void setupReminder() {
|
||||
switch (mEvent.getReminderMinutes()) {
|
||||
case -1:
|
||||
mReminder.setSelection(0);
|
||||
break;
|
||||
case 0:
|
||||
mReminder.setSelection(1);
|
||||
break;
|
||||
default:
|
||||
mReminder.setSelection(2);
|
||||
mReminderOtherET.setVisibility(View.VISIBLE);
|
||||
mReminderOtherET.setText(String.valueOf(mEvent.getReminderMinutes()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@OnItemSelected(R.id.event_reminder)
|
||||
public void handleReminder() {
|
||||
if (!mWasReminderInit) {
|
||||
mWasReminderInit = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mReminder.getSelectedItemPosition() == mReminder.getCount() - 1) {
|
||||
mReminderOtherET.setVisibility(View.VISIBLE);
|
||||
mReminderOtherET.requestFocus();
|
||||
showKeyboard(mReminderOtherET);
|
||||
} else {
|
||||
mReminderOtherET.setVisibility(View.GONE);
|
||||
hideKeyboard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -147,10 +190,12 @@ public class EventActivity extends AppCompatActivity implements DBHelper.DBOpera
|
|||
|
||||
final DBHelper dbHelper = DBHelper.newInstance(getApplicationContext(), this);
|
||||
final String description = mDescriptionET.getText().toString().trim();
|
||||
final int reminderMinutes = getReminderMinutes();
|
||||
mEvent.setStartTS(startTS);
|
||||
mEvent.setEndTS(endTS);
|
||||
mEvent.setTitle(title);
|
||||
mEvent.setDescription(description);
|
||||
mEvent.setReminderMinutes(reminderMinutes);
|
||||
if (mEvent.getId() == 0) {
|
||||
dbHelper.insert(mEvent);
|
||||
} else {
|
||||
|
@ -158,6 +203,21 @@ public class EventActivity extends AppCompatActivity implements DBHelper.DBOpera
|
|||
}
|
||||
}
|
||||
|
||||
private int getReminderMinutes() {
|
||||
switch (mReminder.getSelectedItemPosition()) {
|
||||
case 0:
|
||||
return -1;
|
||||
case 1:
|
||||
return 0;
|
||||
default:
|
||||
final String value = mReminderOtherET.getText().toString().trim();
|
||||
if (value.isEmpty())
|
||||
return 0;
|
||||
|
||||
return Integer.valueOf(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStartDate() {
|
||||
mStartDate.setText(Formatter.getEventDate(mEventStartDateTime));
|
||||
}
|
||||
|
@ -245,14 +305,34 @@ public class EventActivity extends AppCompatActivity implements DBHelper.DBOpera
|
|||
}
|
||||
}
|
||||
|
||||
private void handleNotification(Event event) {
|
||||
if (event.getReminderMinutes() == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long delayFromNow = (long) event.getStartTS() * 1000 - event.getReminderMinutes() * 60000 - System.currentTimeMillis();
|
||||
if (delayFromNow < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long notifInMs = SystemClock.elapsedRealtime() + delayFromNow;
|
||||
final Intent intent = new Intent(this, NotificationPublisher.class);
|
||||
intent.putExtra(NotificationPublisher.EVENT_ID, event.getId());
|
||||
final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, event.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, notifInMs, pendingIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventInserted() {
|
||||
public void eventInserted(Event event) {
|
||||
handleNotification(event);
|
||||
Utils.showToast(getApplicationContext(), R.string.event_added);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventUpdated() {
|
||||
public void eventUpdated(Event event) {
|
||||
handleNotification(event);
|
||||
Utils.showToast(getApplicationContext(), R.string.event_updated);
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -213,8 +213,10 @@ public class MainActivity extends AppCompatActivity implements Calendar {
|
|||
private void setupLabels() {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
final TextView dayTV = (TextView) findViewById(mRes.getIdentifier("label_" + i, "id", mPackageName));
|
||||
dayTV.setTextSize(mDayTextSize);
|
||||
dayTV.setTextColor(mWeakTextColor);
|
||||
if (dayTV != null) {
|
||||
dayTV.setTextSize(mDayTextSize);
|
||||
dayTV.setTextColor(mWeakTextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,12 @@ import java.io.Serializable;
|
|||
|
||||
public class Event implements Serializable {
|
||||
private static final long serialVersionUID = -32456795132354616L;
|
||||
private final int mId;
|
||||
private int mId;
|
||||
private int mStartTS;
|
||||
private int mEndTS;
|
||||
private String mTitle;
|
||||
private String mDescription;
|
||||
private int mReminderMinutes;
|
||||
|
||||
public Event() {
|
||||
mId = 0;
|
||||
|
@ -16,20 +17,26 @@ public class Event implements Serializable {
|
|||
mEndTS = 0;
|
||||
mTitle = "";
|
||||
mDescription = "";
|
||||
mReminderMinutes = -1;
|
||||
}
|
||||
|
||||
public Event(int id, int startTS, int endTS, String title, String description) {
|
||||
public Event(int id, int startTS, int endTS, String title, String description, int reminerMinutes) {
|
||||
mId = id;
|
||||
mStartTS = startTS;
|
||||
mEndTS = endTS;
|
||||
mTitle = title;
|
||||
mDescription = description;
|
||||
mReminderMinutes = reminerMinutes;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public int getStartTS() {
|
||||
return mStartTS;
|
||||
}
|
||||
|
@ -62,6 +69,14 @@ public class Event implements Serializable {
|
|||
mDescription = description;
|
||||
}
|
||||
|
||||
public int getReminderMinutes() {
|
||||
return mReminderMinutes;
|
||||
}
|
||||
|
||||
public void setReminderMinutes(int reminderMinutes) {
|
||||
mReminderMinutes = reminderMinutes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Event {" +
|
||||
|
@ -70,6 +85,7 @@ public class Event implements Serializable {
|
|||
", endTS=" + getEndTS() +
|
||||
", title=" + getTitle() +
|
||||
", description=" + getDescription() +
|
||||
", reminderMinutes=" + getReminderMinutes() +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,5 +121,17 @@
|
|||
android:entries="@array/reminders"
|
||||
android:padding="@dimen/activity_margin"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/event_reminder_other"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/event_reminder_label"
|
||||
android:layout_toRightOf="@+id/event_reminder"
|
||||
android:digits="0123456789"
|
||||
android:inputType="number"
|
||||
android:minEms="5"
|
||||
android:textSize="@dimen/day_text_size"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</ScrollView>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 698 B |
Binary file not shown.
After Width: | Height: | Size: 479 B |
Binary file not shown.
After Width: | Height: | Size: 782 B |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -3,7 +3,6 @@
|
|||
<string-array name="reminders">
|
||||
<item>@string/off</item>
|
||||
<item>@string/at_start</item>
|
||||
<item>@string/ten_mins</item>
|
||||
<item>@string/thirty_mins</item>
|
||||
<item>@string/minutes_before</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
<string name="reminder">Reminder</string>
|
||||
<string name="off">Off</string>
|
||||
<string name="at_start">At start</string>
|
||||
<string name="ten_mins">10 mins before</string>
|
||||
<string name="thirty_mins">30 mins before</string>
|
||||
<string name="minutes_before">Minutes before</string>
|
||||
|
||||
<!-- Day details -->
|
||||
<string name="details">Details</string>
|
||||
|
|
|
@ -50,6 +50,8 @@
|
|||
<item name="android:textSize">20sp</item>
|
||||
</style>
|
||||
|
||||
<style name="EditTextStyle" parent="@android:style/Widget.TextView"/>
|
||||
|
||||
<style name="SpinnerItem" parent="@android:style/Widget.TextView">
|
||||
<item name="android:paddingRight">@dimen/activity_margin</item>
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue