首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android O-通知频道-更改振动模式或声音类型

问Android O-通知频道-更改振动模式或声音类型
EN

Stack Overflow用户
提问于 2017-07-13 21:18:34
回答 4查看 21.4K关注 0票数 25

使用Android O,我们得到了“通知通道”。

据我所知,这意味着用户不能再在应用程序中设置、通知音或其他相关通知设置。

用户需要转到“通知通道设置代码”,并更改tone或vibration等。此处为,因为来自NotificationBuilder的所有方法,如被忽略。

所以确实没有办法通过将音调更改为静音

或者通过代码改变振动模式?

例如,用户可以在我的应用程序中设置振动模式。

或者他可以从警报类型而不是通知类型中选取音调。

这一切都不可能了吗?

这是正确的吗?或者有什么方法可以做到这一点吗?

EN

回答 4

Stack Overflow用户

发布于 2017-10-21 18:54:37

你仍然可以在你的应用程序中提供声音和振动定制,但它需要一种不同的方法。简而言之,这个想法是在Android O中手动播放声音和振动,而不是使用通知通道(它比看起来更容易)。

我是这样做的:

代码语言:javascript
复制
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是我用MediaPlayer播放声音的地方:

代码语言:javascript
复制
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();
    }

}

Recommendations

  • 使用IMPORTANCE_DEFAULT (对于用户来说是“高”),一个空声音(setSound(null,null))和一个空振动(setVibrationPattern(null))创建你的通知通道,并在通道描述中解释这是推荐的设置,以避免与应用程序自己的customization.
  • Turn冲突,整个事情对你有利:与其删除一个功能,不如给用户一个新的功能。您可以让他们有机会使用您的自定义功能或通知通道功能(例如,您可以检查当前通道的重要性,并根据您可以使用哪种功能的级别而定)。

前台通知

启动Android O,后台启动的服务必须作为前台服务启动。这意味着SoundService需要一个前台通知。为此,您有一些选项:

  • 创建一个很好的前景通知,其中有一个按钮,上面写着“停止播放”,这样用户就可以停止声音,而不会删除启动它的通知。
  • 创建一个简单的通知,并将其发送到禁用的通道(如果您使用IMPORTANCE_NONE创建禁用的通道,则可以创建禁用的通道)。执行此操作后,将显示默认系统的“应用程序正在后台运行”通知,而不是您的前台通知,但用户可以根据需要在状态栏中隐藏此通知。

编辑:在Android8.1中,使用IMPORTANCE_NONE创建禁用的频道似乎没有什么用处,因为当你发送通知时,频道会自动启用。从一开始就用IMPORTANCE_LOW创建它可能会更好,如果用户想要的话,让他们改变重要性。

票数 22
EN

Stack Overflow用户

发布于 2017-08-14 19:20:25

可能会对你的情况有所帮助。如果您显示了一个通知,您可以通过设置.setOnlyAlertOnce(true)在更新此通知时禁用声音。此解决方案仅在更新通知时有效。

票数 6
EN

Stack Overflow用户

发布于 2018-04-11 18:05:10

对我来说,安卓>= 8.0的正确方法是隐藏你的声音/振动选项,并使用以下命令将用户重定向到你的应用程序通知设置:

代码语言:javascript
复制
  Intent intent = new Intent();
                intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
                intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
                context.startActivity(intent);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45081815

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档