2

I am using a permission_handler 4.4.0(latest update) plugin to handle permissions on mobile devices which works perfectly on android devices but when i am trying to ask for permissions on iOS it doesn't show permission pop on device and returns the permission status unknown. I think so it might be missing into the info.plist or pod file but I followed and double checked the both files but I didn;t find anything wrong but i uploaded code for that files if someone finds anything missing or wrong into files. please look into the code and let me know your suggestions. Thanks in advance guys.

info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>driverapp</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>$(FLUTTER_BUILD_NAME)</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>$(FLUTTER_BUILD_NUMBER)</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIMainStoryboardFile</key>
    <string>Main</string>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
    <key>io.flutter.embedded_views_preview</key>
    <true/>
    <!-- Permission options for the `location` group -->
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Need Location for Route Map and AppMarker Jobs</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Need Location for Patrolling and AppMarker Jobs</string>
    <key>NSLocationUsageDescription</key>
    <string>Need Location for Patrolling and AppMarker Jobs</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Need Location for Patrolling feature</string>
    <key>PermissionGroupNotification</key>
    <string>To show the notifications</string>
</dict>
</plist>

podfile

# Uncomment this line to define a global platform for your project
 platform :ios, '10.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 parse_KV_file(file, separator='=')
  file_abs_path = File.expand_path(file)
  if !File.exists? file_abs_path
    return [];
  end
  generated_key_values = {}
  skip_line_start_symbols = ["#", "/"]
  File.foreach(file_abs_path) do |line|
    next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
    plugin = line.split(pattern=separator)
    if plugin.length == 2
      podname = plugin[0].strip()
      path = plugin[1].strip()
      podpath = File.expand_path("#{path}", file_abs_path)
      generated_key_values[podname] = podpath
    else
      puts "Invalid plugin specification: #{line}"
    end
  end
  generated_key_values
end

target 'Runner' do
  # Flutter Pod

  copied_flutter_dir = File.join(__dir__, 'Flutter')
  copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
  copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
  unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
    # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
    # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
    # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.

    generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
    unless File.exist?(generated_xcode_build_settings_path)
      raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
    end
    generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
    cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];

    unless File.exist?(copied_framework_path)
      FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
    end
    unless File.exist?(copied_podspec_path)
      FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
    end
  end

  # Keep pod path relative so it can be checked into Podfile.lock.
  pod 'Flutter', :path => 'Flutter'

  # Plugin Pods
  pod 'Firebase/Analytics'
  pod 'Firebase/Database'
  # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
  # referring to absolute paths on developers' machines.
  system('rm -rf .symlinks')
  system('mkdir -p .symlinks/plugins')
  plugin_pods = parse_KV_file('../.flutter-plugins')
  plugin_pods.each do |name, path|
    symlink = File.join('.symlinks', 'plugins', name)
    File.symlink(path, symlink)
    pod name, :path => File.join(symlink, 'ios')
  end
end

# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
install! 'cocoapods', :disable_input_output_paths => true

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0'
      config.build_settings['ENABLE_BITCODE'] = 'NO'


      # You can remove unused permissions here
      # for more infomation: https://github.com/BaseflowIT/flutter-permission-handler/blob/develop/ios/Classes/PermissionHandlerEnums.h
      # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0'
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',

        ## dart: PermissionGroup.calendar
        # 'PERMISSION_EVENTS=0',

        ## dart: PermissionGroup.reminders
        # 'PERMISSION_REMINDERS=0',

        ## dart: PermissionGroup.contacts
        #  'PERMISSION_CONTACTS=0',

        ## dart: PermissionGroup.camera
        # 'PERMISSION_CAMERA=0',

        ## dart: PermissionGroup.microphone
        # 'PERMISSION_MICROPHONE=0',

        ## dart: PermissionGroup.speech
        # 'PERMISSION_SPEECH_RECOGNIZER=0',

        ## dart: PermissionGroup.photos
        # 'PERMISSION_PHOTOS=0',

        ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
         'PERMISSION_LOCATION=0',

        ## dart: PermissionGroup.notification
         'PERMISSION_NOTIFICATIONS=0',

        ## dart: PermissionGroup.mediaLibrary
        # 'PERMISSION_MEDIA_LIBRARY=0',

        ## dart: PermissionGroup.sensors
        # 'PERMISSION_SENSORS=0'
      ]
    end
  end
end

flutter code

Future<bool> checkForDevicePermission() async {
    var status = await PermissionManager.checkForPermissions(
        Platform.isAndroid? PermissionManager.androidPermissionsList:PermissionManager.iOSPermissionsList);
    if (status != null) {
//status returned here is PermissionStatus.unknown for all permissions 
//further code
       }
}

//PermissionManager Function
static Future<Map<PermissionGroup, PermissionStatus>> checkForPermissions(
      List<PermissionGroup> permissions) async {
    List<PermissionGroup> neededPermissions = List<PermissionGroup>();
    for (var permission in permissions) {
      permissionStatus =
          await PermissionHandler().checkPermissionStatus(permission);
      if (permissionStatus == PermissionStatus.unknown ||
          permissionStatus == PermissionStatus.denied) {
        neededPermissions.add(permission);
      }
    }
    if (neededPermissions != null && neededPermissions.length > 0) {
//getting the all permission status means granted or denied for which are requested to user
      try {
        Map<PermissionGroup, PermissionStatus> permissionsStatusList =
            await PermissionHandler().requestPermissions(neededPermissions);
        print(permissionsStatusList);
        return permissionsStatusList;
      } catch (e) {
        print(e.toString());
        return null;
      }
    } else {
      return null;
    }
  }

There is no error logs in debug console when it asks for permissions

Code Runner
  • 868
  • 16
  • 27
  • did you managed to resolve you issue? I am facing similar issue though – newbie Jul 21 '20 at 05:28
  • try to use the latest update of permission_handler plugin it might solve it because at that time I just added temperory fix because I didn't find out the permanent fix at that time that's why I haven't added as answer. Try it and and If it works just add as an answer. Hopefully it works. Thanks – Code Runner Jul 23 '20 at 13:47
  • I am using the latest plug in infact the same issue nothing still. – newbie Jul 23 '20 at 13:50
  • First try to make sure you have purpose strings and all the pod file changes updated and clean your build still no success then there is only way to create issue on plugin repository and you might get someone who can help from there because as I have created question there is no reply from anyone or they didn't face this problem. – Code Runner Jul 23 '20 at 14:16
  • I followed the exact steps in that we website . Yes I did accordingly too. Hope some one can help on this. – newbie Jul 23 '20 at 14:19
  • If you don't mind to put some code which can reproduce the same bug then feel free to edit my question so I or anyone else who looks at code and might find any issue in your code or can provide some fix. – Code Runner Jul 23 '20 at 14:28
  • where you would like me to put the codes? Over here ? I cant edit your question either. – newbie Jul 23 '20 at 14:33
  • ohh then just create new question that's fine as well. and mention your question link here. – Code Runner Jul 23 '20 at 14:35
  • infact I just posted a related question here ready https://stackoverflow.com/questions/63054221/both-widgetsbinding-instance-addpostframecallback-and-schedulerbinding-instance – newbie Jul 23 '20 at 14:38
  • You can maybe answer on it or comment cause I dont know why its down vote I have done my research and google – newbie Jul 23 '20 at 14:38

2 Answers2

1

Your Pod file is incorrect. It's comments say: # You can remove unused permissions here # for more infomation: https://github.com/Baseflow/flutter-permission-handler/blob/develop/permission_handler/ios/Classes/PermissionHandlerEnums.h # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0'

So, if you want to not use location services and don't want to ask for location services related permission then only write below line: 'PERMISSION_LOCATION=0',

Since you have written above line, while building Pod will exclude code from permission_handler package related to location permission. Hence even if you invoke permission popup for location from flutter code it will always return permission staus unknown.

Sravan
  • 1,891
  • 4
  • 23
  • 28
  • Thanks. I have already figured out but it will be good for some who is stuck. – Code Runner Oct 20 '20 at 20:22
  • Thanks @krunal-gandhi, you made me double-check my podfile! I had a look and thought it should be correct. But you reminded me, that if I NEED a permission, than the '#' need to be in front! This should be the accepted answer! – railon Dec 30 '20 at 07:51
-1

I ran into this issue on iOS 14.1 -- it worked on the Simulator but failed on the real device in TestFlight and via USB.

I originally had the location call as:

/// Bad
await Permission.location.request().isGranted

And changed it to this, where it worked as expected:

/// Good
await Permission.locationWhenInUse.request().isGranted

There is also Permission.locationAlways.request().... as well

Sludge
  • 6,072
  • 5
  • 31
  • 43