Failed to build iOS app Swift Compiler Error (Xcode): No such module 'flutter_callkit_incoming'

284 Views Asked by At

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

  1. flutter clean

  2. flutter pub upgrade --major-versions
    it returns:
    flutter_callkit_incoming 2.0.0+1 from git

  3. pop install
    it returns:

    Installing flutter_callkit_incoming (0.0.1)

  4. 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)
    }
}
0

There are 0 best solutions below