Mobile Reminder app

MainActivity.java

Code Snippet: Main Activity Setup

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

database = ReminderDatabase.getInstance(this);
reminderList = new ArrayList<>();

recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

adapter = new ReminderAdapter(reminderList, new ReminderAdapter.OnDeleteClickListener() {
@Override
public void onDeleteClick(Reminder reminder) {
deleteReminder(reminder);
}
});
recyclerView.setAdapter(adapter);

loadReminders();

Button addButton = findViewById(R.id.addButton);
addButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Start AddReminderActivity
Intent intent = new Intent(MainActivity.this, AddReminderActivity.class);
startActivityForResult(intent, ADD_REMINDER_REQUEST);
}
});

// Check and request alarm permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (!alarmPermissionGranted()) {
requestAlarmPermission();
}
}
}

Explanation:

  • This snippet initializes the main activity, sets up the RecyclerView for displaying reminders, and sets up a button for adding new reminders.
  • It also includes a check for the necessary alarm permissions on newer Android versions.

Code Snippet: Adding a Reminder

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (requestCode == ADD_REMINDER_REQUEST && resultCode == RESULT_OK && data != null) {
String name = data.getStringExtra("name");
String date = data.getStringExtra("date");

if (name != null && date != null) {
Reminder reminder = new Reminder(name, date);

new Thread(new Runnable() {
@Override
public void run() {
database.reminderDao().insert(reminder);
loadReminders();

try {
scheduleNotification(parseDate(date), name);
} catch (ParseException e) {
Log.e("MainActivity", "Failed to parse date", e);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Failed to parse date", Toast.LENGTH_SHORT).show();
}
});
}
}
}).start();
}
}
}

Explanation:

  • This code handles the result from the AddReminderActivity, creating a new Reminder object and saving it to the database.
  • It also schedules a notification for the reminder.

Code Snippet: Scheduling a Notification

private void scheduleNotification(Date date, String name) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);

// Set time to midday (12:00 PM)
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

// Subtract 1 day
calendar.add(Calendar.DAY_OF_YEAR, -1);

// Create an intent for NotificationReceiver
Intent notificationIntent = new Intent(this, NotificationReceiver.class);
notificationIntent.putExtra("name", name);

// Create a PendingIntent
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, NOTIFICATION_ID,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

// Get AlarmManager
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
// Schedule the alarm
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}

Explanation:

  • This function schedules a notification to be triggered at midday, one day before the specified date.

Code Snippet: Deleting a Reminder

private void deleteReminder(Reminder reminder) {
new Thread(new Runnable() {
@Override
public void run() {
database.reminderDao().delete(reminder);
loadReminders();

// Optionally, cancel the scheduled notification for this reminder
cancelNotification(reminder);
}
}).start();
}

Explanation:

  • This method deletes a reminder from the database and cancels the associated notification.

Code Snippet: Requesting Alarm Permissions

private boolean alarmPermissionGranted() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
return getSystemService(AlarmManager.class).canScheduleExactAlarms();
}
return true;
}

private void requestAlarmPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
startActivity(intent);
}
}

Explanation:

  • These methods check if the app has the required permission to schedule exact alarms and request it if not granted.

ReminderAdapter.java

Code Snippet: Adapter with Delete Button

public class ReminderAdapter extends RecyclerView.Adapter<ReminderAdapter.ReminderViewHolder> {

private List<Reminder> reminders;
private OnDeleteClickListener deleteClickListener;

public interface OnDeleteClickListener {
void onDeleteClick(Reminder reminder);
}

public ReminderAdapter(List<Reminder> reminders, OnDeleteClickListener deleteClickListener) {
this.reminders = reminders;
this.deleteClickListener = deleteClickListener;
}

@NonNull
@Override
public ReminderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_list, parent, false);
return new ReminderViewHolder(itemView);
}

@Override
public void onBindViewHolder(@NonNull ReminderViewHolder holder, int position) {
Reminder reminder = reminders.get(position);
holder.nameTextView.setText(reminder.getName());
holder.dateTextView.setText(reminder.getDate());
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
deleteClickListener.onDeleteClick(reminder);
}
});
}

@Override
public int getItemCount() {
return reminders.size();
}

class ReminderViewHolder extends RecyclerView.ViewHolder {
TextView nameTextView;
TextView dateTextView;
Button deleteButton;

public ReminderViewHolder(@NonNull View itemView) {
super(itemView);
nameTextView = itemView.findViewById(R.id.nameTextView);
dateTextView = itemView.findViewById(R.id.dateTextView);
deleteButton = itemView.findViewById(R.id.deleteButton);
}
}
}

Explanation:

  • The ReminderAdapter class binds the reminder data to the RecyclerView and sets up a click listener for the delete button.

item_list.xml

Code Snippet: Reminder Item Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">

<TextView
android:id="@+id/nameTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp" />

<TextView
android:id="@+id/dateTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp" />

<Button
android:id="@+id/deleteButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete" />

</LinearLayout>

Explanation:

  • This XML layout defines how each reminder item is displayed in the RecyclerView, with the reminder’s name, date, and a delete button aligned horizontally.

By breaking down the code into smaller, well-documented sections, you can make it easier for readers to understand the structure and functionality of your app.