Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions analysis_options.yaml

This file was deleted.

4 changes: 4 additions & 0 deletions permission_handler/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 14.0.0

- **BREAKING CHANGE:** Updates `permission_handler_apple` dependency to version 10.0.0, which raises the minimum iOS deployment target to `14.0`. Set `platform :ios, '14.0'` in your `Podfile` and `IPHONEOS_DEPLOYMENT_TARGET` to `14.0` in your Xcode project.

## 13.0.0

- **BREAKING CHANGE:** , android compilesdk now set to version `compileSdkVersion 37`
Expand Down
5 changes: 4 additions & 1 deletion permission_handler/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ In general, it's sufficient to add permission only to the `main` version.
<details>
<summary>iOS - Swift Package Manager (click to expand)</summary>

> Requires Flutter 3.24.0 or higher and Xcode 15.0 or higher.
> Requires Flutter 3.24.0 or higher, Xcode 15.0 or higher and a minimum iOS deployment target of 14.0.

With SPM, `Package.swift` automatically detects which permissions to enable by reading your app's `Info.plist`. A permission is compiled in when its corresponding usage description key is present:

Expand Down Expand Up @@ -117,6 +117,9 @@ Then run `flutter build ios` or rebuild in Xcode as usual.
<details>
<summary>iOS - CocoaPods (click to expand)</summary>

> Requires a minimum iOS deployment target of 14.0. Set `platform :ios, '14.0'` in your `Podfile`
> and `IPHONEOS_DEPLOYMENT_TARGET` to `14.0` in your Xcode project.

Add permission to your `Info.plist` file.
[Here](https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler/example/ios/Runner/Info.plist)'s an example `Info.plist` with a complete list of all possible permissions.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
<string>14.0</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion permission_handler/example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
platform :ios, '14.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down Expand Up @@ -448,7 +448,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -497,7 +497,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down
4 changes: 2 additions & 2 deletions permission_handler/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: permission_handler
description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
repository: https://github.com/baseflow/flutter-permission-handler
issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues
version: 13.0.0
version: 14.0.0

environment:
sdk: ^3.6.0
Expand All @@ -26,7 +26,7 @@ dependencies:
sdk: flutter
meta: ^1.7.0
permission_handler_android: ^14.0.0
permission_handler_apple: ^9.5.0
permission_handler_apple: ^10.0.0
permission_handler_html: ^0.1.4+0
permission_handler_windows: ^0.2.2
permission_handler_platform_interface: ^4.4.0
Expand Down
15 changes: 15 additions & 0 deletions permission_handler_apple/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## 10.0.0

* **Breaking change:** Migrates iOS to a Pigeon **ProxyApi** architecture with `sharedDarwinSource: true`.
Permission logic now lives in Dart (`lib/next/`); the Swift plugin (`darwin/`) only registers
`ProxyApiRegistrar` bridges to Apple frameworks.
* Adds `PermissionHandlerApple` as `dartPluginClass` extending `PermissionHandlerPlatform`.
Permission checks/requests live directly on this class (no separate manager/impl layer).
* Exposes native Apple framework proxy APIs via `lib/next/exports/apple_permissions.dart` for
advanced consumers.
* Adds `tool/pigeon_regenerate.sh` to regenerate Pigeon artifacts from `pigeon/apple_permissions.dart`.
* Bumps minimum iOS deployment target to **14.0** for the `darwin/` implementation (required for
`PHAccessLevel`, `ATTrackingManager`, and related APIs).
* Legacy `ios/` Obj-C + MethodChannel sources remain in the repository for reference but are no
longer compiled when using `sharedDarwinSource`.

## 9.5.0

* Adds support for the new Android 17 permission `ACCESS_LOCAL_NETWORK`.
Expand Down
72 changes: 72 additions & 0 deletions permission_handler_apple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,78 @@ Since version 9.1.0 of the [permission_handler](https://pub.dev/packages/permiss

More detailed instructions on using the API can be found in the [README.md](../permission_handler/README.md) of the [permission_handler](https://pub.dev/packages/permission_handler) package.

## Architecture (10.0.0+)

Starting with version 10.0.0, iOS uses a **Pigeon ProxyApi** architecture:

| Directory | Role |
|-----------|------|
| `darwin/` | Active Swift plugin (`PermissionHandlerDarwinPlugin`) — registers Pigeon proxy bridges only |
| `lib/next/` | Dart permission orchestration (`PermissionHandlerApple`, handlers) |
| `pigeon/` | Pigeon schema input (`apple_permissions.dart`) |
| `ios/` | Legacy Obj-C implementation (frozen; not compiled with `sharedDarwinSource: true`) |

Request flow:

```
App → PermissionHandlerApple (Dart)
→ permission handlers
→ Pigeon ProxyApi classes (*.g.dart)
↔ PermissionHandlerDarwinPlugin (Swift)
→ Apple frameworks (CoreLocation, Photos, …)
```

Advanced consumers can import native proxy APIs directly:

```dart
import 'package:permission_handler_apple/next/exports/apple_permissions.dart';
```

## Pigeon code generation

Regenerate Dart and Swift artifacts after editing `pigeon/apple_permissions.dart`:

```bash
cd permission_handler_apple
./tool/pigeon_regenerate.sh
```

Or manually:

```bash
dart run pigeon --input pigeon/apple_permissions.dart
```

Commit both `lib/next/src/pigeon/apple_permissions.g.dart` and
`darwin/permission_handler_apple/Sources/permission_handler_apple/PermissionHandler/PermissionHandlerLibrary.g.swift`.

## iOS setup

### Minimum deployment target

The `darwin/` implementation requires **iOS 14.0** or higher.

### Configuring permissions

Permission compile-time flags (`PERMISSION_*`) still apply. Configure them in your app's
`ios/Podfile` `post_install` block (CocoaPods) or via environment variables / `Info.plist` keys
(Swift Package Manager). See the [permission_handler README](../permission_handler/README.md)
for the full list of macros and required usage-description keys.

Example Podfile snippet:

```ruby
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_CAMERA=1',
'PERMISSION_PHOTOS=1',
# …
]
```

For SPM, the `darwin/permission_handler_apple/Package.swift` resolves enabled permissions from
environment variables and `Info.plist` keys automatically (same logic as the legacy `ios/` package).

## Issues

Please file any issues, bugs, or feature requests as an issue on our [GitHub](https://github.com/Baseflow/flutter-permission-handler/issues) page. Commercial support is available, you can contact us at <hello@baseflow.com>.
Expand Down
11 changes: 11 additions & 0 deletions permission_handler_apple/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
include: package:flutter_lints/flutter.yaml

analyzer:
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
- "**/generated/**"

linter:
rules:
- public_member_api_docs
29 changes: 29 additions & 0 deletions permission_handler_apple/darwin/permission_handler_apple.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
Pod::Spec.new do |s|
s.name = 'permission_handler_apple'
s.version = '9.5.0'
s.summary = 'Permission plugin for Flutter.'
s.description = <<-DESC
Permission plugin for Flutter. This plugin provides a cross-platform API to request and check permissions.
DESC
s.homepage = 'https://github.com/baseflow/flutter-permission-handler'
s.license = { :file => '../LICENSE' }
s.author = { 'Baseflow' => 'hello@baseflow.com' }
s.source = { :path => '.' }
s.source_files = 'permission_handler_apple/Sources/permission_handler_apple/**/*.swift'
s.dependency 'Flutter'

s.ios.deployment_target = '14.0'
s.static_framework = true
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PERMISSION_EVENTS=1 PERMISSION_EVENTS_FULL_ACCESS=1 PERMISSION_REMINDERS=1 PERMISSION_CONTACTS=1 PERMISSION_CAMERA=1 PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1 PERMISSION_PHOTOS=1 PERMISSION_PHOTOS_ADD_ONLY=1 PERMISSION_LOCATION=1 PERMISSION_LOCATION_WHENINUSE=1 PERMISSION_LOCATION_ALWAYS=1 PERMISSION_NOTIFICATIONS=1 PERMISSION_MEDIA_LIBRARY=1 PERMISSION_SENSORS=1 PERMISSION_BLUETOOTH=1 PERMISSION_APP_TRACKING_TRANSPARENCY=1 PERMISSION_CRITICAL_ALERTS=1 PERMISSION_ASSISTANT=1',
}
s.swift_version = '5.0'
s.resource_bundles = {
'permission_handler_apple_privacy' => [
'permission_handler_apple/Sources/permission_handler_apple/PrivacyInfo.xcprivacy',
],
}
end
138 changes: 138 additions & 0 deletions permission_handler_apple/darwin/permission_handler_apple/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// swift-tools-version: 5.9

import PackageDescription
import Foundation

// Permission configuration — same resolution order as legacy ios/ Package.swift.
// See permission_handler/README.md for PERMISSION_* macro documentation.

let env = ProcessInfo.processInfo.environment

func loadInfoPlist(at url: URL) -> [String: Any]? {
NSDictionary(contentsOf: url) as? [String: Any]
}

func findInfoPlist() -> [String: Any] {
let fileManager = FileManager.default
let packageDir = URL(fileURLWithPath: #file).deletingLastPathComponent()
let currentDir = URL(fileURLWithPath: fileManager.currentDirectoryPath)
var visited = Set<String>()

for root in [packageDir, currentDir] {
var dir = root
for _ in 0..<10 {
let key = dir.resolvingSymlinksInPath().path
guard visited.insert(key).inserted else { break }
let pubspecURL = dir.appendingPathComponent("pubspec.yaml")
let plistURL = dir.appendingPathComponent("ios/Runner/Info.plist")
if fileManager.fileExists(atPath: pubspecURL.path),
let plist = loadInfoPlist(at: plistURL) {
return plist
}
let parent = dir.deletingLastPathComponent()
if parent.path == dir.path { break }
dir = parent
}
}
return [:]
}

let infoPlist = findInfoPlist()

func isEnabled(_ envKey: String, plistKeys: String..., defaultValue: Bool = false) -> Bool {
if let val = env[envKey] { return val != "0" }
for key in plistKeys where infoPlist[key] != nil { return true }
return defaultValue
}

func optionalDefine(_ name: String, enabled: Bool) -> SwiftSetting? {
enabled ? .define(name) : nil
}

let permissionSwiftSettings: [SwiftSetting] = [
optionalDefine("PERMISSION_EVENTS",
enabled: isEnabled("PERMISSION_EVENTS",
plistKeys: "NSCalendarsUsageDescription")),
optionalDefine("PERMISSION_EVENTS_FULL_ACCESS",
enabled: isEnabled("PERMISSION_EVENTS_FULL_ACCESS",
plistKeys: "NSCalendarsFullAccessUsageDescription",
"NSCalendarsWriteOnlyAccessUsageDescription")),
optionalDefine("PERMISSION_REMINDERS",
enabled: isEnabled("PERMISSION_REMINDERS",
plistKeys: "NSRemindersUsageDescription")),
optionalDefine("PERMISSION_CONTACTS",
enabled: isEnabled("PERMISSION_CONTACTS",
plistKeys: "NSContactsUsageDescription")),
optionalDefine("PERMISSION_CAMERA",
enabled: isEnabled("PERMISSION_CAMERA",
plistKeys: "NSCameraUsageDescription")),
optionalDefine("PERMISSION_MICROPHONE",
enabled: isEnabled("PERMISSION_MICROPHONE",
plistKeys: "NSMicrophoneUsageDescription")),
optionalDefine("PERMISSION_SPEECH_RECOGNIZER",
enabled: isEnabled("PERMISSION_SPEECH_RECOGNIZER",
plistKeys: "NSSpeechRecognitionUsageDescription")),
optionalDefine("PERMISSION_PHOTOS",
enabled: isEnabled("PERMISSION_PHOTOS",
plistKeys: "NSPhotoLibraryUsageDescription",
"NSPhotoLibraryAddUsageDescription")),
optionalDefine("PERMISSION_PHOTOS_ADD_ONLY",
enabled: isEnabled("PERMISSION_PHOTOS_ADD_ONLY",
plistKeys: "NSPhotoLibraryAddUsageDescription")),
optionalDefine("PERMISSION_LOCATION",
enabled: isEnabled("PERMISSION_LOCATION",
plistKeys: "NSLocationWhenInUseUsageDescription",
"NSLocationAlwaysAndWhenInUseUsageDescription")),
optionalDefine("PERMISSION_LOCATION_WHENINUSE",
enabled: isEnabled("PERMISSION_LOCATION_WHENINUSE",
plistKeys: "NSLocationWhenInUseUsageDescription")),
optionalDefine("PERMISSION_LOCATION_ALWAYS",
enabled: isEnabled("PERMISSION_LOCATION_ALWAYS",
plistKeys: "NSLocationAlwaysAndWhenInUseUsageDescription")),
optionalDefine("PERMISSION_NOTIFICATIONS",
enabled: isEnabled("PERMISSION_NOTIFICATIONS", defaultValue: true)),
optionalDefine("PERMISSION_MEDIA_LIBRARY",
enabled: isEnabled("PERMISSION_MEDIA_LIBRARY",
plistKeys: "NSAppleMusicUsageDescription")),
optionalDefine("PERMISSION_SENSORS",
enabled: isEnabled("PERMISSION_SENSORS",
plistKeys: "NSMotionUsageDescription")),
optionalDefine("PERMISSION_BLUETOOTH",
enabled: isEnabled("PERMISSION_BLUETOOTH",
plistKeys: "NSBluetoothAlwaysUsageDescription",
"NSBluetoothPeripheralUsageDescription")),
optionalDefine("PERMISSION_APP_TRACKING_TRANSPARENCY",
enabled: isEnabled("PERMISSION_APP_TRACKING_TRANSPARENCY",
plistKeys: "NSUserTrackingUsageDescription")),
optionalDefine("PERMISSION_CRITICAL_ALERTS",
enabled: isEnabled("PERMISSION_CRITICAL_ALERTS")),
optionalDefine("PERMISSION_ASSISTANT",
enabled: isEnabled("PERMISSION_ASSISTANT",
plistKeys: "NSSiriUsageDescription")),
].compactMap { $0 }

let package = Package(
name: "permission_handler_apple",
platforms: [
.iOS("14.0"),
],
products: [
.library(name: "permission-handler-apple", targets: ["permission_handler_apple"]),
],
dependencies: [
.package(name: "FlutterFramework", path: "../FlutterFramework"),
],
targets: [
.target(
name: "permission_handler_apple",
dependencies: [
.product(name: "FlutterFramework", package: "FlutterFramework"),
],
path: "Sources/permission_handler_apple",
resources: [
.process("PrivacyInfo.xcprivacy"),
],
swiftSettings: permissionSwiftSettings
),
]
)
Loading
Loading