@qusaieilouti99/call-manager 0.1.99 → 0.1.100
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.
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// File: CallActivity.kt
|
|
1
2
|
package com.margelo.nitro.qusaieilouti99.callmanager
|
|
2
3
|
|
|
3
4
|
import android.app.Activity
|
|
@@ -49,31 +50,23 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
49
50
|
|
|
50
51
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
51
52
|
super.onCreate(savedInstanceState)
|
|
52
|
-
// Samsung lock‐screen bypass flag
|
|
53
53
|
val isSamsungBypass = intent.getBooleanExtra(
|
|
54
54
|
"SAMSUNG_LOCK_SCREEN_BYPASS", false
|
|
55
55
|
)
|
|
56
56
|
setupLockScreenBypass(isSamsungBypass)
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
callType = intent.getStringExtra("callType") ?: "Audio"
|
|
58
|
+
callId = intent.getStringExtra("callId") ?: ""
|
|
59
|
+
callType = intent.getStringExtra("callType") ?: "Audio"
|
|
61
60
|
val callerName = intent.getStringExtra("callerName") ?: "Unknown"
|
|
62
61
|
val avatarUrl = intent.getStringExtra("callerAvatar")
|
|
63
62
|
|
|
64
|
-
// Register for external hang‐up
|
|
65
63
|
CallEngine.registerCallEndListener(this)
|
|
66
|
-
|
|
67
|
-
// Build all‐code UI
|
|
68
64
|
buildUi(callerName, avatarUrl)
|
|
69
|
-
|
|
70
|
-
// Auto‐timeout
|
|
71
65
|
uiHandler.postDelayed(timeoutRunnable, timeoutMs)
|
|
72
66
|
Log.d(TAG, "CallActivity setup complete for callId=$callId")
|
|
73
67
|
}
|
|
74
68
|
|
|
75
69
|
private fun buildUi(name: String, avatarUrl: String?) {
|
|
76
|
-
// Root container
|
|
77
70
|
val root = FrameLayout(this).apply {
|
|
78
71
|
layoutParams = ViewGroup.LayoutParams(
|
|
79
72
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
@@ -81,20 +74,17 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
81
74
|
)
|
|
82
75
|
}
|
|
83
76
|
|
|
84
|
-
//
|
|
85
|
-
// 1) Background ImageView + blur
|
|
86
|
-
//
|
|
77
|
+
// 1) Full-screen background + blur
|
|
87
78
|
val bg = ImageView(this).apply {
|
|
88
79
|
layoutParams = FrameLayout.LayoutParams(
|
|
89
80
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
90
81
|
ViewGroup.LayoutParams.MATCH_PARENT
|
|
91
82
|
)
|
|
92
83
|
scaleType = ImageView.ScaleType.CENTER_CROP
|
|
93
|
-
// On API 31+ apply live RenderEffect blur
|
|
94
84
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
95
85
|
setRenderEffect(
|
|
96
86
|
RenderEffect.createBlurEffect(
|
|
97
|
-
|
|
87
|
+
50f, 50f, Shader.TileMode.CLAMP
|
|
98
88
|
)
|
|
99
89
|
)
|
|
100
90
|
}
|
|
@@ -102,9 +92,7 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
102
92
|
root.addView(bg)
|
|
103
93
|
loadAndBlurBackground(bg, avatarUrl)
|
|
104
94
|
|
|
105
|
-
//
|
|
106
|
-
// 2) Semi-transparent scrim
|
|
107
|
-
//
|
|
95
|
+
// 2) Dark scrim
|
|
108
96
|
root.addView(View(this).apply {
|
|
109
97
|
layoutParams = FrameLayout.LayoutParams(
|
|
110
98
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
@@ -113,9 +101,7 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
113
101
|
setBackgroundColor(Color.parseColor("#80000000"))
|
|
114
102
|
})
|
|
115
103
|
|
|
116
|
-
//
|
|
117
|
-
// 3) Top “Incoming … call” label
|
|
118
|
-
//
|
|
104
|
+
// 3) “Incoming ... call” with extra top padding (48dp)
|
|
119
105
|
val typeLabel = TextView(this).apply {
|
|
120
106
|
text = if (callType.equals("video", true))
|
|
121
107
|
"Incoming video call"
|
|
@@ -129,14 +115,12 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
129
115
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
130
116
|
).apply {
|
|
131
117
|
gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
|
|
132
|
-
topMargin = dp(
|
|
118
|
+
topMargin = dp(48)
|
|
133
119
|
}
|
|
134
120
|
}
|
|
135
121
|
root.addView(typeLabel)
|
|
136
122
|
|
|
137
|
-
//
|
|
138
|
-
// 4) Avatar + Name (in top half)
|
|
139
|
-
//
|
|
123
|
+
// 4) Avatar + name in top half
|
|
140
124
|
val avatarSection = LinearLayout(this).apply {
|
|
141
125
|
orientation = LinearLayout.VERTICAL
|
|
142
126
|
gravity = Gravity.CENTER_HORIZONTAL
|
|
@@ -162,9 +146,7 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
162
146
|
})
|
|
163
147
|
root.addView(avatarSection)
|
|
164
148
|
|
|
165
|
-
//
|
|
166
|
-
// 5) Bottom Answer/Decline Buttons
|
|
167
|
-
//
|
|
149
|
+
// 5) Bottom buttons with extra bottom padding (64dp)
|
|
168
150
|
val actions = LinearLayout(this).apply {
|
|
169
151
|
orientation = LinearLayout.HORIZONTAL
|
|
170
152
|
gravity = Gravity.CENTER
|
|
@@ -173,7 +155,7 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
173
155
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
174
156
|
).apply {
|
|
175
157
|
gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
|
|
176
|
-
bottomMargin = dp(
|
|
158
|
+
bottomMargin = dp(64)
|
|
177
159
|
}
|
|
178
160
|
}
|
|
179
161
|
actions.addView(
|
|
@@ -196,22 +178,24 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
196
178
|
setContentView(root)
|
|
197
179
|
}
|
|
198
180
|
|
|
199
|
-
|
|
200
|
-
private fun createAvatarView(
|
|
201
|
-
name: String,
|
|
202
|
-
url: String?
|
|
203
|
-
): FrameLayout {
|
|
181
|
+
private fun createAvatarView(name: String, url: String?): FrameLayout {
|
|
204
182
|
val size = dp(140)
|
|
183
|
+
// Gradient purple background
|
|
184
|
+
val gradientBg = GradientDrawable(
|
|
185
|
+
GradientDrawable.Orientation.TL_BR,
|
|
186
|
+
intArrayOf(
|
|
187
|
+
Color.parseColor("#8E24AA"),
|
|
188
|
+
Color.parseColor("#CE93D8")
|
|
189
|
+
)
|
|
190
|
+
).apply { shape = GradientDrawable.OVAL }
|
|
191
|
+
|
|
205
192
|
val container = FrameLayout(this).apply {
|
|
206
193
|
layoutParams = LinearLayout.LayoutParams(size, size)
|
|
207
|
-
background =
|
|
208
|
-
shape = GradientDrawable.OVAL
|
|
209
|
-
setColor(Color.parseColor("#DDFFFFFF"))
|
|
210
|
-
}
|
|
194
|
+
background = gradientBg
|
|
211
195
|
clipToOutline = true
|
|
212
196
|
}
|
|
213
197
|
|
|
214
|
-
// ImageView
|
|
198
|
+
// ImageView (only visible when URL != null)
|
|
215
199
|
val iv = ImageView(this).apply {
|
|
216
200
|
layoutParams = FrameLayout.LayoutParams(
|
|
217
201
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
@@ -221,7 +205,7 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
221
205
|
}
|
|
222
206
|
container.addView(iv)
|
|
223
207
|
|
|
224
|
-
// Initials
|
|
208
|
+
// Initials TextView
|
|
225
209
|
val initials = TextView(this).apply {
|
|
226
210
|
layoutParams = FrameLayout.LayoutParams(
|
|
227
211
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
@@ -236,14 +220,14 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
236
220
|
container.addView(initials)
|
|
237
221
|
|
|
238
222
|
if (url.isNullOrEmpty()) {
|
|
239
|
-
|
|
240
|
-
iv.setImageResource(R.drawable.ic_default_avatar)
|
|
223
|
+
iv.visibility = View.GONE
|
|
241
224
|
initials.visibility = View.VISIBLE
|
|
242
225
|
} else {
|
|
243
|
-
|
|
226
|
+
iv.visibility = View.VISIBLE
|
|
244
227
|
initials.visibility = View.GONE
|
|
245
228
|
loadAvatar(iv, url)
|
|
246
229
|
}
|
|
230
|
+
|
|
247
231
|
return container
|
|
248
232
|
}
|
|
249
233
|
|
|
@@ -251,13 +235,11 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
251
235
|
val parts = fullName.trim().split("\\s+".toRegex())
|
|
252
236
|
return when (parts.size) {
|
|
253
237
|
0 -> ""
|
|
254
|
-
1 -> parts[0].substring(0,1).uppercase()
|
|
255
|
-
else -> (parts[0][0].toString() + parts[1][0].toString())
|
|
256
|
-
.uppercase()
|
|
238
|
+
1 -> parts[0].substring(0, 1).uppercase()
|
|
239
|
+
else -> (parts[0][0].toString() + parts[1][0].toString()).uppercase()
|
|
257
240
|
}
|
|
258
241
|
}
|
|
259
242
|
|
|
260
|
-
/** Downloads an image + sets it on the ImageView. */
|
|
261
243
|
private fun loadAvatar(iv: ImageView, url: String) {
|
|
262
244
|
Thread {
|
|
263
245
|
try {
|
|
@@ -265,11 +247,10 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
265
247
|
conn.doInput = true; conn.connect()
|
|
266
248
|
val bmp = BitmapFactory.decodeStream(conn.inputStream)
|
|
267
249
|
runOnUiThread { iv.setImageBitmap(bmp) }
|
|
268
|
-
} catch (_: Exception) {
|
|
250
|
+
} catch (_: Exception) { }
|
|
269
251
|
}.start()
|
|
270
252
|
}
|
|
271
253
|
|
|
272
|
-
/** Downloads bg image (remote or fallback), applies blur if needed. */
|
|
273
254
|
private fun loadAndBlurBackground(iv: ImageView, url: String?) {
|
|
274
255
|
Thread {
|
|
275
256
|
val bmp: Bitmap? = try {
|
|
@@ -278,19 +259,16 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
278
259
|
c.doInput = true; c.connect()
|
|
279
260
|
BitmapFactory.decodeStream(c.inputStream)
|
|
280
261
|
} else {
|
|
281
|
-
// your fallback background
|
|
282
262
|
BitmapFactory.decodeResource(
|
|
283
263
|
resources, R.drawable.default_call_bg
|
|
284
264
|
)
|
|
285
265
|
}
|
|
286
|
-
} catch (_: Exception) {
|
|
287
|
-
null
|
|
288
|
-
}
|
|
266
|
+
} catch (_: Exception) { null }
|
|
289
267
|
bmp ?: return@Thread
|
|
290
268
|
|
|
291
269
|
val finalBmp = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
|
292
|
-
//
|
|
293
|
-
val factor =
|
|
270
|
+
// heavier blur via 16× down/up-scale
|
|
271
|
+
val factor = 16
|
|
294
272
|
val w = bmp.width / factor
|
|
295
273
|
val h = bmp.height / factor
|
|
296
274
|
val small = Bitmap.createScaledBitmap(bmp, w, h, true)
|
|
@@ -303,18 +281,15 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
303
281
|
}.start()
|
|
304
282
|
}
|
|
305
283
|
|
|
306
|
-
|
|
307
|
-
private fun createCircleButton(
|
|
308
|
-
iconRes: Int,
|
|
309
|
-
bgColor: Int
|
|
310
|
-
): FrameLayout {
|
|
284
|
+
private fun createCircleButton(iconRes: Int, bgColor: Int): FrameLayout {
|
|
311
285
|
val size = dp(70)
|
|
312
286
|
return FrameLayout(this).apply {
|
|
313
287
|
layoutParams = LinearLayout.LayoutParams(size, size)
|
|
314
288
|
isClickable = true
|
|
315
289
|
isFocusable = true
|
|
316
290
|
foreground = makeCircleRipple()
|
|
317
|
-
|
|
291
|
+
|
|
292
|
+
// circular background
|
|
318
293
|
addView(View(context).apply {
|
|
319
294
|
layoutParams = FrameLayout.LayoutParams(
|
|
320
295
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
@@ -325,6 +300,7 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
325
300
|
setColor(bgColor)
|
|
326
301
|
}
|
|
327
302
|
})
|
|
303
|
+
|
|
328
304
|
// icon
|
|
329
305
|
addView(ImageView(context).apply {
|
|
330
306
|
layoutParams = FrameLayout.LayoutParams(dp(36), dp(36))
|
|
@@ -335,18 +311,15 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
335
311
|
}
|
|
336
312
|
}
|
|
337
313
|
|
|
338
|
-
/** Circular RippleDrawable. */
|
|
339
314
|
private fun makeCircleRipple(): RippleDrawable {
|
|
340
315
|
val mask = GradientDrawable().apply {
|
|
341
316
|
shape = GradientDrawable.OVAL
|
|
342
317
|
setColor(Color.WHITE)
|
|
343
318
|
}
|
|
344
|
-
val
|
|
345
|
-
|
|
346
|
-
android.content.res.ColorStateList.valueOf(clr),
|
|
347
|
-
null,
|
|
348
|
-
mask
|
|
319
|
+
val color = android.content.res.ColorStateList.valueOf(
|
|
320
|
+
Color.parseColor("#33FFFFFF")
|
|
349
321
|
)
|
|
322
|
+
return RippleDrawable(color, null, mask)
|
|
350
323
|
}
|
|
351
324
|
|
|
352
325
|
private fun onAnswer() {
|
|
@@ -356,6 +329,7 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
356
329
|
CallEngine.answerCall(callId)
|
|
357
330
|
finishCallActivity()
|
|
358
331
|
}
|
|
332
|
+
|
|
359
333
|
private fun onDecline() {
|
|
360
334
|
finishReason = FinishReason.DECLINE
|
|
361
335
|
CallEngine.stopRingtone()
|
|
@@ -391,8 +365,7 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
391
365
|
override fun onDismissError() {
|
|
392
366
|
Log.w(TAG, "Keyguard dismiss error")
|
|
393
367
|
}
|
|
394
|
-
}
|
|
395
|
-
)
|
|
368
|
+
})
|
|
396
369
|
}
|
|
397
370
|
}
|
|
398
371
|
|
|
@@ -431,7 +404,8 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
431
404
|
}
|
|
432
405
|
|
|
433
406
|
private fun dp(v: Int): Int = TypedValue.applyDimension(
|
|
434
|
-
TypedValue.COMPLEX_UNIT_DIP,
|
|
407
|
+
TypedValue.COMPLEX_UNIT_DIP,
|
|
408
|
+
v.toFloat(),
|
|
435
409
|
resources.displayMetrics
|
|
436
410
|
).toInt()
|
|
437
411
|
|
package/package.json
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
-
android:width="24dp"
|
|
3
|
-
android:height="24dp"
|
|
4
|
-
android:viewportWidth="24"
|
|
5
|
-
android:viewportHeight="24">
|
|
6
|
-
<path
|
|
7
|
-
android:fillColor="#BDBDBD"
|
|
8
|
-
android:pathData="
|
|
9
|
-
M12,12c2.21,0 4,-1.79 4,-4
|
|
10
|
-
s-1.79,-4 -4,-4
|
|
11
|
-
s-4,1.79 -4,4
|
|
12
|
-
s1.79,4 4,4z
|
|
13
|
-
M6,20
|
|
14
|
-
c0,-3.31 2.69,-6 6,-6
|
|
15
|
-
s6,2.69 6,6
|
|
16
|
-
v1
|
|
17
|
-
H6v-1z"/>
|
|
18
|
-
</vector>
|