tiempo - Android O-Canales de notificación-Cambiar patrón de vibración o tipo de sonido
notificaciones push android studio (6)
Entonces, ¿realmente NO hay manera de cambiar el tono a silencioso a través del código?
Use setSound()
en NotificationChannel
y apunte a un archivo de sonido que contenga un poco de silencio, tal vez.
¿O cambiar el patrón de vibración a través del código?
Con Android O obtenemos los " Canales de Notificación ".
Según tengo entendido, eso significa que el usuario ya no puede establecer el tono de notificación u otras configuraciones de Notificación relacionadas dentro de la APLICACIÓN .
El usuario debe ir a " Configuración de los canales de notificación " y cambiar el tono o la vibración, etc. aquí porque todos los métodos de NotificationBuilder como setSound se ignoran.
Entonces, ¿realmente NO hay manera de cambiar el tono a silencioso a través del código ?
¿O cambiar el patrón de vibración a través del código?
Por ejemplo, el usuario tiene la capacidad de establecer el patrón de vibración en mi aplicación.
O puede elegir tonos del tipo de alarma en lugar del tipo de notificación.
Todo esto ya no es posible?
¿Es esto correcto o hay alguna manera de hacer esto?
Aún puede ofrecer personalización de sonido y vibración en su aplicación, pero requiere un enfoque diferente. En resumen, la idea es reproducir el sonido y la vibración manualmente en Android O en lugar de usar el canal de notificación (es más fácil de lo que parece).
Así es como lo hice:
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 es el lugar donde reproduzco el sonido con 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();
}
}
Recomendaciones
- Cree su canal de notificación con IMPORTANCE_DEFAULT (para el usuario, esto es ''Alto''), un sonido nulo (
setSound(null,null)
) y una vibración nula (setVibrationPattern(null)
) y explique en la descripción del canal que esta es la configuración recomendada para evitar conflictos con la personalización propia de la aplicación. - Convierta todo en su favor: en lugar de eliminar una característica, dé a los usuarios una nueva. Puede darles la oportunidad de usar sus funciones de personalización o las funciones del canal de notificación (por ejemplo, puede verificar la importancia del canal actual y, dependiendo del nivel, puede usar una cosa u otra).
Notificación de primer plano
Al iniciar Android O, los servicios iniciados desde el fondo deben iniciarse como servicios en primer plano. Esto significa que SoundService necesita una notificación de primer plano. Tienes algunas opciones para esto:
Cree una buena notificación de primer plano con un botón que diga ''Detener reproducción'' para que el usuario pueda detener el sonido sin eliminar la notificación que lo inició.
Cree una notificación simple y envíela a un canal deshabilitado (puede crear canales deshabilitados si los crea con IMPORTANCE_NONE). Al hacer esto, aparecerá la notificación del sistema predeterminado ''La aplicación se ejecuta en segundo plano'' en lugar de la notificación de primer plano, pero los usuarios pueden ocultar esta notificación de la barra de estado si lo desean.
EDITAR : en Android 8.1 parece que la creación de un canal deshabilitado con IMPORTANCE_NONE no es útil, ya que el canal se habilitará automáticamente cuando envíe una notificación. Puede ser mejor crearlo con IMPORTANCE_LOW desde el principio y dejar que los usuarios cambien la importancia si lo desean.
Eso es correcto, una vez que se crea un canal, ya no se pueden hacer cambios.
No puede modificar el comportamiento de un canal de notificación mediante programación una vez que se haya creado y enviado al administrador de notificaciones.
https://developer.android.com/preview/features/notification-channels.html
Lo que tendrías que hacer es eliminar el canal y crear uno nuevo con una identificación diferente
No es una buena idea reproducir el sonido manualmente. El mejor enfoque sería tener dos (o más) canales, uno para cada sonido / vibración que le gustaría reproducir.
En el código, puedes decidir qué canal usar dependiendo del sonido que quieras reproducir.
Aquí está mi código donde reproduzco el sonido de notificación predeterminado o un sonido personalizado según la configuración del cliente. El código también se ocupa de los dispositivos que ejecutan Android antes de 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());
}
Para mí, la forma correcta para Android> = 8.0 es ocultar sus opciones de sonido / vibración y redirigir al usuario a la configuración de notificación de su aplicación usando esto:
Intent intent = new Intent();
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
context.startActivity(intent);
Podría ayudar en su caso. Si tiene una notificación mostrada, puede desactivar el sonido al actualizar esta notificación configurando .setOnlyAlertOnce(true)
. Esta solución funciona solo cuando se actualiza la notificación.