web-dev-qa-db-fra.com

Android O - Notification Canaux - Modifier le motif de vibration ou le type de son

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?

17
chrisonline

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

  • Créez votre canal de notification avec IMPORTANCE_DEFAULT (pour l'utilisateur, c'est «Elevé»), un son nul (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.
  • Mettez tout en votre faveur: au lieu de supprimer une fonctionnalité, donnez-en une nouvelle aux utilisateurs. Vous pouvez leur donner la possibilité d'utiliser vos fonctions de personnalisation ou les fonctions du canal de notification (par exemple, vous pouvez vérifier l'importance du canal actuel et, en fonction du niveau, vous pouvez utiliser l'une ou l'autre chose).

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.

14
jmart

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.

5
Jacek Marchwicki

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

2
tyczj

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

1
Lluis Felisart

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());
}
0
Dimitar Darazhanski

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? 

Utilisez setVibrationPattern() sur NotificationChannel .

0
CommonsWare