Avec Android O, nous obtenons le "Notification Channels".
Autant que je sache, cela signifie que l'utilisateur ne peut pas définir la tonalité de notification ou d'autres paramètres de notification associés à l'intérieur de l'APP.
L'utilisateur doit aller à "Réglage des canaux de notification" et modifier le tonalité ou vibration etc. ici parce que tous méthodes du NotificationBuilder comme setSound sont ignorés.
Donc il y a vraiment NO _ moyen de changer le tonalité en silence via code?
Ou pour changer le modèle de vibration via le code?
Par exemple, l'utilisateur a la possibilité de définir le motif de vibration dans mon application.
Ou il peut choisir des tonalités du type d’alarme au lieu du type de notification.
Tout cela n'est plus possible?
Est-ce juste ou y a-t-il un moyen de le faire?
Vous pouvez toujours proposer une personnalisation du son et des vibrations dans votre application, mais cela nécessite une approche différente. En bref, l’idée est de jouer du son et des vibrations manuellement dans Android O au lieu d’utiliser le canal de notification (c’est plus facile qu’il ne le semble).
Voici comment je l'ai fait:
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId);
// builder.setSmallIcon(...)
// builder.setContentTitle(...)
// builder.setContentText(...)
if (Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// play vibration
vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(VibrationEffect.createWaveform(vibrationPattern, -1));
// play sound
Intent serviceIntent = new Intent(context, SoundService.class);
serviceIntent.setAction("ACTION_START_PLAYBACK");
serviceIntent.putExtra("SOUND_URI", soundUri.toString());
context.startForegroundService(serviceIntent);
// the delete intent will stop the sound when the notification is cleared
Intent deleteIntent = new Intent(context, SoundService.class);
deleteIntent.setAction("ACTION_STOP_PLAYBACK");
PendingIntent pendingDeleteIntent =
PendingIntent.getService(context, 0, deleteIntent, 0);
builder.setDeleteIntent(pendingDeleteIntent);
} else {
builder.setVibrate(vibrationPattern);
builder.setSound(soundUri);
}
notificationManager.notify(notificationId, builder.build());
SoundService.class est l'endroit où je joue le son avec MediaPlayer:
public class SoundService extends Service {
MediaPlayer mMediaPlayer;
@Override
public IBinder onBind(Intent intent) {
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
// foreground notification
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, otherChannelId);
builder.setSmallIcon(...)
.setContentTitle(...)
.setContentText(...)
.setAutoCancel(true);
startForeground(foregroundNotificationId, builder.build());
}
// check action
String action = intent.getAction();
switch (action) {
case "ACTION_START_PLAYBACK":
startSound(intent.getStringExtra("SOUND_URI"));
break;
case "ACTION_STOP_PLAYBACK":
stopSound();
break;
}
// service will not be recreated if abnormally terminated
return START_NOT_STICKY;
}
private void startSound(String uriString) {
// parse sound
Uri soundUri;
try {
soundUri = Uri.parse(uriString);
} catch (Exception e) {
cleanup();
return;
}
// play sound
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
cleanup();
}
});
}
try {
mMediaPlayer.setDataSource(this, soundUri);
mMediaPlayer.prepareAsync();
} catch (Exception e) {
cleanup();
}
}
private void stopSound() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
cleanup();
}
private void cleanup() {
stopSelf();
}
}
Recommandations
setSound(null,null)
) et une vibration nulle (setVibrationPattern(null)
) et expliquez dans la description du canal qu'il s'agit du paramètre recommandé afin d'éviter tout conflit avec l'application. propre personnalisation.Notification de premier plan
À partir de Android O, les services démarrés à partir de l’arrière-plan doivent être démarrés en tant que services de premier plan. Cela signifie que SoundService a besoin d'une notification de premier plan. Vous avez quelques options pour cela:
Créez une notification de premier plan avec un bouton indiquant "Arrêter la lecture" afin que l'utilisateur puisse arrêter le son sans supprimer la notification qui l'a démarré.
Créez une notification simple et envoyez-la sur un canal désactivé (vous pouvez créer des canaux désactivés si vous les créez avec IMPORTANCE_NONE). Ce faisant, la notification système «L'application s'exécute en arrière-plan» apparaîtra à la place de votre notification de premier plan, mais les utilisateurs peuvent masquer cette notification de la barre d'état s'ils le souhaitent.
EDIT: sous Android 8.1, il semble que la création d'un canal désactivé avec IMPORTANCE_NONE ne soit pas utile, car le canal sera automatiquement activé lors de l'envoi d'une notification. Il peut être préférable de le créer avec IMPORTANCE_LOW dès le début et de laisser les utilisateurs changer l’importance s’ils le souhaitent.
Cela pourrait aider dans votre cas. Si vous avez une notification affichée, vous pouvez désactiver le son lors de la mise à jour de cette notification en définissant .setOnlyAlertOnce(true)
. Cette solution ne fonctionne que lors de la mise à jour de la notification.
C'est exact, une fois qu'un canal est créé, vous ne pouvez plus le modifier.
Vous ne pouvez pas modifier par programme le comportement d'une notification canal une fois qu'il est créé et soumis au gestionnaire de notification
https://developer.Android.com/preview/features/notification-channels.html
Ce que vous devez faire supprimer le canal et en créer un nouveau avec un identifiant différent
Pour moi, le bon moyen pour Android> = 8.0 consiste à masquer vos options son/vibration et à rediriger l'utilisateur vers les paramètres de notification de votre application en utilisant ceci:
Intent intent = new Intent();
intent.setAction("Android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("Android.provider.extra.APP_PACKAGE", context.getPackageName());
context.startActivity(intent);
J'espère que ça va aider
Ce n'est pas une bonne idée de jouer le son manuellement. La meilleure approche serait d’avoir deux (ou plus) canaux - un pour chaque son/vibration que vous souhaitez jouer.
Dans le code, vous pouvez choisir le canal à utiliser en fonction du son que vous souhaitez lire.
Voici mon code où je joue le son de notification par défaut ou un son personnalisé en fonction des paramètres du client. Le code prend également en charge les appareils fonctionnant sous Android avant l'API 26:
String sound = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("NotificationsSound", getString(R.string.settingsNotificationSiren));
Uri soundUri = Uri.parse(ContentResolver.SCHEME_Android_RESOURCE + "://"+ getApplicationContext().getPackageName() + "/" + R.raw.siren);
NotificationManager mNotificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel mChannel;
String channel_id = Utils.CHANNEL_DEFAULT_ID;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (sound.toLowerCase().equals(getString(R.string.settingsNotificationSiren).toLowerCase())) {
channel_id = Utils.CHANNEL_SIREN_ID;
mChannel = new NotificationChannel(Utils.CHANNEL_SIREN_ID, Utils.CHANNEL_SIREN_NAME, NotificationManager.IMPORTANCE_HIGH);
mChannel.setLightColor(Color.GRAY);
mChannel.enableLights(true);
mChannel.setDescription(Utils.CHANNEL_SIREN_DESCRIPTION);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
mChannel.setSound(soundUri, audioAttributes);
} else {
mChannel = new NotificationChannel(Utils.CHANNEL_DEFAULT_ID, Utils.CHANNEL_DEFAULT_NAME, NotificationManager.IMPORTANCE_HIGH);
mChannel.setLightColor(Color.GRAY);
mChannel.enableLights(true);
mChannel.setDescription(Utils.CHANNEL_DEFAULT_DESCRIPTION);
}
if (mNotificationManager != null) {
mNotificationManager.createNotificationChannel( mChannel );
}
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, channel_id)
.setSmallIcon(R.drawable.ic_stat_maps_local_library)
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.ic_launcher))
.setTicker(title)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setAutoCancel(true)
.setLights(0xff0000ff, 300, 1000) // blue color
.setWhen(System.currentTimeMillis())
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
if (sound.toLowerCase().equals(getString(R.string.settingsNotificationSiren).toLowerCase())) {
mBuilder.setSound(soundUri);
} else {
mBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
}
}
int NOTIFICATION_ID = 1; // Causes to update the same notification over and over again.
if (mNotificationManager != null) {
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
Donc, il n'y a vraiment AUCUN moyen de changer le ton en silence via code?
Utilisez setSound()
sur NotificationChannel
et pointez sur un fichier son contenant un peu de silence, par exemple.
Ou pour changer le modèle de vibration via le code?