diff --git a/.idea/misc.xml b/.idea/misc.xml index f1fbd79c..964bcb8e 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/CHANGELOG.md b/CHANGELOG.md index dac34cc9..dad9abfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.0.1+2 +* Add Action for onDecline +* Add Action for onEnd +* add android props `isShowCallID` + ## 2.0.1+1 * Add Callback AVAudioSession for WebRTC setup * Fix issue no audio for using WebRTC diff --git a/README.md b/README.md index 65572e21..0c1b4ead 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,8 @@ Our top sponsors are shown below! actionColor: '#4CAF50', textColor: '#ffffff', incomingCallNotificationChannelName: "Incoming Call", - missedCallNotificationChannelName: "Missed Call" + missedCallNotificationChannelName: "Missed Call", + isShowCallID: false ), ios: IOSParams( iconName: 'CallKitLogo', @@ -127,7 +128,7 @@ Our top sponsors are shown below! https://github.com/firebase/flutterfire/blob/master/docs/cloud-messaging/receive.md#apple-platforms-and-android * request permission for post Notification Android 13+ - For Android 13 and above, please `requestNotificationPermission` before `showCallkitIncoming` + For Android 13+, please `requestNotificationPermission` or requestPermission of firebase_messaging before `showCallkitIncoming` ```dart await FlutterCallkitIncoming.requestNotificationPermission({ "rationaleMessagePermission": "Notification permission is required, to show notification.", @@ -369,7 +370,7 @@ Our top sponsors are shown below! case .success(let data): print("Received data: \(data)") //Make sure call action.fulfill() when you are done(connected WebRTC - Start counting seconds) - //action.fulfill() + action.fulfill() case .failure(let error): print("Error: \(error.localizedDescription)") @@ -378,13 +379,15 @@ Our top sponsors are shown below! } // Func Call API for Decline - func onDecline(_ call: Call) { + func onDecline(_ call: Call, _ action: CXEndCallAction) { let json = ["action": "DECLINE", "data": call.data.toJSON()] as [String: Any] print("LOG: onDecline") self.performRequest(parameters: json) { result in switch result { case .success(let data): print("Received data: \(data)") + //Make sure call action.fulfill() when you are done + action.fulfill() case .failure(let error): print("Error: \(error.localizedDescription)") @@ -392,13 +395,16 @@ Our top sponsors are shown below! } } - func onEnd(_ call: Call) { + // Func Call API for End + func onEnd(_ call: Call, _ action: CXEndCallAction) { let json = ["action": "END", "data": call.data.toJSON()] as [String: Any] print("LOG: onEnd") self.performRequest(parameters: json) { result in switch result { case .success(let data): print("Received data: \(data)") + //Make sure call action.fulfill() when you are done + action.fulfill() case .failure(let error): print("Error: \(error.localizedDescription)") @@ -467,18 +473,19 @@ Our top sponsors are shown below! | **`isShowCallback`** | Show callback action from miss call notification. | `true` | * Android - | Prop | Description | Default | - | --------------------------- | ----------------------------------------------------------------------- | ---------------- | - | **`isCustomNotification`** | Using custom notifications. | `false` | - | **`isCustomSmallExNotification`** | Using custom notification small on some devices clipped out in android. | `false` | - | **`isShowLogo`** | Show logo app inside full screen. `/android/src/main/res/drawable-xxxhdpi/ic_logo.png` | `false` | - | **`ringtonePath`** | File name ringtone. put file into `/android/app/src/main/res/raw/ringtone_default.pm3` |`system_ringtone_default`
using ringtone default of the phone| - | **`backgroundColor`** | Incoming call screen background color. | `#0955fa` | - | **`backgroundUrl`** | Using image background for Incoming call screen. example: http://... https://... or "assets/abc.png" | _None_ | - | **`actionColor`** | Color used in button/text on notification. | `#4CAF50` | - | **`textColor`** | Color used for the text in full screen notification. | `#ffffff` | - | **`incomingCallNotificationChannelName`** | Notification channel name of incoming call. | `Incoming call` | - | **`missedCallNotificationChannelName`** | Notification channel name of missed call. | `Missed call` | + | Prop | Description | Default | + | --------------------------- |------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------| + | **`isCustomNotification`** | Using custom notifications. | `false` | + | **`isCustomSmallExNotification`** | Using custom notification small on some devices clipped out in android. | `false` | + | **`isShowLogo`** | Show logo app inside full screen. `/android/src/main/res/drawable-xxxhdpi/ic_logo.png` | `false` | + | **`ringtonePath`** | File name ringtone. put file into `/android/app/src/main/res/raw/ringtone_default.pm3` | `system_ringtone_default`
using ringtone default of the phone | + | **`backgroundColor`** | Incoming call screen background color. | `#0955fa` | + | **`backgroundUrl`** | Using image background for Incoming call screen. example: http://... https://... or "assets/abc.png" | _None_ | + | **`actionColor`** | Color used in button/text on notification. | `#4CAF50` | + | **`textColor`** | Color used for the text in full screen notification. | `#ffffff` | + | **`incomingCallNotificationChannelName`** | Notification channel name of incoming call. | `Incoming call` | + | **`missedCallNotificationChannelName`** | Notification channel name of missed call. | `Missed call` | + | **`isShowCallID`** | Show call id app inside full screen/notification. | false |
diff --git a/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/Call.kt b/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/Call.kt index ce217788..c9c6530e 100644 --- a/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/Call.kt +++ b/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/Call.kt @@ -44,6 +44,8 @@ data class Data(val args: Map) { var isCustomSmallExNotification: Boolean = false @JsonProperty("isShowLogo") var isShowLogo: Boolean = false + @JsonProperty("isShowCallID") + var isShowCallID: Boolean = false @JsonProperty("ringtonePath") var ringtonePath: String @JsonProperty("backgroundColor") @@ -86,6 +88,7 @@ data class Data(val args: Map) { isCustomNotification = android["isCustomNotification"] as? Boolean ?: false isCustomSmallExNotification = android["isCustomSmallExNotification"] as? Boolean ?: false isShowLogo = android["isShowLogo"] as? Boolean ?: false + isShowCallID = android["isShowCallID"] as? Boolean ?: false ringtonePath = android["ringtonePath"] as? String ?: "" backgroundColor = android["backgroundColor"] as? String ?: "#0955fa" backgroundUrl = android["backgroundUrl"] as? String ?: "" @@ -179,6 +182,10 @@ data class Data(val args: Map) { CallkitConstants.EXTRA_CALLKIT_IS_SHOW_LOGO, isShowLogo ) + bundle.putBoolean( + CallkitConstants.EXTRA_CALLKIT_IS_SHOW_CALL_ID, + isShowCallID + ) bundle.putString(CallkitConstants.EXTRA_CALLKIT_RINGTONE_PATH, ringtonePath) bundle.putString( CallkitConstants.EXTRA_CALLKIT_BACKGROUND_COLOR, @@ -253,6 +260,10 @@ data class Data(val args: Map) { CallkitConstants.EXTRA_CALLKIT_IS_SHOW_LOGO, false ) + data.isShowCallID = bundle.getBoolean( + CallkitConstants.EXTRA_CALLKIT_IS_SHOW_CALL_ID, + false + ) data.ringtonePath = bundle.getString( CallkitConstants.EXTRA_CALLKIT_RINGTONE_PATH, "" diff --git a/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitConstants.kt b/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitConstants.kt index 9f50545d..4b75137b 100644 --- a/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitConstants.kt +++ b/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitConstants.kt @@ -51,6 +51,7 @@ object CallkitConstants { const val EXTRA_CALLKIT_IS_CUSTOM_SMALL_EX_NOTIFICATION = "EXTRA_CALLKIT_IS_CUSTOM_SMALL_EX_NOTIFICATION" const val EXTRA_CALLKIT_IS_SHOW_LOGO = "EXTRA_CALLKIT_IS_SHOW_LOGO" + const val EXTRA_CALLKIT_IS_SHOW_CALL_ID = "EXTRA_CALLKIT_IS_SHOW_CALL_ID" const val EXTRA_CALLKIT_RINGTONE_PATH = "EXTRA_CALLKIT_RINGTONE_PATH" const val EXTRA_CALLKIT_BACKGROUND_COLOR = "EXTRA_CALLKIT_BACKGROUND_COLOR" const val EXTRA_CALLKIT_BACKGROUND_URL = "EXTRA_CALLKIT_BACKGROUND_URL" diff --git a/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitIncomingActivity.kt b/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitIncomingActivity.kt index d21e949f..e0a2fd06 100644 --- a/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitIncomingActivity.kt +++ b/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitIncomingActivity.kt @@ -167,8 +167,10 @@ class CallkitIncomingActivity : Activity() { if (data == null) finish() val textColor = data?.getString(CallkitConstants.EXTRA_CALLKIT_TEXT_COLOR, "#ffffff") + val isShowCallID = data?.getBoolean(CallkitConstants.EXTRA_CALLKIT_IS_SHOW_CALL_ID, false) tvNameCaller.text = data?.getString(CallkitConstants.EXTRA_CALLKIT_NAME_CALLER, "") tvNumber.text = data?.getString(CallkitConstants.EXTRA_CALLKIT_HANDLE, "") + tvNumber.visibility = if (isShowCallID == true) View.VISIBLE else View.INVISIBLE try { tvNameCaller.setTextColor(Color.parseColor(textColor)) diff --git a/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitNotificationManager.kt b/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitNotificationManager.kt index faebc84b..e7bf8547 100644 --- a/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitNotificationManager.kt +++ b/android/src/main/kotlin/com/hiennv/flutter_callkit_incoming/CallkitNotificationManager.kt @@ -199,10 +199,13 @@ class CallkitNotificationManager(private val context: Context) { R.id.tvNameCaller, data.getString(CallkitConstants.EXTRA_CALLKIT_NAME_CALLER, "") ) - remoteViews.setTextViewText( + val isShowCallID = data?.getBoolean(CallkitConstants.EXTRA_CALLKIT_IS_SHOW_CALL_ID, false) + if (isShowCallID == true) { + remoteViews.setTextViewText( R.id.tvNumber, data.getString(CallkitConstants.EXTRA_CALLKIT_HANDLE, "") - ) + ) + } remoteViews.setOnClickPendingIntent( R.id.llDecline, getDeclinePendingIntent(notificationId, data) @@ -279,10 +282,13 @@ class CallkitNotificationManager(private val context: Context) { R.id.tvNameCaller, data.getString(CallkitConstants.EXTRA_CALLKIT_NAME_CALLER, "") ) - notificationViews?.setTextViewText( + val isShowCallID = data?.getBoolean(CallkitConstants.EXTRA_CALLKIT_IS_SHOW_CALL_ID, false) + if (isShowCallID == true) { + notificationViews?.setTextViewText( R.id.tvNumber, data.getString(CallkitConstants.EXTRA_CALLKIT_HANDLE, "") - ) + ) + } notificationViews?.setOnClickPendingIntent( R.id.llCallback, getCallbackPendingIntent(notificationId, data) diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 5b1f6ab0..16c64519 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -98,7 +98,7 @@ import flutter_callkit_incoming case .success(let data): print("Received data: \(data)") //Make sure call action.fulfill() when you are done(connected WebRTC - Start counting seconds) - //action.fulfill() + action.fulfill() case .failure(let error): print("Error: \(error.localizedDescription)") @@ -107,13 +107,15 @@ import flutter_callkit_incoming } // Func Call API for Decline - func onDecline(_ call: Call) { + func onDecline(_ call: Call, _ action: CXEndCallAction) { let json = ["action": "DECLINE", "data": call.data.toJSON()] as [String: Any] print("LOG: onDecline") self.performRequest(parameters: json) { result in switch result { case .success(let data): print("Received data: \(data)") + //Make sure call action.fulfill() when you are done + action.fulfill() case .failure(let error): print("Error: \(error.localizedDescription)") @@ -122,13 +124,15 @@ import flutter_callkit_incoming } // Func Call API for End - func onEnd(_ call: Call) { + func onEnd(_ call: Call, _ action: CXEndCallAction) { let json = ["action": "END", "data": call.data.toJSON()] as [String: Any] print("LOG: onEnd") self.performRequest(parameters: json) { result in switch result { case .success(let data): print("Received data: \(data)") + //Make sure call action.fulfill() when you are done + action.fulfill() case .failure(let error): print("Error: \(error.localizedDescription)") diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 8434412a..84d8508a 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -134,7 +134,7 @@ class HomePageState extends State { avatar: 'https://i.pravatar.cc/100', handle: '0123456789', type: 1, - duration: 30000, + duration: 10000, textAccept: 'Accept', textDecline: 'Decline', missedCallNotification: const NotificationParams( diff --git a/example/lib/main.dart b/example/lib/main.dart index 201d3be7..5c49b13a 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -11,6 +11,7 @@ import 'package:uuid/uuid.dart'; Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { print("Handling a background message: ${message.messageId}"); + await Firebase.initializeApp(); //make sure firebase is initialized before using it (showCallkitIncoming) showCallkitIncoming(const Uuid().v4()); } diff --git a/ios/Classes/CallkitIncomingAppDelegate.swift b/ios/Classes/CallkitIncomingAppDelegate.swift index 0d0f3cd2..e1978172 100644 --- a/ios/Classes/CallkitIncomingAppDelegate.swift +++ b/ios/Classes/CallkitIncomingAppDelegate.swift @@ -14,9 +14,9 @@ public protocol CallkitIncomingAppDelegate : NSObjectProtocol { func onAccept(_ call: Call, _ action: CXAnswerCallAction); - func onDecline(_ call: Call); + func onDecline(_ call: Call, _ action: CXEndCallAction); - func onEnd(_ call: Call); + func onEnd(_ call: Call, _ action: CXEndCallAction); func onTimeOut(_ call: Call); diff --git a/ios/Classes/SwiftFlutterCallkitIncomingPlugin.swift b/ios/Classes/SwiftFlutterCallkitIncomingPlugin.swift index b3453afa..a487d91d 100644 --- a/ios/Classes/SwiftFlutterCallkitIncomingPlugin.swift +++ b/ios/Classes/SwiftFlutterCallkitIncomingPlugin.swift @@ -530,9 +530,7 @@ public class SwiftFlutterCallkitIncomingPlugin: NSObject, FlutterPlugin, CXProvi if let appDelegate = UIApplication.shared.delegate as? CallkitIncomingAppDelegate { appDelegate.onAccept(call, action) }else { - DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(2000)) { - action.fulfill() - } + action.fulfill() } } @@ -552,15 +550,17 @@ public class SwiftFlutterCallkitIncomingPlugin: NSObject, FlutterPlugin, CXProvi if (self.answerCall == nil && self.outgoingCall == nil) { sendEvent(SwiftFlutterCallkitIncomingPlugin.ACTION_CALL_DECLINE, self.data?.toJSON()) if let appDelegate = UIApplication.shared.delegate as? CallkitIncomingAppDelegate { - appDelegate.onDecline(call) + appDelegate.onDecline(call, action) + } else { + action.fulfill() } - action.fulfill() }else { sendEvent(SwiftFlutterCallkitIncomingPlugin.ACTION_CALL_ENDED, call.data.toJSON()) if let appDelegate = UIApplication.shared.delegate as? CallkitIncomingAppDelegate { - appDelegate.onEnd(call) + appDelegate.onEnd(call, action) + } else { + action.fulfill() } - action.fulfill() } } diff --git a/lib/entities/android_params.dart b/lib/entities/android_params.dart index 9524e113..93191abc 100644 --- a/lib/entities/android_params.dart +++ b/lib/entities/android_params.dart @@ -9,6 +9,7 @@ class AndroidParams { this.isCustomNotification, this.isCustomSmallExNotification, this.isShowLogo, + this.isShowCallID, this.ringtonePath, this.backgroundColor, this.backgroundUrl, @@ -27,6 +28,9 @@ class AndroidParams { /// Show logo app inside full screen. final bool? isShowLogo; + /// Show call id app inside full screen. + final bool? isShowCallID; + /// File name ringtone, put file into /android/app/src/main/res/raw/ringtone_default.pm3 -> value: `ringtone_default.pm3` final String? ringtonePath; @@ -48,7 +52,8 @@ class AndroidParams { /// Notification channel name of missed call. final String? missedCallNotificationChannelName; - factory AndroidParams.fromJson(Map json) => _$AndroidParamsFromJson(json); + factory AndroidParams.fromJson(Map json) => + _$AndroidParamsFromJson(json); Map toJson() => _$AndroidParamsToJson(this); } diff --git a/lib/entities/android_params.g.dart b/lib/entities/android_params.g.dart index bc3b7bda..66b931af 100644 --- a/lib/entities/android_params.g.dart +++ b/lib/entities/android_params.g.dart @@ -11,6 +11,7 @@ AndroidParams _$AndroidParamsFromJson(Map json) => isCustomNotification: json['isCustomNotification'] as bool?, isCustomSmallExNotification: json['isCustomSmallExNotification'] as bool?, isShowLogo: json['isShowLogo'] as bool?, + isShowCallID: json['isShowCallID'] as bool?, ringtonePath: json['ringtonePath'] as String?, backgroundColor: json['backgroundColor'] as String?, backgroundUrl: json['backgroundUrl'] as String?, @@ -27,6 +28,7 @@ Map _$AndroidParamsToJson(AndroidParams instance) => 'isCustomNotification': instance.isCustomNotification, 'isCustomSmallExNotification': instance.isCustomSmallExNotification, 'isShowLogo': instance.isShowLogo, + 'isShowCallID': instance.isShowCallID, 'ringtonePath': instance.ringtonePath, 'backgroundColor': instance.backgroundColor, 'backgroundUrl': instance.backgroundUrl, diff --git a/lib/entities/notification_params.dart b/lib/entities/notification_params.dart index 42aa5feb..0cc31e18 100644 --- a/lib/entities/notification_params.dart +++ b/lib/entities/notification_params.dart @@ -2,7 +2,7 @@ import 'package:json_annotation/json_annotation.dart'; part 'notification_params.g.dart'; -/// Object config for Android. +/// Object config for Notification Android. @JsonSerializable(explicitToJson: true) class NotificationParams { const NotificationParams({ diff --git a/pubspec.yaml b/pubspec.yaml index 61ecfb70..df7577ee 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_callkit_incoming description: Flutter Callkit Incoming to show callkit screen in your Flutter app. -version: 2.0.1+1 +version: 2.0.1+2 homepage: https://github.com/hiennguyen92/flutter_callkit_incoming repository: https://github.com/hiennguyen92/flutter_callkit_incoming issue_tracker: https://github.com/hiennguyen92/flutter_callkit_incoming/issues