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
ReminderAdapterclass 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.