重叠通知和传入铃声振动
Overlapping notification and incoming ringer vibration
我在RINGER_MODE_VIBRATE
和RINGER_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);
我在RINGER_MODE_VIBRATE
和RINGER_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);