Skip to content

Commit

Permalink
Merge pull request #121 from ConnectyCube/development
Browse files Browse the repository at this point in the history
release 2.5.0
  • Loading branch information
TatankaConCube committed Nov 21, 2023
2 parents 5d48e68 + c005863 commit c43f033
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 10 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 2.5.0
- (Android) Add API to manage the `Manifest.permission.USE_FULL_SCREEN_INTENT` permission;

## 2.4.0
- (Android) Add the Call photo to the Call notification and the Incoming call screen;
- (Android) Add different icons to the Accept buttons depending on the call type;
Expand Down
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ getting token and displaying the Incoming call screen.
- notifying the app about user action performed on the Incoming call screen (accept, reject, mute (for iOS))
- providing the methods for manual managing of the Incoming screen including the manual showing the Incoming call screen
- getting the data about the current call during the call session
- some customizations according to your app needs (ringtone, icon, accent color(for Android))
- some customizations according to your app needs (ringtone, app icon, accent color(for Android))
- checking and changing the access to the `Manifest.permission.USE_FULL_SCREEN_INTENT` permission (for Android 14 and above)


<kbd><img alt="Flutter P2P Calls code sample, incoming call in background Android" src="https://developers.connectycube.com/docs/_images/code_samples/flutter/background_call_android.png" height="440" /></kbd>
Expand Down Expand Up @@ -230,6 +231,20 @@ After finishing that call you should hide your app under the lock screen, do it
ConnectycubeFlutterCallKit.setOnLockScreenVisibility(isVisible: false);
```

### Check the permission `Manifest.permission.USE_FULL_SCREEN_INTENT` state (Android 14 and above)

```dart
var canUseFullScreenIntent = await ConnectycubeFlutterCallKit.canUseFullScreenIntent();
```

### Request the access to the `Manifest.permission.USE_FULL_SCREEN_INTENT` permission (Android 14 and above)

```dart
ConnectycubeFlutterCallKit.provideFullScreenIntentAccess();
```
The function moves the user to the specific setting for your app where you can grant or deny this
permission for your app.

## Show Incoming call screen by push notification
In case you want to display the Incoming call screen automatically by push notification you can do
it easily. For it, the caller should send the push notification to all call members. This push notification should contain some required parameters. If you use the [Connectycube Flutter SDK](https://pub.dev/packages/connectycube_sdk), you can do it using the next code:
Expand Down Expand Up @@ -262,4 +277,18 @@ createEvent(params.getEventForRequest()).then((cubeEvent) {
For hiding the Incoming call screen via push notification use a similar request but with a
different `signal_type`, it can be `'endCall'` or `'rejectCall'`.

## Android 14 features
Starting from Android `Build.VERSION_CODES.UPSIDE_DOWN_CAKE`, apps may not have permission to use
`Manifest.permission.USE_FULL_SCREEN_INTENT`. If permission is denied, the call notification will
show up as an expanded heads up notification on lockscreen. The plugin provides the API for checking
the access state and moves to the System setting for enabling it. Please follow the next code
snippet to manage it:
```dart
var canUseFullScreenIntent = await ConnectycubeFlutterCallKit.canUseFullScreenIntent();
if (!canUseFullScreenIntent){
ConnectycubeFlutterCallKit.provideFullScreenIntentAccess();
}
```

You can check how this plugin works in our [P2P Calls code sample](https://github.com/ConnectyCube/connectycube-flutter-samples/tree/master/p2p_call_sample).
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.3.0'
version '2.5.0'

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

private fun processEndCallEvent(applicationContext: Context, data: Map<String, String>) {
Log.d(TAG, "[processEndCallEvent]")

val callId = data["session_id"] ?: return


processCallEnded(applicationContext, callId)
}

private fun processInviteCallEvent(applicationContext: Context, data: Map<String, String>) {
Log.d(TAG, "[processInviteCallEvent]")
val callId = data["session_id"]

if (callId == null || CALL_STATE_UNKNOWN != getCallState(
applicationContext,
callId
)
) {
Log.d(TAG, "[processInviteCallEvent] callId == null || CALL_STATE_UNKNOWN != getCallState(applicationContext, callId)")
return
}

Expand All @@ -76,6 +80,7 @@ class ConnectycubeFCMReceiver : BroadcastReceiver() {
val userInfo = data["user_info"] ?: JSONObject(emptyMap<String, String>()).toString()

if (callType == null || callInitiatorId == null || callInitiatorName == null || callOpponents.isEmpty()) {
Log.d(TAG, "[processInviteCallEvent] callType == null || callInitiatorId == null || callInitiatorName == null || callOpponents.isEmpty()")
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ class ConnectycubeFCMService : FirebaseMessagingService() {

override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
Log.d(TAG, "[onMessageReceived]")
// Added for commenting purposes;
// We don't handle the message here as we already handle it in the receiver and don't want to duplicate.
}

override fun onNewToken(token: String) {
super.onNewToken(token)
Log.d(TAG, "onNewToken")
Log.d(TAG, "[onNewToken]")

LocalBroadcastManager.getInstance(applicationContext)
.sendBroadcast(Intent(ACTION_TOKEN_REFRESHED).putExtra(EXTRA_PUSH_TOKEN, token))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package com.connectycube.flutter.connectycube_flutter_call_kit

import android.annotation.SuppressLint
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.text.TextUtils
import android.util.Log
import android.view.WindowManager
Expand Down Expand Up @@ -298,6 +301,30 @@ class ConnectycubeFlutterCallKitPlugin : FlutterPlugin, MethodCallHandler,
result.success(null)
}

"canUseFullScreenIntent" -> {
result.success(canUseFullScreenIntent(applicationContext!!))
}

"provideFullScreenIntentAccess" -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
try {
val intent = Intent(
Settings.ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT,
Uri.parse("package:${applicationContext?.packageName}")
)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_HISTORY)
applicationContext?.startActivity(intent)
} catch (e: ActivityNotFoundException) {
applicationContext?.startActivity(Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, applicationContext?.packageName)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
}
} else {
Log.d("ConnectycubeFlutterCallKitPlugin", "Permission request is available from API version 34 (UPSIDE_DOWN_CAKE) and above")
}
result.success(null)
}

else ->
result.notImplemented()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.connectycube.flutter.connectycube_flutter_call_kit

import android.app.Activity
import android.app.KeyguardManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.widget.ImageView
Expand Down Expand Up @@ -55,7 +58,7 @@ class IncomingCallActivity : Activity() {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
setContentView(resources.getIdentifier("activity_incoming_call", "layout", packageName))

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O_MR1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true)
setTurnScreenOn(true)
} else {
Expand All @@ -65,10 +68,35 @@ class IncomingCallActivity : Activity() {
)
}

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
setInheritShowWhenLocked(true)
}

with(getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
requestDismissKeyguard(this@IncomingCallActivity, object :
KeyguardManager.KeyguardDismissCallback() {
override fun onDismissError() {
Log.d("IncomingCallActivity", "[KeyguardDismissCallback.onDismissError]")
}

override fun onDismissSucceeded() {
Log.d(
"IncomingCallActivity",
"[KeyguardDismissCallback.onDismissSucceeded]"
)
}

override fun onDismissCancelled() {
Log.d(
"IncomingCallActivity",
"[KeyguardDismissCallback.onDismissCancelled]"
)
}
})
}
}

processIncomingData(intent)
initUi()
initCallStateReceiver()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,14 @@ fun showCallNotification(
context: Context, callId: String, callType: Int, callInitiatorId: Int,
callInitiatorName: String, callOpponents: ArrayList<Int>, callPhoto: String?, userInfo: String
) {
Log.d("NotificationsManager", "[showCallNotification]")
val notificationManager = NotificationManagerCompat.from(context)

Log.d(
"NotificationsManager",
"[showCallNotification] canUseFullScreenIntent: ${notificationManager.canUseFullScreenIntent()}"
)

val intent = getLaunchIntent(context)

val pendingIntent = PendingIntent.getActivity(
Expand All @@ -55,15 +61,13 @@ fun showCallNotification(
var ringtone: Uri

val customRingtone = getString(context, "ringtone")
Log.d("NotificationsManager", "customRingtone $customRingtone")
if (!TextUtils.isEmpty(customRingtone)) {
ringtone = Uri.parse("android.resource://" + context.packageName + "/raw/" + customRingtone)
Log.d("NotificationsManager", "ringtone 1 $ringtone")
} else {
ringtone = Settings.System.DEFAULT_RINGTONE_URI
}

Log.d("NotificationsManager", "ringtone 2 $ringtone")
Log.d("NotificationsManager", "ringtone: $ringtone")

val isVideoCall = callType == 1

Expand Down Expand Up @@ -386,3 +390,7 @@ fun setNotificationColor(context: Context, notificationBuilder: NotificationComp
}
}
}

fun canUseFullScreenIntent(context: Context): Boolean {
return NotificationManagerCompat.from(context).canUseFullScreenIntent()
}
6 changes: 6 additions & 0 deletions ios/Classes/SwiftConnectycubeFlutterCallKitPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ public class SwiftConnectycubeFlutterCallKitPlugin: NSObject, FlutterPlugin {
SwiftConnectycubeFlutterCallKitPlugin.callController.setMute(uuid: UUID(uuidString: callId)!, muted: muted)
result(true)
}
else if call.method == "canUseFullScreenIntent" {
result(true)
}
else if call.method == "provideFullScreenIntentAccess" {
result(true)
}
else {
result(FlutterMethodNotImplemented)
}
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.4.0'
s.version = '2.5.0'
s.summary = 'Connectycube Call Kit plugin for flutter.'
s.description = <<-DESC
Connectycube Call Kit plugin for flutter.
Expand Down
21 changes: 21 additions & 0 deletions lib/src/connectycube_flutter_call_kit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,27 @@ class ConnectycubeFlutterCallKit {
});
}

/// Returns whether the app can send fullscreen intents (required for showing
/// the Incoming call screen on the Lockscreen)
static Future<bool> canUseFullScreenIntent() async {
if (!Platform.isAndroid) return Future.value(true);

return _methodChannel.invokeMethod("canUseFullScreenIntent").then((result) {
if (result == null) {
return false;
}

return result;
});
}

/// Opens the Setting to grant/deny permission for running the fullscreen Intents
static Future<void> provideFullScreenIntentAccess() async {
if (!Platform.isAndroid) return Future.value();

return _methodChannel.invokeMethod("provideFullScreenIntentAccess");
}

static void _processEvent(Map<String, dynamic> eventData) {
log('[ConnectycubeFlutterCallKit][_processEvent] eventData: $eventData');

Expand Down
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.4.0
version: 2.5.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 c43f033

Please sign in to comment.