Skip to content

Commit

Permalink
Merge pull request #130 from ConnectyCube/development
Browse files Browse the repository at this point in the history
release 2.6.0
  • Loading branch information
TatankaConCube committed Jan 10, 2024
2 parents 7ee115e + abe617a commit b723f25
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 2.6.0
- Implemented the Notify for Incoming Calls feature (thanks for [tungs0ul](https://github.com/tungs0ul));

## 2.5.0
- (Android) Add API to manage the `Manifest.permission.USE_FULL_SCREEN_INTENT` permission;

Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ Add the listeners during initialization of the plugin:
ConnectycubeFlutterCallKit.instance.init(
onCallAccepted: _onCallAccepted,
onCallRejected: _onCallRejected,
onCallIncoming: _onCallIncoming,
);
Future<void> _onCallAccepted(CallEvent callEvent) async {
Expand All @@ -144,16 +145,21 @@ Future<void> _onCallAccepted(CallEvent callEvent) async {
Future<void> _onCallRejected(CallEvent callEvent) async {
// the call was rejected
}
Future<void> _onCallRejected(CallEvent callEvent) async {
// the Incoming call screen/notification was shown for user
}
```

#### Listen in the background or terminated state (Android only):

```dart
ConnectycubeFlutterCallKit.onCallRejectedWhenTerminated = onCallRejectedWhenTerminated;
ConnectycubeFlutterCallKit.onCallAcceptedWhenTerminated = onCallAcceptedWhenTerminated;
ConnectycubeFlutterCallKit.onCallIncomingWhenTerminated = onCallIncomingWhenTerminated;
```

!> Attention: the functions `onCallRejectedWhenTerminated` and `onCallAcceptedWhenTerminated` must
!> Attention: the functions `onCallRejectedWhenTerminated`, `onCallAcceptedWhenTerminated` and `onCallIncomingWhenTerminated` must
be a top-level functions and cannot be anonymous. Mark these callbacks with the `@pragma('vm:entry-point')`
annotation to allow using them from the native code.

Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group 'com.connectycube.flutter.connectycube_flutter_call_kit'
version '2.5.0'
version '2.6.0'

buildscript {
ext.kotlin_version = '1.9.10'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ class ConnectycubeFCMReceiver : BroadcastReceiver() {
return
}

notifyAboutIncomingCall(
applicationContext,
callId,
callType,
callInitiatorId,
callInitiatorName,
callOpponents,
callPhoto,
userInfo
)

showCallNotification(
applicationContext,
callId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class ConnectycubeFlutterCallKitPlugin : FlutterPlugin, MethodCallHandler,
}

"startBackgroundIsolate" -> {

@Suppress("UNCHECKED_CAST") val arguments: Map<String, Any> =
call.arguments as Map<String, Any>

Expand All @@ -94,7 +95,6 @@ class ConnectycubeFlutterCallKitPlugin : FlutterPlugin, MethodCallHandler,
val userCallbackHandleName: String =
arguments["userCallbackHandleName"]?.toString() ?: ""


val arg1 = arguments["pluginCallbackHandle"] ?: -1L
val arg2 = arguments["userCallbackHandle"] ?: -1L

Expand Down Expand Up @@ -126,6 +126,8 @@ class ConnectycubeFlutterCallKitPlugin : FlutterPlugin, MethodCallHandler,
saveBackgroundRejectHandler(applicationContext, userCallbackHandle)
} else if (ACCEPTED_IN_BACKGROUND == userCallbackHandleName) {
saveBackgroundAcceptHandler(applicationContext, userCallbackHandle)
} else if (INCOMING_IN_BACKGROUND == userCallbackHandleName) {
saveBackgroundIncomingCallHandler(applicationContext, userCallbackHandle)
}

ConnectycubeFlutterBgPerformingService.startBackgroundIsolate(
Expand Down Expand Up @@ -378,6 +380,33 @@ class ConnectycubeFlutterCallKitPlugin : FlutterPlugin, MethodCallHandler,
}
}

fun notifyAboutIncomingCall(
context: Context, callId: String, callType: Int, callInitiatorId: Int,
callInitiatorName: String, callOpponents: ArrayList<Int>, callPhoto: String?, userInfo: String
) {
val intent = Intent(ACTION_CALL_INCOMING)
.putExtra(EXTRA_CALL_ID, callId)
.putExtra(EXTRA_CALL_TYPE, callType)
.putExtra(EXTRA_CALL_INITIATOR_ID, callInitiatorId)
.putExtra(EXTRA_CALL_INITIATOR_NAME, callInitiatorName)
.putExtra(EXTRA_CALL_OPPONENTS, callOpponents)
.putExtra(EXTRA_CALL_PHOTO, callPhoto)
.putExtra(EXTRA_CALL_USER_INFO, userInfo)

if (isApplicationForeground(context)) {
LocalBroadcastManager.getInstance(context)
.sendBroadcast(intent)
} else {
intent.putExtra("userCallbackHandleName", INCOMING_IN_BACKGROUND)
ConnectycubeFlutterBgPerformingService.enqueueMessageProcessing(
context,
intent
)
}

Log.d("ConnectycubeFlutterCallKitPlugin", "[notifyAboutIncomingCall] sendBroadcast ACTION_CALL_INCOMING $callId")
}

fun saveCallState(applicationContext: Context?, callId: String, callState: String) {
if (applicationContext == null) return

Expand Down Expand Up @@ -468,6 +497,22 @@ fun getBackgroundAcceptHandler(applicationContext: Context?): Long {
return getLong(applicationContext, "background_callback_accept")
}

fun saveBackgroundIncomingCallHandler(applicationContext: Context?, callbackId: Long) {
if (applicationContext == null) return

try {
putLong(applicationContext, "background_callback_incoming_call", callbackId)
} catch (e: Exception) {
// ignore
}
}

fun getBackgroundIncomingCallHandler(applicationContext: Context?): Long {
if (applicationContext == null) return -1L

return getLong(applicationContext, "background_callback_incoming_call")
}

fun saveBackgroundRejectHandler(applicationContext: Context?, callbackId: Long) {
if (applicationContext == null) return

Expand Down Expand Up @@ -525,6 +570,7 @@ class CallStreamHandler(private var context: Context) : EventChannel.StreamHandl
val intentFilter = IntentFilter()
intentFilter.addAction(ACTION_CALL_REJECT)
intentFilter.addAction(ACTION_CALL_ACCEPT)
intentFilter.addAction(ACTION_CALL_INCOMING)
localBroadcastManager.registerReceiver(this, intentFilter)
}

Expand All @@ -547,11 +593,12 @@ class CallStreamHandler(private var context: Context) : EventChannel.StreamHandl

events?.success(parameters)
return
} else if (ACTION_CALL_REJECT != action && ACTION_CALL_ACCEPT != action) {
} else if (ACTION_CALL_REJECT != action && ACTION_CALL_ACCEPT != action && ACTION_CALL_INCOMING != action) {
return
}

val callIdToProcess: String? = intent.getStringExtra(EXTRA_CALL_ID)

if (TextUtils.isEmpty(callIdToProcess)) return

val callEventMap = HashMap<String, Any?>()
Expand Down Expand Up @@ -589,6 +636,11 @@ class CallStreamHandler(private var context: Context) : EventChannel.StreamHandl
launchIntent?.action = ACTION_CALL_ACCEPT
context.startActivity(launchIntent)
}

ACTION_CALL_INCOMING -> {
callbackData["event"] = "incomingCall"
events?.success(callbackData)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ const val EXTRA_CALL_PHOTO = "photo_url"

const val ACTION_CALL_ACCEPT = "action_call_accept"
const val ACTION_CALL_REJECT = "action_call_reject"
const val ACTION_CALL_INCOMING = "action_call_incoming"
const val ACTION_CALL_NOTIFICATION_CANCELED = "action_call_notification_canceled"
const val ACTION_CALL_ENDED = "action_call_ended"
const val ACTION_TOKEN_REFRESHED = "action_token_refreshed"

const val REJECTED_IN_BACKGROUND = "rejected_in_background"
const val ACCEPTED_IN_BACKGROUND = "accepted_in_background"
const val INCOMING_IN_BACKGROUND = "incoming_in_background"

const val CALL_TYPE_PLACEHOLDER = "Incoming %s call"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import com.connectycube.flutter.connectycube_flutter_call_kit.utils.isApplicatio

class EventReceiver : BroadcastReceiver() {
private val TAG = "EventReceiver"

override fun onReceive(context: Context, intent: Intent?) {

if (intent == null || TextUtils.isEmpty(intent.action)) return

Log.d(TAG, "NotificationReceiver onReceive action: ${intent.action}")

when (intent.action) {
ACTION_CALL_REJECT -> {
val extras = intent.extras
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,14 @@ class FlutterConnectycubeBackgroundExecutor : MethodCallHandler {
userCallbackHandle = getBackgroundRejectHandler(ContextHolder.applicationContext)
} else if (ACCEPTED_IN_BACKGROUND == callEventName) {
userCallbackHandle = getBackgroundAcceptHandler(ContextHolder.applicationContext)
} else if (INCOMING_IN_BACKGROUND == callEventName) {
userCallbackHandle = getBackgroundIncomingCallHandler(ContextHolder.applicationContext)
}

if (userCallbackHandle == -1L) {
Log.e(
"FlutterConnectycubeBackgroundExecutor",
"No one background handler has been registered."
"${intent.action} background handler has not been registered."
)
return
}
Expand Down
3 changes: 3 additions & 0 deletions ios/Classes/CallKitController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import AVFoundation
import CallKit

enum CallEvent : String {
case incomingCall = "incomingCall"
case answerCall = "answerCall"
case endCall = "endCall"
case setHeld = "setHeld"
Expand Down Expand Up @@ -125,6 +126,8 @@ class CallKitController : NSObject {

self.callStates[uuid] = .pending
self.callsData[uuid] = self.currentCallData

self.actionListener?(.incomingCall, UUID(uuidString: uuid)!, self.currentCallData)
}
}
} else if (self.currentCallData["session_id"] as! String == uuid) {
Expand Down
2 changes: 1 addition & 1 deletion ios/connectycube_flutter_call_kit.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
Pod::Spec.new do |s|
s.name = 'connectycube_flutter_call_kit'
s.version = '2.5.0'
s.version = '2.6.0'
s.summary = 'Connectycube Call Kit plugin for flutter.'
s.description = <<-DESC
Connectycube Call Kit plugin for flutter.
Expand Down
25 changes: 25 additions & 0 deletions lib/src/connectycube_flutter_call_kit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,29 @@ class ConnectycubeFlutterCallKit {
static CallEventHandler? _onCallRejectedWhenTerminated;
static CallEventHandler? _onCallAcceptedWhenTerminated;
static CallEventHandler? _onCallIncomingWhenTerminated;

static CallEventHandler? _onCallAccepted;
static CallEventHandler? _onCallRejected;

static CallEventHandler? _onCallIncoming;

/// Initialize the plugin and provided user callbacks.
///
/// - This function should only be called once at the beginning of
/// your application.
void init(
{CallEventHandler? onCallAccepted,
CallEventHandler? onCallRejected,
CallEventHandler? onCallIncoming,
String? ringtone,
String? icon,
@Deprecated('Use `AndroidManifest.xml` meta-data instead')
String? notificationIcon,
String? color}) {
_onCallAccepted = onCallAccepted;
_onCallRejected = onCallRejected;
_onCallIncoming = onCallIncoming;

updateConfig(
ringtone: ringtone,
Expand Down Expand Up @@ -103,6 +108,20 @@ class ConnectycubeFlutterCallKit {
}
}

/// Set an incoming call handler function which is called when the app is in the
/// background or terminated.
///
/// This provided handler must be a top-level function and cannot be
/// anonymous otherwise an [ArgumentError] will be thrown.
static set onCallIncomingWhenTerminated(CallEventHandler? handler) {
_onCallIncomingWhenTerminated = handler;

if (handler != null) {
instance._registerBackgroundCallEventHandler(
handler, BackgroundCallbackName.INCOMING_IN_BACKGROUND);
}
}

Future<void> _registerBackgroundCallEventHandler(
CallEventHandler handler, String callbackName) async {
if (!Platform.isAndroid) {
Expand Down Expand Up @@ -335,6 +354,11 @@ class ConnectycubeFlutterCallKit {
onCallMuted?.call(false, arguments["session_id"]);
break;

case 'incomingCall':
var callEvent = CallEvent.fromMap(arguments);
_onCallIncoming?.call(callEvent);
break;

case '':
break;

Expand Down Expand Up @@ -399,4 +423,5 @@ class CallState {
class BackgroundCallbackName {
static const String REJECTED_IN_BACKGROUND = "rejected_in_background";
static const String ACCEPTED_IN_BACKGROUND = "accepted_in_background";
static const String INCOMING_IN_BACKGROUND = "incoming_in_background";
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: connectycube_flutter_call_kit
description: A Flutter plugin for displaying call screen when app in background or terminated.
version: 2.5.0
version: 2.6.0
homepage: https://connectycube.com/
issue_tracker: https://github.com/ConnectyCube/connectycube-flutter-call-kit/issues
documentation: https://github.com/ConnectyCube/connectycube-flutter-call-kit/blob/master/README.md
Expand Down

0 comments on commit b723f25

Please sign in to comment.