@qusaieilouti99/call-manager 0.1.89 → 0.1.91
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -14,7 +14,9 @@ import android.widget.Button
|
|
|
14
14
|
import android.widget.TextView
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Full‐screen incoming‐call UI. Implements CallEndListener
|
|
18
|
+
* so it always auto‐finishes when the engine ends the call.
|
|
19
|
+
* **SAMSUNG FIX**: Enhanced lock screen bypass for Samsung devices
|
|
18
20
|
*/
|
|
19
21
|
class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
20
22
|
|
|
@@ -40,57 +42,21 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
40
42
|
super.onCreate(savedInstanceState)
|
|
41
43
|
Log.d(TAG, "CallActivity onCreate")
|
|
42
44
|
|
|
43
|
-
// Enhanced lock screen bypass
|
|
44
|
-
|
|
45
|
+
// **SAMSUNG FIX**: Enhanced lock screen bypass
|
|
46
|
+
val isSamsungLockScreenBypass = intent.getBooleanExtra("SAMSUNG_LOCK_SCREEN_BYPASS", false)
|
|
47
|
+
setupLockScreenBypass(isSamsungLockScreenBypass)
|
|
45
48
|
|
|
46
49
|
setContentView(R.layout.activity_call)
|
|
47
50
|
|
|
48
|
-
// Read incoming
|
|
51
|
+
// Read incoming‐call params
|
|
49
52
|
callId = intent.getStringExtra("callId") ?: ""
|
|
50
53
|
callType = intent.getStringExtra("callType") ?: "Audio"
|
|
51
54
|
Log.d(TAG, "CallActivity received callId: $callId, callType: $callType")
|
|
52
55
|
|
|
53
|
-
// Register for call
|
|
56
|
+
// Register for call‐end callbacks BEFORE timeout or user can dismiss
|
|
54
57
|
CallEngine.registerCallEndListener(this)
|
|
55
58
|
|
|
56
59
|
// Bind UI
|
|
57
|
-
setupUI()
|
|
58
|
-
|
|
59
|
-
// Start auto-timeout
|
|
60
|
-
timeoutHandler.postDelayed(timeoutRunnable, 60_000)
|
|
61
|
-
Log.d(TAG, "CallActivity setup complete")
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private fun setupLockScreenBypass() {
|
|
65
|
-
// For Android O_MR1 and above
|
|
66
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
67
|
-
setShowWhenLocked(true)
|
|
68
|
-
setTurnScreenOn(true)
|
|
69
|
-
|
|
70
|
-
// Additional Samsung-specific setup
|
|
71
|
-
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
|
72
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
73
|
-
keyguardManager.requestDismissKeyguard(this, null)
|
|
74
|
-
}
|
|
75
|
-
} else {
|
|
76
|
-
// For older versions
|
|
77
|
-
window.addFlags(
|
|
78
|
-
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
79
|
-
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
80
|
-
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
|
|
81
|
-
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Additional flags for better compatibility
|
|
86
|
-
window.addFlags(
|
|
87
|
-
WindowManager.LayoutParams.FLAG_FULLSCREEN or
|
|
88
|
-
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
|
|
89
|
-
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private fun setupUI() {
|
|
94
60
|
val callerName = intent.getStringExtra("callerName") ?: "Unknown"
|
|
95
61
|
findViewById<TextView>(R.id.caller_name).text = callerName
|
|
96
62
|
|
|
@@ -111,15 +77,64 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
111
77
|
CallEngine.endCall(callId)
|
|
112
78
|
finishCallActivity()
|
|
113
79
|
}
|
|
80
|
+
|
|
81
|
+
// Start auto‐timeout
|
|
82
|
+
timeoutHandler.postDelayed(timeoutRunnable, 60_000)
|
|
83
|
+
Log.d(TAG, "CallActivity setup complete")
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// **SAMSUNG FIX**: Enhanced lock screen bypass method
|
|
87
|
+
private fun setupLockScreenBypass(isSamsungSpecific: Boolean) {
|
|
88
|
+
// Standard lock screen bypass
|
|
89
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
90
|
+
setShowWhenLocked(true)
|
|
91
|
+
setTurnScreenOn(true)
|
|
92
|
+
} else {
|
|
93
|
+
window.addFlags(
|
|
94
|
+
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
95
|
+
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
96
|
+
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// **SAMSUNG SPECIFIC**: Additional fixes for Samsung One UI 7
|
|
101
|
+
if (isSamsungSpecific) {
|
|
102
|
+
Log.d(TAG, "Applying Samsung-specific lock screen bypass")
|
|
103
|
+
|
|
104
|
+
// **CRITICAL**: Samsung requires BOTH new and old methods
|
|
105
|
+
window.addFlags(
|
|
106
|
+
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
107
|
+
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
108
|
+
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
|
|
109
|
+
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
// **SAMSUNG SPECIFIC**: Request keyguard dismissal
|
|
113
|
+
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
|
114
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
115
|
+
keyguardManager.requestDismissKeyguard(this, object : KeyguardManager.KeyguardDismissCallback() {
|
|
116
|
+
override fun onDismissSucceeded() {
|
|
117
|
+
Log.d(TAG, "Samsung keyguard dismissed successfully")
|
|
118
|
+
}
|
|
119
|
+
override fun onDismissError() {
|
|
120
|
+
Log.w(TAG, "Samsung keyguard dismissal failed")
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
}
|
|
114
125
|
}
|
|
115
126
|
|
|
116
127
|
override fun onDestroy() {
|
|
117
128
|
super.onDestroy()
|
|
118
129
|
Log.d(TAG, "CallActivity onDestroy for callId: $callId. Reason: $finishReason")
|
|
119
130
|
|
|
131
|
+
// Unregister listener
|
|
120
132
|
CallEngine.unregisterCallEndListener(this)
|
|
133
|
+
|
|
134
|
+
// Cancel timeout
|
|
121
135
|
timeoutHandler.removeCallbacks(timeoutRunnable)
|
|
122
136
|
|
|
137
|
+
// If user never answered, clean up ringtone/UI
|
|
123
138
|
if (finishReason != FinishReason.ANSWER) {
|
|
124
139
|
CallEngine.stopRingtone()
|
|
125
140
|
CallEngine.cancelIncomingCallUI()
|
|
@@ -135,6 +150,10 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
135
150
|
finishCallActivity()
|
|
136
151
|
}
|
|
137
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Called by CallEngine whenever ANY call ends.
|
|
155
|
+
* We only care about our own callId.
|
|
156
|
+
*/
|
|
138
157
|
override fun onCallEnded(endedCallId: String) {
|
|
139
158
|
if (endedCallId == callId && !isFinishing) {
|
|
140
159
|
Log.d(TAG, "CallActivity onCallEnded callback for callId: $callId")
|
|
@@ -880,6 +880,7 @@ object CallEngine {
|
|
|
880
880
|
}
|
|
881
881
|
|
|
882
882
|
// --- Notification Management ---
|
|
883
|
+
// **SAMSUNG FIX**: Enhanced notification channel creation
|
|
883
884
|
private fun createNotificationChannel() {
|
|
884
885
|
val context = requireContext()
|
|
885
886
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
@@ -893,6 +894,10 @@ object CallEngine {
|
|
|
893
894
|
channel.lightColor = Color.GREEN
|
|
894
895
|
channel.enableVibration(true)
|
|
895
896
|
|
|
897
|
+
// **SAMSUNG FIX**: Set bypass DND and lock screen visibility
|
|
898
|
+
channel.setBypassDnd(true)
|
|
899
|
+
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
|
|
900
|
+
|
|
896
901
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
|
897
902
|
channel.setSound(
|
|
898
903
|
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE),
|
|
@@ -911,6 +916,7 @@ object CallEngine {
|
|
|
911
916
|
}
|
|
912
917
|
}
|
|
913
918
|
|
|
919
|
+
// **SAMSUNG FIX**: Enhanced showIncomingCallUI method
|
|
914
920
|
private fun showIncomingCallUI(callId: String, callerName: String, callType: String) {
|
|
915
921
|
val context = requireContext()
|
|
916
922
|
Log.d(TAG, "Showing incoming call UI for $callId")
|
|
@@ -918,34 +924,12 @@ object CallEngine {
|
|
|
918
924
|
val notificationManager =
|
|
919
925
|
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
920
926
|
|
|
921
|
-
// Enhanced full screen intent
|
|
922
|
-
val fullScreenIntent = Intent(context, CallActivity::class.java).apply {
|
|
923
|
-
addFlags(
|
|
924
|
-
Intent.FLAG_ACTIVITY_NEW_TASK or
|
|
925
|
-
Intent.FLAG_ACTIVITY_CLEAR_TASK or
|
|
926
|
-
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS or
|
|
927
|
-
Intent.FLAG_ACTIVITY_NO_ANIMATION or
|
|
928
|
-
Intent.FLAG_ACTIVITY_SINGLE_TOP
|
|
929
|
-
)
|
|
930
|
-
putExtra("callId", callId)
|
|
931
|
-
putExtra("callerName", callerName)
|
|
932
|
-
putExtra("callType", callType)
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
val fullScreenPendingIntent = PendingIntent.getActivity(
|
|
936
|
-
context,
|
|
937
|
-
callId.hashCode(), // Use unique request code
|
|
938
|
-
fullScreenIntent,
|
|
939
|
-
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
940
|
-
)
|
|
941
|
-
|
|
942
|
-
// Answer and decline intents
|
|
943
927
|
val answerIntent = Intent(context, CallNotificationActionReceiver::class.java).apply {
|
|
944
928
|
action = "com.qusaieilouti99.callmanager.ANSWER_CALL"
|
|
945
929
|
putExtra("callId", callId)
|
|
946
930
|
}
|
|
947
931
|
val answerPendingIntent = PendingIntent.getBroadcast(
|
|
948
|
-
context,
|
|
932
|
+
context, 0, answerIntent,
|
|
949
933
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
950
934
|
)
|
|
951
935
|
|
|
@@ -954,10 +938,33 @@ object CallEngine {
|
|
|
954
938
|
putExtra("callId", callId)
|
|
955
939
|
}
|
|
956
940
|
val declinePendingIntent = PendingIntent.getBroadcast(
|
|
957
|
-
context,
|
|
941
|
+
context, 1, declineIntent,
|
|
958
942
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
959
943
|
)
|
|
960
944
|
|
|
945
|
+
// **SAMSUNG FIX**: Enhanced full-screen intent
|
|
946
|
+
|
|
947
|
+
// First, wake up the screen using PowerManager
|
|
948
|
+
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
|
|
949
|
+
val wakeLock = powerManager.newWakeLock(
|
|
950
|
+
PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP,
|
|
951
|
+
"CallEngine:IncomingCallWake"
|
|
952
|
+
)
|
|
953
|
+
wakeLock.acquire(5000) // 5 sec
|
|
954
|
+
val fullScreenIntent = Intent(context, CallActivity::class.java).apply {
|
|
955
|
+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
956
|
+
putExtra("callId", callId)
|
|
957
|
+
putExtra("callerName", callerName)
|
|
958
|
+
putExtra("callType", callType)
|
|
959
|
+
// **SAMSUNG SPECIFIC**: Add Samsung lock screen bypass flag
|
|
960
|
+
putExtra("SAMSUNG_LOCK_SCREEN_BYPASS", true)
|
|
961
|
+
}
|
|
962
|
+
val fullScreenPendingIntent = PendingIntent.getActivity(
|
|
963
|
+
context, 2, fullScreenIntent,
|
|
964
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
965
|
+
)
|
|
966
|
+
|
|
967
|
+
// **SAMSUNG FIX**: Enhanced notification
|
|
961
968
|
val notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
962
969
|
val person = android.app.Person.Builder()
|
|
963
970
|
.setName(callerName)
|
|
@@ -977,19 +984,24 @@ object CallEngine {
|
|
|
977
984
|
.setAutoCancel(false)
|
|
978
985
|
.setCategory(Notification.CATEGORY_CALL)
|
|
979
986
|
.setPriority(Notification.PRIORITY_MAX)
|
|
987
|
+
// **SAMSUNG SPECIFIC**: Add lock screen visibility
|
|
988
|
+
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
|
989
|
+
.setPublicVersion(null)
|
|
980
990
|
.build()
|
|
981
991
|
} else {
|
|
982
992
|
Notification.Builder(context, NOTIF_CHANNEL_ID)
|
|
983
993
|
.setSmallIcon(android.R.drawable.sym_call_incoming)
|
|
984
994
|
.setContentTitle("Incoming Call")
|
|
985
995
|
.setContentText(callerName)
|
|
986
|
-
.setPriority(Notification.
|
|
996
|
+
.setPriority(Notification.PRIORITY_HIGH)
|
|
987
997
|
.setCategory(Notification.CATEGORY_CALL)
|
|
988
998
|
.setFullScreenIntent(fullScreenPendingIntent, true)
|
|
989
999
|
.addAction(android.R.drawable.sym_action_call, "Answer", answerPendingIntent)
|
|
990
1000
|
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Decline", declinePendingIntent)
|
|
991
1001
|
.setOngoing(true)
|
|
992
1002
|
.setAutoCancel(false)
|
|
1003
|
+
// **SAMSUNG SPECIFIC**: Add lock screen visibility
|
|
1004
|
+
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
|
993
1005
|
.build()
|
|
994
1006
|
}
|
|
995
1007
|
|