I have created a simple project that works as an alarm clock. The user enters a specific date and time, and when the application reaches the previously set time and date, the user receives an alert as a notification.
But I am currently facing a problem executing the application after updating the sdk to 32 and newer versions
this all Project
manifest
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AlarmNotification"
tools:targetApi="32">
<activity
android:name=".MainPage"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".NotifierAlarm"/>
</application>
</manifest>
Classes
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class AdapterReminders extends RecyclerView.Adapter<AdapterReminders.MyViewHolder>{
private final List<Reminders> allReminders;
private TextView message,time;
public ImageView deleteReminder;
private onItemClickListener mListener;
public AdapterReminders(List<Reminders> allReminders) {
this.allReminders = allReminders;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.reminder_item,viewGroup,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
Reminders reminders = allReminders.get(i);
if(!reminders.getMessage().equals(""))
message.setText(reminders.getMessage());
else
message.setHint("No Message");
time.setText(reminders.getRemindDate().toString());
}
@Override
public int getItemCount() {
return allReminders.size();
}
public interface onItemClickListener{
void onDeleteClick(int position);
}
public void setOnItemClickListener(onItemClickListener object){
mListener = object;
}
public class MyViewHolder extends RecyclerView.ViewHolder{
public MyViewHolder(@NonNull View itemView) {
super(itemView);
message = itemView.findViewById(R.id.textView1);
time = itemView.findViewById(R.id.textView21);
deleteReminder = itemView.findViewById(R.id.ReminderDelete);
deleteReminder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mListener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
mListener.onDeleteClick(position);
}
}
}
});
}
}
}
@Database(entities = {Reminders.class},version = 1)
@TypeConverters({DateTypeConverter.class})
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE = null;
public abstract RoomDAO getRoomDAO();
public static AppDatabase geAppdatabase(Context context){
if(INSTANCE==null){
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),AppDatabase.class,"stiwi")
.allowMainThreadQueries()
.build();
}
return INSTANCE;
}
public static void destroyInstance(){
INSTANCE = null;
}
}
import androidx.room.TypeConverter;
import java.util.Date;
public class DateTypeConverter {
@TypeConverter
public Date LongtoDateConverter(Long date){
return new Date(date);
}
@TypeConverter
public Long DatetoLongConverter(Date date){
return date.getTime();
}
}
public class MainPage extends AppCompatActivity {
private FloatingActionButton add;
private Dialog dialog;
private AppDatabase appDatabase;
private RecyclerView recyclerView;
private AdapterReminders adapter;
private List<Reminders> temp;
private TextView empty;
private ArrayList<Integer> parallelArrayOf_Ids;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
Toolbar toolbar1 = findViewById(R.id.ReminderToolbar1);
setSupportActionBar(toolbar1);
appDatabase = AppDatabase.geAppdatabase(MainPage.this);
add = findViewById(R.id.floatingButton);
empty = findViewById(R.id.empty);
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addReminder();
}
});
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainPage.this);
recyclerView.setLayoutManager(linearLayoutManager);
setItemsInRecyclerView();
}
public void addReminder(){
dialog = new Dialog(MainPage.this);
dialog.setContentView(R.layout.floating_popup);
final TextView textView = dialog.findViewById(R.id.date);
Button select,add,cancel;
select = dialog.findViewById(R.id.selectDate);
add = dialog.findViewById(R.id.addButton);
cancel = dialog.findViewById(R.id.cancelButton);
final EditText message = dialog.findViewById(R.id.reminderMessage);
final Calendar newCalender = Calendar.getInstance();
select.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DatePickerDialog dialog = new DatePickerDialog(MainPage.this, new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, final int year, final int month, final int dayOfMonth) {
final Calendar newDate = Calendar.getInstance();
Calendar newTime = Calendar.getInstance();
TimePickerDialog time = new TimePickerDialog(MainPage.this, new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
newDate.set(year,month,dayOfMonth,hourOfDay,minute,0);
Calendar tem = Calendar.getInstance();
Log.w("TIME",System.currentTimeMillis()+"");
if(newDate.getTimeInMillis()-tem.getTimeInMillis()>0)
textView.setText(newDate.getTime().toString());
else
Toast.makeText(MainPage.this,"Invalid time",Toast.LENGTH_SHORT).show();
}
},newTime.get(Calendar.HOUR_OF_DAY),newTime.get(Calendar.MINUTE),true);
time.show();
}
},newCalender.get(Calendar.YEAR),newCalender.get(Calendar.MONTH),newCalender.get(Calendar.DAY_OF_MONTH));
dialog.getDatePicker().setMinDate(System.currentTimeMillis());
dialog.show();
}
});
add.setOnClickListener(new View.OnClickListener() {
@SuppressLint("ScheduleExactAlarm")
@Override
public void onClick(View v) {
RoomDAO roomDAO = appDatabase.getRoomDAO();
Reminders reminders = new Reminders();
reminders.setMessage(message.getText().toString().trim());
Date remind;
try {
SimpleDateFormat format =
new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
remind = format.parse(textView.getText().toString().trim());
}
catch(ParseException pe) {
Toast.makeText(MainPage.this, "mainPage error line 133", Toast.LENGTH_SHORT).show();
throw new IllegalArgumentException(pe);
}
reminders.setRemindDate(remind);
roomDAO.Insert(reminders);
List<Reminders> l = roomDAO.getAll();
reminders = l.get(l.size()-1);
Log.e("ID chahiye",reminders.getId()+"");
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+5:30"));
calendar.setTime(remind);
calendar.set(Calendar.SECOND,0);
Intent intent = new Intent(MainPage.this,NotifierAlarm.class);
intent.putExtra("Message",reminders.getMessage());
intent.putExtra("RemindDate",reminders.getRemindDate().toString());
intent.putExtra("id",reminders.getId());
PendingIntent intent1 = PendingIntent.getBroadcast(MainPage.this,reminders.getId(),intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),intent1);
Toast.makeText(MainPage.this,"Inserted Successfully",Toast.LENGTH_SHORT).show();
setItemsInRecyclerView();
AppDatabase.destroyInstance();
dialog.dismiss();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.show();
}
public void setItemsInRecyclerView(){
RoomDAO dao = appDatabase.getRoomDAO();
temp = dao.orderThetable();
if(temp.size()>0) {
empty.setVisibility(View.INVISIBLE);
recyclerView.setVisibility(View.VISIBLE);
}
parallelArrayOf_Ids = new ArrayList<>();
for(int i = 0; i < temp.size();i++)
parallelArrayOf_Ids.add(temp.get(i).getId());
adapter = new AdapterReminders(temp);
recyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(new AdapterReminders.onItemClickListener() {
@Override
public void onDeleteClick(int position) {
//removing alarm
alarmRemover(parallelArrayOf_Ids.get(position));
//removing from data base
AppDatabase appDatabase2 = AppDatabase.geAppdatabase(MainPage.this);
final RoomDAO dao1 = appDatabase2.getRoomDAO();
Reminders reminder = dao1.getObjectUsingID(parallelArrayOf_Ids.get(position));
dao1.Delete(reminder);
AppDatabase.destroyInstance();
Toast.makeText(MainPage.this, "Deleted", Toast.LENGTH_SHORT).show();
setItemsInRecyclerView();
}
});
}
public void DeleteAll(View v){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Do you want to delete all reminders?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
AppDatabase appDatabase2 = AppDatabase.geAppdatabase(MainPage.this);
final RoomDAO dao1 = appDatabase2.getRoomDAO();
List<Integer> ids = dao1.getAllIds();
for(int i = 0; i<ids.size();i++) {
alarmRemover(ids.get(i));
//Log.d("ReminderId", ids.get(i)+ "n");
}
// for(int i = 0;i< parallelArrayOf_Ids.size();i++)
// Log.d("ReminderId","parallel id" +parallelArrayOf_Ids.get(i));
dao1.DeleteAll();//iss line ko last me he rahne de
AppDatabase.destroyInstance();
Toast.makeText(MainPage.this, "All deleted", Toast.LENGTH_SHORT).show();
setItemsInRecyclerView();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
}
public void alarmRemover(int id){
Intent intent = new Intent(this,NotifierAlarm.class);
PendingIntent intent1 = PendingIntent.getBroadcast(this,id,intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.cancel(intent1);
}
}
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import androidx.core.app.NotificationCompat;
public class NotifierAlarm extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
AppDatabase appDatabase = AppDatabase.geAppdatabase(context.getApplicationContext());
RoomDAO roomDAO = appDatabase.getRoomDAO();
Reminders reminder;
//by pranav
reminder = roomDAO.getObjectUsingID(intent.getIntExtra("id",0));
roomDAO.Delete(reminder);
AppDatabase.destroyInstance();
Uri alarmsound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
Intent intent1 = new Intent(context,MainPage.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);
taskStackBuilder.addParentStack(MainPage.class);
taskStackBuilder.addNextIntent(intent1);
PendingIntent intent2 = taskStackBuilder.getPendingIntent(1,PendingIntent.FLAG_UPDATE_CURRENT);
// NotificationCompat.Builder builder = new NotificationCompat.Builder(context);//by pranav
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,"891");
NotificationChannel channel = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channel = new NotificationChannel("my_channel_02","hello1", NotificationManager.IMPORTANCE_HIGH);
}
Notification notification = builder.setContentTitle("Reminder")
.setContentText(intent.getStringExtra("Message")).setAutoCancel(true)
.setSound(alarmsound).setSmallIcon(R.mipmap.ic_launcher_round)
.setContentIntent(intent2)
.setChannelId("my_channel_02")
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(1, notification);
}
}
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.util.Date;
@Entity(tableName = "reminder")
public class Reminders {
@PrimaryKey(autoGenerate = true)
@NonNull
public int id;
String message;
Date remindDate;
public String getMessage() {
return message;
}
public Date getRemindDate() {
return remindDate;
}
public int getId() {
return id;
}
public void setMessage(String message) {
this.message = message;
}
public void setRemindDate(Date remindDate) {
this.remindDate = remindDate;
}
public void setId(int id) {
this.id = id;
}
}
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
@Dao
public interface RoomDAO {
@Insert
public void Insert(Reminders... reminders);
@Update
public void Update(Reminders... reminders);
@Delete
public void Delete(Reminders reminders);
@Query("Select * from reminder order by remindDate")
public List<Reminders> orderThetable();
@Query("Select * from reminder Limit 1")
public Reminders getRecentEnteredData();
@Query("Select * from reminder")
public List<Reminders> getAll();
@Query("Delete from reminder")
void DeleteAll();
@Query("SELECT * FROM reminder WHERE reminder.id LIKE :objectID")
Reminders getObjectUsingID(int objectID);
@Query("SELECT id FROM REMINDER")
List<Integer> getAllIds();
}
layout
**activity_main_page
**
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainPage">
<androidx.appcompat.widget.Toolbar
android:id="@+id/ReminderToolbar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:title="Reminders" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete All"
android:onClick="DeleteAll"
app:layout_constraintEnd_toEndOf="@+id/ReminderToolbar1"
android:layout_marginEnd="10dp"
app:layout_constraintTop_toTopOf="@+id/ReminderToolbar1"
app:layout_constraintBottom_toBottomOf="@+id/ReminderToolbar1"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:src="@drawable/floating_button_foreground"
app:maxImageSize="@android:dimen/app_icon_size"
app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.943"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.957" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ReminderToolbar1" />
<TextView
android:id="@+id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="No Reminders SetnClick + to add the reminders"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="@+id/recyclerView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/recyclerView" />
</androidx.constraintlayout.widget.ConstraintLayout>
**floating_popup
**
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#CCCCFF"
android:layout_gravity="center"
android:padding="25dp">
<EditText
android:id="@+id/reminderMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:maxLines="3"
android:layout_marginBottom="5dp"
android:hint="Message"
android:layout_gravity="center"/>
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:maxLines="3"
android:hint="Date And Time"
android:layout_gravity="center"/>
<Button
android:id="@+id/selectDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:text="SELECT"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center">
<Button
android:id="@+id/addButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginEnd="5dp"
android:text="Add"
android:layout_weight="1"
android:layout_gravity="center" />
<Button
android:id="@+id/cancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="10dp"
android:text="Cancel"
android:layout_weight="1"
android:layout_gravity="center" />
</LinearLayout>
</LinearLayout>
**reminder_item
**
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="10dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout_editor_absoluteX="-25dp"
tools:layout_editor_absoluteY="112dp"
android:padding="10dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardCornerRadius="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80C6FF"
android:orientation="vertical"
android:padding="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:padding="5dp"
android:shadowColor="#000000"
android:textSize="20sp" />
<TextView
android:id="@+id/textView21"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:padding="5dp" />
</LinearLayout>
<ImageView
android:id="@+id/ReminderDelete"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginEnd="10sp"
android:paddingBottom="3sp"
android:src="@drawable/ic_baseline_delete_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.cardview.widget.CardView>
</LinearLayout>
I am currently facing a problem executing the application after updating the sdk to 32 and newer versions
Ougmosta is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.