@qusaieilouti99/call-manager 0.1.88 → 0.1.90
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,25 @@ 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
|
+
val fullScreenIntent = Intent(context, CallActivity::class.java).apply {
|
|
947
|
+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
948
|
+
putExtra("callId", callId)
|
|
949
|
+
putExtra("callerName", callerName)
|
|
950
|
+
putExtra("callType", callType)
|
|
951
|
+
// **SAMSUNG SPECIFIC**: Add Samsung lock screen bypass flag
|
|
952
|
+
putExtra("SAMSUNG_LOCK_SCREEN_BYPASS", true)
|
|
953
|
+
}
|
|
954
|
+
val fullScreenPendingIntent = PendingIntent.getActivity(
|
|
955
|
+
context, 2, fullScreenIntent,
|
|
956
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
957
|
+
)
|
|
958
|
+
|
|
959
|
+
// **SAMSUNG FIX**: Enhanced notification
|
|
961
960
|
val notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
962
961
|
val person = android.app.Person.Builder()
|
|
963
962
|
.setName(callerName)
|
|
@@ -977,19 +976,24 @@ object CallEngine {
|
|
|
977
976
|
.setAutoCancel(false)
|
|
978
977
|
.setCategory(Notification.CATEGORY_CALL)
|
|
979
978
|
.setPriority(Notification.PRIORITY_MAX)
|
|
979
|
+
// **SAMSUNG SPECIFIC**: Add lock screen visibility
|
|
980
|
+
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
|
981
|
+
.setPublicVersion(null)
|
|
980
982
|
.build()
|
|
981
983
|
} else {
|
|
982
984
|
Notification.Builder(context, NOTIF_CHANNEL_ID)
|
|
983
985
|
.setSmallIcon(android.R.drawable.sym_call_incoming)
|
|
984
986
|
.setContentTitle("Incoming Call")
|
|
985
987
|
.setContentText(callerName)
|
|
986
|
-
.setPriority(Notification.
|
|
988
|
+
.setPriority(Notification.PRIORITY_HIGH)
|
|
987
989
|
.setCategory(Notification.CATEGORY_CALL)
|
|
988
990
|
.setFullScreenIntent(fullScreenPendingIntent, true)
|
|
989
991
|
.addAction(android.R.drawable.sym_action_call, "Answer", answerPendingIntent)
|
|
990
992
|
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Decline", declinePendingIntent)
|
|
991
993
|
.setOngoing(true)
|
|
992
994
|
.setAutoCancel(false)
|
|
995
|
+
// **SAMSUNG SPECIFIC**: Add lock screen visibility
|
|
996
|
+
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
|
993
997
|
.build()
|
|
994
998
|
}
|
|
995
999
|
|