I vibrate phone when RINGER_MODE_VIBRATE
and RINGER_MODE_NORMAL
and stop vibrate to answering call or cancelling call. But exactly at this point
foreground notification is working and notification vibration is overlapping incomingRinger notification. Therefore vibration is not working when startForeground(notification)
function is working.
I have tried disable vibration for notification like this question : Disable vibration for a notification
but enableVibration(false)
or setVibrate(new long[]{0L})
is not working.
All of them are not working at Oreo (android 8). Other all versions are working.
IncomingRinger:
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);
}
}
Manifest permissions:
<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 function:
startForeground(CallNotificationBuilder.WEBRTC_NOTIFICATION,
CallNotificationBuilder.getCallInProgressNotification(getApplicationContext(), type));
I only changed importance level and ran it:
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(id, appName, importance);