diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index df258816d..4c7fe1df9 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -22,7 +22,11 @@ jobs: name: App facing package # The type of runner that the job will run on - runs-on: macos-latest + # + # TODO(mvanbeusekom): Manually set to macOS 13 to support Xcode 15 and iOS 17 SDKs. + # Currently `macos-latest` is based on macOS 12 and doesn't support iOS 17 SDK. This + # should be moved back to `macos-latest` when GitHub Actions images are updated. + runs-on: macos-13 env: source-directory: ./permission_handler @@ -33,6 +37,13 @@ jobs: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v3 + # Override current Xcode version with version 15.0.1. + # + # TODO(mvanbeusekom): Remove when the macos-latest image supports version 15.0.1 + # out of the box (see https://github.com/actions/runner-images/blob/main/README.md). + - name: Select Xcode version + run: sudo xcode-select -s '/Applications/Xcode_15.0.1.app/Contents/Developer' + # Make sure JAVA version 17 is installed on build agent. - uses: actions/setup-java@v3 with: diff --git a/.github/workflows/permission_handler_apple.yaml b/.github/workflows/permission_handler_apple.yaml index 11dbaaac0..966f1c318 100644 --- a/.github/workflows/permission_handler_apple.yaml +++ b/.github/workflows/permission_handler_apple.yaml @@ -22,7 +22,11 @@ jobs: name: Apple platform package # The type of runner that the job will run on - runs-on: macos-latest + # + # TODO(mvanbeusekom): Manually set to macOS 13 to support Xcode 15 and iOS 17 SDKs. + # Currently `macos-latest` is based on macOS 12 and doesn't support iOS 17 SDK. This + # should be moved back to `macos-latest` when GitHub Actions images are updated. + runs-on: macos-13 env: source-directory: ./permission_handler_apple @@ -32,6 +36,13 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v3 + + # Override current Xcode version with version 15.0.1. + # + # TODO(mvanbeusekom): Remove when the macos-latest image supports version 15.0.1 + # out of the box (see https://github.com/actions/runner-images/blob/main/README.md). + - name: Select Xcode version + run: sudo xcode-select -s '/Applications/Xcode_15.0.1.app/Contents/Developer' # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 @@ -54,7 +65,7 @@ jobs: working-directory: ${{env.source-directory}} # Build iOS version of the example App - - name: Run Android build + - name: Run iOS build run: flutter build ios --no-codesign --release working-directory: ${{env.example-directory}} - \ No newline at end of file + diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 744950cba..6be571d12 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -3,7 +3,7 @@ ## Our Pledge In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and +contributors and maintainers pledge to participate in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and @@ -23,12 +23,12 @@ include: Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or -advances + advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment -* Publishing others' private information, such as a physical or electronic +* Publishing others' private information, such as physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a +* Other conduct that could reasonably be considered inappropriate in a professional setting ## Our Responsibilities @@ -45,8 +45,8 @@ threatening, offensive, or harmful. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of +This Code of Conduct applies both within and in public spaces +when an individual represents the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be @@ -59,10 +59,10 @@ reported by contacting the project team at [hello@baseflow.com](mailto:hello@bas complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +You can post more details of specific enforcement policies separately. Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other +Faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b06bdb26f..8b3852d9d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,49 +1,44 @@ -Contributing to the Flutter Permission handler plugin -============================================= +# Contributing to the Flutter Permission handler plugin -What you will need ------------------- +## What you will need - * A Linux, Mac OS X, or Windows machine (note: to run and compile iOS specific parts you'll need access to a Mac OS X machine); - * git (used for source version control, installation instruction can be found [here](https://git-scm.com/)); - * The Flutter SDK (installation instructions can be found [here](https://flutter.io/get-started/install/)); - * A personal GitHub account (if you don't have one, you can sign-up for free [here](https://github.com/)) +* A Linux, Mac OS X, or Windows machine (note: to run and compile iOS-specific parts you'll need access to a Mac OS X machine); +* git (used for source version control, installation instructions can be found [here](https://git-scm.com/)); +* The Flutter SDK (installation instructions can be found [here](https://flutter.io/get-started/install/)); +* A personal GitHub account (if you don't have one, you can sign up for free [here](https://github.com/)) -Setting up your development environment ---------------------------------------- +## Setting up your development environment - * Fork `https://github.com/Baseflow/flutter-permission-handler` into your own GitHub account. If you already have a fork and moving to a new computer, make sure you update you fork. - * If you haven't configured your machine with an SSH key that's known to github, then - follow [GitHub's directions](https://help.github.com/articles/generating-ssh-keys/) - to generate an SSH key. - * Clone your forked repo on your local development machine: `git clone git@github.com:/flutter-permission-handler.git` - * Change into the `flutter-permission-handler` directory: `cd flutter-permission-handler` - * Add an upstream to the original repo, so that fetch from the master repository and not your clone: `git remote add upstream git@github.com:Baseflow/flutter-permission-handler.git` +* Fork `https://github.com/Baseflow/flutter-permission-handler` into your own GitHub account. If you already have a fork and moving to a new computer, make sure you update your fork. +* If you haven't configured your machine with an SSH key that's known to GitHub, then + follow [GitHub's directions](https://help.github.com/articles/generating-ssh-keys/) + to generate an SSH key. +* Clone your forked repo on your local development machine: `git clone git@github.com:/flutter-permission-handler.git` +* Change into the `flutter-permission-handler` directory: `cd flutter-permission-handler` +* Add an upstream to the original repo, so that fetches from the master repository and not your clone: `git remote add upstream git@github.com:Baseflow/flutter-permission-handler.git` -Running the example project ---------------------------- +## Running the example project - * Change into the example directory: `cd example` - * Run the App: `flutter run` +* Change into the example directory: `cd example` +* Run the App: `flutter run` -Contribute ----------- +## Contribute We really appreciate contributions via GitHub pull requests. To contribute take the following steps: - * Make sure you are up to date with the latest code on the master: - * `git fetch upstream` - * `git checkout upstream/develop -b ` - * Apply your changes - * Verify your changes and fix potential warnings/ errors: - * Check formatting: `flutter format .` - * Run static analyses: `flutter analyze` - * Run unit-tests: `flutter test` - * Commit your changes: `git commit -am ""` - * Push changes to your fork: `git push origin ` +* Make sure you are up to date with the latest code on the master: + * `git fetch upstream` + * `git checkout upstream/develop -b ` +* Apply your changes +* Verify your changes and fix potential warnings/ errors: + * Check formatting: `flutter format .` + * Run static analyses: `flutter analyze` + * Run unit-tests: `flutter test` +* Commit your changes: `git commit -am ""` +* Push changes to your fork: `git push origin ` Send us your pull request: - * Go to `https://github.com/Baseflow/flutter-permission-handler` and click the "Compare & pull request" button. +* Go to `https://github.com/Baseflow/flutter-permission-handler` and click the "Compare & pull request" button. - Please make sure you solved all warnings and errors reported by the static code analyses and that you fill in the full pull request template. Failing to do so will result in us asking you to fix it. +Please make sure you solved all warnings and errors reported by the static code analyses and that you fill in the full pull request template. Failing to do so will result in us asking you to fix it. diff --git a/README.md b/README.md index 95587908a..a1e015c61 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ The Flutter permission_handler plugin is build following the federated plugin architecture. A detailed explanation of the federated plugin concept can be found in the [Flutter documentation](https://flutter.dev/docs/development/packages-and-plugins/developing-packages#federated-plugins). This means the permission_handler plugin is separated into the following packages: 1. [`permission_handler`][1]: the app facing package. This is the package users depend on to use the plugin in their project. For details on how to use the `permission_handler` plugin you can refer to its [README.md][2] file. At this moment the Android and iOS platform implementations are also part of this package. Additional platform support will be added in their own individual "platform package(s)". -2. [`permission_handler_platform_interface`][3]: this packages declares the interface which all platform packages must implement to support the app-facing package. Instructions on how to implement a platform packages can be found int the [README.md][4] of the `permission_handler_platform_interface` package. +2. [`permission_handler_platform_interface`][3]: this packages declares the interface which all platform packages must implement to support the app-facing package. Instructions on how to implement a platform packages can be found in the [README.md][4] of the `permission_handler_platform_interface` package. [1]: https://pub.dev/packages/permission_handler [2]: ./permission_handler/README.md diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 9c4f79e23..070b194c9 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -1,9 +1,32 @@ -## 11.0.1 +## 11.3.0 * Adds a new permission `Permission.backgroundRefresh` to check the background refresh permission status via: * Updates `permission_handler_apple` dependency to version 9.1.5. * Updates `permission_handler_platform_interface` dependency to version 3.11.6. +## 11.2.1 + +* Adds `PermissionGroup.photosAddOnly` to the README. + +## 11.2.0 + +* Adds the `Permission.assistant` which allows users to request permissions to access SiriKit on iOS and macOS platforms. This is a no-op on all other platforms. + +## 11.1.0 + +* Adds support for iOS 17+ [Calendar access levels](https://developer.apple.com/documentation/technotes/tn3152-migrating-to-the-latest-calendar-access-levels). +* Deprecates `Permission.calendar`. Use `Permission.calendarWriteOnly` to request a write-only access to the calendar. For full access to calendar use `Permission.calendarFullAccess`. +* For `Permission.calendarFullAccess` on iOS 17+ use `PERMISSION_EVENTS_FULL_ACCESS` in Podfile instead of `PERMISSION_EVENTS`. +* Adds web support by endorsing `permission_handler_html` as the web implementation of the permission handler. Only some permissions are supported at this time. +* Updates `permission_handler_android` dependency to version 12.0.1. +* Updates `permission_handler_apple` dependency to version 9.2.0. +* Updates `permission_handler_windows` dependency to version 0.2.0. +* Updates `permission_handler_platform_interface` dependency to version 4.0.2. + +## 11.0.1 + +* Adds extension methods to the `PermissionStatus` enum allowing developers to register callback methods, which will improve code readability. + ## 11.0.0 * **BREAKING CHANGE:** Updates `permission_handler_android` dependency to version 11.0.0. @@ -43,8 +66,8 @@ ## 10.2.1 -* Fixes missing POST_NOTIFICATIONS permission in Android example project. - +* Fix missing POST_NOTIFICATIONS permission in the Android example project. + ## 10.2.0 * Added support for the new Android 13 permissions: SCHEDULE_EXACT_ALARM, READ_MEDIA_IMAGES, READ_MEDIA_VIDEO and READ_MEDIA_AUDIO @@ -59,12 +82,12 @@ ## 10.0.1 -- Fix PermissionHandlerEnums link in the README.md +* Fix the PermissionHandlerEnums link in the README.md ## 10.0.0 -* __BREAKING CHANGE__: Updated Android `compileSdkVersion` to `33` to handle the new `POST_NOTIFICATIONS` permission. -> When updating to version 10.0.0 make sure to update the `android/app/build.gradle` file and set the `compileSdkVersion` to `33`. +* **BREAKING CHANGE**: Updated Android `compileSdkVersion` to `33` to handle the new `POST_NOTIFICATIONS` permission. + > When updating to version 10.0.0 make sure to update the `android/app/build.gradle` file and set the `compileSdkVersion` to `33`. ## 9.2.0 @@ -76,7 +99,7 @@ ## 9.0.2 -* Fixes regression when requesting 'locationAlways' permission on Andriod 9 (Pie) and earlier. +* Fixes regression when requesting 'locationAlways' permission on Android 9 (Pie) and earlier. ## 9.0.1 @@ -86,15 +109,15 @@ ## 9.0.0 * iOS: Bluetooth permission dialog now appears when requested instead of when the app is initialized. -Note: Requesting Bluetooth status will also prompt the permission dialog (see issue [#591](https://github.com/Baseflow/flutter-permission-handler/issues/591)). + Note: Requesting Bluetooth status will also prompt the permission dialog (see issue [#591](https://github.com/Baseflow/flutter-permission-handler/issues/591)). ## 8.3.0 -* Updated Android Gradle Plugin to 4.1.0 and Gradle Wrapper to 6.7 which is inline with the current Flutter stable version (Flutter 2.5.3). +* Updated Android Gradle Plugin to 4.1.0 and Gradle Wrapper to 6.7 which is in line with the current Flutter stable version (Flutter 2.5.3). ## 8.2.6 -* Fixed broken androidx migration link in the README.md. +* Fixed broken Androidx migration link in the README.md. ## 8.2.5 @@ -102,11 +125,11 @@ Note: Requesting Bluetooth status will also prompt the permission dialog (see is ## 8.2.4 -* Solved bug where output would log that there is no permission in manifest for BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE and BLUETOOTH_CONNECT on Android 11 devices and lower(see issue [#691](https://github.com/Baseflow/flutter-permission-handler/issues/691)). +* Solved bug where output would log that there is no permission in the manifest for BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, and BLUETOOTH_CONNECT on Android 11 devices and lower(see issue [#691](https://github.com/Baseflow/flutter-permission-handler/issues/691)). ## 8.2.3 -* iOS: Enhanced the `bluetooth` permission for iOS 13 and up, so the user gets prompted with the "bluetooth" permission dialog (see issue [#591](https://github.com/Baseflow/flutter-permission-handler/issues/591)). +* iOS: Enhanced the `bluetooth` permission for iOS 13 and up, so the user gets prompted with the "Bluetooth" permission dialog (see issue [#591](https://github.com/Baseflow/flutter-permission-handler/issues/591)). ## 8.2.2 @@ -115,23 +138,24 @@ Note: Requesting Bluetooth status will also prompt the permission dialog (see is ## 8.2.1 -* Resolved an issue where checking permissions on pre Android M devices always resolved to `PermissionStatus.denied` (see issue [#60](https://github.com/Baseflow/flutter-permission-plugins/issues/60)); +* Resolved an issue where checking permissions on pre-Android M devices always resolved to `PermissionStatus.denied` (see issue [#60](https://github.com/Baseflow/flutter-permission-plugins/issues/60)); * Updated the url_launcher dependency in the example App to `^6.0.12`. ## 8.2.0 -> **IMPORTANT:** when updating to version 8.2.0 make sure to also set the `compileSdkVersion` in the `app/build.gradle` file to `31`. +> **IMPORTANT:** When updating to version 8.2.0 make sure to also set the `compileSdkVersion` in the `app/build.gradle` file to `31`. -* Added support for the new Android 12 Bluetooth permissions: BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE and BLUETOOTH_CONNECT. +* Added support for the new Android 12 Bluetooth permissions: BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, and BLUETOOTH_CONNECT. * Updated Android compile and target SDK to 31 (Android 12 (S)). -* Updated Gradle and dependencies of Android project. -* Updated applicationID of example app +* Updated Gradle and dependencies of the Android project. +* Updated application of the example app ## 8.1.6 * Android: Fixed a `NullPointerException` when changing permissions in the Location Settings intent. ## 8.1.5 + * Android: Fixed deprecation warnings/errors when `compileSdkVersion` was set to 31 (Android S/12). ## 8.1.4+2 @@ -153,7 +177,7 @@ Note: Requesting Bluetooth status will also prompt the permission dialog (see is ## 8.1.2 -* Suppress deprecation warnings on iOS for code that specifically targets older iOS versions (see issue [#607](https://github.com/Baseflow/flutter-permission-handler/issues/607)). +* Suppress deprecation warnings on iOS for code that specifically targets older iOS versions (see issue [#607](https://github.com/Baseflow/flutter-permission-handler/issues/607)). ## 8.1.1 @@ -162,9 +186,9 @@ Note: Requesting Bluetooth status will also prompt the permission dialog (see is ## 8.1.0 * Added support for iOS 12+ Critical Alerts permission requesting. - * NOTE: This requires applying to Apple and receiving a special entitlement from them inorder to work. See [this article](https://medium.com/@shashidharyamsani/implementing-ios-critical-alerts-7d82b4bb5026) for an explination on how to use Critical Alerts. + * NOTE: This requires applying to Apple and receiving a special entitlement from them in order to work. See [this article](https://medium.com/@shashidharyamsani/implementing-ios-critical-alerts-7d82b4bb5026) for an explanation of how to use Critical Alerts. * Added support for Android M+ Access Notification Policy permission requesting (ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS). - * Note: This opens a general page in settings, not specific to the package. + * Note: This opens a general page in settings, not specific to the package. ## 8.0.1 @@ -181,8 +205,9 @@ Note: Requesting Bluetooth status will also prompt the permission dialog (see is ## 8.0.0 -This release contains the following **breaking changes**: -* Starting from this version the permissions on iOS are disabled by default. To enable a permission, specify the correct `GCC_PREPROCESSOR_DEFINITIONS` in the `ios/Podfile` file. For an example check out the [Podfile](permission_handler/example/ios/Podfile) of the example application. +This release contains the following **breaking changes**: + +* Starting from this version the permissions on iOS are disabled by default. To enable permission, specify the correct `GCC_PREPROCESSOR_DEFINITIONS` in the `ios/Podfile` file. For an example check out the [Podfile](permission_handler/example/ios/Podfile) of the example application. * Added support for the "AppTrackingTransparency" permission on iOS. ## 7.2.0 @@ -191,7 +216,7 @@ This release contains the following **breaking changes**: ## 7.1.1 -* Improved the example app by using the Baseflow Plugin Template and move all the functionality to the `main.dart` file. +* Improved the example app by using the Baseflow Plugin Template and moving all the functionality to the `main.dart` file. ## 7.1.0 @@ -199,29 +224,30 @@ This release contains the following **breaking changes**: ## 7.0.0 -This release contains the following **breaking changes**: +This release contains the following **breaking changes**: + * Updated compile SDK version to 30 in the build.gradle for handling the MANAGE_EXTERNAL_STORAGE permission; * Added the MANAGE_EXTERNAL_STORAGE permission for Android R and up; -* Registered listeners on the plugin level to prevent memory leaks or unwanted behaviour. +* Registered listeners on the plugin level to prevent memory leaks or unwanted behavior. ## 6.1.3 * Implement equality operator on the `Permission` class; -* Updated the README.md with instructions on enabling/ disabling the bluetooth permissions on iOS; +* Updated the README.md with instructions on enabling/ disabling the Bluetooth permissions on iOS; * Corrected some spelling mistakes in the `CHANGELOG.md`. ## 6.1.2 -* Correctly handle the ACCESS_MEDIA_LOCATION and ACCESS_ACTIVITY_RECOGNITION permissions on pre Android Q devices (permissions should be implicitly granted on pre Android Q). +* Correctly handle the ACCESS_MEDIA_LOCATION and ACCESS_ACTIVITY_RECOGNITION permissions on pre-Android Q devices (permissions should be implicitly granted on pre-Android Q). ## 6.1.1 -* Added unit-tests to guard API against breaking changes. +* Added unit tests to guard API against breaking changes. ## 6.1.0 -* Added support for bluetooth permissions; -* Workaround for ignore battery optimizations on pre-M Android devices (see PR [#376](https://github.com/Baseflow/flutter-permission-handler/pull/376)). +* Added support for Bluetooth permissions; +* Workaround for ignoring battery optimizations on pre-M Android devices (see PR [#376](https://github.com/Baseflow/flutter-permission-handler/pull/376)). ## 6.0.1+1 @@ -229,26 +255,27 @@ This release contains the following **breaking changes**: ## 6.0.1 -* Fixed deprecation warning when building Android project. +* Fixed deprecation warning when building Android projects. ## 6.0.0 This release includes the following **breaking changes**: -* Migrated to null safety + +* Migrated to null safety * Removed PermissionStatus.undetermined, PermissionStatus.denied will be used instead (see our "[Changes in 6.0.0](https://github.com/Baseflow/flutter-permission-handler/wiki/Changes-in-6.0.0)" wiki page for more details). ## 5.1.0+2 -* Solve mismatch with permission constants between Dart and Android (due to addition of permission on iOS); -* Fix compile error which occurred when on iOS the "PERMISSION_PHOTOS" macro is deactivated (meaning code dealing with the `PHPhotoLibrary` library is removed from the code base). +* Solve mismatch with permission constants between Dart and Android (due to the addition of permission on iOS); +* Fix the compile error that occurred when on iOS the "PERMISSION_PHOTOS" macro is deactivated (meaning code dealing with the `PHPhotoLibrary` library is removed from the code base). ## 5.1.0+1 -* Recreate the iOS part of the example project based on the Flutter stable channel (previous version was accidentally created with the Flutter beta channel). +* Recreate the iOS part of the example project based on the Flutter stable channel (the previous version was accidentally created with the Flutter beta channel). ## 5.1.0 -* Added support for the limited photos permission available on iOS 14 and up; +* Added support for the limited photo permission available on iOS 14 and up; * Fixed deprecated warning on iOS; * Added support for the "READ_PHONE_NUMBERS" permission on Android; * Fix a link to the contribution guide in the README.md. @@ -260,7 +287,7 @@ This release includes the following **breaking changes**: ## 5.0.1+1 * Fixes Typo -* Issue #233 - on 5.0: Solved a bug that prevented Android applications running in the background to check the permission status. +* Issue #233 * on 5.0: Solved a bug that prevented Android applications running in the background to check the permission status. ## 5.0.1 @@ -288,7 +315,7 @@ This release includes the following **breaking changes**: ## 5.0.0+hotfix.5 -* Remove use of the deprecated pre iOS 8 API causing users compile issues (see issue [#277](https://github.com/Baseflow/flutter-permission-handler/issues/277)). +* Remove the use of the deprecated pre-iOS 8 API causing users to compile issues (see issue [#277](https://github.com/Baseflow/flutter-permission-handler/issues/277)). ## 5.0.0+hotfix.4 @@ -296,7 +323,7 @@ This release includes the following **breaking changes**: ## 5.0.0+hotfix.3 -* Includes the changes of 4.4.0+hotfix.4 (which was released to be backwards compatible). +* Includes the changes of 4.4.0+hotfix.4 (which was released to be backward compatible). ## 5.0.0+hotfix.2 @@ -320,19 +347,19 @@ IGNORE THIS VERSION, it was released by accident and contains the same code as 4 ## 4.4.0+hotfix.2 -* Issue #235: Solved a bug which made it impossible to request service status on Android 7; -* Issue #237: Solved a bug which crashes the application when cancelling the "Ignore battery optimizations" request for permissions. +* Issue #235: Solved a bug that made it impossible to request service status on Android 7; +* Issue #237: Solved a bug that crashes the application when canceling the "Ignore battery optimizations" request for permissions. ## 4.4.0+hotfix.1 -* Issue #233: Solved a bug that prevented Android applications running in the background to check the permission status. +* Issue #233: Solved a bug that prevented Android applications from running in the background to check the permission status. ## 4.4.0 -* Updated plugin structure to confirm to the Flutter federated plugin architecture. This will make it easier to add new platform implementations (see: https://medium.com/flutter/how-to-write-a-flutter-web-plugin-part-2-afdddb69ece6); +* Updated plugin structure to conform to the Flutter federated plugin architecture. This will make it easier to add new platform implementations (see: https://medium.com/flutter/how-to-write-a-flutter-web-plugin-part-2-afdddb69ece6); * Android: Migrate to FlutterPlugin Android API (better support for Add-to-App); * Android: Suppress JAVA warnings which are generated to old platform code (only executes on older platforms); -* Android: Fixed issue which sometimes resulting in illegal cast exception. +* Android: Fixed issue which sometimes results in illegal cast exception. ## 4.3.0 @@ -350,14 +377,13 @@ IGNORE THIS VERSION, it was released by accident and contains the same code as 4 * Android: Fixes a bug where permissions are reported as `neverAskAgain` incorrectly after calling `requestPermissions` method. - ## 4.2.0+hotfix.1 * Android: Fixes a bug where permissions are reported as `neverAskAgain` incorrectly. ## 4.2.0 -* Android: Methods `checkPermissionStatus` and `requestPermissions` now support addition `neverAskAgain` status. +* Android: Methods `checkPermissionStatus` and `requestPermissions` now support the additional `neverAskAgain` status. ## 4.1.0 @@ -374,7 +400,7 @@ IGNORE THIS VERSION, it was released by accident and contains the same code as 4 ## 3.3.0 * Android: Add support for requesting the background location permission within the `locationAlways` group. -* Android: Update AGP, Gradle and AndroidX dependencies +* Android: Update AGP, Gradle, and AndroidX dependencies ## 3.2.2 @@ -386,7 +412,7 @@ IGNORE THIS VERSION, it was released by accident and contains the same code as 4 ## 3.2.1 -* Updated dependency on 'meta' to latest version. +* Updated dependency on 'meta' to the latest version. ## 3.2.0 @@ -401,7 +427,7 @@ IGNORE THIS VERSION, it was released by accident and contains the same code as 4 ## 3.0.2 * Fixed bug when rapidly requesting permissions (#23); -* Rename Enums.h to PermissionHandlerEnums.h to prevent conflicts with geolocator (#104); +* Rename Enums.h to PermissionHandlerEnums.h to prevent conflicts with the geolocator (#104); * Update the Android permission request code to prevent conflicts with geolocator (#111); * Update Gradle infrastructure. @@ -420,14 +446,14 @@ IGNORE THIS VERSION, it was released by accident and contains the same code as 4 ## 2.1.3 -* Fixed bug on iOS where result of the `openAppSettings` call always returned `false`; -* Upgrade Android plugin to support AndroidX and latest Gradle and Kotlin versions; +* Fixed bug on iOS where the result of the `openAppSettings` call always returned `false`; +* Upgrade the Android plugin to support AndroidX and the latest Gradle and Kotlin versions; * Added Swift version number to the Podfile of the plugin; -* Updated flutter static analyzes to conform to latest recommendations. +* Updated flutter static analyses to conform to the latest recommendations. ## 2.1.2 -* Make sure the Permission Handler compiles with latest iOS SDK +* Make sure the Permission Handler compiles with the latest iOS SDK ## 2.1.1 @@ -446,12 +472,12 @@ IGNORE THIS VERSION, it was released by accident and contains the same code as 4 ## 2.0.0 -* Make methods non static so users can create an instance or override +* Make methods non-static so users can create an instance or override ## 1.0.1 * Converted the plugin into a library so that developers don't have to import additional files; -* Updated the README.md to fix example code. +* Updated the README.md to fix the example code. ## 1.0.0 diff --git a/permission_handler/README.md b/permission_handler/README.md index 644510eea..b0beb2c24 100644 --- a/permission_handler/README.md +++ b/permission_handler/README.md @@ -1,28 +1,28 @@ [![pub package](https://img.shields.io/pub/v/permission_handler.svg)](https://pub.dartlang.org/packages/permission_handler) [![Build status](https://github.com/Baseflow/flutter-permission-handler/actions/workflows/permission_handler.yaml/badge.svg?branch=master)](https://github.com/Baseflow/flutter-permission-handler/actions/workflows/permission_handler.yaml) [![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://github.com/tenhobi/effective_dart) [![codecov](https://codecov.io/gh/Baseflow/flutter-permission-handler/branch/master/graph/badge.svg)](https://codecov.io/gh/Baseflow/flutter-permission-handler) On most operating systems, permissions aren't just granted to apps at install time. -Rather, developers have to ask the user for permissions while the app is running. +Rather, developers have to ask the user for permission while the app is running. This plugin provides a cross-platform (iOS, Android) API to request permissions and check their status. -You can also open the device's app settings so users can grant a permission. -On Android, you can show a rationale for requesting a permission. +You can also open the device's app settings so users can grant permission. +On Android, you can show a rationale for requesting permission. See the [FAQ](#faq) section for more information on common questions when using the permission_handler plugin. ## Setup -While the permissions are being requested during runtime, you'll still need to tell the OS which permissions your app might potentially use. That requires adding permission configuration to Android- and iOS-specific files. +While the permissions are being requested during runtime, you'll still need to tell the OS which permissions your app might potentially use. That requires adding permission configuration to Android* and iOS-specific files.
Android -**Upgrade pre 1.12 Android projects** +**Upgrade pre-1.12 Android projects** -Since version 4.4.0 this plugin is implemented using the Flutter 1.12 Android plugin APIs. Unfortunately this means App developers also need to migrate their Apps to support the new Android infrastructure. You can do so by following the [Upgrading pre 1.12 Android projects](https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects) migration guide. Failing to do so might result in unexpected behaviour. Most common known error is the permission_handler not returning after calling the `.request()` method on a permission. +Since version 4.4.0 this plugin is implemented using the Flutter 1.12 Android plugin APIs. Unfortunately, this means App developers also need to migrate their Apps to support the new Android infrastructure. You can do so by following the [Upgrading pre 1.12 Android projects](https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects) migration guide. Failing to do so might result in unexpected behavior. The most common known error is the permission_handler not returning after calling the `.request()` method on permission. **AndroidX** -As of version 3.1.0 the permission_handler plugin switched to the AndroidX version of the Android Support Libraries. This means you need to make sure your Android project is also upgraded to support AndroidX. Detailed instructions can be found [here](https://flutter.dev/docs/development/packages-and-plugins/androidx-compatibility). +As of version 3.1.0, the permission_handler plugin switched to the AndroidX version of the Android Support Libraries. This means you need to make sure your Android project is also upgraded to support AndroidX. Detailed instructions can be found [here](https://flutter.dev/docs/development/packages-and-plugins/androidx-compatibility). The TL;DR version is: @@ -45,7 +45,7 @@ android { 3. Make sure you replace all the `android.` dependencies to their AndroidX counterparts (a full list can be found [here](https://developer.android.com/jetpack/androidx/migrate)). Add permissions to your `AndroidManifest.xml` file. -There's a `debug`, `main` and `profile` version which are chosen depending on how you start your app. +There are `debug`, `main`, and `profile` versions which are chosen depending on how you start your app. In general, it's sufficient to add permission only to the `main` version. [Here](https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler/example/android/app/src/main/AndroidManifest.xml)'s an example `AndroidManifest.xml` with a complete list of all possible permissions. @@ -57,11 +57,11 @@ In general, it's sufficient to add permission only to the `main` version. 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. -> IMPORTANT: ~~You will have to include all permission options when you want to submit your App.~~ This is because the `permission_handler` plugin touches all different SDKs and because the static code analyser (run by Apple upon App submission) detects this and will assert if it cannot find a matching permission option in the `Info.plist`. More information about this can be found [here](https://github.com/Baseflow/flutter-permission-handler/issues/26). +> IMPORTANT: ~~You will have to include all permission options when you want to submit your App.~~ This is because the `permission_handler` plugin touches all different SDKs and because the static code analyzer (run by Apple upon App submission) detects this and will assert if it cannot find a matching permission option in the `Info.plist`. More information about this can be found [here](https://github.com/Baseflow/flutter-permission-handler/issues/26). The permission_handler plugin use [macros](https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h) to control whether a permission is enabled. -You must list permission you want to use in your application: +You must list the permission you want to use in your application: 1. Add the following to your `Podfile` file: @@ -69,70 +69,76 @@ You must list permission you want to use in your application: post_install do |installer| installer.pods_project.targets.each do |target| ... # Here are some configurations automatically generated by flutter - + # Start of the permission_handler configuration target.build_configurations.each do |config| - + # You can enable the permissions needed here. For example to enable camera # permission, just remove the `#` character in front so it looks like this: # # ## dart: PermissionGroup.camera # 'PERMISSION_CAMERA=1' # - # Preprocessor definitions can be found in: https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h + # Preprocessor definitions can be found at: https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', - - ## dart: PermissionGroup.calendar + + ## dart: [PermissionGroup.calendarWriteOnly, PermissionGroup.calendar (iOS 16 and below)] # 'PERMISSION_EVENTS=1', + + ## dart: [PermissionGroup.calendarFullAccess, PermissionGroup.calendar (iOS 17 and above)] + # 'PERMISSION_EVENTS_FULL_ACCESS=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.photosAddOnly + # 'PERMISSION_PHOTOS_ADD_ONLY=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', - + # '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 of the permission_handler configuration end end ``` -2. Remove the `#` character in front of the permission you do want to use. For example if you need access to the calendar make sure the code looks like this: +2. Remove the `#` character in front of the permission you want to use. For example, if you need access to the calendar make sure the code looks like this: ```ruby ## dart: PermissionGroup.calendar @@ -143,22 +149,22 @@ You must list permission you want to use in your application: e.g. when you don't need camera permission, just delete 'NSCameraUsageDescription' The following lists the relationship between `Permission` and `The key of Info.plist`: - | Permission | Info.plist | Macro | - | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------ | - | PermissionGroup.calendar | NSCalendarsUsageDescription | PERMISSION_EVENTS | - | PermissionGroup.reminders | NSRemindersUsageDescription | PERMISSION_REMINDERS | - | PermissionGroup.contacts | NSContactsUsageDescription | PERMISSION_CONTACTS | - | PermissionGroup.camera | NSCameraUsageDescription | PERMISSION_CAMERA | - | PermissionGroup.microphone | NSMicrophoneUsageDescription | PERMISSION_MICROPHONE | - | PermissionGroup.speech | NSSpeechRecognitionUsageDescription | PERMISSION_SPEECH_RECOGNIZER | - | PermissionGroup.photos | NSPhotoLibraryUsageDescription | PERMISSION_PHOTOS | - | PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse | NSLocationUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, NSLocationWhenInUseUsageDescription | PERMISSION_LOCATION | - | PermissionGroup.notification | PermissionGroupNotification | PERMISSION_NOTIFICATIONS | - | PermissionGroup.mediaLibrary | NSAppleMusicUsageDescription, kTCCServiceMediaLibrary | PERMISSION_MEDIA_LIBRARY | - | PermissionGroup.sensors | NSMotionUsageDescription | PERMISSION_SENSORS | - | PermissionGroup.bluetooth | NSBluetoothAlwaysUsageDescription, NSBluetoothPeripheralUsageDescription | PERMISSION_BLUETOOTH | - | PermissionGroup.appTrackingTransparency | NSUserTrackingUsageDescription | PERMISSION_APP_TRACKING_TRANSPARENCY | - | PermissionGroup.criticalAlerts | PermissionGroupCriticalAlerts | PERMISSION_CRITICAL_ALERTS | +| Permission | Info.plist | Macro | +|-------------------------------------------------------------------------------------------| ------------------------------------------------------------------------------------------------------------- | ------------------------------------ | +| PermissionGroup.calendar (< iOS 17) | NSCalendarsUsageDescription | PERMISSION_EVENTS | +| PermissionGroup.calendarWriteOnly (iOS 17+) | NSCalendarsWriteOnlyAccessUsageDescription | PERMISSION_EVENTS | +| PermissionGroup.calendarFullAccess (iOS 17+) | NSCalendarsFullAccessUsageDescription | PERMISSION_EVENTS_FULL_ACCESS | +| PermissionGroup.reminders | NSRemindersUsageDescription | PERMISSION_REMINDERS | +| PermissionGroup.contacts | NSContactsUsageDescription | PERMISSION_CONTACTS | +| PermissionGroup.camera | NSCameraUsageDescription | PERMISSION_CAMERA | +| PermissionGroup.microphone | NSMicrophoneUsageDescription | PERMISSION_MICROPHONE | +| PermissionGroup.speech | NSSpeechRecognitionUsageDescription | PERMISSION_SPEECH_RECOGNIZER | +| PermissionGroup.photos | NSPhotoLibraryUsageDescription | PERMISSION_PHOTOS | +| PermissionGroup.photosAddOnly | NSPhotoLibraryAddUsageDescription | PERMISSION_PHOTOS_ADD_ONLY | +| PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse | NSLocationUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, NSLocationWhenInUseUsageDescription | PERMISSION_LOCATION | +| PermissionGroup.notification | PermissionGroupNotification | PERMISSION_NOTIFICATIONS | +| PermissionGroup.mediaLibrary | NSAppleMusicUsageDescription, kTCCServiceMedia + 4. Clean & Rebuild
@@ -171,15 +177,40 @@ You can get a `Permission`'s `status`, which is either `granted`, `denied`, `res ```dart var status = await Permission.camera.status; if (status.isDenied) { - // We didn't ask for permission yet or the permission has been denied before, but not permanently. + // We haven't asked for permission yet or the permission has been denied before, but not permanently. } -// You can can also directly ask the permission about its status. +// You can also directly ask permission about its status. if (await Permission.location.isRestricted) { - // The OS restricts access, for example because of parental controls. + // The OS restricts access, for example, because of parental controls. } ``` +Can use also this style for better readability of your code when using the `Permission` class. + +```dart +await Permission.camera + .onDeniedCallback(() { + // Your code + }) + .onGrantedCallback(() { + // Your code + }) + .onPermanentlyDeniedCallback(() { + // Your code + }) + .onRestrictedCallback(() { + // Your code + }) + .onLimitedCallback(() { + // Your code + }) + .onProvisionalCallback(() { + // Your code + }) + .request(); +``` + Call `request()` on a `Permission` to request it. If it has already been granted before, nothing happens. `request()` returns the new status of the `Permission`. @@ -197,7 +228,7 @@ Map statuses = await [ print(statuses[Permission.location]); ``` -Some permissions, for example location or acceleration sensor permissions, have an associated service, which can be `enabled` or `disabled`. +Some permissions, for example, location or acceleration sensor permissions, have an associated service, which can be `enabled` or `disabled`. ```dart if (await Permission.locationWhenInUse.serviceStatus.isEnabled) { @@ -211,12 +242,12 @@ You can also open the app settings: if (await Permission.speech.isPermanentlyDenied) { // The user opted to never again see the permission request dialog for this // app. The only way to change the permission's status now is to let the - // user manually enable it in the system settings. + // user manually enables it in the system settings. openAppSettings(); } ``` -On Android, you can show a rationale for using a permission: +On Android, you can show a rationale for using permission: ```dart bool isShown = await Permission.contacts.shouldShowRequestRationale; @@ -224,14 +255,14 @@ bool isShown = await Permission.contacts.shouldShowRequestRationale; Some permissions will not show a dialog asking the user to allow or deny the requested permission. This is because the OS setting(s) of the app are being retrieved for the corresponding permission. -The status of the setting will determine whether the permission is `granted` or `denied`. +The status of the setting will determine whether the permission is `granted` or `denied`. -The following permissions will show no dialog: +The following permissions will show no dialog: - Notification - Bluetooth -The following permissions will show no dialog, but will open the corresponding setting intent for the user to change the permission status: +The following permissions will show no dialog, but will open the corresponding setting intent for the user to change the permission status: - manageExternalStorage - systemAlertWindow @@ -246,23 +277,42 @@ This will then bring up another permission popup asking you to `Keep Only While ### Requesting "storage" permissions always returns "denied" on Android 13+. What can I do? -On Android the `Permission.storage` permission is linked to the Android `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE` permissions. Starting from Android 10 (API 29) the `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE` permissions have been marked deprecated and have been fully removed/disabled since Android 13 (API 33). +On Android, the `Permission.storage` permission is linked to the Android `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE` permissions. Starting from Android 10 (API 29) the `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE` permissions have been marked deprecated and have been fully removed/disabled since Android 13 (API 33). -If your application needs access to media files Google recommends using the `READ_MEDIA_IMAGES`, `READ_MEDIA_VIDEOS` or `READ_MEDIA_AUDIO` permissions instead. These can be requested using the `Permission.photos`, `Permission.videos` and `Permission.audio` respectively. To request these permissions make sure the `compileSdkVersion` in the `android/app/build.gradle` file is set to `33`. +If your application needs access to media files Google recommends using the `READ_MEDIA_IMAGES`, `READ_MEDIA_VIDEO`, or `READ_MEDIA_AUDIO` permissions instead. These can be requested using the `Permission.photos`, `Permission.videos`, and `Permission.audio` respectively. To request these permissions make sure the `compileSdkVersion` in the `android/app/build.gradle` file is set to `33`. If your application needs access to Android's file system, it is possible to request the `MANAGE_EXTERNAL_STORAGE` permission (using `Permission.manageExternalStorage`). As of Android 11 (API 30), the `MANAGE_EXTERNAL_STORAGE` permission is considered a high-risk or sensitive permission. Therefore it is required to [declare the use of these permissions](https://support.google.com/googleplay/android-developer/answer/9214102) if you intend to release the application via the Google Play Store. ### Requesting `Permission.locationAlways` always returns "denied" on Android 10+ (API 29+). What can I do? -Starting with Android 10, apps are required to first obtain the permission to read the device's location in the foreground, before requesting to read the location in the background as well. When requesting for the 'location always' permission directly, or when requesting both permissions at the same time, the system will ignore the request. So, instead of calling only `Permission.location.request()`, make sure to first call either `Permission.location.request()` or `Permission.locationWhenInUse.request()`, and obtain permission to read the GPS. Once you obtain this permission, you can call `Permission.locationAlways.request()`. This will present the user with the option to update the settings so the location can always be read in the background. For more information, visit the [Android documentation on requesting location permissions](https://developer.android.com/training/location/permissions#request-only-foreground). +Starting with Android 10, apps are required to first obtain permission to read the device's location in the foreground, before requesting to read the location in the background as well. When requesting the 'location always' permission directly, or when requesting both permissions at the same time, the system will ignore the request. So, instead of calling only `Permission.location.request()`, make sure to first call either `Permission.location.request()` or `Permission.locationWhenInUse.request()`, and obtain permission to read the GPS. Once you obtain this permission, you can call `Permission.locationAlways.request()`. This will present the user with the option to update the settings so the location can always be read in the background. For more information, visit the [Android documentation on requesting location permissions](https://developer.android.com/training/location/permissions#request-only-foreground). + +### Checking or requesting a permission terminates the application on iOS. What can I do? + +First of all make sure all that the `ios/Runner/Info.plist` file contains entries for all the permissions the application requires. If an entry is missing iOS will terminate the application as soon as the particular permission is being checked or requested. + +If the application requires access to SiriKit (by requesting the `Permission.assistant` permission), also make sure to add the `com.apple.developer.siri` entitlement to the application configuration. To do so create a file (if it doesn't exists already) called `Runner.entitlements` in the `ios/Runner` folder that is part of the project. Open the file and add the following contents: + +```xml + + + + + com.apple.developer.siri + + + +``` + +The important part here is the `key` with value `com.apple.developer.siri` and the element ``. It is possible that this file also contains other entitlements depending on the needs of the application. ## Issues -Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Baseflow/flutter-permission-handler/issues) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [hello@baseflow.com](mailto:hello@baseflow.com). +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 if you need help with integration with your app or services. You can contact us at [hello@baseflow.com](mailto:hello@baseflow.com). ## Want to contribute -If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug, or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). ## Author diff --git a/permission_handler/example/README.md b/permission_handler/example/README.md index f1bcd3433..cca8fca64 100644 --- a/permission_handler/example/README.md +++ b/permission_handler/example/README.md @@ -11,6 +11,6 @@ A few resources to get you started if this is your first Flutter project: - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) -For help getting started with Flutter, view our -[online documentation](https://flutter.io/docs), which offers tutorials, +For help getting started with Flutter, view our +[online documentation](https://flutter.io/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference. diff --git a/permission_handler/example/ios/Podfile b/permission_handler/example/ios/Podfile index e935a0078..0eef7cfb8 100644 --- a/permission_handler/example/ios/Podfile +++ b/permission_handler/example/ios/Podfile @@ -45,8 +45,11 @@ post_install do |installer| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', - ## dart: PermissionGroup.calendar + ## dart: [PermissionGroup.calendarWriteOnly, PermissionGroup.calendar (until iOS 16)] 'PERMISSION_EVENTS=1', + + ## dart: [PermissionGroup.calendarFullAccess, PermissionGroup.calendar (from iOS 17)] + 'PERMISSION_EVENTS_FULL_ACCESS=1', ## dart: PermissionGroup.reminders 'PERMISSION_REMINDERS=1', @@ -68,7 +71,7 @@ post_install do |installer| ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse] 'PERMISSION_LOCATION=1', - + ## dart: PermissionGroup.notification 'PERMISSION_NOTIFICATIONS=1', @@ -86,6 +89,9 @@ post_install do |installer| ## dart: PermissionGroup.criticalAlerts 'PERMISSION_CRITICAL_ALERTS=1', + + ## dart: PermissionGroup.assistant + 'PERMISSION_ASSISTANT=1', ] end diff --git a/permission_handler/example/ios/Runner.xcodeproj/project.pbxproj b/permission_handler/example/ios/Runner.xcodeproj/project.pbxproj index 04a88e7a7..5b918732b 100644 --- a/permission_handler/example/ios/Runner.xcodeproj/project.pbxproj +++ b/permission_handler/example/ios/Runner.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ C446183715B92022DDB68882 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CEA40B36DE135D81D16B7399 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; DA7CB50DE8057A7A8D126AC9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + F6BD02752B56D87600C59EAA /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -112,6 +113,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + F6BD02752B56D87600C59EAA /* RunnerDebug.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -494,6 +496,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; diff --git a/permission_handler/example/ios/Runner/Info.plist b/permission_handler/example/ios/Runner/Info.plist index f8a036875..e31eecab1 100644 --- a/permission_handler/example/ios/Runner/Info.plist +++ b/permission_handler/example/ios/Runner/Info.plist @@ -61,6 +61,8 @@ NSCalendarsUsageDescription Calendars + NSCalendarsFullAccessUsageDescription + Calendar full access NSCameraUsageDescription @@ -99,9 +101,14 @@ NSUserTrackingUsageDescription appTrackingTransparency - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - + + + NSSiriUsageDescription + The example app would like access to Siri Kit to demonstrate requesting authorization. + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + diff --git a/permission_handler/example/ios/Runner/RunnerDebug.entitlements b/permission_handler/example/ios/Runner/RunnerDebug.entitlements new file mode 100644 index 000000000..21d95c45f --- /dev/null +++ b/permission_handler/example/ios/Runner/RunnerDebug.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.developer.siri + + + diff --git a/permission_handler/example/lib/main.dart b/permission_handler/example/lib/main.dart index 9648d4cc6..b1615f332 100644 --- a/permission_handler/example/lib/main.dart +++ b/permission_handler/example/lib/main.dart @@ -63,7 +63,8 @@ class _PermissionHandlerWidgetState extends State { permission != Permission.reminders && permission != Permission.bluetooth && permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts; + permission != Permission.criticalAlerts && + permission != Permission.assistant; } }) .map((permission) => PermissionWidget(permission)) diff --git a/permission_handler/example/pubspec.yaml b/permission_handler/example/pubspec.yaml index 122c6124d..f72dbeae5 100644 --- a/permission_handler/example/pubspec.yaml +++ b/permission_handler/example/pubspec.yaml @@ -29,4 +29,3 @@ flutter: assets: - res/images/baseflow_logo_def_light-02.png - res/images/poweredByBaseflowLogoLight@3x.png - diff --git a/permission_handler/lib/permission_handler.dart b/permission_handler/lib/permission_handler.dart index 1ba73aae7..31db1936e 100644 --- a/permission_handler/lib/permission_handler.dart +++ b/permission_handler/lib/permission_handler.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/foundation.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; @@ -21,6 +23,60 @@ Future openAppSettings() => _handler.openAppSettings(); /// Actions that can be executed on a permission. extension PermissionActions on Permission { + /// Callback for when permission is denied. + static FutureOr? Function()? _onDenied; + + /// Callback for when permission is granted. + static FutureOr? Function()? _onGranted; + + /// Callback for when permission is permanently denied. + static FutureOr? Function()? _onPermanentlyDenied; + + /// Callback for when permission is restricted. + static FutureOr? Function()? _onRestricted; + + /// Callback for when permission is limited. + static FutureOr? Function()? _onLimited; + + /// Callback for when permission is Provisional. + static FutureOr? Function()? _onProvisional; + + /// Method to set a callback for when permission is denied. + Permission onDeniedCallback(FutureOr? Function()? callback) { + _onDenied = callback; + return this; + } + + /// Method to set a callback for when permission is granted. + Permission onGrantedCallback(FutureOr? Function()? callback) { + _onGranted = callback; + return this; + } + + /// Method to set a callback for when permission is permanently denied. + Permission onPermanentlyDeniedCallback(FutureOr? Function()? callback) { + _onPermanentlyDenied = callback; + return this; + } + + /// Method to set a callback for when permission is restricted. + Permission onRestrictedCallback(FutureOr? Function()? callback) { + _onRestricted = callback; + return this; + } + + /// Method to set a callback for when permission is limited. + Permission onLimitedCallback(FutureOr? Function()? callback) { + _onLimited = callback; + return this; + } + + /// Method to set a callback for when permission is provisional. + Permission onProvisionalCallback(FutureOr? Function()? callback) { + _onProvisional = callback; + return this; + } + /// Checks the current status of the given [Permission]. /// /// Notes about specific permissions: @@ -49,8 +105,24 @@ extension PermissionActions on Permission { /// /// Returns the new [PermissionStatus]. Future request() async { - final permissionStatus = (await [this].request())[this]; - return permissionStatus ?? PermissionStatus.denied; + final permissionStatus = + (await [this].request())[this] ?? PermissionStatus.denied; + + if (permissionStatus.isDenied) { + _onDenied?.call(); + } else if (permissionStatus.isGranted) { + _onGranted?.call(); + } else if (permissionStatus.isPermanentlyDenied) { + _onPermanentlyDenied?.call(); + } else if (permissionStatus.isRestricted) { + _onRestricted?.call(); + } else if (permissionStatus.isLimited) { + _onLimited?.call(); + } else if (permissionStatus.isProvisional) { + _onProvisional?.call(); + } + + return permissionStatus; } } diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 72c447170..c6be8ee07 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -2,7 +2,8 @@ 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: 11.0.1 +version: 11.3.0 + environment: sdk: ">=2.15.0 <4.0.0" @@ -15,6 +16,8 @@ flutter: default_package: permission_handler_android ios: default_package: permission_handler_apple + web: + default_package: permission_handler_html windows: default_package: permission_handler_windows @@ -22,10 +25,11 @@ dependencies: flutter: sdk: flutter meta: ^1.7.0 - permission_handler_android: ^11.0.0 - permission_handler_apple: ^9.1.5 - permission_handler_windows: ^0.1.3 - permission_handler_platform_interface: ^3.11.6 + permission_handler_android: ^12.0.3 + permission_handler_apple: ^9.4.0 + permission_handler_html: ^0.1.1 + permission_handler_windows: ^0.2.1 + permission_handler_platform_interface: ^4.2.0 dev_dependencies: flutter_lints: ^1.0.4 diff --git a/permission_handler/test/permission_handler_test.dart b/permission_handler/test/permission_handler_test.dart index e8efa88dc..ae666e9a2 100644 --- a/permission_handler/test/permission_handler_test.dart +++ b/permission_handler/test/permission_handler_test.dart @@ -17,7 +17,7 @@ void main() { }); test('PermissionActions on Permission: get status', () async { - final permissionStatus = await Permission.calendar.status; + final permissionStatus = await Permission.contacts.status; expect(permissionStatus, PermissionStatus.granted); }); @@ -29,50 +29,50 @@ void main() { final mockPermissionHandlerPlatform = PermissionHandlerPlatform.instance; when(mockPermissionHandlerPlatform - .shouldShowRequestPermissionRationale(Permission.calendar)) + .shouldShowRequestPermissionRationale(Permission.contacts)) .thenAnswer((_) => Future.value(true)); - await Permission.calendar.shouldShowRequestRationale; + await Permission.contacts.shouldShowRequestRationale; verify(mockPermissionHandlerPlatform - .shouldShowRequestPermissionRationale(Permission.calendar)) + .shouldShowRequestPermissionRationale(Permission.contacts)) .called(1); }); test('PermissionActions on Permission: request()', () async { - final permissionRequest = Permission.calendar.request(); + final permissionRequest = Permission.contacts.request(); expect(permissionRequest, isA>()); }); test('PermissionCheckShortcuts on Permission: get isGranted', () async { - final isGranted = await Permission.calendar.isGranted; + final isGranted = await Permission.contacts.isGranted; expect(isGranted, true); }); test('PermissionCheckShortcuts on Permission: get isDenied', () async { - final isDenied = await Permission.calendar.isDenied; + final isDenied = await Permission.contacts.isDenied; expect(isDenied, false); }); test('PermissionCheckShortcuts on Permission: get isRestricted', () async { - final isRestricted = await Permission.calendar.isRestricted; + final isRestricted = await Permission.contacts.isRestricted; expect(isRestricted, false); }); test('PermissionCheckShortcuts on Permission: get isLimited', () async { - final isLimited = await Permission.calendar.isLimited; + final isLimited = await Permission.contacts.isLimited; expect(isLimited, false); }); test('PermissionCheckShortcuts on Permission: get isPermanentlyDenied', () async { - final isPermanentlyDenied = await Permission.calendar.isPermanentlyDenied; + final isPermanentlyDenied = await Permission.contacts.isPermanentlyDenied; expect(isPermanentlyDenied, false); }); test('PermissionCheckShortcuts on Permission: get isProvisional', () async { - final isProvisional = await Permission.calendar.isProvisional; + final isProvisional = await Permission.contacts.isProvisional; expect(isProvisional, false); }); @@ -94,6 +94,71 @@ void main() { expect(permissionMap, isA>()); }); + + test('onDeniedCallback sets onDenied', () async { + bool callbackCalled = false; + callback() => callbackCalled = true; + await Permission.location.onDeniedCallback(callback).request(); + expect(callbackCalled, isTrue); + }); + + test('onGrantedCallback sets onGranted', () async { + bool callbackCalled = false; + callback() => callbackCalled = true; + await Permission.location.onGrantedCallback(callback).request(); + expect(callbackCalled, isFalse); + }); + + test('onPermanentlyDeniedCallback sets onPermanentlyDenied', () async { + bool callbackCalled = false; + callback() => callbackCalled = true; + await Permission.location.onPermanentlyDeniedCallback(callback).request(); + expect(callbackCalled, isFalse); + }); + + test('onRestrictedCallback sets onRestricted', () async { + bool callbackCalled = false; + callback() => callbackCalled = true; + await Permission.location.onRestrictedCallback(callback).request(); + expect(callbackCalled, isFalse); + }); + + test('onLimitedCallback sets onLimited', () async { + bool callbackCalled = false; + callback() => callbackCalled = true; + await Permission.location.onLimitedCallback(callback).request(); + expect(callbackCalled, isFalse); + }); + + test('onProvisionalCallback sets onProvisional', () async { + bool callbackCalled = false; + callback() => callbackCalled = true; + await Permission.location.onProvisionalCallback(callback).request(); + expect(callbackCalled, isFalse); + }); + + test('onGrantedCallback sets onGranted', () async { + bool callbackCalled = false; + callback() => callbackCalled = true; + await Permission.location.onGrantedCallback(callback).request(); + expect(callbackCalled, isFalse); + }); + + test('ask calls the appropriate callback', () async { + List callbackCalled = []; + + await Permission.camera + .onDeniedCallback(() => callbackCalled.add('Denied')) + .onGrantedCallback(() => callbackCalled.add('Granted')) + .onPermanentlyDeniedCallback( + () => callbackCalled.add('PermanentlyDenied')) + .onRestrictedCallback(() => callbackCalled.add('Restricted')) + .onLimitedCallback(() => callbackCalled.add('Limited')) + .onProvisionalCallback(() => callbackCalled.add('Provisional')) + .request(); + + expect(callbackCalled, ['Denied']); + }); }); } diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index ee80b7085..7b6e64b00 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,3 +1,30 @@ +## 12.0.4 + +* Returns `granted` on permission `Permission.scheduleExactAlarm` for devices running lower than Android S (API 31), before this change the default return was `denied`. +* Updates `minSdkVersion` version to `flutter.minSdkVersion`. + +## 12.0.3 + +* Updates the dependency on `permission_handler_platform_interface` to version 4.1.0 (SiriKit support is only available for iOS or macOS). + +## 12.0.2 + +* Fixes bug where Android activity is leaked when embedded in native Android application. + +## 12.0.1 + +* Fixes a bug where the `ignoreBatteryOptimizations` permission didn't report the correct status when the permission is requested and granted. + +## 12.0.0 + +* **BREAKING CHANGES:** + * Adds `Permission.calendarWriteOnly`. + * Removes `Permission.calendarReadOnly`. + +## 11.1.0 + +* Implements the `Permission.calendarReadOnly` and `PermissionCalendarFullAccess` permissions. + ## 11.0.5 * Removes the obsolete `updatePermissionShouldShowStatus` method from the Java code base. @@ -31,12 +58,12 @@ ## 10.3.5 * Fixes a bug where `Permission.ScheduleExactAlarm` was not opening the settings -screen. + screen. ## 10.3.4 * Fixes a bug where the permission status would return 'permanently denied' -instead of 'denied' when the user would dismiss the permission dialog. + instead of 'denied' when the user dismisses the permission dialog. ## 10.3.3 @@ -48,7 +75,7 @@ instead of 'denied' when the user would dismiss the permission dialog. ## 10.3.1 -* Fixes `java.lang.IllegalStateException: Reply already submitted` when checking status of Bluetooth service. +* Fixes `java.lang.IllegalStateException: Reply already submitted` when checking the status of Bluetooth service. ## 10.3.0 @@ -56,7 +83,7 @@ instead of 'denied' when the user would dismiss the permission dialog. ## 10.2.3 -* Fixes missing POST_NOTIFICATIONS permission in Android example project. +* Fix missing POST_NOTIFICATIONS permission in the Android example project. ## 10.2.2 @@ -76,8 +103,8 @@ instead of 'denied' when the user would dismiss the permission dialog. ## 10.0.0 - * __BREAKING CHANGE__: Updates Android `compileSdkVersion` to `33` to handle the new `POST_NOTIFICATIONS` permission. - > When updating to version 10.0.0 make sure to update the `android/app/build.gradle` file and set the `compileSdkVersion` to `33`. +* **BREAKING CHANGE**: Updates Android `compileSdkVersion` to `33` to handle the new `POST_NOTIFICATIONS` permission. + > When updating to version 10.0.0 make sure to update the `android/app/build.gradle` file and set the `compileSdkVersion` to `33`. ## 9.0.2+1 diff --git a/permission_handler_android/README.md b/permission_handler_android/README.md index e7336e92e..41c8fd848 100644 --- a/permission_handler_android/README.md +++ b/permission_handler_android/README.md @@ -12,12 +12,12 @@ More detailed instructions on using the API can be found in the [README.md](../p ## 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 . +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 . ## Want to contribute -If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug, or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). ## Author -This permission_handler plugin for Flutter is developed by [Baseflow](https://baseflow.com). \ No newline at end of file +This permission_handler plugin for Flutter is developed by [Baseflow](https://baseflow.com). diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java index e56e65bc7..841595e6a 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java @@ -17,7 +17,11 @@ final class PermissionConstants { static final int PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY = 213; static final int PERMISSION_CODE_SCHEDULE_EXACT_ALARM = 214; - //PERMISSION_GROUP + + // PERMISSION_GROUP + + // Deprecated in favor of PERMISSION_GROUP_CALENDAR_WRITE_ONLY and + // PERMISSION_GROUP_CALENDAR_FULL_ACCESS. static final int PERMISSION_GROUP_CALENDAR = 0; static final int PERMISSION_GROUP_CAMERA = 1; static final int PERMISSION_GROUP_CONTACTS = 2; @@ -54,7 +58,10 @@ final class PermissionConstants { static final int PERMISSION_GROUP_AUDIO = 33; static final int PERMISSION_GROUP_SCHEDULE_EXACT_ALARM = 34; static final int PERMISSION_GROUP_SENSORS_ALWAYS = 35; - static final int PERMISSION_GROUP_BACKGROUND_REFRESH = 36; + static final int PERMISSION_GROUP_CALENDAR_WRITE_ONLY = 36; + static final int PERMISSION_GROUP_CALENDAR_FULL_ACCESS = 37; + static final int PERMISSION_GROUP_ASSISTANT = 38; + static final int PERMISSION_GROUP_BACKGROUND_REFRESH = 39; @Retention(RetentionPolicy.SOURCE) @IntDef({ @@ -90,7 +97,10 @@ final class PermissionConstants { PERMISSION_GROUP_NEARBY_WIFI_DEVICES, PERMISSION_GROUP_VIDEOS, PERMISSION_GROUP_AUDIO, - PERMISSION_GROUP_SCHEDULE_EXACT_ALARM + PERMISSION_GROUP_SCHEDULE_EXACT_ALARM, + PERMISSION_GROUP_CALENDAR_WRITE_ONLY, + PERMISSION_GROUP_CALENDAR_FULL_ACCESS, + PERMISSION_GROUP_ASSISTANT }) @interface PermissionGroup { } diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionHandlerPlugin.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionHandlerPlugin.java index d76f37185..830ce4ec7 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionHandlerPlugin.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionHandlerPlugin.java @@ -75,7 +75,7 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { binding.getActivity() ); - this.pluginBinding = binding; + pluginBinding = binding; registerListeners(); } @@ -87,8 +87,8 @@ public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBindin @Override public void onDetachedFromActivity() { stopListeningToActivity(); - deregisterListeners(); + pluginBinding = null; } @Override diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionManager.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionManager.java index 4ec095b6f..ad420830d 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionManager.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionManager.java @@ -24,6 +24,7 @@ import androidx.core.content.ContextCompat; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -34,15 +35,12 @@ final class PermissionManager implements PluginRegistry.ActivityResultListener, PluginRegistry.RequestPermissionsResultListener { + @NonNull + private final Context context; @Nullable private RequestPermissionsSuccessCallback successCallback; - @Nullable private Activity activity; - - @NonNull - private final Context context; - /** * The number of pending permission requests. *

@@ -76,14 +74,20 @@ public boolean onActivityResult(int requestCode, int resultCode, Intent data) { return false; } - int status = resultCode == Activity.RESULT_OK - ? PermissionConstants.PERMISSION_STATUS_GRANTED - : PermissionConstants.PERMISSION_STATUS_DENIED; - - int permission; + int status, permission; if (requestCode == PermissionConstants.PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS) { permission = PermissionConstants.PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + String packageName = context.getPackageName(); + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + status = (pm != null && pm.isIgnoringBatteryOptimizations(packageName)) + ? PermissionConstants.PERMISSION_STATUS_GRANTED + : PermissionConstants.PERMISSION_STATUS_DENIED; + } else { + status = PermissionConstants.PERMISSION_STATUS_RESTRICTED; + } } else if (requestCode == PermissionConstants.PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { status = Environment.isExternalStorageManager() @@ -122,14 +126,14 @@ public boolean onActivityResult(int requestCode, int resultCode, Intent data) { return false; } } else if (requestCode == PermissionConstants.PERMISSION_CODE_SCHEDULE_EXACT_ALARM) { + permission = PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM; + AlarmManager alarmManager = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - AlarmManager alarmManager = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE); status = alarmManager.canScheduleExactAlarms() ? PermissionConstants.PERMISSION_STATUS_GRANTED : PermissionConstants.PERMISSION_STATUS_DENIED; - permission = PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM; } else { - return false; + status = PermissionConstants.PERMISSION_STATUS_GRANTED; } } else { return false; @@ -165,9 +169,38 @@ public boolean onRequestPermissionsResult( return false; } + // Calendar permissions are split between WRITE and READ in Android, and split between WRITE + // and FULL ACCESS in the plugin. We need special logic for this translation. + final List permissionList = Arrays.asList(permissions); + final int calendarWriteIndex = permissionList.indexOf(Manifest.permission.WRITE_CALENDAR); + // WRITE -> WRITE. + if (calendarWriteIndex >= 0) { + final int writeGrantResult = grantResults[calendarWriteIndex]; + final @PermissionConstants.PermissionStatus int writeStatus = + PermissionUtils.toPermissionStatus(this.activity, Manifest.permission.WRITE_CALENDAR, writeGrantResult); + requestResults.put(PermissionConstants.PERMISSION_GROUP_CALENDAR_WRITE_ONLY, writeStatus); + + // WRITE + READ -> FULL ACCESS. + final int calendarReadIndex = permissionList.indexOf(Manifest.permission.READ_CALENDAR); + if (calendarReadIndex >= 0) { + final int readGrantResult = grantResults[calendarReadIndex]; + final @PermissionConstants.PermissionStatus int readStatus = + PermissionUtils.toPermissionStatus(this.activity, Manifest.permission.READ_CALENDAR, readGrantResult); + final @PermissionConstants.PermissionStatus int fullAccessStatus = strictestStatus(writeStatus, readStatus); + requestResults.put(PermissionConstants.PERMISSION_GROUP_CALENDAR_FULL_ACCESS, fullAccessStatus); + // Support deprecated CALENDAR permission. + requestResults.put(PermissionConstants.PERMISSION_GROUP_CALENDAR, fullAccessStatus); + } + } + for (int i = 0; i < permissions.length; i++) { final String permissionName = permissions[i]; + // WRITE_CALENDAR and READ_CALENDAR permission results have already been handled. + if (permissionName.equals(Manifest.permission.WRITE_CALENDAR) || permissionName.equals(Manifest.permission.READ_CALENDAR)) { + continue; + } + @PermissionConstants.PermissionGroup final int permission = PermissionUtils.parseManifestName(permissionName); @@ -234,21 +267,6 @@ public boolean onRequestPermissionsResult( return true; } - @FunctionalInterface - interface RequestPermissionsSuccessCallback { - void onSuccess(Map results); - } - - @FunctionalInterface - interface CheckPermissionsSuccessCallback { - void onSuccess(@PermissionConstants.PermissionStatus int permissionStatus); - } - - @FunctionalInterface - interface ShouldShowRequestPermissionRationaleSuccessCallback { - void onSuccess(boolean shouldShowRequestPermissionRationale); - } - /** * Determines the permission status of the provided permission. *

@@ -378,6 +396,16 @@ void requestPermissions( launchSpecialPermission( Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM, PermissionConstants.PERMISSION_CODE_SCHEDULE_EXACT_ALARM); + } else if (permission == PermissionConstants.PERMISSION_GROUP_CALENDAR_FULL_ACCESS || permission == PermissionConstants.PERMISSION_GROUP_CALENDAR) { + // Deny CALENDAR_FULL_ACCESS permission if manifest is not listing both write- and read permissions. + final boolean isValidManifest = isValidManifestForCalendarFullAccess(); + if (isValidManifest) { + permissionsToRequest.add(Manifest.permission.WRITE_CALENDAR); + permissionsToRequest.add(Manifest.permission.READ_CALENDAR); + pendingRequestCount += 2; + } else { + requestResults.put(permission, PermissionConstants.PERMISSION_STATUS_DENIED); + } } else { permissionsToRequest.addAll(names); pendingRequestCount += names.size(); @@ -418,6 +446,13 @@ private int determinePermissionStatus(final @PermissionConstants.PermissionGroup } } + // Inspect the manifest for CALENDAR_FULL_ACCESS, as a misconfigured manifest will give a false positive if READ access has been provided. + if (permission == PermissionConstants.PERMISSION_GROUP_CALENDAR_FULL_ACCESS || permission == PermissionConstants.PERMISSION_GROUP_CALENDAR) { + boolean isValidManifest = isValidManifestForCalendarFullAccess(); + if (!isValidManifest) + return PermissionConstants.PERMISSION_STATUS_DENIED; + } + final List names = PermissionUtils.getManifestNames(context, permission); if (names == null) { @@ -451,24 +486,19 @@ private int determinePermissionStatus(final @PermissionConstants.PermissionGroup : PermissionConstants.PERMISSION_STATUS_DENIED; } - final boolean targetsMOrHigher = context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.M; + final boolean requiresExplicitPermission = context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.M; + + if (requiresExplicitPermission) { + final Set<@PermissionConstants.PermissionStatus Integer> permissionStatuses = new HashSet<>(); - Set<@PermissionConstants.PermissionStatus Integer> permissionStatuses = new HashSet<>(); - for (String name : names) { - // Only handle them if the client app actually targets a API level greater than M. - if (targetsMOrHigher) { + for (String name : names) { if (permission == PermissionConstants.PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS) { String packageName = context.getPackageName(); PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - // PowerManager.isIgnoringBatteryOptimizations has been included in Android M first. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (pm != null && pm.isIgnoringBatteryOptimizations(packageName)) { - permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_GRANTED); - } else { - permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_DENIED); - } + if (pm != null && pm.isIgnoringBatteryOptimizations(packageName)) { + permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_GRANTED); } else { - permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_RESTRICTED); + permissionStatuses.add(PermissionConstants.PERMISSION_STATUS_DENIED); } } else if (permission == PermissionConstants.PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { @@ -480,12 +510,10 @@ private int determinePermissionStatus(final @PermissionConstants.PermissionGroup : PermissionConstants.PERMISSION_STATUS_DENIED; permissionStatuses.add(status); } else if (permission == PermissionConstants.PERMISSION_GROUP_SYSTEM_ALERT_WINDOW) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - int status = Settings.canDrawOverlays(context) - ? PermissionConstants.PERMISSION_STATUS_GRANTED - : PermissionConstants.PERMISSION_STATUS_DENIED; - permissionStatuses.add(status); - } + int status = Settings.canDrawOverlays(context) + ? PermissionConstants.PERMISSION_STATUS_GRANTED + : PermissionConstants.PERMISSION_STATUS_DENIED; + permissionStatuses.add(status); } else if (permission == PermissionConstants.PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { int status = context.getPackageManager().canRequestPackageInstalls() @@ -494,13 +522,11 @@ private int determinePermissionStatus(final @PermissionConstants.PermissionGroup permissionStatuses.add(status); } } else if (permission == PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - NotificationManager notificationManager = (NotificationManager) context.getSystemService(Application.NOTIFICATION_SERVICE); - int status = notificationManager.isNotificationPolicyAccessGranted() - ? PermissionConstants.PERMISSION_STATUS_GRANTED - : PermissionConstants.PERMISSION_STATUS_DENIED; - permissionStatuses.add(status); - } + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Application.NOTIFICATION_SERVICE); + int status = notificationManager.isNotificationPolicyAccessGranted() + ? PermissionConstants.PERMISSION_STATUS_GRANTED + : PermissionConstants.PERMISSION_STATUS_DENIED; + permissionStatuses.add(status); } else if (permission == PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); @@ -518,11 +544,11 @@ private int determinePermissionStatus(final @PermissionConstants.PermissionGroup } } } + if (!permissionStatuses.isEmpty()) { + return strictestStatus(permissionStatuses); + } } - if (!permissionStatuses.isEmpty()) { - return strictestStatus(permissionStatuses); - } return PermissionConstants.PERMISSION_STATUS_GRANTED; } @@ -609,4 +635,38 @@ private int checkBluetoothPermissionStatus() { } return PermissionConstants.PERMISSION_STATUS_GRANTED; } + + /** + * Checks if the manifest contains both {@link Manifest.permission#WRITE_CALENDAR} and + * {@link Manifest.permission#READ_CALENDAR} permission declarations. + */ + private boolean isValidManifestForCalendarFullAccess() { + List names = PermissionUtils.getManifestNames(context, PermissionConstants.PERMISSION_GROUP_CALENDAR_FULL_ACCESS); + final boolean writeInManifest = names != null && names.contains(Manifest.permission.WRITE_CALENDAR); + final boolean readInManifest = names != null && names.contains(Manifest.permission.READ_CALENDAR); + final boolean validManifest = writeInManifest && readInManifest; + if (!validManifest) { + if (!writeInManifest) + Log.d(PermissionConstants.LOG_TAG, Manifest.permission.WRITE_CALENDAR + " missing in manifest"); + if (!readInManifest) + Log.d(PermissionConstants.LOG_TAG, Manifest.permission.READ_CALENDAR + " missing in manifest"); + return false; + } + return true; + } + + @FunctionalInterface + interface RequestPermissionsSuccessCallback { + void onSuccess(Map results); + } + + @FunctionalInterface + interface CheckPermissionsSuccessCallback { + void onSuccess(@PermissionConstants.PermissionStatus int permissionStatus); + } + + @FunctionalInterface + interface ShouldShowRequestPermissionRationaleSuccessCallback { + void onSuccess(boolean shouldShowRequestPermissionRationale); + } } diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index a7af15a04..888a3893e 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -27,8 +27,8 @@ public class PermissionUtils { @PermissionConstants.PermissionGroup static int parseManifestName(String permission) { switch (permission) { - case Manifest.permission.READ_CALENDAR: case Manifest.permission.WRITE_CALENDAR: + case Manifest.permission.READ_CALENDAR: return PermissionConstants.PERMISSION_GROUP_CALENDAR; case Manifest.permission.CAMERA: return PermissionConstants.PERMISSION_GROUP_CAMERA; @@ -103,11 +103,17 @@ static List getManifestNames(Context context, @PermissionConstants.Permi final ArrayList permissionNames = new ArrayList<>(); switch (permission) { + case PermissionConstants.PERMISSION_GROUP_CALENDAR_WRITE_ONLY: + if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CALENDAR)) + permissionNames.add(Manifest.permission.WRITE_CALENDAR); + break; + + case PermissionConstants.PERMISSION_GROUP_CALENDAR_FULL_ACCESS: case PermissionConstants.PERMISSION_GROUP_CALENDAR: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_CALENDAR)) - permissionNames.add(Manifest.permission.READ_CALENDAR); if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CALENDAR)) permissionNames.add(Manifest.permission.WRITE_CALENDAR); + if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_CALENDAR)) + permissionNames.add(Manifest.permission.READ_CALENDAR); break; case PermissionConstants.PERMISSION_GROUP_CAMERA: @@ -342,9 +348,8 @@ static List getManifestNames(Context context, @PermissionConstants.Permi permissionNames.add(Manifest.permission.READ_MEDIA_AUDIO); break; case PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM: - // The SCHEDULE_EXACT_ALARM permission is introduced in Android S, meaning we should - // not handle permissions on pre Android S devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && hasPermissionInManifest(context, permissionNames, Manifest.permission.SCHEDULE_EXACT_ALARM)) + // The SCHEDULE_EXACT_ALARM permission is introduced in Android S, before Android 31 it should alway return Granted + if (hasPermissionInManifest(context, permissionNames, Manifest.permission.SCHEDULE_EXACT_ALARM)) permissionNames.add(Manifest.permission.SCHEDULE_EXACT_ALARM); break; case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY: diff --git a/permission_handler_android/example/README.md b/permission_handler_android/example/README.md index f1bcd3433..cca8fca64 100644 --- a/permission_handler_android/example/README.md +++ b/permission_handler_android/example/README.md @@ -11,6 +11,6 @@ A few resources to get you started if this is your first Flutter project: - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) -For help getting started with Flutter, view our -[online documentation](https://flutter.io/docs), which offers tutorials, +For help getting started with Flutter, view our +[online documentation](https://flutter.io/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference. diff --git a/permission_handler_android/example/android/app/build.gradle b/permission_handler_android/example/android/app/build.gradle index 2c1692d79..fa79d71d6 100644 --- a/permission_handler_android/example/android/app/build.gradle +++ b/permission_handler_android/example/android/app/build.gradle @@ -31,7 +31,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.baseflow.permissionhandler.example" - minSdkVersion 16 + minSdkVersion flutter.minSdkVersion targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/permission_handler_android/example/android/app/src/main/AndroidManifest.xml b/permission_handler_android/example/android/app/src/main/AndroidManifest.xml index 7cd8b8f28..6f7c32fd4 100644 --- a/permission_handler_android/example/android/app/src/main/AndroidManifest.xml +++ b/permission_handler_android/example/android/app/src/main/AndroidManifest.xml @@ -2,6 +2,13 @@ xmlns:tools="http://schemas.android.com/tools" package="com.baseflow.permissionhandler.example"> + + + NSCalendarsUsageDescription Calendars + NSCalendarsFullAccessUsageDescription + Calendar full access NSCameraUsageDescription @@ -99,6 +101,11 @@ NSUserTrackingUsageDescription appTrackingTransparency + + + NSSiriUsageDescription + The example app would like access to Siri Kit to demonstrate requesting authorization. + CADisableMinimumFrameDurationOnPhone UIApplicationSupportsIndirectInputEvents diff --git a/permission_handler_apple/example/ios/Runner/RunnerDebug.entitlements b/permission_handler_apple/example/ios/Runner/RunnerDebug.entitlements new file mode 100644 index 000000000..21d95c45f --- /dev/null +++ b/permission_handler_apple/example/ios/Runner/RunnerDebug.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.developer.siri + + + diff --git a/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h b/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h index 69f64892e..90ef59c56 100644 --- a/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h +++ b/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h @@ -5,15 +5,15 @@ // Created by Razvan Lung on 15/02/2019. // -// ios: PermissionGroupCalendar -// Info.plist: NSCalendarsUsageDescription +// ios: [PermissionGroupCalendar, PermissionGroupCalendarWriteOnly] +// Info.plist: [NSCalendarsUsageDescription, NSCalendarWriteOnlyAccessUsageDescription] // dart: PermissionGroup.calendar #ifndef PERMISSION_EVENTS #define PERMISSION_EVENTS 0 #endif // ios: PermissionGroupReminders -// Info.plist: NSRemindersUsageDescription +// Info.plist: NSRemindersFullAccessUsageDescription // dart: PermissionGroup.reminders #ifndef PERMISSION_REMINDERS #define PERMISSION_REMINDERS 0 @@ -55,7 +55,7 @@ #endif // ios: PermissionGroupPhotosAddOnly -// Info.plist: NSPhotoLibraryUsageDescription +// Info.plist: NSPhotoLibraryAddUsageDescription // dart: PermissionGroup.photosAddOnly #ifndef PERMISSION_PHOTOS_ADD_ONLY #define PERMISSION_PHOTOS_ADD_ONLY 0 @@ -102,7 +102,6 @@ #define PERMISSION_APP_TRACKING_TRANSPARENCY 0 #endif - // ios: PermissionGroupCriticalAlerts // Info.plist: UNAuthorizationOptionCriticalAlert // dart: PermissionGroup.criticalAlerts @@ -110,6 +109,20 @@ #define PERMISSION_CRITICAL_ALERTS 0 #endif +// ios: PermissionGroupAssistant +// Info.plist: [NSSiriUsageDescription] +// dart: PermissionGroup.assistant +#ifndef PERMISSION_ASSISTANT + #define PERMISSION_ASSISTANT 0 +#endif + +// ios: PermissionGroupCalendarFullAccess +// Info.plist: [NSCalendarFullAccessUsageDescription] +// dart: PermissionGroup.calendarFullAccess +#ifndef PERMISSION_EVENTS_FULL_ACCESS + #define PERMISSION_EVENTS_FULL_ACCESS 0 +#endif + typedef NS_ENUM(int, PermissionGroup) { PermissionGroupCalendar = 0, PermissionGroupCamera, @@ -147,6 +160,9 @@ typedef NS_ENUM(int, PermissionGroup) { PermissionGroupAudio, PermissionGroupScheduleExactAlarm, PermissionGroupSensorsAlways, + PermissionGroupCalendarWriteOnly, + PermissionGroupCalendarFullAccess, + PermissionGroupAssistant, PermissionGroupBackgroundRefresh }; diff --git a/permission_handler_apple/ios/Classes/PermissionManager.h b/permission_handler_apple/ios/Classes/PermissionManager.h index 97bfdffd9..4118ff83d 100644 --- a/permission_handler_apple/ios/Classes/PermissionManager.h +++ b/permission_handler_apple/ios/Classes/PermissionManager.h @@ -26,6 +26,7 @@ #import "UnknownPermissionStrategy.h" #import "NotificationPermissionStrategy.h" #import "CriticalAlertsPermissionStrategy.h" +#import "AssistantPermissionStrategy.h" #import "PermissionHandlerEnums.h" #import "Codec.h" diff --git a/permission_handler_apple/ios/Classes/PermissionManager.m b/permission_handler_apple/ios/Classes/PermissionManager.m index 9b0b87ef6..7ce972f05 100644 --- a/permission_handler_apple/ios/Classes/PermissionManager.m +++ b/permission_handler_apple/ios/Classes/PermissionManager.m @@ -98,6 +98,8 @@ + (void)openAppSettings:(FlutterResult)result { + (id)createPermissionStrategy:(PermissionGroup)permission { switch (permission) { case PermissionGroupCalendar: + case PermissionGroupCalendarWriteOnly: + case PermissionGroupCalendarFullAccess: return [EventPermissionStrategy new]; case PermissionGroupCamera: return [AudioVideoPermissionStrategy new]; @@ -145,6 +147,8 @@ + (id)createPermissionStrategy:(PermissionGroup)permission { return [AppTrackingTransparencyPermissionStrategy new]; case PermissionGroupCriticalAlerts: return [CriticalAlertsPermissionStrategy new]; + case PermissionGroupAssistant: + return [AssistantPermissionStrategy new]; case PermissionGroupBackgroundRefresh: return [BackgroundRefreshStrategy new]; default: diff --git a/permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.h b/permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.h new file mode 100644 index 000000000..eed630b59 --- /dev/null +++ b/permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.h @@ -0,0 +1,22 @@ +// +// Created by Baptiste Dupuch(dupuchba) on 2023-09-04. +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// + +#import +#import "PermissionStrategy.h" + +#if PERMISSION_ASSISTANT + +#import + +@interface AssistantPermissionStrategy : NSObject +@end + +#else + +#import "UnknownPermissionStrategy.h" +@interface AssistantPermissionStrategy : UnknownPermissionStrategy +@end + +#endif diff --git a/permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.m b/permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.m new file mode 100644 index 000000000..a40af4290 --- /dev/null +++ b/permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.m @@ -0,0 +1,63 @@ +// +// Assistant.m +// permission_handler +// +// Created by Baptiste Dupuch (dupuchba) on Tue Sep 5 08:50:04 2023 +// + +#import "AssistantPermissionStrategy.h" + +#if PERMISSION_ASSISTANT + +@implementation AssistantPermissionStrategy + +- (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission { + if (@available(iOS 10, *)) { + INSiriAuthorizationStatus assistantPermission = [INPreferences siriAuthorizationStatus]; + return [AssistantPermissionStrategy parsePermission:assistantPermission]; + } + + return PermissionStatusGranted; +} + +- (void)checkServiceStatus:(PermissionGroup)permission completionHandler:(ServiceStatusHandler)completionHandler { + completionHandler(ServiceStatusNotApplicable); +} + +- (void)requestPermission:(PermissionGroup)permission completionHandler:(PermissionStatusHandler)completionHandler { + PermissionStatus status = [self checkPermissionStatus:permission]; + if (status != PermissionStatusDenied) { + completionHandler(status); + return; + } + + if (@available(iOS 10, *)){ + [INPreferences requestSiriAuthorization:^(INSiriAuthorizationStatus status) { + PermissionStatus permissionStatus = [AssistantPermissionStrategy parsePermission:status]; + completionHandler(permissionStatus); + }]; + } else { + completionHandler(PermissionStatusGranted); + } +} + ++ (PermissionStatus)parsePermission:(INSiriAuthorizationStatus)assistantPermission API_AVAILABLE(ios(10)){ + switch(assistantPermission){ + case INSiriAuthorizationStatusAuthorized: + return PermissionStatusGranted; + case INSiriAuthorizationStatusRestricted: + return PermissionStatusRestricted; + case INSiriAuthorizationStatusDenied: + return PermissionStatusPermanentlyDenied; + case INSiriAuthorizationStatusNotDetermined: + return PermissionStatusDenied; + } +} +@end + +#else + +@implementation AssistantPermissionStrategy +@end + +#endif diff --git a/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.h b/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.h index b5bddc8b9..3789cfb05 100644 --- a/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.h +++ b/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.h @@ -6,7 +6,7 @@ #import #import "PermissionStrategy.h" -#if PERMISSION_EVENTS | PERMISSION_REMINDERS +#if PERMISSION_EVENTS | PERMISSION_EVENTS_FULL_ACCESS | PERMISSION_REMINDERS #import diff --git a/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.m b/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.m index e4f8974e6..b41a725ff 100644 --- a/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.m +++ b/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.m @@ -5,22 +5,12 @@ #import "EventPermissionStrategy.h" -#if PERMISSION_EVENTS | PERMISSION_REMINDERS +#if PERMISSION_EVENTS | PERMISSION_EVENTS_FULL_ACCESS | PERMISSION_REMINDERS @implementation EventPermissionStrategy - (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission { - if (permission == PermissionGroupCalendar) { - #if PERMISSION_EVENTS - return [EventPermissionStrategy permissionStatus:EKEntityTypeEvent]; - #endif - } else if (permission == PermissionGroupReminders) { - #if PERMISSION_REMINDERS - return [EventPermissionStrategy permissionStatus:EKEntityTypeReminder]; - #endif - } - - return PermissionStatusDenied; + return [EventPermissionStrategy permissionStatus:permission]; } - (void)checkServiceStatus:(PermissionGroup)permission completionHandler:(ServiceStatusHandler)completionHandler { @@ -34,55 +24,124 @@ - (void)requestPermission:(PermissionGroup)permission completionHandler:(Permiss completionHandler(permissionStatus); return; } - - EKEntityType entityType; - - if (permission == PermissionGroupCalendar) { - #if PERMISSION_EVENTS - entityType = EKEntityTypeEvent; - #else + + if (permission == PermissionGroupCalendar || permission == PermissionGroupCalendarFullAccess) { + if (@available(iOS 17.0, *)) { + #if !PERMISSION_EVENTS_FULL_ACCESS + completionHandler(PermissionStatusDenied); + return; + #endif + } else { + #if !PERMISSION_EVENTS + completionHandler(PermissionStatusDenied); + return; + #endif + } + } else if (permission == PermissionGroupCalendarWriteOnly) { + #if !PERMISSION_EVENTS && !PERMISSION_EVENTS_FULL_ACCESS completionHandler(PermissionStatusDenied); return; #endif } else if (permission == PermissionGroupReminders) { - #if PERMISSION_REMINDERS - entityType = EKEntityTypeReminder; - #else + #if !PERMISSION_REMINDERS completionHandler(PermissionStatusDenied); return; #endif - } else { - completionHandler(PermissionStatusPermanentlyDenied); - return; } - + EKEventStore *eventStore = [[EKEventStore alloc] init]; - [eventStore requestAccessToEntityType:entityType completion:^(BOOL granted, NSError *error) { - if (granted) { - completionHandler(PermissionStatusGranted); - } else { - completionHandler(PermissionStatusPermanentlyDenied); + + if (@available(iOS 17.0, *)) { + if (permission == PermissionGroupCalendar || permission == PermissionGroupCalendarFullAccess) { + [eventStore requestFullAccessToEventsWithCompletion:^(BOOL granted, NSError *error) { + if (granted) { + completionHandler(PermissionStatusGranted); + } else { + completionHandler(PermissionStatusPermanentlyDenied); + } + }]; + } else if (permission == PermissionGroupCalendarWriteOnly) { + [eventStore requestWriteOnlyAccessToEventsWithCompletion:^(BOOL granted, NSError *error) { + if (granted) { + completionHandler(PermissionStatusGranted); + } else { + completionHandler(PermissionStatusPermanentlyDenied); + } + }]; + } else if (permission == PermissionGroupReminders) { + [eventStore requestFullAccessToRemindersWithCompletion:^(BOOL granted, NSError *error) { + if (granted) { + completionHandler(PermissionStatusGranted); + } else { + completionHandler(PermissionStatusPermanentlyDenied); + } + }]; } - }]; + } else { + EKEntityType entityType = [EventPermissionStrategy getEntityType:permission]; + + [eventStore requestAccessToEntityType:entityType completion:^(BOOL granted, NSError *error) { + if (granted) { + completionHandler(PermissionStatusGranted); + } else { + completionHandler(PermissionStatusPermanentlyDenied); + } + }]; + } + } -+ (PermissionStatus)permissionStatus:(EKEntityType)entityType { ++ (PermissionStatus)permissionStatus:(PermissionGroup)permission { + EKEntityType entityType = [EventPermissionStrategy getEntityType:permission]; EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:entityType]; - - switch (status) { - case EKAuthorizationStatusNotDetermined: - return PermissionStatusDenied; - case EKAuthorizationStatusRestricted: - return PermissionStatusRestricted; - case EKAuthorizationStatusDenied: - return PermissionStatusPermanentlyDenied; - case EKAuthorizationStatusAuthorized: - return PermissionStatusGranted; + + if (@available(iOS 17.0, *)) { + switch (status) { + case EKAuthorizationStatusNotDetermined: + return PermissionStatusDenied; + case EKAuthorizationStatusRestricted: + return PermissionStatusRestricted; + case EKAuthorizationStatusDenied: + return PermissionStatusPermanentlyDenied; + case EKAuthorizationStatusFullAccess: + return PermissionStatusGranted; + case EKAuthorizationStatusWriteOnly: + if (permission == PermissionGroupCalendarWriteOnly) { + return PermissionStatusGranted; + } + return PermissionStatusDenied; + } + } else { + switch (status) { + case EKAuthorizationStatusNotDetermined: + return PermissionStatusDenied; + case EKAuthorizationStatusRestricted: + return PermissionStatusRestricted; + case EKAuthorizationStatusDenied: + return PermissionStatusPermanentlyDenied; + case EKAuthorizationStatusAuthorized: + return PermissionStatusGranted; + case EKAuthorizationStatusWriteOnly: + //not available on iOS 16 and below + break; + } } + + return PermissionStatusDenied; } ++ (EKEntityType)getEntityType:(PermissionGroup)permission { + if (permission == PermissionGroupCalendar || permission == PermissionGroupCalendarFullAccess || permission == PermissionGroupCalendarWriteOnly) { + return EKEntityTypeEvent; + } else if (permission == PermissionGroupReminders) { + return EKEntityTypeReminder; + } + + return nil; +} + @end #else diff --git a/permission_handler_apple/ios/permission_handler_apple.podspec b/permission_handler_apple/ios/permission_handler_apple.podspec index 4d85bf6f8..c9708d614 100644 --- a/permission_handler_apple/ios/permission_handler_apple.podspec +++ b/permission_handler_apple/ios/permission_handler_apple.podspec @@ -3,7 +3,7 @@ # Pod::Spec.new do |s| s.name = 'permission_handler_apple' - s.version = '9.1.1' + s.version = '9.3.0' s.summary = 'Permission plugin for Flutter.' s.description = <<-DESC Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. diff --git a/permission_handler_apple/pubspec.yaml b/permission_handler_apple/pubspec.yaml index eb8390f0f..68f1cdaff 100644 --- a/permission_handler_apple/pubspec.yaml +++ b/permission_handler_apple/pubspec.yaml @@ -2,7 +2,8 @@ name: permission_handler_apple description: Permission plugin for Flutter. This plugin provides the iOS 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: 9.1.5 +version: 9.4.0 + environment: sdk: ">=2.15.0 <4.0.0" @@ -18,7 +19,7 @@ flutter: dependencies: flutter: sdk: flutter - permission_handler_platform_interface: ^3.11.6 + permission_handler_platform_interface: ^4.2.0 dev_dependencies: flutter_lints: ^1.0.4 diff --git a/permission_handler_web/.metadata b/permission_handler_html/.metadata similarity index 100% rename from permission_handler_web/.metadata rename to permission_handler_html/.metadata diff --git a/permission_handler_html/CHANGELOG.md b/permission_handler_html/CHANGELOG.md new file mode 100644 index 000000000..429e12338 --- /dev/null +++ b/permission_handler_html/CHANGELOG.md @@ -0,0 +1,17 @@ +## 0.1.1 + +* Updates the dependency on `permission_handler_platform_interface` to version 4.1.0 (SiriKit support is only available for iOS and macOS). + +## 0.1.0+2 + +* Fixes plugin initialization for non-https web app. +* Fixes location permission name. +* Improves error handling in the example app. + +## 0.1.0+1 + +* Updates `permission_handler_platform_interface` dependency to version `^4.0.2`. + +## 0.1.0 + +* Adds an initial implementation of Web support for the permission_handler plugin with camera, notifications, and microphone permissions available. diff --git a/permission_handler_web/LICENSE b/permission_handler_html/LICENSE similarity index 99% rename from permission_handler_web/LICENSE rename to permission_handler_html/LICENSE index f150c8522..bd6192f25 100644 --- a/permission_handler_web/LICENSE +++ b/permission_handler_html/LICENSE @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/permission_handler_html/README.md b/permission_handler_html/README.md new file mode 100644 index 000000000..d37eb5cea --- /dev/null +++ b/permission_handler_html/README.md @@ -0,0 +1,23 @@ +# permission_handler_html + +[![pub package](https://img.shields.io/pub/v/permission_handler_html.svg)](https://pub.dartlang.org/packages/permission_handler_html) ![Build status](https://github.com/Baseflow/flutter-permission-handler/workflows/permission_handler_html/badge.svg?branch=master) [![style: flutter lints](https://img.shields.io/badge/style-flutter_lints-40c4ff.svg)](https://pub.dev/packages/flutter_lints) + +The official web implementation of the [permission_handler](https://pub.dev/packages/permission_handler) plugin by [Baseflow](https://baseflow.com). + +## Usage + +This is the officially endorsed web implementation of the permission_handler plugin. This means it will automatically be added to your dependencies when you depend on `permission_handler` in your applications pubspec.yaml. + +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. + +## 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 . + +## Want to contribute + +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug, or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). + +## Author + +This permission_handler plugin for Flutter is developed by [Baseflow](https://baseflow.com). diff --git a/permission_handler_web/example/.gitignore b/permission_handler_html/example/.gitignore similarity index 100% rename from permission_handler_web/example/.gitignore rename to permission_handler_html/example/.gitignore diff --git a/permission_handler_web/example/.metadata b/permission_handler_html/example/.metadata similarity index 100% rename from permission_handler_web/example/.metadata rename to permission_handler_html/example/.metadata diff --git a/permission_handler_web/example/README.md b/permission_handler_html/example/README.md similarity index 100% rename from permission_handler_web/example/README.md rename to permission_handler_html/example/README.md diff --git a/permission_handler_web/example/lib/main.dart b/permission_handler_html/example/lib/main.dart similarity index 74% rename from permission_handler_web/example/lib/main.dart rename to permission_handler_html/example/lib/main.dart index ea1d95e85..cc887d50f 100644 --- a/permission_handler_web/example/lib/main.dart +++ b/permission_handler_html/example/lib/main.dart @@ -11,21 +11,17 @@ void main() { } ///Defines the main theme color -final MaterialColor themeMaterialColor = - BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1)); +final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor(const Color.fromRGBO(48, 49, 60, 1)); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { /// Create a page containing the functionality of this plugin static ExamplePage createPage() { - return ExamplePage( - Icons.location_on, (context) => PermissionHandlerWidget()); + return ExamplePage(Icons.location_on, (context) => PermissionHandlerWidget()); } @override - _PermissionHandlerWidgetState createState() => - _PermissionHandlerWidgetState(); + _PermissionHandlerWidgetState createState() => _PermissionHandlerWidgetState(); } class _PermissionHandlerWidgetState extends State { @@ -64,8 +60,7 @@ class _PermissionState extends State { _PermissionState(this._permission); final Permission _permission; - final PermissionHandlerPlatform _permissionHandler = - PermissionHandlerPlatform.instance; + final PermissionHandlerPlatform _permissionHandler = PermissionHandlerPlatform.instance; PermissionStatus _permissionStatus = PermissionStatus.denied; @override @@ -76,8 +71,9 @@ class _PermissionState extends State { } void _listenForPermissionStatus() async { - final status = await _permissionHandler.checkPermissionStatus(_permission); - setState(() => _permissionStatus = status); + await _permissionHandler + .checkPermissionStatus(_permission) + .then((status) => setState(() => _permissionStatus = status), onError: (error, st) => print('$error')); } Color getPermissionColor() { @@ -111,8 +107,7 @@ class _PermissionState extends State { color: Colors.white, ), onPressed: () { - checkServiceStatus( - context, _permission as PermissionWithService); + checkServiceStatus(context, _permission as PermissionWithService); }) : null, onTap: () { @@ -121,21 +116,19 @@ class _PermissionState extends State { ); } - void checkServiceStatus( - BuildContext context, PermissionWithService permission) async { + void checkServiceStatus(BuildContext context, PermissionWithService permission) async { ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - (await _permissionHandler.checkServiceStatus(permission)).toString()), + content: Text((await _permissionHandler.checkServiceStatus(permission)).toString()), )); } Future requestPermission(Permission permission) async { - final status = await _permissionHandler.requestPermissions([permission]); - - setState(() { - print(status); - _permissionStatus = status[permission] ?? PermissionStatus.denied; - print(_permissionStatus); - }); + await _permissionHandler.requestPermissions([permission]).then( + (status) => setState(() { + print(status); + _permissionStatus = status[permission] ?? PermissionStatus.denied; + print(_permissionStatus); + }), + onError: (error, st) => print('$error')); } } diff --git a/permission_handler_html/example/pubspec.yaml b/permission_handler_html/example/pubspec.yaml new file mode 100644 index 000000000..0e495ea80 --- /dev/null +++ b/permission_handler_html/example/pubspec.yaml @@ -0,0 +1,29 @@ +name: permission_handler_html_example +description: Demonstrates how to use the permission_handler_html plugin. + +environment: + sdk: ">=3.0.5 <4.0.0" + +dependencies: + baseflow_plugin_template: ^2.1.2 + flutter: + sdk: flutter + +dev_dependencies: + integration_test: + sdk: flutter + flutter_test: + sdk: flutter + + permission_handler_html: + # When depending on this package from a real application you should use: + # permission_handler_web: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + url_launcher: ^6.0.12 + +flutter: + uses-material-design: true diff --git a/permission_handler_web/example/web/favicon.png b/permission_handler_html/example/web/favicon.png similarity index 100% rename from permission_handler_web/example/web/favicon.png rename to permission_handler_html/example/web/favicon.png diff --git a/permission_handler_web/example/web/icons/Icon-192.png b/permission_handler_html/example/web/icons/Icon-192.png similarity index 100% rename from permission_handler_web/example/web/icons/Icon-192.png rename to permission_handler_html/example/web/icons/Icon-192.png diff --git a/permission_handler_web/example/web/icons/Icon-512.png b/permission_handler_html/example/web/icons/Icon-512.png similarity index 100% rename from permission_handler_web/example/web/icons/Icon-512.png rename to permission_handler_html/example/web/icons/Icon-512.png diff --git a/permission_handler_web/example/web/icons/Icon-maskable-192.png b/permission_handler_html/example/web/icons/Icon-maskable-192.png similarity index 100% rename from permission_handler_web/example/web/icons/Icon-maskable-192.png rename to permission_handler_html/example/web/icons/Icon-maskable-192.png diff --git a/permission_handler_web/example/web/icons/Icon-maskable-512.png b/permission_handler_html/example/web/icons/Icon-maskable-512.png similarity index 100% rename from permission_handler_web/example/web/icons/Icon-maskable-512.png rename to permission_handler_html/example/web/icons/Icon-maskable-512.png diff --git a/permission_handler_web/example/web/index.html b/permission_handler_html/example/web/index.html similarity index 100% rename from permission_handler_web/example/web/index.html rename to permission_handler_html/example/web/index.html diff --git a/permission_handler_web/example/web/manifest.json b/permission_handler_html/example/web/manifest.json similarity index 100% rename from permission_handler_web/example/web/manifest.json rename to permission_handler_html/example/web/manifest.json diff --git a/permission_handler_web/lib/permission_handler_web.dart b/permission_handler_html/lib/permission_handler_html.dart similarity index 92% rename from permission_handler_web/lib/permission_handler_web.dart rename to permission_handler_html/lib/permission_handler_html.dart index 49d0a81f2..69d259834 100644 --- a/permission_handler_web/lib/permission_handler_web.dart +++ b/permission_handler_html/lib/permission_handler_html.dart @@ -4,11 +4,12 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; -import 'package:permission_handler_web/web_delegate.dart'; + +import 'web_delegate.dart'; /// Platform implementation of the permission_handler Flutter plugin. class WebPermissionHandler extends PermissionHandlerPlatform { - static final html.MediaDevices _devices = html.window.navigator.mediaDevices!; + static final html.MediaDevices? _devices = html.window.navigator.mediaDevices; static final html.Geolocation _geolocation = html.window.navigator.geolocation; static final html.Permissions? _htmlPermissions = diff --git a/permission_handler_web/lib/web_delegate.dart b/permission_handler_html/lib/web_delegate.dart similarity index 72% rename from permission_handler_web/lib/web_delegate.dart rename to permission_handler_html/lib/web_delegate.dart index 63b6eccbd..463a3d836 100644 --- a/permission_handler_web/lib/web_delegate.dart +++ b/permission_handler_html/lib/web_delegate.dart @@ -34,7 +34,8 @@ class WebDelegate { static const _notificationsPermissionName = 'notifications'; /// The permission name to request access to the user's location. - static const _locationPermissionName = 'location'; + /// https://developer.mozilla.org/en-US/docs/Web/API/Permissions/query#name + static const _locationPermissionName = 'geolocation'; /// The status indicates that permission has been granted by the user. static const _grantedPermissionStatus = 'granted'; @@ -57,18 +58,18 @@ class WebDelegate { } } - Future _permissionStatusState( - String webPermissionName, html.Permissions? permissions) async { - final webPermissionStatus = - await permissions?.query({'name': webPermissionName}); + Future _permissionStatusState(String webPermissionName, html.Permissions? permissions) async { + final webPermissionStatus = await permissions?.query({'name': webPermissionName}); return _toPermissionStatus(webPermissionStatus?.state); } - Future _requestMicrophonePermission(html.MediaDevices devices) async { - html.MediaStream? mediaStream; + Future _requestMicrophonePermission() async { + if (_devices == null) { + return false; + } try { - mediaStream = await devices.getUserMedia({'audio': true}); + html.MediaStream mediaStream = await _devices!.getUserMedia({'audio': true}); // In browsers, calling [getUserMedia] will start the recording // automatically right after. This is undesired behavior as @@ -77,7 +78,7 @@ class WebDelegate { // The manual stop action is then needed here for to stop the automatic // recording. - if (mediaStream.active!) { + if (mediaStream.active ?? false) { final audioTracks = mediaStream.getAudioTracks(); if (audioTracks.isNotEmpty) { audioTracks[0].stop(); @@ -90,11 +91,13 @@ class WebDelegate { return true; } - Future _requestCameraPermission(html.MediaDevices devices) async { - html.MediaStream? mediaStream; + Future _requestCameraPermission() async { + if (_devices == null) { + return false; + } try { - mediaStream = await devices.getUserMedia({'video': true}); + html.MediaStream mediaStream = await _devices!.getUserMedia({'video': true}); // In browsers, calling [getUserMedia] will start the recording // automatically right after. This is undesired behavior as @@ -103,7 +106,7 @@ class WebDelegate { // The manual stop action is then needed here for to stop the automatic // recording. - if (mediaStream.active!) { + if (mediaStream.active ?? false) { final videoTracks = mediaStream.getVideoTracks(); if (videoTracks.isNotEmpty) { videoTracks[0].stop(); @@ -117,45 +120,25 @@ class WebDelegate { } Future _requestNotificationPermission() async { - bool granted = false; - html.Notification.requestPermission().then((permission) => { - if (permission == "granted") {granted = true} - }); - - return granted; + return html.Notification.requestPermission().then((permission) => permission == "granted"); } - Future _requestLocationPermission(html.Geolocation geolocation) async { + Future _requestLocationPermission() async { try { - await geolocation.getCurrentPosition(); - return true; + return await _geolocation?.getCurrentPosition().then((value) => true) ?? false; } on html.PositionError { return false; } } - Future _requestSingularPermission( - Permission permission) async { - bool permissionGranted = false; - - switch (permission) { - case Permission.microphone: - permissionGranted = await _requestMicrophonePermission(_devices!); - break; - case Permission.camera: - permissionGranted = await _requestCameraPermission(_devices!); - break; - case Permission.notification: - permissionGranted = await _requestNotificationPermission(); - break; - case Permission.location: - permissionGranted = await _requestLocationPermission(_geolocation!); - break; - default: - throw UnsupportedError( - 'The ${permission.toString()} permission is currently not supported on web.', - ); - } + Future _requestSingularPermission(Permission permission) async { + bool permissionGranted = switch (permission) { + Permission.microphone => await _requestMicrophonePermission(), + Permission.camera => await _requestCameraPermission(), + Permission.notification => await _requestNotificationPermission(), + Permission.location => await _requestLocationPermission(), + _ => throw UnsupportedError('The ${permission.toString()} permission is currently not supported on web.') + }; if (!permissionGranted) { return PermissionStatus.permanentlyDenied; @@ -167,14 +150,12 @@ class WebDelegate { /// they have not already been granted before. /// /// Returns a [Map] containing the status per requested [Permission]. - Future> requestPermissions( - List permissions) async { + Future> requestPermissions(List permissions) async { final Map permissionStatusMap = {}; for (final permission in permissions) { try { - permissionStatusMap[permission] = - await _requestSingularPermission(permission); + permissionStatusMap[permission] = await _requestSingularPermission(permission); } on UnimplementedError { rethrow; } diff --git a/permission_handler_html/pubspec.yaml b/permission_handler_html/pubspec.yaml new file mode 100644 index 000000000..7713422b4 --- /dev/null +++ b/permission_handler_html/pubspec.yaml @@ -0,0 +1,31 @@ +name: permission_handler_html +description: Permission plugin for Flutter. This plugin provides the web API to request and check permissions. +version: 0.1.1 +homepage: https://github.com/baseflow/flutter-permission-handler + +environment: + sdk: ">=3.0.5 <4.0.0" + flutter: ">=3.16.0" + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + permission_handler_platform_interface: ^4.1.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + mockito: ^5.4.2 + build_runner: ^2.1.2 + test: ^1.24.4 + +flutter: + plugin: + implements: permission_handler + platforms: + web: + pluginClass: WebPermissionHandler + fileName: permission_handler_html.dart diff --git a/permission_handler_web/test/permission_handler_web_test.dart b/permission_handler_html/test/permission_handler_web_test.dart similarity index 99% rename from permission_handler_web/test/permission_handler_web_test.dart rename to permission_handler_html/test/permission_handler_web_test.dart index 39674652e..763c05fe7 100644 --- a/permission_handler_web/test/permission_handler_web_test.dart +++ b/permission_handler_html/test/permission_handler_web_test.dart @@ -4,7 +4,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:mockito/annotations.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; -import 'package:permission_handler_web/web_delegate.dart'; +import 'package:permission_handler_html/web_delegate.dart'; import 'permission_handler_web_test.mocks.dart'; @GenerateMocks([ diff --git a/permission_handler_web/test/permission_handler_web_test.mocks.dart b/permission_handler_html/test/permission_handler_web_test.mocks.dart similarity index 100% rename from permission_handler_web/test/permission_handler_web_test.mocks.dart rename to permission_handler_html/test/permission_handler_web_test.mocks.dart diff --git a/permission_handler_platform_interface/CHANGELOG.md b/permission_handler_platform_interface/CHANGELOG.md index bd27dbe5e..e5204299f 100644 --- a/permission_handler_platform_interface/CHANGELOG.md +++ b/permission_handler_platform_interface/CHANGELOG.md @@ -1,6 +1,27 @@ -## 3.11.6 +## 4.2.0 -* Adds a new permission `Permission.backgroundRefresh` to check the background refresh permission status. +* Adds a new permission `Permission.backgroundRefresh` to check the background refresh permission status on iOS & macOS platforms. This is a no-op on all other platforms. + +## 4.1.0 + +* Adds the `Permission.assistant` which allows users to request permissions to access SiriKit on iOS and macOS platforms. This is a no-op on all other platforms. + +## 4.0.2 + +* Improved the documentation around the `PermissionStatus`, `PermissionStatusGetters` and `FuturePermissionStatusGetters`. + +## 4.0.1 + +* Updates Android documentation on how to use `permission.photo` on Android 12 (API 32) and below and Android 13 (API 33) and above. + +## 4.0.0 + +* **BREAKING CHANGE**: Replaces `Permission.calendarReadOnly` with `Permission.calendarWriteOnly`. + +## 3.12.0 + +* Adds `Permission.calendarReadOnly` and `Permission.calendarFullAccess`. +* Deprecates `Permission.calendar`. Developers should use `Permission.calendarReadOnly` and `Permission.calendarFullAccess` instead. ## 3.11.5 @@ -9,7 +30,7 @@ ## 3.11.4 * Clarifies the documentation on requesting background location permission -through `Permission.locationAlways` on Android 10+ (API 29+). + through `Permission.locationAlways` on Android 10+ (API 29+). ## 3.11.3 @@ -49,7 +70,7 @@ through `Permission.locationAlways` on Android 10+ (API 29+). ## 3.7.0 -* Adds support for the new Android 12 Bluetooth permissions: BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE and BLUETOOTH_CONNECT. +* Adds support for the new Android 12 Bluetooth permissions: BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, and BLUETOOTH_CONNECT. ## 3.6.2 @@ -62,7 +83,7 @@ through `Permission.locationAlways` on Android 10+ (API 29+). ## 3.6.0 -* Adds support for iOS Critical alerts and Android Access Notification Policy. +* Adds support for iOS Critical Alerts and Android Access Notification Policy. ## 3.5.1 @@ -82,25 +103,25 @@ through `Permission.locationAlways` on Android 10+ (API 29+). ## 3.2.0 -* Adds support for manage external storage permission available on Android 10 and up. +* Adds support for managing external storage permission available on Android 10 and up. -## 3.1.3 +## 3.1.3 -* Implements the equality operator for `Permission` class; -* Reverts the services status check for notification permission. Turns out implementation does not fit with idea's of permission_handler plugin. +* Implements the equality operator for the `Permission` class; +* Reverts the status of the services check for notification permission. Turns out the implementation does not fit with the ideas of the permission_handler plugin. ## 3.1.2 -* Allows checking serviceStatus for notification permission. +* Allows checking service status for notification permission. ## 3.1.1 * Fixes conversion issue where `PermissionStatus.denied` was not translated to the correct index. -* Adds unit-tests to guard API against breaking changes. +* Adds unit tests to guard API against breaking changes. ## 3.1.0 -* Adds support for bluetooth permissions. +* Adds support for Bluetooth permissions. ## 3.0.0+1 @@ -112,17 +133,17 @@ through `Permission.locationAlways` on Android 10+ (API 29+). ## 2.0.2 -* Adds support for the limited photos permission available on iOS 14 and up. +* Adds support for the limited photo permission available on iOS 14 and up. ## 2.0.1 * Updates to `platform_interface 1.0.2` -* Fixes bug which allows requesting is the device has phone capabilities. +* Fixes bug that allows requesting if the device has phone capabilities. ## 2.0.0 -- **BREAKING**: Creates a much more intuitive API using Dart's new extension methods ([#230](https://github.com/Baseflow/flutter-permission-handler/issues/230)). Big thank you to [@marcelgarus](https://github.com/marcelgarus) for the idea and doing all the grunt work. +* **BREAKING**: Creates a much more intuitive API using Dart's new extension methods ([#230](https://github.com/Baseflow/flutter-permission-handler/issues/230)). Big thank you to [@marcelgarus](https://github.com/marcelgarus) for the idea and for doing all the grunt work. ## 1.0.0 -- Initial open-source release. +* Initial open-source release. diff --git a/permission_handler_platform_interface/README.md b/permission_handler_platform_interface/README.md index 6726865c4..069fc2f00 100644 --- a/permission_handler_platform_interface/README.md +++ b/permission_handler_platform_interface/README.md @@ -4,25 +4,25 @@ A common platform interface for the [`permission_handler`][1] plugin. -This interface allows platform-specific implementations of the +This interface allows platform-specific implementations of the `permission_handler` plugin, as well as the plugin itself, to ensure they are supporting the same interface. # Usage -To implement a new platform-specific implementation of `permission_handler`, -extend [`PermissionHandlerPlatform`][2] with an implementation that performs -the platform-specific behavior, and when you register your plugin, set the +To implement a new platform-specific implementation of `permission_handler`, +extend [`PermissionHandlerPlatform`][2] with an implementation that performs +the platform-specific behavior, and when you register your plugin, set the default `PermissionHandlerPlatform` by calling `PermissionHandlerPlatform.instance = MyPlatformPermissionHandler()`. # Issues -Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Baseflow/flutter-permission-handler/issues) page. +Please file any issues, bugs, or feature requests as an issue on our [GitHub](https://github.com/Baseflow/flutter-permission-handler/issues) page. # Want to contribute -If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug, or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). ## Note on breaking changes @@ -30,11 +30,11 @@ Strongly prefer non-breaking changes (such as adding a method to the interface) over breaking changes for this package. See https://flutter.dev/go/platform-interface-breaking-changes for a discussion -on why a less-clean interface is preferable to a breaking change. +on why a less clean interface is preferable to a breaking change. # Author This Permission handler plugin for Flutter is developed by [Baseflow](https://baseflow.com). You can contact us at [1]: ../permission_handler -[2]: lib/permission_handler_platform_interface.dart \ No newline at end of file +[2]: lib/permission_handler_platform_interface.dart diff --git a/permission_handler_platform_interface/analysis_options.yaml b/permission_handler_platform_interface/analysis_options.yaml index 2e693b701..28560557e 100644 --- a/permission_handler_platform_interface/analysis_options.yaml +++ b/permission_handler_platform_interface/analysis_options.yaml @@ -1,11 +1,10 @@ - include: package:flutter_lints/flutter.yaml analyzer: exclude: # Ignore generated files - - '**/*.g.dart' - - 'lib/src/generated/*.dart' + - "**/*.g.dart" + - "lib/src/generated/*.dart" linter: rules: - - public_member_api_docs \ No newline at end of file + - public_member_api_docs diff --git a/permission_handler_platform_interface/lib/src/permission_status.dart b/permission_handler_platform_interface/lib/src/permission_status.dart index 82286cd0a..52db045db 100644 --- a/permission_handler_platform_interface/lib/src/permission_status.dart +++ b/permission_handler_platform_interface/lib/src/permission_status.dart @@ -2,8 +2,8 @@ part of permission_handler_platform_interface; /// Defines the state of a [Permission]. enum PermissionStatus { - /// The user denied access to the requested feature, - /// permission needs to be asked first. + /// The user denied access to the requested feature, permission needs to be + /// asked first. denied, /// The user granted access to the requested feature. @@ -12,19 +12,31 @@ enum PermissionStatus { /// The OS denied access to the requested feature. The user cannot change /// this app's status, possibly due to active restrictions such as parental /// controls being in place. + /// /// *Only supported on iOS.* restricted, - ///User has authorized this application for limited access. + /// The user has authorized this application for limited access. So far this + /// is only relevant for the Photo Library picker. + /// /// *Only supported on iOS (iOS14+).* limited, /// Permission to the requested feature is permanently denied, the permission /// dialog will not be shown when requesting this permission. The user may /// still change the permission status in the settings. + /// + /// *On Android:* + /// Android 11+ (API 30+): whether the user denied the permission for a second + /// time. + /// Below Android 11 (API 30): whether the user denied access to the requested + /// feature and selected to never again show a request. + /// + /// *On iOS:* + /// If the user has denied access to the requested feature. permanentlyDenied, - /// The application is provisionally authorized to post noninterruptive user + /// The application is provisionally authorized to post non-interruptive user /// notifications. /// /// *Only supported on iOS (iOS12+).* @@ -68,8 +80,7 @@ extension PermissionStatusValue on PermissionStatus { /// Utility getter extensions for the [PermissionStatus] type. extension PermissionStatusGetters on PermissionStatus { - /// If the user denied access to the requested feature, - /// permission needs to be asked first. + /// If the user denied access to the requested feature. bool get isDenied => this == PermissionStatus.denied; /// If the user granted access to the requested feature. @@ -78,9 +89,14 @@ extension PermissionStatusGetters on PermissionStatus { /// If the OS denied access to the requested feature. The user cannot change /// this app's status, possibly due to active restrictions such as parental /// controls being in place. + /// /// *Only supported on iOS.* bool get isRestricted => this == PermissionStatus.restricted; + /// If the permission to the requested feature is permanently denied, the + /// permission dialog will not be shown when requesting this permission. The + /// user may still change the permission status in the settings. + /// /// *On Android:* /// Android 11+ (API 30+): whether the user denied the permission for a second /// time. @@ -90,17 +106,18 @@ extension PermissionStatusGetters on PermissionStatus { /// /// *On iOS:* /// If the user has denied access to the requested feature. - /// The user may still change the permission status in the settings - /// - /// WARNING: This can only be determined AFTER requesting this permission. - /// Therefore make a `request` call first. bool get isPermanentlyDenied => this == PermissionStatus.permanentlyDenied; - /// Indicates that permission for limited use of the resource is granted. + /// If the user has authorized this application for limited access. So far + /// this is only relevant for the Photo Library picker. + /// + /// *Only supported on iOS (iOS14+).* bool get isLimited => this == PermissionStatus.limited; - /// If the application is provisionally authorized to post noninterruptive + /// If the application is provisionally authorized to post non-interruptive /// user notifications. + /// + /// *Only supported on iOS (iOS12+).* bool get isProvisional => this == PermissionStatus.provisional; } @@ -119,25 +136,30 @@ extension FuturePermissionStatusGetters on Future { /// *Only supported on iOS.* Future get isRestricted async => (await this).isRestricted; + /// If the permission to the requested feature is permanently denied, the + /// permission dialog will not be shown when requesting this permission. The + /// user may still change the permission status in the settings. + /// /// *On Android:* /// Android 11+ (API 30+): whether the user denied the permission for a second /// time. /// Below Android 11 (API 30): whether the user denied access to the requested /// feature and selected to never again show a request. - /// The user may still change the permission status in the settings. /// /// *On iOS:* /// If the user has denied access to the requested feature. - /// The user may still change the permission status in the settings Future get isPermanentlyDenied async => (await this).isPermanentlyDenied; - /// Indicates that permission for limited use of the resource is granted. + /// If the user has authorized this application for limited access. So far + /// this is only relevant for the Photo Library picker. + /// + /// *Only supported on iOS (iOS14+).* Future get isLimited async => (await this).isLimited; - /// If the application is provisionally authorized to post noninterruptive + /// If the application is provisionally authorized to post non-interruptive /// user notifications. /// - /// *Only supported on iOS.* + /// *Only supported on iOS (iOS12+).* Future get isProvisional async => (await this).isProvisional; } diff --git a/permission_handler_platform_interface/lib/src/permissions.dart b/permission_handler_platform_interface/lib/src/permissions.dart index b84beaf81..8f6a6a63b 100644 --- a/permission_handler_platform_interface/lib/src/permissions.dart +++ b/permission_handler_platform_interface/lib/src/permissions.dart @@ -29,6 +29,7 @@ class Permission { /// /// Android: Calendar /// iOS: Calendar (Events) + @Deprecated('Use [calendarWriteOnly] and [calendarFullAccess].') static const calendar = Permission._(0); /// Permission for accessing the device's camera. @@ -93,13 +94,27 @@ class Permission { /// Depending on the platform and version, the requirements are slightly /// different: /// - /// **Android:** - /// - When running on Android 13 (API 33) and above: Read image files from - /// external storage - /// - When running below Android 13 (API 33): Nothing - /// /// **iOS:** /// - When running Photos (iOS 14+ read & write access level) + /// + /// **Android:** + /// - Devices running Android 12 (API level 32) or lower: use [Permissions.storage]. + /// - Devices running Android 13 (API level 33) and above: Should use [Permissions.photos]. + /// + /// EXAMPLE: in Manifest: + /// + /// + /// + /// In Flutter to check the status: + /// + /// if (Platform.isAndroid) { + /// final androidInfo = await DeviceInfoPlugin().androidInfo; + /// if (androidInfo.version.sdkInt <= 32) { + /// use [Permissions.storage.status] + /// } else { + /// use [Permissions.photos.status] + /// } + /// } static const photos = Permission._(9); /// Permission for adding photos to the device's photo library (iOS only). @@ -296,11 +311,24 @@ class Permission { /// Android 13+ (API 33+) static const sensorsAlways = Permission._(35); + /// Permission for writing to the device's calendar. + /// + /// On iOS 16 and lower, this permission is identical to [Permission.calendarFullAccess]. + static const calendarWriteOnly = Permission._(36); + + /// Permission for reading from and writing to the device's calendar. + static const calendarFullAccess = Permission._(37); + + /// Android: Nothing + /// iOS: SiriKit + static const assistant = Permission._(38); + /// Permission for reading the current background refresh status. (iOS only) - static const backgroundRefresh = Permission._(36); + static const backgroundRefresh = Permission._(39); - /// Returns a list of all possible [Permission] values. + /// Returns a list of all possible [PermissionGroup] values. static const List values = [ + // ignore: deprecated_member_use_from_same_package calendar, camera, contacts, @@ -337,6 +365,9 @@ class Permission { audio, scheduleExactAlarm, sensorsAlways, + calendarWriteOnly, + calendarFullAccess, + assistant, backgroundRefresh, ]; @@ -377,6 +408,9 @@ class Permission { 'audio', 'scheduleExactAlarm', 'sensorsAlways', + 'calendarWriteOnly', + 'calendarFullAccess', + 'assistant', 'backgroundRefresh' ]; diff --git a/permission_handler_platform_interface/pubspec.yaml b/permission_handler_platform_interface/pubspec.yaml index 9956692dc..a638b4dfb 100644 --- a/permission_handler_platform_interface/pubspec.yaml +++ b/permission_handler_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the permission_handler plugin. homepage: https://github.com/baseflow/flutter-permission-handler/tree/master/permission_handler_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 3.11.6 +version: 4.2.0 dependencies: flutter: diff --git a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart index 1269c3a96..c03c279a1 100644 --- a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart @@ -3,8 +3,11 @@ import 'package:permission_handler_platform_interface/permission_handler_platfor import 'package:permission_handler_platform_interface/src/method_channel/method_channel_permission_handler.dart'; import 'method_channel_mock.dart'; -List get mockPermissions => List.of( - {Permission.calendar, Permission.camera, Permission.contacts}); +List get mockPermissions => List.of({ + Permission.contacts, + Permission.camera, + Permission.calendarWriteOnly, + }); Map get mockPermissionMap => {}; @@ -21,7 +24,7 @@ void main() { ); final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.calendar); + .checkPermissionStatus(Permission.contacts); expect(permissionStatus, PermissionStatus.denied); }); @@ -35,7 +38,7 @@ void main() { ); final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.calendar); + .checkPermissionStatus(Permission.contacts); expect(permissionStatus, PermissionStatus.denied); }); @@ -51,7 +54,7 @@ void main() { ); final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.calendar); + .checkPermissionStatus(Permission.contacts); expect(permissionStatus, PermissionStatus.restricted); }); @@ -67,7 +70,7 @@ void main() { ); final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.calendar); + .checkPermissionStatus(Permission.contacts); expect(permissionStatus, PermissionStatus.limited); }); @@ -83,7 +86,7 @@ void main() { ); final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.calendar); + .checkPermissionStatus(Permission.contacts); expect(permissionStatus, PermissionStatus.permanentlyDenied); }); @@ -101,7 +104,7 @@ void main() { ); final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.calendar); + .checkServiceStatus(Permission.contacts); expect(serviceStatus, ServiceStatus.disabled); }); @@ -115,7 +118,7 @@ void main() { ); final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.calendar); + .checkServiceStatus(Permission.contacts); expect(serviceStatus, ServiceStatus.enabled); }); @@ -131,7 +134,7 @@ void main() { ); final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.calendar); + .checkServiceStatus(Permission.contacts); expect(serviceStatus, ServiceStatus.notApplicable); }); diff --git a/permission_handler_platform_interface/test/src/permissions_test.dart b/permission_handler_platform_interface/test/src/permissions_test.dart index 993189e1a..0f8beb470 100644 --- a/permission_handler_platform_interface/test/src/permissions_test.dart +++ b/permission_handler_platform_interface/test/src/permissions_test.dart @@ -5,7 +5,7 @@ void main() { test('Permission has the right amount of possible Permission values', () { const values = Permission.values; - expect(values.length, 37); + expect(values.length, 40); }); test('check if byValue returns corresponding Permission value', () { diff --git a/permission_handler_web/CHANGELOG.md b/permission_handler_web/CHANGELOG.md deleted file mode 100644 index 68199689b..000000000 --- a/permission_handler_web/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -## 0.1.0 - -* Adds an initial implementation of Web support for the permission_handler plugin with camera, notifications, and microphone permissions available. diff --git a/permission_handler_web/README.md b/permission_handler_web/README.md deleted file mode 100644 index c022fe853..000000000 --- a/permission_handler_web/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# permission_handler_web - -[![pub package](https://img.shields.io/pub/v/permission_handler_web.svg)](https://pub.dartlang.org/packages/permission_handler_web) ![Build status](https://github.com/Baseflow/flutter-permission-handler/workflows/permission_handler_web/badge.svg?branch=master) [![style: flutter lints](https://img.shields.io/badge/style-flutter_lints-40c4ff.svg)](https://pub.dev/packages/flutter_lints) - -The official web implementation of the [permission_handler](https://pub.dev/packages/permission_handler) plugin by [Baseflow](https://baseflow.com). - -## Usage - -This is the officially endorsed web implementation of the permission_handler plugin. This means it will automatically be added to your dependencies when you depend on `permission_handler` in your applications pubspec.yaml. - -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. - -## 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 . - -## Want to contribute - -If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). - -## Author - -This permission_handler plugin for Flutter is developed by [Baseflow](https://baseflow.com). \ No newline at end of file diff --git a/permission_handler_web/example/pubspec.yaml b/permission_handler_web/example/pubspec.yaml deleted file mode 100644 index e63645acf..000000000 --- a/permission_handler_web/example/pubspec.yaml +++ /dev/null @@ -1,81 +0,0 @@ -name: permission_handler_web_example -description: Demonstrates how to use the permission_handler_web plugin.. - -environment: - sdk: '>=3.0.5 <4.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: - baseflow_plugin_template: ^2.1.2 - flutter: - sdk: flutter - meta: ^1.3.0 - permission_handler_platform_interface: any - -dev_dependencies: - integration_test: - sdk: flutter - flutter_test: - sdk: flutter - - permission_handler_web: - # When depending on this package from a real application you should use: - # permission_handler_web: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ - - url_launcher: ^6.0.12 - -# 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 - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # 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: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages - assets: - - res/images/baseflow_logo_def_light-02.png - - res/images/poweredByBaseflowLogoLight@3x.png - - res/images/logo.png - - res/images/poweredByBaseflow.png diff --git a/permission_handler_web/example/res/images/baseflow_logo_def_light-02.png b/permission_handler_web/example/res/images/baseflow_logo_def_light-02.png deleted file mode 100644 index 85f071f27..000000000 Binary files a/permission_handler_web/example/res/images/baseflow_logo_def_light-02.png and /dev/null differ diff --git a/permission_handler_web/example/res/images/logo.png b/permission_handler_web/example/res/images/logo.png deleted file mode 100644 index 85f071f27..000000000 Binary files a/permission_handler_web/example/res/images/logo.png and /dev/null differ diff --git a/permission_handler_web/example/res/images/poweredByBaseflow.png b/permission_handler_web/example/res/images/poweredByBaseflow.png deleted file mode 100644 index 36fbdff38..000000000 Binary files a/permission_handler_web/example/res/images/poweredByBaseflow.png and /dev/null differ diff --git a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight.png b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight.png deleted file mode 100644 index 6b9f1aae1..000000000 Binary files a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight.png and /dev/null differ diff --git a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@2x.png b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@2x.png deleted file mode 100644 index 66901d9ea..000000000 Binary files a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@2x.png and /dev/null differ diff --git a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@3x.png b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@3x.png deleted file mode 100644 index 36fbdff38..000000000 Binary files a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@3x.png and /dev/null differ diff --git a/permission_handler_web/pubspec.yaml b/permission_handler_web/pubspec.yaml deleted file mode 100644 index 40159b01c..000000000 --- a/permission_handler_web/pubspec.yaml +++ /dev/null @@ -1,36 +0,0 @@ -name: permission_handler_web -description: A new Flutter package project. -version: 0.0.1 -homepage: - -environment: - sdk: '>=3.0.5 <4.0.0' - flutter: ">=3.3.0" - -dependencies: - flutter: - sdk: flutter - flutter_web_plugins: - sdk: flutter - permission_handler_platform_interface: ^3.7.0 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^2.0.0 - mockito: ^5.4.2 - build_runner: ^2.1.2 - test: ^1.24.4 - -# 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: - - plugin: - implements: permission_handler - platforms: - web: - pluginClass: WebPermissionHandler - fileName: permission_handler_web.dart diff --git a/permission_handler_windows/CHANGELOG.md b/permission_handler_windows/CHANGELOG.md index 2be51cf66..91c2f5049 100644 --- a/permission_handler_windows/CHANGELOG.md +++ b/permission_handler_windows/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.2.1 + +* Updates the dependency on `permission_handler_platform_interface` to version 4.1.0 (SiriKit support is only available for iOS and macOS). + +## 0.2.0 + +* Implements the `Permission.calendarWriteOnly` and `Permission.calendarFullAccess` permissions. +* Bumps `permission_handler_platform_interface` to version `4.0.0`. + ## 0.1.3 * Adds the new Android 13 permission "BODY_SENSORS_BACKGROUND" to PermissionHandlerEnums.h. diff --git a/permission_handler_windows/example/README.md b/permission_handler_windows/example/README.md index f1bcd3433..cca8fca64 100644 --- a/permission_handler_windows/example/README.md +++ b/permission_handler_windows/example/README.md @@ -11,6 +11,6 @@ A few resources to get you started if this is your first Flutter project: - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) -For help getting started with Flutter, view our -[online documentation](https://flutter.io/docs), which offers tutorials, +For help getting started with Flutter, view our +[online documentation](https://flutter.io/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference. diff --git a/permission_handler_windows/example/pubspec.yaml b/permission_handler_windows/example/pubspec.yaml index bb6bf5fdc..2deb8e72c 100644 --- a/permission_handler_windows/example/pubspec.yaml +++ b/permission_handler_windows/example/pubspec.yaml @@ -22,7 +22,7 @@ dev_dependencies: path: ../ url_launcher: ^6.0.12 - + flutter: uses-material-design: true @@ -31,4 +31,3 @@ flutter: - res/images/poweredByBaseflowLogoLight@3x.png - packages/baseflow_plugin_template/logo.png - packages/baseflow_plugin_template/poweredByBaseflow.png - diff --git a/permission_handler_windows/pubspec.yaml b/permission_handler_windows/pubspec.yaml index ad00b559c..f5553e0d6 100644 --- a/permission_handler_windows/pubspec.yaml +++ b/permission_handler_windows/pubspec.yaml @@ -1,6 +1,6 @@ name: permission_handler_windows description: Permission plugin for Flutter. This plugin provides the Windows API to request and check permissions. -version: 0.1.3 +version: 0.2.1 homepage: https://github.com/baseflow/flutter-permission-handler flutter: @@ -13,7 +13,7 @@ flutter: dependencies: flutter: sdk: flutter - permission_handler_platform_interface: ^3.11.0 + permission_handler_platform_interface: ^4.1.0 dev_dependencies: flutter_test: diff --git a/permission_handler_windows/windows/permission_constants.h b/permission_handler_windows/windows/permission_constants.h index 7e741c85e..1bc10737c 100644 --- a/permission_handler_windows/windows/permission_constants.h +++ b/permission_handler_windows/windows/permission_constants.h @@ -47,7 +47,10 @@ class PermissionConstants { AUDIO = 33, SCHEDULE_EXACT_ALARM = 34, SENSORS_ALWAYS = 35, - BACKGROUND_REFRESH = 36 + CALENDAR_WRITE_ONLY = 36, + CALENDAR_FULL_ACCESS = 37, + ASSISTANT = 38, + BACKGROUND_REFRESH = 39 }; //PERMISSION_STATUS