chatgui-android: входящий звонок поверх блокировки (inline-оверлей) + вибрация всегда кроме silent
This commit is contained in:
1 parent
fb4343fca6
commit
ceaf466b1c
3 files changed
+30
-23
No files matched your search
@@ -50,7 +50,13 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
requestNotificationPermission()
|
||||
requestFgsMicPermission()
|
||||
handleIncomingCallIntent(intent)
|
||||
|
||||
/* Входящий звонок: showWhenLocked/turnScreenOn ДО setContent, иначе полноэкранный
|
||||
intent мигает и UI не отрисовывается поверх keyguard (холодный старт). */
|
||||
if (incomingCallId(intent) != 0L) {
|
||||
LogManager.addLog("INFO", "MAIN", "launched for incoming call 0x%016x".format(incomingCallId(intent)))
|
||||
showOverLockScreen()
|
||||
}
|
||||
|
||||
/* Edge-to-edge with dark status/navigation bar icons (light app theme) */
|
||||
enableEdgeToEdge(
|
||||
@@ -359,23 +365,26 @@ class MainActivity : ComponentActivity() {
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
handleIncomingCallIntent(intent)
|
||||
if (incomingCallId(intent) != 0L) {
|
||||
LogManager.addLog("INFO", "MAIN", "launched for incoming call 0x%016x".format(incomingCallId(intent)))
|
||||
showOverLockScreen()
|
||||
}
|
||||
}
|
||||
|
||||
/** Full-screen intent входящего звонка: показать activity поверх блокировки. */
|
||||
private fun handleIncomingCallIntent(intent: Intent?) {
|
||||
val callId = intent?.getLongExtra(IncomingCallManager.EXTRA_CALL_ID, 0L) ?: 0L
|
||||
if (callId == 0L) return
|
||||
LogManager.addLog("INFO", "MAIN", "launched for incoming call 0x%016x".format(callId))
|
||||
private fun incomingCallId(intent: Intent?): Long =
|
||||
intent?.getLongExtra(IncomingCallManager.EXTRA_CALL_ID, 0L) ?: 0L
|
||||
|
||||
/** Показать активити поверх блокировки и включить экран (входящий звонок). */
|
||||
private fun showOverLockScreen() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
setShowWhenLocked(true)
|
||||
setTurnScreenOn(true)
|
||||
overLock = true
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
|
||||
or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
||||
}
|
||||
overLock = true
|
||||
}
|
||||
|
||||
/** Снять «показ поверх блокировки», выставленный для входящего звонка. */
|
||||
|
||||
@@ -11,7 +11,6 @@ import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import android.provider.Settings
|
||||
import com.utun.chat.ChatApplication
|
||||
import com.utun.chat.R
|
||||
|
||||
@@ -19,12 +18,13 @@ import com.utun.chat.R
|
||||
* Мелодия входящего звонка через профиль звонка (STREAM_RING) + ручная вибрация.
|
||||
*
|
||||
* Поведение по системному режиму звонка (AudioManager.getRingerMode):
|
||||
* - NORMAL : звук + вибрация, если включена настройка «вибрировать при вызове»
|
||||
* (Settings.System.VIBRATE_WHEN_RINGING);
|
||||
* - NORMAL : звук + вибрация;
|
||||
* - VIBRATE: без звука, только вибрация;
|
||||
* - SILENT : без звука и вибрации.
|
||||
*
|
||||
* Вибрация всегда запускается вручную через Vibrator (класс Ringtone сам не вибрирует).
|
||||
* Настройка «вибрировать при вызове» (VIBRATE_WHEN_RINGING) устарела и на новых
|
||||
* Android/Samsung не отражает реальное поведение телефонии — поэтому не используется.
|
||||
*
|
||||
* API 28+ : звук через Ringtone (RingtoneManager), громкость — «громкость вызова».
|
||||
* API 26–27: звук через MediaPlayer(STREAM_RING, loop) + audio focus.
|
||||
@@ -48,8 +48,7 @@ class RingtonePlayer {
|
||||
|
||||
val ringerMode = am.ringerMode
|
||||
val playSound = ringerMode == AudioManager.RINGER_MODE_NORMAL
|
||||
val playVibrate = ringerMode == AudioManager.RINGER_MODE_VIBRATE
|
||||
|| (playSound && systemVibrateWhenRinging())
|
||||
val playVibrate = ringerMode != AudioManager.RINGER_MODE_SILENT
|
||||
|
||||
LogManager.addLog("INFO", "Ringtone",
|
||||
"ringerMode=%d sound=%b vibrate=%b".format(ringerMode, playSound, playVibrate))
|
||||
@@ -120,14 +119,7 @@ class RingtonePlayer {
|
||||
LogManager.addLog("INFO", "Ringtone", "stopped")
|
||||
}
|
||||
|
||||
/* ── вибрация (решение принято в play(): VIBRATE-режим или VIBRATE_WHEN_RINGING) ── */
|
||||
|
||||
private fun systemVibrateWhenRinging(): Boolean = try {
|
||||
Settings.System.getInt(
|
||||
ChatApplication.instance.contentResolver, Settings.System.VIBRATE_WHEN_RINGING, 0) != 0
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
/* ── вибрация (решение принято в play(): вибрируем всегда, кроме SILENT) ── */
|
||||
|
||||
private fun startVibrate() {
|
||||
val v = try {
|
||||
|
||||
+8
-2
@@ -15,9 +15,12 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import com.utun.chat.viewmodel.ChatViewModel
|
||||
|
||||
/**
|
||||
* Входящий звонок — inline-оверлей внутри окна активити (не отдельное Dialog-окно):
|
||||
* так он отрисовывается и поверх keyguard при пробуждении полноэкранным intent'ом.
|
||||
*/
|
||||
@Composable
|
||||
fun IncomingCallDialog(
|
||||
viewModel: ChatViewModel
|
||||
@@ -25,7 +28,10 @@ fun IncomingCallDialog(
|
||||
val st = viewModel.callState.collectAsState().value ?: return
|
||||
val name = st.peerName.ifEmpty { "0x%016x".format(st.peerNodeId) }
|
||||
|
||||
Dialog(onDismissRequest = { }) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize().background(Color(0xCC000000)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Surface(
|
||||
shape = MaterialTheme.shapes.large,
|
||||
color = Color(0xFF1B2733)
|
||||
|
||||
Reference in new issue
Block a user