zastro_android_call_notifications 0.0.13
zastro_android_call_notifications: ^0.0.13 copied to clipboard
A Flutter plugin to trigger call and microphone notifications.
0.0.1 #
0.0.2 - 2025-05-12 #
- Min Flutter SDK updated to 3.0.2
0.0.3 - 2025-05-12 #
- Compatible with AGP 8.1.0 and compileSdk 34
0.0.4 - 2025-05-12 #
- Solving unknown caller issue
0.0.5 - 2025-05-12 #
- Solving unknown caller issue, 0.0.4 version was a failed attempt.
0.0.6 - 2025-05-12 #
- Solving unknown caller issue, 0.0.5 version had a return error.
0.0.7 - 2025-05-12 #
- Solved unknown caller issue and Notification not cancelling issue. Please don`t use 0.0.4 - 0.0.6 versions .
0.0.8 - 2025-05-23 #
- Solved Ghost ring issue.
0.0.9 - 2025-07-03 #
- Fixed crash causing code.
0.0.10 #
- Fixed notification field: replaced
contentTitlewithcontentTextto correctly detect notification types (chat, video call, audio call).
0.0.11 #
- Added a WhatsApp-style full screen incoming call screen (
IncomingCallActivity). The full screen intent on the call notification was previously built from an emptyIntent(), so it resolved to nothing and never opened any UI — the call only ever appeared as a heads-up / lock screen notification. It now shows a real call screen while the app is in the background, terminated, or the device is locked or asleep. - Accept / Decline on the new screen fire the exact same
PendingIntents the notification's own buttons carry, so existing host app call handling keeps working unchanged — no migration needed. - Added
ChatNotificationPlugin.canUseFullScreenIntent()andChatNotificationPlugin.openFullScreenIntentSettings(). Android 14 (API 34) madeUSE_FULL_SCREEN_INTENTa user-revocable special access; when it is revoked Android silently downgrades the call to a heads-up notification, so host apps need to be able to detect and repair that. - The call screen shows the host app's icon and name, the caller's photo with the app icon badged on it, the call type, and the time the call started ringing.
- Caller photo loading rewritten (
CallerPhotoLoader). The old inline loader calledBitmapFactory.decodeStream()straight on a socket, which returns null for slow or chunked responses, and did not follow redirects — the two usual reasons a caller photo silently never appeared. It now buffers the body, follows redirects, downsamples large images, and is shared between the notification and the call screen so the photo is fetched once. - Cleartext
http://photo urls are retried overhttps://. Android blocks cleartext by default from targetSdk 28, so anhttp://url in a push payload always failed natively even though the same url loads fine in Flutter. - Added
InitialsAvatar: when no photo is available the caller's initials are drawn in a colour derived from their name, in both the notification and the call screen. - Custom ringtone support. A ringtone can be supplied per call via
showCallNotification({'ringtone': ...}), per call from the server via aringtonefield in the FCM payload, or app-wide viaChatNotificationPlugin.setDefaultRingtone(...). Accepts a Flutter asset path, anres/rawname, acontent:///file:///http(s)://uri, or an absolute path. Anything unresolvable falls back to the system ringtone, so a bad value can never leave a call silent. - Incoming calls now use their own silent notification channel,
zastro_incoming_call. Previously the call posted to the host app's channel, whose sound and vibration are fixed at creation and could not be overridden — so the channel rang the system ringtone while the service rang its own. Two ringtones and two vibrations, masked only because both sounds used to be the same system ringtone. The ringtone and vibration belong to the service, which is what makes a custom ringtone possible. - The ringtone now starts immediately instead of at the end of the caller-photo download, which had left the phone silent until the picture was fetched — up to the full network timeout on a cold start, i.e. exactly the terminated-app case. A refused audio-focus request no longer silently suppresses the ring either; it is logged and playback proceeds.
- Added
ChatNotificationPlugin.setCallNotificationAppearance(...)for the notification's small icon and accent colour. The small icon now defaults to the host app's ownic_notificationwhere one exists. - The notification's timestamp is the moment the call started ringing rather than being restamped whenever the notification is rebuilt, and the call type and start time are written into the body text.
- Answer and decline now reliably bring the app to the foreground.
FLAG_ACTIVITY_NEW_TASKwas being wiped from the launch intent by an assignment toflags, so an activity started from those pending intents had no task to land in whenever the app was not already foregrounded. The call screen also no longer routes actions throughTransparentActivity(they share an emptytaskAffinity, so finishing the call screen tore down the freshly launched activity with it) and closes withfinish()rather thanfinishAndRemoveTask(), which was navigating to the home screen. - Implemented
clearNotificationData, which host apps were already calling and which previously always threwMissingPluginException. It clears both the cached data and the activity's intent extras.
0.0.12 #
- Fixed: with no custom ringtone configured, an incoming call could ring with no
sound at all. Only
RingtoneManager.getDefaultUri(TYPE_RINGTONE)was tried, which resolves to whatever tone the user picked — and when that pick lives in external media, reading it needsREAD_MEDIA_AUDIOon Android 13+, a permission a calling app has no reason to hold.setDataSourcethrewSecurityException, and because 0.0.11 made the call notification channel silent by design there was nothing else left to make a sound. The system ringtone now falls through several sources — the user's tone, the default alias, then the built-in ringtone and notification tones, which never need a permission — and logs which one it ended up using.
0.0.13 - 2026-09-16 #
- Fixed the ghost ring: a call could keep ringing after it was already over.
Cancels were sent as a fresh
IntentthroughstartService/stopService, which either started a second service or arrived after Android had already respawned theSTART_STICKYservice with a null intent — so the ringtone survived its own cancel. Cancelling is now an in-process call (CallNotificationService.cancelIncoming) matched on the call'suniqueId, so it always reaches the instance that is actually ringing. The service also returnsSTART_NOT_STICKYand ignores null intents, so a finished call is never resurrected when the system reclaims memory. - Added a session watchdog. While a call rings the plugin watches the session in
Firebase Realtime Database —
CALLS/<uniqueId>and the legacyCHAT/<customer>-<astrologerOwnerUniId>[-Call|-Video]node — and tears down the notification, ringtone, vibration and full screen call screen as soon as the session is marked ended. The ring now stops when the caller hangs up or the call is answered on another device, even if no cancel push ever arrives. - Added a hard ring expiry: a call stops ringing at
invitationExpiresAtMsfrom the payload, capped at three minutes, so nothing can ring forever. - Starting a new call now cancels a previous one that is still ringing, and the background caller photo refresh is dropped if its call has already ended — a slow photo could previously redraw a notification for a dead call.
ChatNotificationPlugin.cancelCallNotification()takes an optionaluniqueId. Notification ids are reused between calls, so passing the session id is what makes a cancel target the right call. Omitting it keeps the old id-only behaviour.- Requires Firebase Realtime Database. The plugin now depends on
com.google.firebase:firebase-database(viafirebase-bom:34.4.0), so the host app needs Firebase configured —google-services.jsonand thecom.google.gms.google-servicesplugin. Apps already using FCM for these calls have this. If the database is unreachable the watchdog is skipped and the ring expiry still applies.