Skip to content

Commit dc67c36

Browse files
committed
Clear and group missed call notifications
- Clear notification if an action button is clicked. - Group missed call notifications.
1 parent 72e09a8 commit dc67c36

4 files changed

Lines changed: 132 additions & 52 deletions

File tree

app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@
211211
android:exported="true">
212212
<intent-filter>
213213
<action android:name="android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION" />
214+
<action android:name="org.fossify.phone.action.MISSED_CALL_BACK" />
215+
<action android:name="org.fossify.phone.action.MISSED_CALL_MESSAGE" />
216+
<action android:name="org.fossify.phone.action.MISSED_CALL_CANCEL" />
214217
</intent-filter>
215218
</receiver>
216219

app/src/main/kotlin/org/fossify/phone/helpers/Constants.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,8 @@ private const val PATH = "org.fossify.phone.action."
2828
const val ACCEPT_CALL = PATH + "accept_call"
2929
const val DECLINE_CALL = PATH + "decline_call"
3030
const val MISSED_CALLS = PATH + "missed_call"
31+
const val MISSED_CALL_BACK = PATH + "missed_call_back"
32+
const val MISSED_CALL_MESSAGE = PATH + "missed_call_message"
33+
const val MISSED_CALL_CANCEL = PATH + "missed_call_cancel"
3134

3235
const val DIALPAD_TONE_LENGTH_MS = 150L // The length of DTMF tones in milliseconds
Lines changed: 115 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.fossify.phone.receivers
22

3+
import android.app.Notification
34
import android.app.NotificationChannel
45
import android.app.NotificationManager
56
import android.app.PendingIntent
@@ -10,68 +11,137 @@ import android.graphics.drawable.Icon
1011
import android.net.Uri
1112
import android.os.Build
1213
import android.telecom.TelecomManager
14+
import android.util.Log
1315
import androidx.annotation.RequiresApi
1416
import androidx.core.app.NotificationCompat
1517
import org.fossify.commons.extensions.getLaunchIntent
1618
import org.fossify.commons.extensions.notificationManager
19+
import org.fossify.commons.extensions.telecomManager
1720
import org.fossify.commons.helpers.SimpleContactsHelper
1821
import org.fossify.phone.R
1922
import org.fossify.phone.helpers.MISSED_CALLS
23+
import org.fossify.phone.helpers.MISSED_CALL_BACK
24+
import org.fossify.phone.helpers.MISSED_CALL_CANCEL
25+
import org.fossify.phone.helpers.MISSED_CALL_MESSAGE
2026
import kotlin.random.Random
2127

2228
@RequiresApi(Build.VERSION_CODES.O)
2329
class MissedCallReceiver : BroadcastReceiver() {
2430
override fun onReceive(context: Context, intent: Intent) {
25-
if (intent.action == TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION) {
26-
val extras = intent.extras!!
27-
val notificationCount = extras.getInt(TelecomManager.EXTRA_NOTIFICATION_COUNT)
28-
if (notificationCount != 0) {
29-
val phoneNumber = extras.getString(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER)!!
30-
val helper = SimpleContactsHelper(context)
31-
val name = helper.getNameFromPhoneNumber(phoneNumber)
32-
val photoUri = helper.getPhotoUriFromPhoneNumber(phoneNumber)
31+
val extras = intent.extras ?: return
32+
var phoneNumber = extras.getString("phoneNumber")
33+
var notificationId = extras.getInt("notificationId", -1)
34+
val notificationManager = context.notificationManager
3335

34-
val notificationManager = context.notificationManager
35-
val channel = NotificationChannel(
36-
"missed_call_channel",
37-
context.getString(R.string.missed_call_channel),
38-
NotificationManager.IMPORTANCE_LOW
39-
)
40-
notificationManager.createNotificationChannel(channel)
36+
when (intent.action) {
37+
TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION -> {
38+
notificationId = Random.nextInt()
39+
phoneNumber = extras.getString(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER)
40+
val notificationCount = extras.getInt(TelecomManager.EXTRA_NOTIFICATION_COUNT)
41+
if (notificationCount != 0) {
42+
createNotificationChannel(context)
43+
notificationManager.notify(MISSED_CALLS.hashCode(), getNotificationGroup(context))
44+
notificationManager.notify(notificationId, buildNotification(context, notificationId, phoneNumber ?: return))
45+
}
46+
null
47+
}
4148

42-
val pendingIntent = PendingIntent.getActivity(
43-
context, 0, context.getLaunchIntent(), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
44-
)
45-
val callBack = Intent(Intent.ACTION_CALL).apply {
46-
data = Uri.fromParts("tel", phoneNumber, null)
49+
MISSED_CALL_BACK -> phoneNumber?.let {
50+
Intent(Intent.ACTION_CALL).apply {
51+
data = Uri.fromParts("tel", it, null)
52+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
4753
}
48-
val callBackIntent = PendingIntent.getActivity(
49-
context, 0, callBack, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
50-
)
51-
val smsIntent = Intent(Intent.ACTION_VIEW).apply {
52-
data = Uri.fromParts("sms", phoneNumber, null)
54+
}
55+
56+
MISSED_CALL_MESSAGE -> phoneNumber?.let {
57+
Intent(Intent.ACTION_VIEW).apply {
58+
data = Uri.fromParts("sms", it, null)
59+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
5360
}
54-
val messageIntent = PendingIntent.getActivity(
55-
context, 0, smsIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
56-
)
57-
val cancel = Intent("android.intent.action.CANCEL_MISSED_CALLS_NOTIFICATION")
58-
val cancelIntent = PendingIntent.getActivity(
59-
context, 0, cancel, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
60-
)
61-
val notification = NotificationCompat.Builder(context, "missed_call_channel")
62-
.setSmallIcon(android.R.drawable.sym_call_missed)
63-
.setContentTitle(context.getString(R.string.missed_call))
64-
.setContentText(context.getString(R.string.missed_call_from, name))
65-
.setLargeIcon(Icon.createWithContentUri(photoUri))
66-
.setAutoCancel(true)
67-
.setGroup(MISSED_CALLS)
68-
.setContentIntent(pendingIntent)
69-
.addAction(0, context.getString(R.string.call_back), callBackIntent)
70-
.addAction(0, context.getString(R.string.message), messageIntent)
71-
.setDeleteIntent(cancelIntent)
72-
.build()
73-
notificationManager.notify(Random.nextInt(), notification)
7461
}
62+
63+
MISSED_CALL_CANCEL -> {
64+
context.telecomManager.cancelMissedCallsNotification()
65+
null
66+
}
67+
68+
else -> null
69+
}?.let {
70+
Log.d("MISSEDCALL", it.toString())
71+
context.startActivity(it)
72+
context.notificationManager.cancel(notificationId)
73+
}
74+
}
75+
76+
private fun createNotificationChannel(context: Context) {
77+
val notificationManager = context.notificationManager
78+
val channel = NotificationChannel(
79+
"missed_call_channel",
80+
context.getString(R.string.missed_call_channel),
81+
NotificationManager.IMPORTANCE_LOW
82+
)
83+
notificationManager.createNotificationChannel(channel)
84+
}
85+
86+
private fun launchIntent(context: Context): PendingIntent {
87+
return PendingIntent.getActivity(
88+
context, 0, context.getLaunchIntent(), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
89+
)
90+
}
91+
92+
private fun getNotificationGroup(context: Context): Notification {
93+
return NotificationCompat.Builder(context, "missed_call_channel")
94+
.setSmallIcon(android.R.drawable.sym_call_missed)
95+
.setAutoCancel(true)
96+
.setGroupSummary(true)
97+
.setGroup(MISSED_CALLS)
98+
.setContentIntent(launchIntent(context))
99+
.build()
100+
}
101+
102+
private fun buildNotification(context: Context, notificationId: Int, phoneNumber: String): Notification {
103+
val helper = SimpleContactsHelper(context)
104+
val name = helper.getNameFromPhoneNumber(phoneNumber)
105+
val photoUri = helper.getPhotoUriFromPhoneNumber(phoneNumber)
106+
107+
val callBack = Intent(context, MissedCallReceiver::class.java).apply {
108+
action = MISSED_CALL_BACK
109+
putExtra("notificationId", notificationId)
110+
putExtra("phoneNumber", phoneNumber)
75111
}
112+
val callBackIntent = PendingIntent.getBroadcast(
113+
context, 0, callBack, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
114+
)
115+
116+
val smsIntent = Intent(context, MissedCallReceiver::class.java).apply {
117+
action = MISSED_CALL_MESSAGE
118+
putExtra("notificationId", notificationId)
119+
putExtra("phoneNumber", phoneNumber)
120+
}
121+
val messageIntent = PendingIntent.getBroadcast(
122+
context, 0, smsIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
123+
)
124+
125+
val cancel = Intent(context, MissedCallReceiver::class.java).apply {
126+
action = MISSED_CALL_CANCEL
127+
putExtra("notificationId", notificationId)
128+
putExtra("phoneNumber", phoneNumber)
129+
}
130+
val cancelIntent = PendingIntent.getActivity(
131+
context, 0, cancel, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
132+
)
133+
134+
return NotificationCompat.Builder(context, "missed_call_channel")
135+
.setSmallIcon(android.R.drawable.sym_call_missed)
136+
.setContentTitle(context.resources.getQuantityString(R.plurals.missed_calls, 1, 1))
137+
.setContentText(context.getString(R.string.missed_call_from, name))
138+
.setLargeIcon(Icon.createWithContentUri(photoUri))
139+
.setAutoCancel(true)
140+
.setGroup(MISSED_CALLS)
141+
.setContentIntent(launchIntent(context))
142+
.addAction(0, context.getString(R.string.call_back), callBackIntent)
143+
.addAction(0, context.getString(R.string.message), messageIntent)
144+
.setDeleteIntent(cancelIntent)
145+
.build()
76146
}
77147
}

app/src/main/res/values/strings.xml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@
6565
<string name="choose_audio_route">Choose audio route</string>
6666
<string name="calling_blocked_number">The number you are calling is blocked</string>
6767

68+
<!-- Notifications -->
69+
<string name="missed_call_channel">Missed Calls</string>
70+
<plurals name="missed_calls">
71+
<item quantity="one">Missed call</item>
72+
<item quantity="few">%d missed calls</item>
73+
<item quantity="other">%d missed calls</item>
74+
</plurals>
75+
<string name="missed_call_from">Missed call from %s</string>
76+
<string name="call_back">Call back</string>
77+
<string name="message">Message</string>
78+
6879
<!-- Speed dial -->
6980
<string name="speed_dial">Speed dial</string>
7081
<string name="manage_speed_dial">Manage speed dial</string>
@@ -84,13 +95,6 @@
8495
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
8596
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
8697

87-
<!-- Notifications -->
88-
<string name="missed_call_channel">Missed Calls</string>
89-
<string name="missed_call">Missed call</string>
90-
<string name="missed_call_from">Missed call from %s</string>
91-
<string name="call_back">Call back</string>
92-
<string name="message">Message</string>
93-
9498
<!--
9599
Haven't found some strings? There's more at
96100
https://github.com/FossifyOrg/Commons/tree/master/commons/src/main/res

0 commit comments

Comments
 (0)