This commit is contained in:
2026-06-09 17:12:11 +01:00
parent d192568ed8
commit eaa3d86fc9
2 changed files with 173 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
package com.example.pap_teste;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.IBinder;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import com.example.pap_teste.models.Reserva;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
public class ReservationNotificationService extends Service {
private static final String CHANNEL_ID = "ReservaNotifications";
private DatabaseReference reservasRef;
private ChildEventListener childEventListener;
private String currentUserEmail;
@Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null && user.getEmail() != null) {
currentUserEmail = user.getEmail();
startListeningForReservations();
} else {
stopSelf();
}
return START_STICKY;
}
private void startListeningForReservations() {
if (reservasRef != null && childEventListener != null) {
return; // Already listening
}
reservasRef = FirebaseDatabase.getInstance().getReference("reservas");
childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
// Not needed for new reservations created by the user
}
@Override
public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
Reserva reserva = snapshot.getValue(Reserva.class);
if (reserva != null && currentUserEmail.equals(reserva.getClienteEmail())) {
String estado = reserva.getEstado();
if (estado != null && (estado.startsWith("Confirmada") || estado.equals("Recusada"))) {
sendNotification(reserva);
}
}
}
@Override
public void onChildRemoved(@NonNull DataSnapshot snapshot) {}
@Override
public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {}
@Override
public void onCancelled(@NonNull DatabaseError error) {}
};
reservasRef.addChildEventListener(childEventListener);
}
private void sendNotification(Reserva reserva) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
ContextCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
return; // Permission not granted
}
Intent intent = new Intent(this, MainActivity.class); // Or deep link to reservations
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
String title = "Atualização de Reserva";
String message = "A sua reserva no " + reserva.getRestauranteName() + " foi " + reserva.getEstado().toLowerCase() + ".";
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.na_mesa) // Assuming na_mesa is a valid drawable
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.notify(reserva.getId().hashCode(), builder.build());
}
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Notificações de Reservas";
String description = "Notificações sobre o estado das suas reservas";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (reservasRef != null && childEventListener != null) {
reservasRef.removeEventListener(childEventListener);
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical"
android:layout_marginTop="24dp">
<TextView
android:id="@+id/txtCategoryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:textColor="@color/colorTextPrimary"
android:textSize="20sp"
android:textStyle="bold"
android:fontFamily="sans-serif"
tools:text="Sushi" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvCategoryRestaurants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:clipToPadding="false"
android:paddingStart="24dp"
android:paddingEnd="8dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_restaurant_featured" />
</LinearLayout>