Feat: Notifications OFF par défaut et Implémentation Sonore
- Notifications: - Valeur par défaut pour l'activation des notifications mise à 'false'. - L'utilisateur doit maintenant activer explicitement les notifications via les paramètres. - Son: - Ajout de la structure pour les effets sonores via SoundPool. - Création du dossier 'res/raw' (si nécessaire) pour les fichiers audio (placeholders: move, merge, win, game_over). - Initialisation de SoundPool et chargement des sons dans MainActivity.onCreate. - Ajout méthode playSound() pour jouer les effets (vérifie si chargé et activé). - Déclenchement des sons 'move' et 'merge' dans handleSwipe. - Déclenchement des sons 'win' et 'game_over' à l'affichage des dialogues correspondants. - Activation du switch 'Son' dans les paramètres, sauvegarde/chargement de la préférence 'sound_enabled'. - Libération de SoundPool dans MainActivity.onDestroy.
This commit is contained in:
parent
470649ad36
commit
c4f960f332
@ -45,6 +45,8 @@ import android.animation.AnimatorListenerAdapter;
|
|||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.media.AudioAttributes; // Pour SoundPool
|
||||||
|
import android.media.SoundPool; // Pour SoundPool
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -68,7 +70,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
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 static final String NOTIFICATION_CHANNEL_ID = "BEST_2048_CHANNEL";
|
||||||
private boolean notificationsEnabled = true;
|
private boolean notificationsEnabled = false;
|
||||||
private static final String LAST_PLAYED_TIME_KEY = "last_played_time";
|
private static final String LAST_PLAYED_TIME_KEY = "last_played_time";
|
||||||
|
|
||||||
// --- State Management ---
|
// --- State Management ---
|
||||||
@ -85,6 +87,15 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private static final String HIGH_SCORE_KEY = "high_score";
|
private static final String HIGH_SCORE_KEY = "high_score";
|
||||||
private static final String GAME_STATE_KEY = "game_state";
|
private static final String GAME_STATE_KEY = "game_state";
|
||||||
|
|
||||||
|
// --- Champs Son ---
|
||||||
|
private SoundPool soundPool;
|
||||||
|
private int soundMoveId = -1; // Initialise à -1 pour savoir s'ils sont chargés
|
||||||
|
private int soundMergeId = -1;
|
||||||
|
private int soundWinId = -1;
|
||||||
|
private int soundGameOverId = -1;
|
||||||
|
private boolean soundPoolLoaded = false; // Flag pour savoir si les sons sont prêts
|
||||||
|
private boolean soundEnabled = true; // Son activé par défaut
|
||||||
|
|
||||||
// --- Activity Lifecycle ---
|
// --- Activity Lifecycle ---
|
||||||
|
|
||||||
private final ActivityResultLauncher<String> requestPermissionLauncher =
|
private final ActivityResultLauncher<String> requestPermissionLauncher =
|
||||||
@ -115,6 +126,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
NotificationHelper.createNotificationChannel(this);
|
NotificationHelper.createNotificationChannel(this);
|
||||||
createNotificationChannel();
|
createNotificationChannel();
|
||||||
findViews();
|
findViews();
|
||||||
|
initializeSoundPool();
|
||||||
initializeGameAndStats();
|
initializeGameAndStats();
|
||||||
setupListeners();
|
setupListeners();
|
||||||
if (notificationsEnabled) {
|
if (notificationsEnabled) {
|
||||||
@ -231,6 +243,15 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() { // Important de libérer SoundPool
|
||||||
|
super.onDestroy();
|
||||||
|
if (soundPool != null) {
|
||||||
|
soundPool.release();
|
||||||
|
soundPool = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Initialisation ---
|
// --- Initialisation ---
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -256,6 +277,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
||||||
gameStats = new GameStats(this);
|
gameStats = new GameStats(this);
|
||||||
loadNotificationPreference();
|
loadNotificationPreference();
|
||||||
|
loadSoundPreference();
|
||||||
loadGame(); // Charge jeu et met à jour high score
|
loadGame(); // Charge jeu et met à jour high score
|
||||||
updateUI();
|
updateUI();
|
||||||
if (game == null) {
|
if (game == null) {
|
||||||
@ -265,6 +287,73 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Initialise le SoundPool et charge les effets sonores. */
|
||||||
|
private void initializeSoundPool() {
|
||||||
|
// Configuration pour les effets sonores de jeu
|
||||||
|
AudioAttributes attributes = new AudioAttributes.Builder()
|
||||||
|
.setUsage(AudioAttributes.USAGE_GAME)
|
||||||
|
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Crée le SoundPool
|
||||||
|
soundPool = new SoundPool.Builder()
|
||||||
|
.setMaxStreams(3) // Nombre max de sons joués simultanément
|
||||||
|
.setAudioAttributes(attributes)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Listener pour savoir quand les sons sont chargés
|
||||||
|
soundPool.setOnLoadCompleteListener((soundPool, sampleId, status) -> {
|
||||||
|
if (status == 0) {
|
||||||
|
// Vérifie si TOUS les sons sont chargés (ou gère individuellement)
|
||||||
|
// Ici, on met juste un flag général pour simplifier
|
||||||
|
soundPoolLoaded = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Charge les sons depuis res/raw
|
||||||
|
// Le 3ème argument (priority) est 1 (priorité normale)
|
||||||
|
try {
|
||||||
|
soundMoveId = soundPool.load(this, R.raw.move, 1);
|
||||||
|
soundMergeId = soundPool.load(this, R.raw.merge, 1);
|
||||||
|
soundWinId = soundPool.load(this, R.raw.win, 1);
|
||||||
|
soundGameOverId = soundPool.load(this, R.raw.game_over, 1);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Gérer l'erreur, peut-être désactiver le son
|
||||||
|
soundEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Préférences Son ---
|
||||||
|
|
||||||
|
/** Sauvegarde la préférence d'activation du son. */
|
||||||
|
private void saveSoundPreference(boolean enabled) {
|
||||||
|
if (preferences != null) {
|
||||||
|
preferences.edit().putBoolean("sound_enabled", enabled).apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Charge la préférence d'activation du son. */
|
||||||
|
private void loadSoundPreference() {
|
||||||
|
if (preferences != null) {
|
||||||
|
soundEnabled = preferences.getBoolean("sound_enabled", true); // Son activé par défaut
|
||||||
|
} else {
|
||||||
|
soundEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Lecture Son ---
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joue un effet sonore si le SoundPool est chargé et si le son est activé.
|
||||||
|
* @param soundId L'ID du son retourné par soundPool.load().
|
||||||
|
*/
|
||||||
|
private void playSound(int soundId) {
|
||||||
|
if (soundPoolLoaded && soundEnabled && soundPool != null && soundId > 0) {
|
||||||
|
// Arguments: soundID, leftVolume, rightVolume, priority, loop, rate
|
||||||
|
soundPool.play(soundId, 1.0f, 1.0f, 1, 0, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Crée le canal de notification nécessaire pour Android 8.0+. */
|
/** Crée le canal de notification nécessaire pour Android 8.0+. */
|
||||||
private void createNotificationChannel() {
|
private void createNotificationChannel() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
@ -419,6 +508,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (boardChanged) {
|
if (boardChanged) {
|
||||||
|
playSound(soundMoveId);
|
||||||
// Capture l'état APRÈS le push mais AVANT l'ajout de la nouvelle tuile
|
// Capture l'état APRÈS le push mais AVANT l'ajout de la nouvelle tuile
|
||||||
int[][] boardAfterPush = game.getBoard();
|
int[][] boardAfterPush = game.getBoard();
|
||||||
|
|
||||||
@ -426,6 +516,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
gameStats.recordMove();
|
gameStats.recordMove();
|
||||||
int scoreAfter = game.getCurrentScore();
|
int scoreAfter = game.getCurrentScore();
|
||||||
if (scoreAfter > scoreBefore) {
|
if (scoreAfter > scoreBefore) {
|
||||||
|
playSound(soundMergeId);
|
||||||
gameStats.recordMerge(1); // Simplifié
|
gameStats.recordMerge(1); // Simplifié
|
||||||
if (scoreAfter > game.getHighestScore()) {
|
if (scoreAfter > game.getHighestScore()) {
|
||||||
game.setHighestScore(scoreAfter);
|
game.setHighestScore(scoreAfter);
|
||||||
@ -608,6 +699,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
* Propose de continuer à jouer ou de commencer une nouvelle partie.
|
* Propose de continuer à jouer ou de commencer une nouvelle partie.
|
||||||
*/
|
*/
|
||||||
private void showGameWonKeepPlayingDialog() {
|
private void showGameWonKeepPlayingDialog() {
|
||||||
|
playSound(soundWinId);
|
||||||
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_game_won, null);
|
View dialogView = inflater.inflate(R.layout.dialog_game_won, null);
|
||||||
@ -634,6 +726,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
* Propose Nouvelle Partie ou Quitter.
|
* Propose Nouvelle Partie ou Quitter.
|
||||||
*/
|
*/
|
||||||
private void showGameOverDialog() {
|
private void showGameOverDialog() {
|
||||||
|
playSound(soundGameOverId);
|
||||||
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_game_over, null);
|
View dialogView = inflater.inflate(R.layout.dialog_game_over, null);
|
||||||
@ -749,10 +842,16 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
final AlertDialog dialog = builder.create();
|
final AlertDialog dialog = builder.create();
|
||||||
|
|
||||||
// Config Son (Placeholder)
|
// Config Son (MAINTENANT ACTIF)
|
||||||
switchSound.setEnabled(false);
|
switchSound.setEnabled(true); // Activé
|
||||||
switchSound.setChecked(false);
|
switchSound.setChecked(soundEnabled); // État actuel chargé
|
||||||
switchSound.setOnCheckedChangeListener((v, i) -> Toast.makeText(this, "Gestion du son à venir.", Toast.LENGTH_SHORT).show());
|
switchSound.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
|
soundEnabled = isChecked; // Met à jour l'état
|
||||||
|
saveSoundPreference(isChecked); // Sauvegarde la préférence
|
||||||
|
Toast.makeText(this,
|
||||||
|
isChecked ? R.string.sound_enabled : R.string.sound_disabled,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
|
||||||
// Config Notifications (Activé + Gestion Permission)
|
// Config Notifications (Activé + Gestion Permission)
|
||||||
switchNotifications.setEnabled(true); // Activé
|
switchNotifications.setEnabled(true); // Activé
|
||||||
@ -803,7 +902,10 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
/** Charge la préférence d'activation des notifications. */
|
/** Charge la préférence d'activation des notifications. */
|
||||||
private void loadNotificationPreference() {
|
private void loadNotificationPreference() {
|
||||||
if (preferences != null) {
|
if (preferences != null) {
|
||||||
notificationsEnabled = preferences.getBoolean("notifications_enabled", true); // Activé par défaut
|
// Change le défaut de true à false
|
||||||
|
notificationsEnabled = preferences.getBoolean("notifications_enabled", false);
|
||||||
|
} else {
|
||||||
|
notificationsEnabled = false; // Assure une valeur par défaut si prefs est null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:fontFamily="@font/nunito_family"
|
android:fontFamily="@font/nunito_family"
|
||||||
android:textColor="@color/text_tile_low"
|
android:textColor="@color/text_tile_low"
|
||||||
android:enabled="false" /> <com.google.android.material.switchmaterial.SwitchMaterial
|
android:enabled="true" /> <com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
android:id="@+id/switchNotifications"
|
android:id="@+id/switchNotifications"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -39,7 +39,7 @@
|
|||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:fontFamily="@font/nunito_family"
|
android:fontFamily="@font/nunito_family"
|
||||||
android:textColor="@color/text_tile_low"
|
android:textColor="@color/text_tile_low"
|
||||||
android:enabled="false" /> </LinearLayout>
|
android:enabled="true" /> </LinearLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/buttonManagePermissions"
|
android:id="@+id/buttonManagePermissions"
|
||||||
|
BIN
app/src/main/res/raw/game_over.mp3
Normal file
BIN
app/src/main/res/raw/game_over.mp3
Normal file
Binary file not shown.
BIN
app/src/main/res/raw/merge.mp3
Normal file
BIN
app/src/main/res/raw/merge.mp3
Normal file
Binary file not shown.
BIN
app/src/main/res/raw/move.mp3
Normal file
BIN
app/src/main/res/raw/move.mp3
Normal file
Binary file not shown.
BIN
app/src/main/res/raw/win.mp3
Normal file
BIN
app/src/main/res/raw/win.mp3
Normal file
Binary file not shown.
@ -63,8 +63,8 @@
|
|||||||
<string name="about_website_text">Website : legion-muyue.fr</string> <string name="about_website_url">https://legion-muyue.fr</string>
|
<string name="about_website_text">Website : legion-muyue.fr</string> <string name="about_website_url">https://legion-muyue.fr</string>
|
||||||
<string name="ok">OK</string>
|
<string name="ok">OK</string>
|
||||||
<string name="settings_title">Settings</string>
|
<string name="settings_title">Settings</string>
|
||||||
<string name="settings_sound_label">Sound (coming soon)</string>
|
<string name="settings_sound_label">Sound</string>
|
||||||
<string name="settings_notifications_label">Notifications (coming soon)</string>
|
<string name="settings_notifications_label">Notifications</string>
|
||||||
<string name="settings_permissions_button">Manage Permissions</string>
|
<string name="settings_permissions_button">Manage Permissions</string>
|
||||||
<string name="settings_share_stats_button">Share my Statistics</string>
|
<string name="settings_share_stats_button">Share my Statistics</string>
|
||||||
<string name="settings_reset_stats_button">Reset Statistics</string>
|
<string name="settings_reset_stats_button">Reset Statistics</string>
|
||||||
@ -91,4 +91,6 @@
|
|||||||
<string name="notifications_disabled">Notifications disabled.</string>
|
<string name="notifications_disabled">Notifications disabled.</string>
|
||||||
<string name="settings_test_notif_highscore">Test High Score Notif</string>
|
<string name="settings_test_notif_highscore">Test High Score Notif</string>
|
||||||
<string name="settings_test_notif_inactivity">Test Inactivity Notif</string>
|
<string name="settings_test_notif_inactivity">Test Inactivity Notif</string>
|
||||||
|
<string name="sound_enabled">Sound effects enabled.</string>
|
||||||
|
<string name="sound_disabled">Sound effects disabled.</string>
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user