重叠通知和传入铃声振动

Overlapping notification and incoming ringer vibration

我在RINGER_MODE_VIBRATERINGER_MODE_NORMAL时振动phone,停止振动以接听电话或取消电话。但恰恰在此时 前台通知正在运行,并且通知振动与 incomingRinger 通知重叠。因此当startForeground(notification)功能起作用时振动不起作用。

我试过像这个问题一样禁用通知振动:Disable vibration for a notification

但是 enableVibration(false)setVibrate(new long[]{0L}) 不工作。

他们都不在奥利奥工作 (android 8)。其他所有版本都可以使用。

来电铃声:

    public class IncomingRinger {

    private static final String TAG = IncomingRinger.class.getSimpleName();

    private static final long[] VIBRATE_PATTERN = {0, 1000, 1000};

    private final Context context;
    private final Vibrator vibrator;
    private final AudioManager audioManager;

    public IncomingRinger(Context context) {
        this.context = context.getApplicationContext();
        this.vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

        start(!audioManager.isWiredHeadsetOn() && !audioManager.isBluetoothScoOn());
    }

    private void start(boolean speakerphone) {

        ringerMode = audioManager.getRingerMode();

        switch (ringerMode) {

            case AudioManager.RINGER_MODE_SILENT:
                stop();
                break;

            case AudioManager.RINGER_MODE_VIBRATE:
            case AudioManager.RINGER_MODE_NORMAL:

                vibrate();
                break;

            default:
                audioManager.setSpeakerphoneOn(false);
                break;
        }

    }

    private void vibrate() {
        if (shouldVibrate()) {
            vibrator.vibrate(VIBRATE_PATTERN, 1);
        }
    }

    public void stop() {
        audioManager.setSpeakerphoneOn(false);
        cancelVibrator();
    }

    public void cancelVibrator() {
        vibrator.cancel();
    }

    private boolean shouldVibrate() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            return shouldVibrateNew();
        } else {
            return shouldVibrateOld();
        }
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private boolean shouldVibrateNew() {
        if (vibrator == null || !vibrator.hasVibrator()) {
            return false;
        }

        boolean vibrateWhenRinging = Settings.System.getInt(context.getContentResolver(), "vibrate_when_ringing", 0) != 0;
        int ringerMode = audioManager.getRingerMode();

        if (vibrateWhenRinging) {
            return ringerMode != AudioManager.RINGER_MODE_SILENT;
        } else {
            return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
        }
    }

    private boolean shouldVibrateOld() {
        return audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER);
    }

}

清单权限:

 <uses-permission android:name="android.permission.VIBRATE" />
 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

CallNotificationBuilder:

public class CallNotificationBuilder {

public static final int WEBRTC_NOTIFICATION = 313388;

public static final int TYPE_INCOMING_RINGING = 1;
public static final int TYPE_OUTGOING_RINGING = 2;
public static final int TYPE_ESTABLISHED = 3;

private static final String callChannelId = "23455";
private static NotificationCompat.Builder builder;

public static Notification getCallInProgressNotification(Context context, int type) {

    builder = new NotificationCompat.Builder(context, callChannelId)
            .setContentIntent(goActivity(context, null))
            .setLights(Color.GREEN, 3000, 3000)
            .setOngoing(true) 
            .setShowWhen(true)
            .setWhen(System.currentTimeMillis());

    initialize(context);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        builder.setVisibility(android.app.Notification.VISIBILITY_PUBLIC);
    }

    NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel mChannel = new NotificationChannel(callChannelId, context.getString(R.string.app_name), importance);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this
        mChannel.setLockscreenVisibility(android.app.Notification.VISIBILITY_PUBLIC);
        mChannel.setShowBadge(true);
        mChannel.enableLights(true);
        notificationManager.createNotificationChannel(mChannel);
    }

    String contentTitle = new UserQueries().getDisplayNameInRealm(friendId);
    if (contentTitle.isEmpty()) {
        contentTitle = context.getString(R.string.app_name);
    }
    builder.setContentTitle(contentTitle);

    if (type == TYPE_INCOMING_RINGING) {
        builder.setContentText(context.getString(R.string.incoming_call));
        builder.setSmallIcon(R.drawable.call_in);

        builder.addAction(getActivityNotificationAction(context, friendId, callServerId, isOffer, isVideo, CallActivity.END_CALL_ACTION, R.drawable.ic_call_end_grey600_32dp, R.string.deny_call));
        builder.addAction(getActivityNotificationAction(context, friendId, callServerId, isOffer, isVideo, CallActivity.ANSWER_ACTION, R.drawable.ic_phone_grey600_32dp, R.string.answer_call));

    } else if (type == TYPE_OUTGOING_RINGING) {

        builder.setSmallIcon(R.drawable.call_out);

        builder.setContentText(context.getString(R.string.dialing));
        builder.addAction(getActivityNotificationAction(context, friendId, callServerId, isOffer, isVideo, CallActivity.END_CALL_ACTION, R.drawable.ic_call_end_grey600_32dp, R.string.cancel_call));

    } else {

        builder.setSmallIcon(R.drawable.call_icon);

        builder.setContentText(context.getString(R.string.call_in_progress));
        builder.addAction(getActivityNotificationAction(context, friendId, callServerId, isOffer, isVideo, CallActivity.END_CALL_ACTION, R.drawable.ic_call_end_grey600_32dp, R.string.end_call));

        builder.setUsesChronometer(true);
        builder.setShowWhen(false);
    }

    return builder.build();
}

private static PendingIntent goActivity(Context context, String action) {

    Intent activityIntent = new Intent(MyApplication.getContext(), CallActivity.class);

    if (action != null) {
        activityIntent.setAction(action);
    }

    activityIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
            | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
            | Intent.FLAG_ACTIVITY_NEW_TASK);

    return PendingIntent.getActivity(context, (int) System.currentTimeMillis(), activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}

private static void initialize(Context context) {

    //For when the screen might have been locked
    context.registerReceiver(notificationUpdateReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));

    //Just in case the screen didn't get a chance to finish turning off but still locked
    context.registerReceiver(notificationUpdateReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));

    //For when the user unlocks the device
    context.registerReceiver(notificationUpdateReceiver, new IntentFilter(Intent.ACTION_USER_PRESENT));

    //For when the user changes users
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        context.registerReceiver(notificationUpdateReceiver, new IntentFilter(Intent.ACTION_USER_BACKGROUND));
        context.registerReceiver(notificationUpdateReceiver, new IntentFilter(Intent.ACTION_USER_FOREGROUND));
    }

}

private static BroadcastReceiver notificationUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            if (keyguardManager != null && keyguardManager.isKeyguardLocked()) {
                builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
            }
        }
    }
};

private static NotificationCompat.Action getActivityNotificationAction(Context context,
                                                                       @NonNull String action,
                                                                       @DrawableRes int iconResId,
                                                                       @StringRes int titleResId) {

    return new NotificationCompat.Action(iconResId, MyApplication.getContext().getString(titleResId), goActivity(context, friendId, isOffer, callServerId, isVideo, action));
}

启动前台函数:

startForeground(CallNotificationBuilder.WEBRTC_NOTIFICATION,
                CallNotificationBuilder.getCallInProgressNotification(getApplicationContext(), type));

我没有发现您的代码有任何问题,我在 Nexus 6P 8.1.0 设备上进行了测试。

this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

我正在呼叫停止,振动器正在正常停止。

我只更改了重要性级别 运行 它:

int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(id, appName, importance);