it-swarm.com.de

Android O - Benachrichtigungskanäle - Ändern Sie das Vibrationsmuster oder den Sound-Typ

Mit Android O erhalten wir das "Notification Channels". 

Soweit ich es verstehe, bedeutet dies, dass der Benutzer kann nicht gesetzt werden der Benachrichtigungston oder andere verwandte Benachrichtigungseinstellungen in der APP mehr. 

Der Benutzer muss zu "Einstellung der Benachrichtigungskanäle" wechseln und den Ton oder Vibration usw. hier weil alle.) Ändern Methoden aus dem NotificationBuilder wie setSound werden ignoriert.

Es gibt also wirklich NO Weg, um den Ton in stumm über code zu ändern?
Oder das Vibrationsmuster per Code ändern? 

Beispielsweise kann der Benutzer das Vibrationsmuster in meiner App einstellen.
.__ Oder er kann anstelle des Benachrichtigungstyps Töne aus dem Alarmtyp auswählen. 

Das alles ist nicht mehr möglich?
Ist das richtig oder gibt es eine Möglichkeit, dies zu tun?

17
chrisonline

Sie können die Anpassung von Sounds und Vibrationen zwar in Ihrer App anbieten, dies erfordert jedoch einen anderen Ansatz. Kurz gesagt, die Idee besteht darin, Sound und Vibration in Android O manuell abzuspielen, anstatt den Benachrichtigungskanal zu verwenden (es ist einfacher als es scheint).

So habe ich es gemacht:

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 ist der Ort, an dem ich den Sound mit MediaPlayer wiedergebe:

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

}

Empfehlungen

  • Erstellen Sie Ihren Benachrichtigungskanal mit IMPORTANCE_DEFAULT (für den Benutzer "High"), einem Null-Sound (setSound(null,null)) und einer Null-Vibration (setVibrationPattern(null)) und erklären Sie in der Kanalbeschreibung, dass dies die empfohlene Einstellung ist, um Konflikte mit der App zu vermeiden eigene Anpassung.
  • Machen Sie das Ganze zu Ihren Gunsten: Anstatt eine Funktion zu entfernen, geben Sie den Benutzern eine neue. Sie können ihnen die Möglichkeit geben, Ihre Anpassungsfunktionen oder die Benachrichtigungskanal-Funktionen zu verwenden (beispielsweise können Sie die aktuelle Kanalbedeutung überprüfen und abhängig von der Ebene können Sie die eine oder andere Sache verwenden).

Vordergrundbenachrichtigung

Beim Starten von Android O müssen Dienste, die aus dem Hintergrund gestartet werden, als Vordergrunddienste gestartet werden. Dies bedeutet, dass SoundService eine Vordergrundbenachrichtigung benötigt. Sie haben dafür einige Möglichkeiten:

  • Erstellen Sie eine Nice-Vordergrundbenachrichtigung mit einer Schaltfläche mit der Aufschrift "Wiedergabe anhalten", sodass der Benutzer den Ton stoppen kann, ohne die Benachrichtigung zu entfernen, die ihn gestartet hat.

  • Erstellen Sie eine einfache Benachrichtigung und senden Sie sie an einen deaktivierten Kanal (Sie können deaktivierte Kanäle erstellen, wenn Sie sie mit IMPORTANCE_NONE erstellen). Auf diese Weise wird die Standardbenachrichtigung "App läuft im Hintergrund" anstelle der Vordergrundbenachrichtigung angezeigt. Benutzer können diese Benachrichtigung jedoch in der Statusleiste ausblenden, wenn sie möchten.

EDIT: In Android 8.1 scheint das Erstellen eines deaktivierten Kanals mit IMPORTANCE_NONE nicht sinnvoll zu sein, da der Kanal automatisch aktiviert wird, wenn Sie eine Benachrichtigung senden. Es ist möglicherweise besser, es mit IMPORTANCE_LOW von Anfang an zu erstellen und Benutzern zu erlauben, die Wichtigkeit zu ändern, wenn sie möchten.

14
jmart

Könnte in Ihrem Fall helfen. Wenn eine Benachrichtigung angezeigt wird, können Sie den Ton beim Aktualisieren dieser Benachrichtigung deaktivieren, indem Sie .setOnlyAlertOnce(true) einstellen. Diese Lösung funktioniert nur beim Aktualisieren der Benachrichtigung.

5

Das ist richtig, sobald ein Kanal erstellt wurde, können Sie keine Änderungen mehr daran vornehmen.

Das Verhalten einer Benachrichtigung kann nicht programmgesteuert geändert werden Kanal, sobald er erstellt und an den Benachrichtigungsmanager übermittelt wurde

https://developer.Android.com/preview/features/notification-channels.html

Was müssten Sie tun den Kanal löschen und einen neuen mit einer anderen ID erstellen

2
tyczj

Für mich ist der richtige Weg für Android> = 8.0 das Ausblenden Ihrer Sound-/Vibrationsoptionen und das Umleiten des Benutzers zu den App-Benachrichtigungseinstellungen, indem Sie Folgendes verwenden:

  Intent intent = new Intent();
                intent.setAction("Android.settings.APP_NOTIFICATION_SETTINGS");
                intent.putExtra("Android.provider.extra.APP_PACKAGE", context.getPackageName());
                context.startActivity(intent);

Ich hoffe es wird helfen

1
Lluis Felisart

Es ist keine gute Idee, den Ton manuell abzuspielen. Der beste Ansatz wäre, zwei (oder mehr) Kanäle zu haben - einen für jeden Sound/Vibration, den Sie spielen möchten.

Im Code können Sie entscheiden, welchen Kanal Sie verwenden möchten, je nachdem, welchen Sound Sie spielen möchten.

Hier ist mein Code, wo ich entweder den Standardbenachrichtigungston oder einen benutzerdefinierten Sound abspiele, je nach den Einstellungen des Kunden. Der Code kümmert sich auch um Geräte, auf denen Android vor API 26 ausgeführt wird:

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

Also gibt es wirklich KEINE Möglichkeit, den Ton per Code in stumm zu ändern?

Verwenden Sie setSound() für NotificationChannel und zeigen Sie auf eine Sounddatei, die möglicherweise ein wenig Stille enthält. 

Oder das Vibrationsmuster per Code ändern? 

Verwenden Sie setVibrationPattern() für NotificationChannel .

0
CommonsWare