diff --git a/dogfooding/lib/screens/home_screen.dart b/dogfooding/lib/screens/home_screen.dart index 20df7a192..42261d382 100644 --- a/dogfooding/lib/screens/home_screen.dart +++ b/dogfooding/lib/screens/home_screen.dart @@ -13,6 +13,7 @@ import 'package:flutter_dogfooding/widgets/stream_button.dart'; import 'package:stream_video_flutter/stream_video_flutter.dart'; import 'package:stream_video_flutter/stream_video_flutter_background.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:stream_video_push_notification/stream_video_push_notification.dart'; import '../app/user_auth_controller.dart'; import '../di/injector.dart'; @@ -43,6 +44,8 @@ class _HomeScreenState extends State { Permission.microphone, ].request(); + StreamVideoPushNotificationManager.ensureFullScreenIntentPermission(); + StreamBackgroundService.init( StreamVideo.instance, onButtonClick: (call, type, serviceType) async { diff --git a/packages/stream_video/CHANGELOG.md b/packages/stream_video/CHANGELOG.md index 3d01dc88c..56dd8da6b 100644 --- a/packages/stream_video/CHANGELOG.md +++ b/packages/stream_video/CHANGELOG.md @@ -2,6 +2,7 @@ ✅ Added * Added the 'call.collectUserFeedback()' method which allows users to send call quality rating. These ratings are visible on the Dashboard and are aggregated in call stats for easy tracking. For a sample implementation, please refer to the [cookbook](https://getstream.io/video/docs/flutter/ui-cookbook/call-quality-rating/). +* Added device thermal status reporting to better optimize call quality. ## 0.6.0 diff --git a/packages/stream_video_flutter/CHANGELOG.md b/packages/stream_video_flutter/CHANGELOG.md index b3aba7f5b..1b9118b44 100644 --- a/packages/stream_video_flutter/CHANGELOG.md +++ b/packages/stream_video_flutter/CHANGELOG.md @@ -2,6 +2,13 @@ ✅ Added * Added the 'call.collectUserFeedback()' method which allows users to send call quality rating. These ratings are visible on the Dashboard and are aggregated in call stats for easy tracking. For a sample implementation, please refer to the [cookbook](https://getstream.io/video/docs/flutter/ui-cookbook/call-quality-rating/). +* Added device thermal status reporting to better optimize call quality. +* Added the `StreamVideoPushNotificationManager.ensureFullScreenIntentPermission()` method. This resolves an issue on some Android 14 devices where full-screen notifications would not appear due to missing permissions. +You can now invoke this method to show a settings screen, allowing users to enable the required permission if it's not already enabled. + +🐞 Fixed +* Resolved an issue where CallKit calls would not connect when accepted while the screen was locked. +* Fixed a bug where the Android foreground service would not stop when the app was killed, keeping the call connection active. ## 0.6.0 diff --git a/packages/stream_video_push_notification/.metadata b/packages/stream_video_push_notification/.metadata index dbaac8f5c..1d3437068 100644 --- a/packages/stream_video_push_notification/.metadata +++ b/packages/stream_video_push_notification/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: "2f708eb8396e362e280fac22cf171c2cb467343c" + revision: "2663184aa79047d0a33a14a3b607954f8fdd8730" channel: "stable" project_type: plugin @@ -13,11 +13,14 @@ project_type: plugin migration: platforms: - platform: root - create_revision: 2f708eb8396e362e280fac22cf171c2cb467343c - base_revision: 2f708eb8396e362e280fac22cf171c2cb467343c + create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 + base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 + - platform: android + create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 + base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 - platform: ios - create_revision: 2f708eb8396e362e280fac22cf171c2cb467343c - base_revision: 2f708eb8396e362e280fac22cf171c2cb467343c + create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 + base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 # User provided section diff --git a/packages/stream_video_push_notification/CHANGELOG.md b/packages/stream_video_push_notification/CHANGELOG.md index 99779d6d5..050c0b5cf 100644 --- a/packages/stream_video_push_notification/CHANGELOG.md +++ b/packages/stream_video_push_notification/CHANGELOG.md @@ -1,3 +1,12 @@ +## Unreleased + +✅ Added +* Added the `StreamVideoPushNotificationManager.ensureFullScreenIntentPermission()` method. This resolves an issue on some Android 14 devices where full-screen notifications would not appear due to missing permissions. +You can now invoke this method to show a settings screen, allowing users to enable the required permission if it's not already enabled. + +🐞 Fixed +* Resolved an issue where CallKit calls would not connect when accepted while the screen was locked. + ## 0.6.0 🔄 Dependency updates diff --git a/packages/stream_video_push_notification/android/.gitignore b/packages/stream_video_push_notification/android/.gitignore new file mode 100644 index 000000000..161bdcdaf --- /dev/null +++ b/packages/stream_video_push_notification/android/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.cxx diff --git a/packages/stream_video_push_notification/android/build.gradle b/packages/stream_video_push_notification/android/build.gradle new file mode 100644 index 000000000..97dd3e20e --- /dev/null +++ b/packages/stream_video_push_notification/android/build.gradle @@ -0,0 +1,65 @@ +buildscript { + ext.kotlin_version = "1.9.10" + repositories { + google() + mavenCentral() + } + + dependencies { + classpath("com.android.tools.build:gradle:7.3.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: "com.android.library" +apply plugin: "kotlin-android" + +android { + if (project.android.hasProperty("namespace")) { + namespace = "com.example.stream_video_push_notification" + } + + compileSdk = 34 + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 + } + + sourceSets { + main.java.srcDirs += "src/main/kotlin" + test.java.srcDirs += "src/test/kotlin" + } + + defaultConfig { + minSdk = 21 + } + + dependencies { + testImplementation("org.jetbrains.kotlin:kotlin-test") + testImplementation("org.mockito:mockito-core:5.0.0") + } + + testOptions { + unitTests.all { + useJUnitPlatform() + + testLogging { + events "passed", "skipped", "failed", "standardOut", "standardError" + outputs.upToDateWhen {false} + showStandardStreams = true + } + } + } +} diff --git a/packages/stream_video_push_notification/android/gradle/wrapper/gradle-wrapper.properties b/packages/stream_video_push_notification/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..6e57b8f08 --- /dev/null +++ b/packages/stream_video_push_notification/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ + +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/packages/stream_video_push_notification/android/settings.gradle b/packages/stream_video_push_notification/android/settings.gradle new file mode 100644 index 000000000..cd3052c71 --- /dev/null +++ b/packages/stream_video_push_notification/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'stream_video_push_notification' diff --git a/packages/stream_video_push_notification/android/src/main/AndroidManifest.xml b/packages/stream_video_push_notification/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..cf889989a --- /dev/null +++ b/packages/stream_video_push_notification/android/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + diff --git a/packages/stream_video_push_notification/android/src/main/kotlin/io/getstream/video/flutter/stream_video_push_notification/StreamVideoPushNotificationPlugin.kt b/packages/stream_video_push_notification/android/src/main/kotlin/io/getstream/video/flutter/stream_video_push_notification/StreamVideoPushNotificationPlugin.kt new file mode 100644 index 000000000..f11883a9f --- /dev/null +++ b/packages/stream_video_push_notification/android/src/main/kotlin/io/getstream/video/flutter/stream_video_push_notification/StreamVideoPushNotificationPlugin.kt @@ -0,0 +1,66 @@ +package io.getstream.video.flutter.stream_video_push_notification + +import android.app.Activity +import android.app.NotificationManager +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Build +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.embedding.engine.plugins.activity.ActivityAware +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding +import com.hiennv.flutter_callkit_incoming.CallkitNotificationManager + +/** StreamVideoPushNotificationPlugin */ +class StreamVideoPushNotificationPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { + private lateinit var channel : MethodChannel + private var activity: Activity? = null + private var context: Context? = null + private lateinit var callkitNotificationManager: CallkitNotificationManager + + override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + context = flutterPluginBinding.applicationContext + + channel = MethodChannel(flutterPluginBinding.binaryMessenger, "stream_video_push_notification") + channel.setMethodCallHandler(this) + + callkitNotificationManager = CallkitNotificationManager(flutterPluginBinding.applicationContext) + } + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + if (call.method == "ensureFullScreenIntentPermission") { + val notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + if (Build.VERSION.SDK_INT >= 34) { + if (!notificationManager.canUseFullScreenIntent()) { + callkitNotificationManager?.requestFullIntentPermission(activity) + } + } + result.success(true) + } else { + result.notImplemented() + } + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + channel.setMethodCallHandler(null) + } + + override fun onAttachedToActivity(binding: ActivityPluginBinding) { + activity = binding.activity + } + + override fun onDetachedFromActivityForConfigChanges() { + activity = null + } + + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + activity = binding.activity + } + + override fun onDetachedFromActivity() { + activity = null + } +} diff --git a/packages/stream_video_push_notification/ios/Classes/StreamVideoPushNotificationPlugin.swift b/packages/stream_video_push_notification/ios/Classes/StreamVideoPushNotificationPlugin.swift index 3c94a1322..ddc974cf1 100644 --- a/packages/stream_video_push_notification/ios/Classes/StreamVideoPushNotificationPlugin.swift +++ b/packages/stream_video_push_notification/ios/Classes/StreamVideoPushNotificationPlugin.swift @@ -6,7 +6,7 @@ public class StreamVideoPushNotificationPlugin: NSObject, FlutterPlugin { let persistentState: UserDefaults = UserDefaults.standard public static func register(with registrar: FlutterPluginRegistrar) { - let mainChannel = FlutterMethodChannel(name: "stream_video_push_notifications", binaryMessenger: registrar.messenger()) + let mainChannel = FlutterMethodChannel(name: "stream_video_push_notification", binaryMessenger: registrar.messenger()) let instance = StreamVideoPushNotificationPlugin() registrar.addMethodCallDelegate(instance, channel: mainChannel) diff --git a/packages/stream_video_push_notification/lib/src/stream_video_push_notification.dart b/packages/stream_video_push_notification/lib/src/stream_video_push_notification.dart index ab53266a3..acc6c2a4e 100644 --- a/packages/stream_video_push_notification/lib/src/stream_video_push_notification.dart +++ b/packages/stream_video_push_notification/lib/src/stream_video_push_notification.dart @@ -417,6 +417,11 @@ class StreamVideoPushNotificationManager implements PushNotificationManager { Future dispose() async { _subscriptions.cancelAll(); } + + static Future ensureFullScreenIntentPermission() { + return StreamVideoPushNotificationPlatform.instance + .ensureFullScreenIntentPermission(); + } } const _defaultPushParams = StreamVideoPushParams( diff --git a/packages/stream_video_push_notification/lib/stream_video_push_notification_method_channel.dart b/packages/stream_video_push_notification/lib/stream_video_push_notification_method_channel.dart index e39d942a2..95cce7142 100644 --- a/packages/stream_video_push_notification/lib/stream_video_push_notification_method_channel.dart +++ b/packages/stream_video_push_notification/lib/stream_video_push_notification_method_channel.dart @@ -3,6 +3,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; +import 'package:stream_video/stream_video.dart'; import 'stream_video_push_notification_platform_interface.dart'; @@ -11,7 +12,7 @@ class MethodChannelStreamVideoPushNotification extends StreamVideoPushNotificationPlatform { /// The method channel used to interact with the native platform. @visibleForTesting - final methodChannel = const MethodChannel('stream_video_push_notifications'); + final methodChannel = const MethodChannel('stream_video_push_notification'); CallerCustomizationFunction? callerCustomizationCallback; @@ -51,4 +52,11 @@ class MethodChannelStreamVideoPushNotification } await methodChannel.invokeMethod('initData', pushParams); } + + @override + Future ensureFullScreenIntentPermission() async { + if (!CurrentPlatform.isAndroid) return; + + await methodChannel.invokeMethod('ensureFullScreenIntentPermission'); + } } diff --git a/packages/stream_video_push_notification/lib/stream_video_push_notification_platform_interface.dart b/packages/stream_video_push_notification/lib/stream_video_push_notification_platform_interface.dart index 45a6d631d..b2d846b89 100644 --- a/packages/stream_video_push_notification/lib/stream_video_push_notification_platform_interface.dart +++ b/packages/stream_video_push_notification/lib/stream_video_push_notification_platform_interface.dart @@ -51,6 +51,11 @@ abstract class StreamVideoPushNotificationPlatform extends PlatformInterface { CallerCustomizationFunction? callerCustomizationCallback, BackgroundVoipCallHandler? backgroundVoipCallHandler, ) { - throw UnimplementedError('platformVersion() has not been implemented.'); + throw UnimplementedError('init() has not been implemented.'); + } + + Future ensureFullScreenIntentPermission() { + throw UnimplementedError( + 'ensureFullScreenIntentPermission() has not been implemented.'); } } diff --git a/packages/stream_video_push_notification/pubspec.yaml b/packages/stream_video_push_notification/pubspec.yaml index 347586ee4..575f19546 100644 --- a/packages/stream_video_push_notification/pubspec.yaml +++ b/packages/stream_video_push_notification/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: flutter: sdk: flutter flutter_webrtc: ^0.11.7 - flutter_callkit_incoming: ^2.0.4+1 + flutter_callkit_incoming: ^2.0.4+2 json_annotation: ^4.9.0 meta: ^1.9.1 plugin_platform_interface: ^2.1.8 @@ -25,7 +25,7 @@ dependencies: stream_video: ^0.6.0 uuid: ^4.2.1 shared_preferences: ^2.3.2 - + dev_dependencies: build_runner: ^2.4.4 flutter_lints: ^2.0.2 @@ -50,7 +50,8 @@ flutter: ios: pluginClass: StreamVideoPushNotificationPlugin android: - default_package: stream_video_push_notification + package: io.getstream.video.flutter.stream_video_push_notification + pluginClass: StreamVideoPushNotificationPlugin topics: - video