I am trying to run my flutter app for iOS part but there is a problem in the "flutter_callkit_incoming" module
the terminal error when run: flutter build ipa --release --export-options-plist /Users/builder/export_options.plist --flavor prod -t lib/main_prod.dart
Building with sound null safety
Archiving com.mindscape.app...
Automatically signing iOS for device deployment using specified development team in Xcode project: 9PF4M6PSKX
Running pod install... 5.2s
Running Xcode build...
Xcode archive done. 78.6s
Failed to build iOS app
Swift Compiler Error (Xcode): No such module 'flutter_callkit_incoming'
/Users/builder/clone/ios/Runner/AppDelegate.swift:3:7
Encountered error while archiving for device.
I need to use flutter_callkit_incoming version "2.0.0+1"
I am using flutter 3.7.10
I am using code magic to build my iOS flutter application (as my device is windows)
I found out that it is a flavor problem as when I run "--release --flavor dev" it works file but the problem happens when running "--release --flavor prod"
The steps I followed
flutter clean
flutter pub upgrade --major-versions
it returns:
flutter_callkit_incoming 2.0.0+1 from git
pop install
it returns:Installing flutter_callkit_incoming (0.0.1)
xcode builds
it returns:Failed to build iOS app
Swift Compiler Error (Xcode): No such module 'flutter_callkit_incoming'/Users/builder/clone/ios/Runner/AppDelegate.swift:3:7
here is the pubspec.yaml file:
environment: sdk: '>=2.18.6 <3.0.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions # consider running `flutter pub upgrade --major-versions`. Alternatively, # dependencies can be manually updated by changing the version numbers below to # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. # network dio: ^5.1.0 dio_cache_interceptor: ^3.4.1 dio_cache_interceptor_hive_store: ^3.2.1 connectivity_plus: ^3.0.3 flutter_timezone: ^1.0.7 # firebase firebase_messaging: ^14.4.0 firebase_core: ^2.9.0 # socket socket_io_client: ^2.0.1 # agora agora_rtc_engine: 6.1.0 # call kit flutter_callkit_incoming: git: url: https://github.com/Mindsacpe/callkit-plugin.git ref: main # branch name version: 2.0.0+1 # audio_session: ^0.1.13 # localization easy_localization: ^3.0.3 # state management path_provider: ^2.0.14 flutter_riverpod: ^2.3.2 # storage shared_preferences: ^2.0.15 flutter_secure_storage: ^8.0.0 # permission permission_handler: ^10.2.0 # ui - core cupertino_icons: ^1.0.2 device_info_plus: ^8.0.0 flutter_sim_country_code: ^0.1.2 fluttertoast: ^8.1.2 logger: ^1.1.0 shimmer: ^2.0.0 easy_debounce: ^2.0.3 tap_debouncer: ^2.1.0 flutter_native_splash: ^2.2.17 keyboard_actions: ^4.2.0 webview_flutter: ^4.2.0 flutter_rating_bar: ^4.0.1 carousel_slider: ^4.2.1 screen_protector: ^1.2.0 uuid: ^3.0.7 # notification flutter_local_notifications: ^13.0.0 # authentication sign_in_with_apple: ^4.3.0 google_sign_in: ^6.1.0 flutter_facebook_auth: 5.0.7 firebase_auth: ^4.4.0 # files and images file_picker: ^5.2.4 image_cropper: ^3.0.1 image_picker: ^0.8.6 open_filex: ^4.3.2 extended_image: ^7.0.2 cached_network_image: ^3.2.3 # ui - otp pin_code_fields: ^7.4.0 # Calender table_calendar: ^3.0.8 add_2_calendar: ^2.2.3 easy_localization_generator: ^0.3.0 dev_dependencies: flutter_test: sdk: flutter # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^2.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter packages. flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true generate: true # To add assets to your application, add an assets section, like this: assets: - assets/translations/ - assets/images/ - assets/flags/ - assets/raw/ - assets/pngs/ # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware # For details regarding adding assets from package dependencies, see # https://flutter.dev/assets-and-images/#from-packages # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a # "family" key with the font family name, and a "fonts" key with a # list giving the asset and other descriptors for the font. For # example: fonts: - family: Abel fonts: - asset: assets/fonts/Abel-Regular.ttf # - family: Poppins # fonts: # - asset: assets/fonts/Poppins-Regular.ttf # # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages flutter_native_splash: color: "#44AA87" image: assets/splash_images/splash_logo.png branding: assets/splash_images/blank_bg.png color_dark: "#44AA87" image_dark: assets/splash_images/splash_logo.png branding_dark: assets/splash_images/blank_bg.png android_12: image: assets/splash_images/splash_logo.png icon_background_color: "#44AA87" image_dark: assets/splash_images/splash_logo.png icon_background_color_dark: "#44AA87" web: false android_gravity: center ios_content_mode: center
here is the related part in pubspec.lock file:
# Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: flutter_callkit_incoming: dependency: "direct main" description: path: "." ref: main resolved-ref: "66c127445afbd69813485a00e572d1e091c70ed6" url: "https://github.com/Mindsacpe/callkit-plugin.git" source: git version: "2.0.0+1" sdks: dart: ">=2.19.0 <3.0.0" flutter: ">=3.7.0"
here is my pod file:
# Uncomment this line to define a global platform for your project platform :ios, '12.0' deployment_target = '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' project 'Runner', { 'Debug' => :debug, 'Profile' => :release, 'Release' => :release, } def flutter_root generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) unless File.exist?(generated_xcode_build_settings_path) raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" end File.foreach(generated_xcode_build_settings_path) do |line| matches = line.match(/FLUTTER_ROOT\=(.*)/) return matches[1].strip if matches end raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" end require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) flutter_ios_podfile_setup target 'Runner' do use_frameworks! use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = deployment_target config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', ## dart: PermissionGroup.calendar 'PERMISSION_EVENTS=1', ## dart: PermissionGroup.reminders # 'PERMISSION_REMINDERS=1', ## dart: PermissionGroup.contacts # 'PERMISSION_CONTACTS=1', ## dart: PermissionGroup.camera 'PERMISSION_CAMERA=1', ## dart: PermissionGroup.microphone 'PERMISSION_MICROPHONE=1', ## dart: PermissionGroup.speech # 'PERMISSION_SPEECH_RECOGNIZER=1', ## dart: PermissionGroup.photos 'PERMISSION_PHOTOS=1', ## dart: PermissionGroup.audio session 'AUDIO_SESSION_MICROPHONE=1', ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse] # 'PERMISSION_LOCATION=1', ## dart: PermissionGroup.notification # 'PERMISSION_NOTIFICATIONS=1', ## dart: PermissionGroup.mediaLibrary 'PERMISSION_MEDIA_LIBRARY=1', ## dart: PermissionGroup.sensors # 'PERMISSION_SENSORS=1', ## dart: PermissionGroup.bluetooth # 'PERMISSION_BLUETOOTH=1', ## dart: PermissionGroup.appTrackingTransparency # 'PERMISSION_APP_TRACKING_TRANSPARENCY=1', ## dart: PermissionGroup.criticalAlerts # 'PERMISSION_CRITICAL_ALERTS=1' ] end end end
here is my AppDelegate.swift file:
import UIKit import PushKit import Flutter import flutter_callkit_incoming @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate { var methodOff = "UserOffline_Ios" var methodOn = "UserOnline_Ios" var channel = "com_mindscape_ios" var flutterChannel = FlutterMethodChannel() override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) //Setup VOIP let mainQueue = DispatchQueue.main let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue) voipRegistry.delegate = self voipRegistry.desiredPushTypes = [PKPushType.voIP] if #available(iOS 10.0, *) { // For iOS 10 display notification (sent via APNS) UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: {_, _ in }) } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() let controller : FlutterViewController = window?.rootViewController as! FlutterViewController flutterChannel = FlutterMethodChannel(name: channel, binaryMessenger: controller.binaryMessenger) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground. override func applicationWillTerminate(_ application: UIApplication) { print("applicationWillTerminate called") self.flutterChannel.invokeMethod(methodOff,arguments: "") } // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. override func applicationWillEnterForeground(_ application: UIApplication) { print("applicationWillResume called") self.flutterChannel.invokeMethod(methodOn,arguments: "") } // // Call back from Recent history // override func application(_ application: UIApplication, // continue userActivity: NSUserActivity, // restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { // // guard let handleObj = userActivity.handle else { // return false // } // // guard let isVideo = userActivity.isVideo else { // return false // } // let nameCaller = handleObj.getDecryptHandle()["nameCaller"] as? String ?? "" // let handle = handleObj.getDecryptHandle()["handle"] as? String ?? "" // let data = flutter_callkit_incoming.Data(id: UUID().uuidString, nameCaller: nameCaller, handle: handle, type: isVideo ? 1 : 0) // //set more data... // SwiftFlutterCallkitIncomingPlugin.sharedInstance?.startCall(data, fromPushKit: true) // // return super.application(application, continue: userActivity, restorationHandler: restorationHandler) // } // // Handle updated push credentials func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined() print(deviceToken) //Save deviceToken to your server SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken) } func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { print("didInvalidatePushTokenFor") SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP("") } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { print("didReceiveIncomingPushWith") guard type == .voIP else { return } let id = payload.dictionaryPayload["id"] as? String ?? "" let nameCaller = payload.dictionaryPayload["nameCaller"] as? String ?? "" let handle = payload.dictionaryPayload["handle"] as? String ?? "" let isVideo = payload.dictionaryPayload["isVideo"] as? Bool ?? false let data = flutter_callkit_incoming.Data(id: id, nameCaller: nameCaller, handle: handle, type: isVideo ? 1 : 0) data.extra = payload.dictionaryPayload["extra"] as? NSDictionary ?? NSDictionary() //set more data //data.iconName = ... //data..... SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(data, fromPushKit: true) } }