Feat: Implémentation de base des notifications
- Ajout permission POST_NOTIFICATIONS dans AndroidManifest.xml (Android 13+). - Création d'un canal de notification ('BEST_2048_CHANNEL') dans MainActivity.onCreate. - Ajout d'une icône de notification simple (ic_stat_notification_2048.xml). - Ajout de strings pour les notifications et la gestion des permissions. - Modification de MainActivity : - Implémentation de la demande de permission POST_NOTIFICATIONS via ActivityResultLauncher, déclenchée par l'activation du switch dans les paramètres. - Ajout méthode utilitaire 'showNotification' utilisant NotificationCompat.Builder. - Ajout méthodes 'showAchievementNotification', 'showHighScoreNotification' (test), 'showInactivityNotification' (test). - Déclenchement de 'showAchievementNotification' dans handleSwipe lors de la première victoire. - Activation du switch 'Notifications' dans le dialogue des paramètres et gestion de son état via SharedPreferences et demande de permission. - Ajout (commenté/optionnel) boutons de test pour notifications HighScore/Inactivité. - NOTE: Notifications périodiques (HighScore, Inactivité) non planifiées, déclenchées manuellement pour test dans ce commit. Nécessite WorkManager/AlarmManager pour implémentation réelle.
This commit is contained in:
parent
a61f110992
commit
7dc7360e14
@ -2,6 +2,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
@ -9,7 +9,13 @@ package legion.muyue.best2048;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -23,9 +29,13 @@ import android.view.View;
|
|||||||
import android.view.ViewStub;
|
import android.view.ViewStub;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.gridlayout.widget.GridLayout;
|
import androidx.gridlayout.widget.GridLayout;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@ -49,6 +59,8 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private Game game;
|
private Game game;
|
||||||
private GameStats gameStats;
|
private GameStats gameStats;
|
||||||
private static final int BOARD_SIZE = 4;
|
private static final int BOARD_SIZE = 4;
|
||||||
|
private static final String NOTIFICATION_CHANNEL_ID = "BEST_2048_CHANNEL";
|
||||||
|
private boolean notificationsEnabled = true;
|
||||||
|
|
||||||
// --- State Management ---
|
// --- State Management ---
|
||||||
private boolean statisticsVisible = false;
|
private boolean statisticsVisible = false;
|
||||||
@ -63,12 +75,32 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
// --- Activity Lifecycle ---
|
// --- Activity Lifecycle ---
|
||||||
|
|
||||||
|
private final ActivityResultLauncher<String> requestPermissionLauncher =
|
||||||
|
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
|
||||||
|
if (isGranted) {
|
||||||
|
// La permission est accordée. On peut activer/planifier les notifications.
|
||||||
|
notificationsEnabled = true;
|
||||||
|
saveNotificationPreference(true);
|
||||||
|
Toast.makeText(this, R.string.notifications_enabled, Toast.LENGTH_SHORT).show();
|
||||||
|
// Ici, on pourrait (re)planifier les notifications périodiques avec WorkManager/AlarmManager
|
||||||
|
} else {
|
||||||
|
// La permission est refusée. L'utilisateur ne recevra pas de notifications.
|
||||||
|
notificationsEnabled = false;
|
||||||
|
saveNotificationPreference(false);
|
||||||
|
// Désactive le switch dans les paramètres si l'utilisateur vient de refuser
|
||||||
|
updateNotificationSwitchState(false);
|
||||||
|
Toast.makeText(this, R.string.notifications_disabled, Toast.LENGTH_SHORT).show();
|
||||||
|
// Afficher une explication si nécessaire
|
||||||
|
// showNotificationPermissionRationale();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
EdgeToEdge.enable(this);
|
EdgeToEdge.enable(this);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
createNotificationChannel();
|
||||||
findViews();
|
findViews();
|
||||||
initializeGameAndStats();
|
initializeGameAndStats();
|
||||||
setupListeners();
|
setupListeners();
|
||||||
@ -132,6 +164,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private void initializeGameAndStats() {
|
private void initializeGameAndStats() {
|
||||||
preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
||||||
gameStats = new GameStats(this);
|
gameStats = new GameStats(this);
|
||||||
|
loadNotificationPreference();
|
||||||
loadGame(); // Charge jeu et met à jour high score
|
loadGame(); // Charge jeu et met à jour high score
|
||||||
updateUI();
|
updateUI();
|
||||||
if (game == null) {
|
if (game == null) {
|
||||||
@ -141,6 +174,22 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
// L'état (currentGameState) est défini dans loadGame ou startNewGame
|
// L'état (currentGameState) est défini dans loadGame ou startNewGame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Crée le canal de notification nécessaire pour Android 8.0+. */
|
||||||
|
private void createNotificationChannel() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
CharSequence name = getString(R.string.notification_channel_name);
|
||||||
|
String description = getString(R.string.notification_channel_description);
|
||||||
|
int importance = NotificationManager.IMPORTANCE_DEFAULT;
|
||||||
|
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance);
|
||||||
|
channel.setDescription(description);
|
||||||
|
// Enregistre le canal avec le système; ne peut pas être changé après ça
|
||||||
|
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
||||||
|
if (notificationManager != null) {
|
||||||
|
notificationManager.createNotificationChannel(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure les listeners pour les boutons et le plateau de jeu (swipes).
|
* Configure les listeners pour les boutons et le plateau de jeu (swipes).
|
||||||
* Mise à jour pour le bouton Menu.
|
* Mise à jour pour le bouton Menu.
|
||||||
@ -299,6 +348,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
currentGameState = GameFlowState.WON_DIALOG_SHOWN;
|
currentGameState = GameFlowState.WON_DIALOG_SHOWN;
|
||||||
long timeTaken = System.currentTimeMillis() - gameStats.getCurrentGameStartTimeMs();
|
long timeTaken = System.currentTimeMillis() - gameStats.getCurrentGameStartTimeMs();
|
||||||
gameStats.recordWin(timeTaken);
|
gameStats.recordWin(timeTaken);
|
||||||
|
showAchievementNotification(2048);
|
||||||
showGameWonKeepPlayingDialog();
|
showGameWonKeepPlayingDialog();
|
||||||
} else if (game.isGameOver()) {
|
} else if (game.isGameOver()) {
|
||||||
currentGameState = GameFlowState.GAME_OVER;
|
currentGameState = GameFlowState.GAME_OVER;
|
||||||
@ -483,74 +533,191 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
LayoutInflater inflater = getLayoutInflater();
|
LayoutInflater inflater = getLayoutInflater();
|
||||||
View dialogView = inflater.inflate(R.layout.dialog_settings, null);
|
View dialogView = inflater.inflate(R.layout.dialog_settings, null);
|
||||||
builder.setView(dialogView);
|
builder.setView(dialogView).setCancelable(true);
|
||||||
builder.setCancelable(true); // Permet de fermer en cliquant à côté
|
|
||||||
|
|
||||||
// Récupération des vues
|
// Vues
|
||||||
SwitchMaterial switchSound = dialogView.findViewById(R.id.switchSound);
|
SwitchMaterial switchSound = dialogView.findViewById(R.id.switchSound);
|
||||||
SwitchMaterial switchNotifications = dialogView.findViewById(R.id.switchNotifications);
|
SwitchMaterial switchNotifications = dialogView.findViewById(R.id.switchNotifications); // Activé
|
||||||
Button permissionsButton = dialogView.findViewById(R.id.buttonManagePermissions);
|
Button permissionsButton = dialogView.findViewById(R.id.buttonManagePermissions);
|
||||||
Button shareStatsButton = dialogView.findViewById(R.id.buttonShareStats);
|
Button shareStatsButton = dialogView.findViewById(R.id.buttonShareStats);
|
||||||
Button resetStatsButton = dialogView.findViewById(R.id.buttonResetStats);
|
Button resetStatsButton = dialogView.findViewById(R.id.buttonResetStats);
|
||||||
Button quitAppButton = dialogView.findViewById(R.id.buttonQuitApp);
|
Button quitAppButton = dialogView.findViewById(R.id.buttonQuitApp);
|
||||||
Button closeButton = dialogView.findViewById(R.id.buttonCloseSettings);
|
Button closeButton = dialogView.findViewById(R.id.buttonCloseSettings);
|
||||||
|
// Ajout boutons de test (optionnel, pour débugger)
|
||||||
|
Button testNotifHS = new Button(this); // Crée programmatiquement
|
||||||
|
testNotifHS.setText(R.string.settings_test_notif_highscore);
|
||||||
|
Button testNotifInactiv = new Button(this);
|
||||||
|
testNotifInactiv.setText(R.string.settings_test_notif_inactivity);
|
||||||
|
// Ajouter ces boutons au layout 'dialogView' si nécessaire (ex: ((LinearLayout)dialogView).addView(...) )
|
||||||
|
|
||||||
final AlertDialog dialog = builder.create();
|
final AlertDialog dialog = builder.create();
|
||||||
|
|
||||||
// Configuration initiale des switches (désactivés pour l'instant)
|
// Config Son (Placeholder)
|
||||||
switchSound.setEnabled(false);
|
switchSound.setEnabled(false);
|
||||||
switchSound.setChecked(false); // Mettre à jour avec la vraie valeur si implémenté
|
switchSound.setChecked(false);
|
||||||
switchSound.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
switchSound.setOnCheckedChangeListener((v, i) -> Toast.makeText(this, "Gestion du son à venir.", Toast.LENGTH_SHORT).show());
|
||||||
// TODO: Implémenter la logique Son ON/OFF
|
|
||||||
Toast.makeText(this, "Gestion du son à venir.", Toast.LENGTH_SHORT).show();
|
|
||||||
// switchSound.setChecked(!isChecked); // Revenir en arrière car pas implémenté
|
|
||||||
});
|
|
||||||
|
|
||||||
switchNotifications.setEnabled(false);
|
// Config Notifications (Activé + Gestion Permission)
|
||||||
switchNotifications.setChecked(false); // Mettre à jour avec la vraie valeur si implémenté
|
switchNotifications.setEnabled(true); // Activé
|
||||||
|
switchNotifications.setChecked(notificationsEnabled); // État actuel
|
||||||
switchNotifications.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
switchNotifications.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
// TODO: Implémenter la logique Notifications ON/OFF
|
if (isChecked) {
|
||||||
Toast.makeText(this, "Gestion des notifications à venir.", Toast.LENGTH_SHORT).show();
|
// L'utilisateur VEUT activer les notifications
|
||||||
// switchNotifications.setChecked(!isChecked);
|
requestNotificationPermission(); // Demande la permission si nécessaire
|
||||||
});
|
} else {
|
||||||
|
// L'utilisateur désactive les notifications
|
||||||
// Listener bouton Permissions
|
notificationsEnabled = false;
|
||||||
permissionsButton.setOnClickListener(v -> {
|
saveNotificationPreference(false);
|
||||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
Toast.makeText(this, R.string.notifications_disabled, Toast.LENGTH_SHORT).show();
|
||||||
Uri uri = Uri.fromParts("package", getPackageName(), null);
|
// Ici, annuler les éventuelles notifications planifiées (WorkManager/AlarmManager)
|
||||||
intent.setData(uri);
|
|
||||||
try {
|
|
||||||
startActivity(intent);
|
|
||||||
} catch (ActivityNotFoundException e) {
|
|
||||||
Toast.makeText(this, "Impossible d'ouvrir les paramètres de l'application.", Toast.LENGTH_LONG).show();
|
|
||||||
}
|
}
|
||||||
dialog.dismiss(); // Ferme les paramètres après clic
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listener bouton Partager Stats
|
// Listeners autres boutons (Permissions, Share, Reset, Quit, Close)
|
||||||
shareStatsButton.setOnClickListener(v -> {
|
permissionsButton.setOnClickListener(v -> { openAppSettings(); dialog.dismiss(); });
|
||||||
shareStats();
|
shareStatsButton.setOnClickListener(v -> { shareStats(); dialog.dismiss(); });
|
||||||
dialog.dismiss(); // Ferme après partage (ou tentative)
|
resetStatsButton.setOnClickListener(v -> { dialog.dismiss(); showResetStatsConfirmationDialog(); });
|
||||||
});
|
quitAppButton.setOnClickListener(v -> { dialog.dismiss(); finishAffinity(); });
|
||||||
|
|
||||||
// Listener bouton Réinitialiser Stats
|
|
||||||
resetStatsButton.setOnClickListener(v -> {
|
|
||||||
dialog.dismiss(); // Ferme d'abord la dialogue des paramètres
|
|
||||||
showResetStatsConfirmationDialog(); // Ouvre la confirmation
|
|
||||||
});
|
|
||||||
|
|
||||||
// Listener bouton Quitter
|
|
||||||
quitAppButton.setOnClickListener(v -> {
|
|
||||||
dialog.dismiss();
|
|
||||||
finishAffinity(); // Ferme toutes les activités de l'application
|
|
||||||
});
|
|
||||||
|
|
||||||
// Listener bouton Fermer
|
|
||||||
closeButton.setOnClickListener(v -> dialog.dismiss());
|
closeButton.setOnClickListener(v -> dialog.dismiss());
|
||||||
|
|
||||||
|
// Listeners boutons de test (si ajoutés)
|
||||||
|
testNotifHS.setOnClickListener(v -> { showHighScoreNotification(gameStats.getOverallHighScore()); });
|
||||||
|
testNotifInactiv.setOnClickListener(v -> { showInactivityNotification(); });
|
||||||
|
|
||||||
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Met à jour l'état du switch notification (utile si permission refusée). */
|
||||||
|
private void updateNotificationSwitchState(boolean isEnabled) {
|
||||||
|
// Si la vue des paramètres est actuellement affichée, met à jour le switch
|
||||||
|
View settingsDialogView = getLayoutInflater().inflate(R.layout.dialog_settings, null); // Attention, regonfler n'est pas idéal
|
||||||
|
// Mieux: Garder une référence à la vue ou au switch si la dialog est affichée.
|
||||||
|
// Pour la simplicité ici, on suppose qu'il faut rouvrir les paramètres pour voir le changement.
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sauvegarde la préférence d'activation des notifications. */
|
||||||
|
private void saveNotificationPreference(boolean enabled) {
|
||||||
|
if (preferences != null) {
|
||||||
|
preferences.edit().putBoolean("notifications_enabled", enabled).apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Charge la préférence d'activation des notifications. */
|
||||||
|
private void loadNotificationPreference() {
|
||||||
|
if (preferences != null) {
|
||||||
|
notificationsEnabled = preferences.getBoolean("notifications_enabled", true); // Activé par défaut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Ouvre les paramètres système de l'application. */
|
||||||
|
private void openAppSettings() {
|
||||||
|
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
Uri uri = Uri.fromParts("package", getPackageName(), null);
|
||||||
|
intent.setData(uri);
|
||||||
|
try {
|
||||||
|
startActivity(intent);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Toast.makeText(this, "Impossible d'ouvrir les paramètres.", Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Gestion des Permissions (Notifications) ---
|
||||||
|
|
||||||
|
/** Demande la permission POST_NOTIFICATIONS si nécessaire (Android 13+). */
|
||||||
|
private void requestNotificationPermission() {
|
||||||
|
// Vérifie si on est sur Android 13+
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
// Vérifie si la permission n'est PAS déjà accordée
|
||||||
|
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
// Demande la permission
|
||||||
|
requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS);
|
||||||
|
// Le résultat sera géré dans le callback du requestPermissionLauncher
|
||||||
|
} else {
|
||||||
|
// La permission est déjà accordée, on peut activer directement
|
||||||
|
notificationsEnabled = true;
|
||||||
|
saveNotificationPreference(true);
|
||||||
|
Toast.makeText(this, R.string.notifications_enabled, Toast.LENGTH_SHORT).show();
|
||||||
|
// Planifier les notifications ici si ce n'est pas déjà fait
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Sur les versions antérieures à Android 13, pas besoin de demander la permission
|
||||||
|
notificationsEnabled = true;
|
||||||
|
saveNotificationPreference(true);
|
||||||
|
Toast.makeText(this, R.string.notifications_enabled, Toast.LENGTH_SHORT).show();
|
||||||
|
// Planifier les notifications ici
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Logique de Notification ---
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée l'Intent qui sera lancé au clic sur une notification (ouvre MainActivity).
|
||||||
|
* @return PendingIntent configuré.
|
||||||
|
*/
|
||||||
|
private PendingIntent createNotificationTapIntent() {
|
||||||
|
Intent intent = new Intent(this, MainActivity.class);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // Ouvre l'app ou la ramène devant
|
||||||
|
// FLAG_IMMUTABLE est requis pour Android 12+
|
||||||
|
int flags = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) ? PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT;
|
||||||
|
return PendingIntent.getActivity(this, 0, intent, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construit et affiche une notification simple.
|
||||||
|
* @param context Contexte.
|
||||||
|
* @param title Titre de la notification.
|
||||||
|
* @param message Corps du message de la notification.
|
||||||
|
* @param notificationId ID unique pour cette notification.
|
||||||
|
*/
|
||||||
|
private void showNotification(Context context, String title, String message, int notificationId) {
|
||||||
|
// Vérifie si les notifications sont activées et si la permission est accordée (pour Android 13+)
|
||||||
|
if (!notificationsEnabled || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
|
||||||
|
ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED)) {
|
||||||
|
// Ne pas envoyer la notification si désactivé ou permission manquante
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
|
||||||
|
.setSmallIcon(R.drawable.ic_stat_notification_2048) // Votre icône
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(message)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||||
|
.setContentIntent(createNotificationTapIntent()) // Action au clic
|
||||||
|
.setAutoCancel(true); // Ferme la notif après clic
|
||||||
|
|
||||||
|
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
||||||
|
// L'ID notificationId est utilisé pour mettre à jour une notif existante ou en afficher une nouvelle
|
||||||
|
notificationManager.notify(notificationId, builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Affiche la notification d'accomplissement (ex: tuile 2048 atteinte). */
|
||||||
|
private void showAchievementNotification(int tileValue) {
|
||||||
|
String title = getString(R.string.notification_title_achievement);
|
||||||
|
String message = getString(R.string.notification_text_achievement, tileValue);
|
||||||
|
// Utiliser un ID spécifique pour ce type de notif (ex: 1)
|
||||||
|
showNotification(this, title, message, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Affiche la notification de rappel du meilleur score (pour test). */
|
||||||
|
private void showHighScoreNotification(int highScore) {
|
||||||
|
String title = getString(R.string.notification_title_highscore);
|
||||||
|
String message = getString(R.string.notification_text_highscore, highScore);
|
||||||
|
// Utiliser un ID spécifique (ex: 2)
|
||||||
|
showNotification(this, title, message, 2);
|
||||||
|
// NOTE: La planification réelle utiliserait WorkManager/AlarmManager
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Affiche la notification de rappel d'inactivité (pour test). */
|
||||||
|
private void showInactivityNotification() {
|
||||||
|
String title = getString(R.string.notification_title_inactivity);
|
||||||
|
String message = getString(R.string.notification_text_inactivity);
|
||||||
|
// Utiliser un ID spécifique (ex: 3)
|
||||||
|
showNotification(this, title, message, 3);
|
||||||
|
// NOTE: La planification réelle utiliserait WorkManager/AlarmManager et suivi du temps
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crée et lance une Intent pour partager les statistiques du joueur.
|
* Crée et lance une Intent pour partager les statistiques du joueur.
|
||||||
*/
|
*/
|
||||||
|
8
app/src/main/res/drawable/ic_stat_notification_2048.xml
Normal file
8
app/src/main/res/drawable/ic_stat_notification_2048.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:tint="?attr/colorControlNormal"> <path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z"/> </vector>
|
@ -76,5 +76,19 @@
|
|||||||
<string name="share_stats_subject">My 2048 Statistics</string>
|
<string name="share_stats_subject">My 2048 Statistics</string>
|
||||||
<string name="share_stats_body">Here are my stats on Best 2048:\n- Best Score: %d\n- Highest Tile: %d\n- Games Won: %d / %d\n- Total Time: %s\n- Total Moves: %d</string>
|
<string name="share_stats_body">Here are my stats on Best 2048:\n- Best Score: %d\n- Highest Tile: %d\n- Games Won: %d / %d\n- Total Time: %s\n- Total Moves: %d</string>
|
||||||
<string name="stats_reset_confirmation">Statistics reset.</string>
|
<string name="stats_reset_confirmation">Statistics reset.</string>
|
||||||
|
<string name="notification_channel_name">Game Updates</string>
|
||||||
|
<string name="notification_channel_description">Notifications related to the 2048 game</string>
|
||||||
|
<string name="notification_title_achievement">Congratulations!</string>
|
||||||
|
<string name="notification_text_achievement">You reached the %d tile!</string>
|
||||||
|
<string name="notification_title_highscore">New Challenge!</string>
|
||||||
|
<string name="notification_text_highscore">Your best score is %d. Can you do better?</string>
|
||||||
|
<string name="notification_title_inactivity">We miss you!</string>
|
||||||
|
<string name="notification_text_inactivity">How about a quick game of 2048 to relax?</string>
|
||||||
|
<string name="notifications_permission_required_title">Permission Required</string>
|
||||||
|
<string name="notifications_permission_required_message">To receive notifications (reminders, achievements), please allow the application to send notifications in the settings.</string>
|
||||||
|
<string name="go_to_settings">Go to Settings</string>
|
||||||
|
<string name="notifications_enabled">Notifications enabled.</string>
|
||||||
|
<string name="notifications_disabled">Notifications disabled.</string>
|
||||||
|
<string name="settings_test_notif_highscore">Test High Score Notif</string>
|
||||||
|
<string name="settings_test_notif_inactivity">Test Inactivity Notif</string>
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user