diff --git a/.github/ISSUE_TEMPLATE/BUG.yaml b/.github/ISSUE_TEMPLATE/BUG.yaml index de6c30e13b..994ebd597c 100644 --- a/.github/ISSUE_TEMPLATE/BUG.yaml +++ b/.github/ISSUE_TEMPLATE/BUG.yaml @@ -1,7 +1,7 @@ name: Bug Report description: You are using one of plugins in some project but due to the plugin the application is crashing or throws an exception, the plugin is buggy, or something looks wrong. title: "[Bug]: " -labels: ["bug", "triage"] +labels: [ "bug", "triage" ] body: - type: markdown attributes: @@ -16,7 +16,7 @@ body: If you have found a bug or if our documentation doesn't have an answer to what you're looking for, then fill our the template below. - + IMPORTANT: Bug reports that don't follow this template will be closed - type: input id: platform diff --git a/.github/ISSUE_TEMPLATE/COMPILATION.yaml b/.github/ISSUE_TEMPLATE/COMPILATION.yaml index c512668957..b3a8173eff 100644 --- a/.github/ISSUE_TEMPLATE/COMPILATION.yaml +++ b/.github/ISSUE_TEMPLATE/COMPILATION.yaml @@ -1,7 +1,7 @@ name: Compile Issue description: You added a plugin to your project but it does not compile or run anymore. title: "[Compile]: " -labels: ["compile", "triage"] +labels: [ "compile", "triage" ] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yaml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yaml index cbc7a1c691..f1a8d9d8e6 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yaml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yaml @@ -1,7 +1,7 @@ name: Feature request description: Suggest a new idea for one of plugins. title: "[Request]: " -labels: ["enhancement", "triage"] +labels: [ "enhancement", "triage" ] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/QUESTION.yaml b/.github/ISSUE_TEMPLATE/QUESTION.yaml index 8e74f4eabb..5fee212b9b 100644 --- a/.github/ISSUE_TEMPLATE/QUESTION.yaml +++ b/.github/ISSUE_TEMPLATE/QUESTION.yaml @@ -1,7 +1,7 @@ name: I need help description: You have a question for how to achieve a particular effect, or you need help with using a particular API. title: "[Question]: " -labels: ["question"] +labels: [ "question" ] assignees: - octocat body: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d6550ee210..559474d2d8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -13,7 +13,9 @@ e.g. ## Checklist -- [ ] I read the [Contributor Guide](https://github.com/fluttercommunity/plus_plugins/blob/main/CONTRIBUTING.md) and followed the process outlined there for submitting PRs. +- [ ] I read + the [Contributor Guide](https://github.com/fluttercommunity/plus_plugins/blob/main/CONTRIBUTING.md) + and followed the process outlined there for submitting PRs. - [ ] I titled the PR using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0). - [ ] I did not modify the `CHANGELOG.md` nor the plugin version in `pubspec.yaml` files. - [ ] All existing and new tests are passing. @@ -23,6 +25,7 @@ e.g. Does your PR require plugin users to manually update their apps to accommodate your change? -- [ ] Yes, this is a breaking change (please indicate that with a `!` in the title as explained in [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0)). +- [ ] Yes, this is a breaking change (please indicate that with a `!` in the title as explained + in [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0)). - [ ] No, this is *not* a breaking change. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1e6185f2f2..63052982ad 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -26,7 +26,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/android_alarm_manager_plus/example" @@ -38,7 +38,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] # Android Intent Plus dependencies updates config @@ -52,7 +52,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/android_intent_plus/example" @@ -64,7 +64,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] # Battery Plus dependencies updates config @@ -78,7 +78,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/battery_plus/battery_plus/example" @@ -90,7 +90,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/battery_plus/battery_plus_platform_interface" @@ -102,7 +102,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] # Connectivity Plus dependencies updates config @@ -116,7 +116,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/connectivity_plus/connectivity_plus/example" @@ -128,7 +128,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/connectivity_plus/connectivity_plus_platform_interface" @@ -140,7 +140,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] # Device Info Plus dependencies updates config @@ -154,7 +154,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/device_info_plus/device_info_plus/example" @@ -166,7 +166,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/device_info_plus/device_info_plus_platform_interface" @@ -178,7 +178,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] # Network Info Plus dependencies updates config @@ -192,7 +192,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/network_info_plus/network_info_plus/example" @@ -204,7 +204,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/network_info_plus/network_info_plus_platform_interface" @@ -216,7 +216,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] # Package Info Plus dependencies updates config @@ -230,7 +230,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/package_info_plus/package_info_plus/example" @@ -242,7 +242,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/package_info_plus/package_info_plus_platform_interface" @@ -254,7 +254,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] # Sensors Plus dependencies updates config @@ -268,7 +268,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/sensors_plus/sensors_plus/example" @@ -280,7 +280,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/sensors_plus/sensors_plus_platform_interface" @@ -292,7 +292,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] # Share Plus dependencies updates config @@ -306,7 +306,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/share_plus/share_plus/example" @@ -318,7 +318,7 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] - package-ecosystem: "pub" directory: "/packages/share_plus/share_plus_platform_interface" @@ -330,4 +330,4 @@ updates: include: "scope" ignore: - dependency-name: "*" - update-types: ["version-update:semver-minor", "version-update:semver-patch"] + update-types: [ "version-update:semver-minor", "version-update:semver-patch" ] diff --git a/.github/workflows/android_alarm_manager_plus.yaml b/.github/workflows/android_alarm_manager_plus.yaml index 3fcc15765e..0c7da32194 100644 --- a/.github/workflows/android_alarm_manager_plus.yaml +++ b/.github/workflows/android_alarm_manager_plus.yaml @@ -59,7 +59,7 @@ jobs: strategy: fail-fast: false matrix: - android-api-level: [22, 26, 31, 34] + android-api-level: [ 22, 26, 31, 34 ] steps: - name: "Checkout repository" diff --git a/.github/workflows/connectivity_plus.yaml b/.github/workflows/connectivity_plus.yaml index 025536c02b..5a19d205bf 100644 --- a/.github/workflows/connectivity_plus.yaml +++ b/.github/workflows/connectivity_plus.yaml @@ -63,7 +63,7 @@ jobs: strategy: fail-fast: false matrix: - android-api-level: [ 21, 26, 31, 34] + android-api-level: [ 21, 26, 31, 34 ] steps: - name: "Checkout repository" diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 3affc77c40..e3f417a338 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an +standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3f67ca3b99..c58218a4a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,8 +7,9 @@ _See also: [Flutter's code of conduct](https://flutter.dev/design-principles/#co We welcome all contributions to the project, however some contributions will need extra work in order to be accepted. -> [!IMPORTANT] -> Before submitting a large PR, create a ticket with a proposal and wait for the maintainers to give you feedback. +> [!IMPORTANT] +> Before submitting a large PR, create a ticket with a proposal and wait for the maintainers to give +> you feedback. Here's some examples: @@ -23,7 +24,8 @@ Here's some examples: - New features covering all platforms -We need to make sure it works well before merging and each platform needs to be reviewed individually. +We need to make sure it works well before merging and each platform needs to be reviewed +individually. - Changing a platform implementation @@ -49,7 +51,8 @@ Please follow this steps when working on the PlusPlugins. - Linux, Mac OS X, or Windows. - [git](https://git-scm.com) (used for source version control). - An ssh client (used to authenticate with GitHub). -- An IDE such as [Android Studio](https://developer.android.com/studio) or [Visual Studio Code](https://code.visualstudio.com/). +- An IDE such as [Android Studio](https://developer.android.com/studio) + or [Visual Studio Code](https://code.visualstudio.com/). - [`flutter_plugin_tools`](https://pub.dev/packages/flutter_plugin_tools) locally activated. - [`tuneup`](https://pub.dev/packages/tuneup) locally activated. @@ -103,7 +106,8 @@ cd packages/sensors_plus/sensors_plus/example flutter run ``` -Using Melos (installed in step 3), any changes made to the plugins locally will also be reflected within all +Using Melos (installed in step 3), any changes made to the plugins locally will also be reflected +within all example applications code automatically. ## 4. Running tests @@ -112,9 +116,12 @@ PlusPlugins comprises of a number of tests for each plugin, either end-to-end (e ### Unit tests -Unit tests are responsible for ensuring expected behavior whilst developing the plugins Dart code. Unit tests do not -interact with 3rd party services, and mock where possible. To run unit tests for a specific plugin, run the -`flutter test` command from the plugins root directory. For example, sensors_plus platform interface tests can be run +Unit tests are responsible for ensuring expected behavior whilst developing the plugins Dart code. +Unit tests do not +interact with 3rd party services, and mock where possible. To run unit tests for a specific plugin, +run the +`flutter test` command from the plugins root directory. For example, sensors_plus platform interface +tests can be run with the following commands: ```bash @@ -124,10 +131,12 @@ flutter test ### End-to-end (e2e) tests -E2e tests are those which directly communicate with Flutter, whose results cannot be mocked. **These tests run directly from +E2e tests are those which directly communicate with Flutter, whose results cannot be mocked. **These +tests run directly from an example application.** -To run e2e tests, run the `flutter test` command from the plugins main `example` directory, and provide the path to the +To run e2e tests, run the `flutter test` command from the plugins main `example` directory, and +provide the path to the e2e test file. For example, to run the `sensors_plus` e2e tests: #### Mobile @@ -139,7 +148,8 @@ flutter test integration_test/sensors_plus_test.dart #### Web -To run tests against web environments, you will need to have Chrome and ChromeDriver installed and use the `flutter drive` command. +To run tests against web environments, you will need to have Chrome and ChromeDriver installed and +use the `flutter drive` command. First start ChromeDriver on port 4444: @@ -147,8 +157,10 @@ First start ChromeDriver on port 4444: chromedriver --port=4444 ``` -Then go to the `example` directory of the plugin you want to test and run the `flutter drive` command -with the specific driver and `*_web_test.dart` target. For example, to run the `package_info_plus` web tests: +Then go to the `example` directory of the plugin you want to test and run the `flutter drive` +command +with the specific driver and `*_web_test.dart` target. For example, to run the `package_info_plus` +web tests: ```bash cd packages/package_info_plus/package_info_plus/example @@ -169,7 +181,8 @@ run the following command from the root of your cloned repository: melos run test:mobile_e2e ``` -A full list of all commands can be found within the [`melos.yaml`](https://github.com/fluttercommunity/plus_plugins/blob/main/melos.yaml) +A full list of all commands can be found within the [ +`melos.yaml`](https://github.com/fluttercommunity/plus_plugins/blob/main/melos.yaml) file. ## 5. Contributing code @@ -182,7 +195,7 @@ Please follow the working on anything non-trivial. These guidelines are intended to keep the code consistent and avoid common pitfalls. -> [!IMPORTANT] +> [!IMPORTANT] > When modifying multiple packages, **create a different branch and pull request per package.** > This facilitates maintenance, the review process, and generating changelogs. @@ -194,13 +207,15 @@ To start working on a patch: 2. `git checkout upstream/main -b ` 3. Hack away! -> [!CAUTION] -> Do not create PRs directly from the `main` branch of your repository, as it causes problems when pushing changes by reviewers. +> [!CAUTION] +> Do not create PRs directly from the `main` branch of your repository, as it causes problems when +> pushing changes by reviewers. > Always create a new branch for your pull requests. ### 5.2 Check the code -Once you have made your changes, ensure that it passes the internal analyzer & formatting checks. The following +Once you have made your changes, ensure that it passes the internal analyzer & formatting checks. +The following commands can be run locally to highlight any issues before committing your code: ```bash @@ -214,7 +229,8 @@ melos run format ### 5.3 Do not update version and changelog > [!CAUTION] -> Do not modify the `CHANGELOG.md` or the version in the `pubspec.yaml`, this is handled by the maintainers from now on +> Do not modify the `CHANGELOG.md` or the version in the `pubspec.yaml`, this is handled by the +> maintainers from now on ### 5.4 Commit and push your changes @@ -233,8 +249,10 @@ To send us a pull request: Please make sure all your check-ins have detailed commit messages explaining the patch. -When naming the title of your pull request, please follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) -guide, and include the package name in parenthesis. For example, for a fix to the `sensor_plus` plugin: +When naming the title of your pull request, please follow +the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) +guide, and include the package name in parenthesis. For example, for a fix to the `sensor_plus` +plugin: `fix(sensor_plus): fixed a bug!` @@ -261,13 +279,16 @@ Newly opened PRs first go through initial triage which results in one of: - **Merging the PR** - if the PR can be quickly reviewed and looks good. - **Closing the PR** - if the maintainer decides that the PR should not be merged. -- **Moving the PR to the backlog** - if the review requires non trivial effort and the issue isn't a priority; in this case the maintainer will: - - Make sure that the PR has an associated issue labeled with "plugin". - - Add the "backlog" label to the issue. - - Leave a comment on the PR explaining that the review is not trivial and that the issue will be looked at according to priority order. -- **Starting a non trivial review** - if the review requires non trivial effort and the issue is a priority; in this case the maintainer will: - - Add the "in review" label to the issue. - - Self assign the PR. +- **Moving the PR to the backlog** - if the review requires non trivial effort and the issue isn't a + priority; in this case the maintainer will: + - Make sure that the PR has an associated issue labeled with "plugin". + - Add the "backlog" label to the issue. + - Leave a comment on the PR explaining that the review is not trivial and that the issue will be + looked at according to priority order. +- **Starting a non trivial review** - if the review requires non trivial effort and the issue is a + priority; in this case the maintainer will: + - Add the "in review" label to the issue. + - Self assign the PR. ### The release process @@ -297,11 +318,14 @@ Some things to keep in mind before publishing the release: 1. Switch to `main` branch locally. 2. Run `git pull origin main`. 3. Run `git pull --tags` to make sure all tags are fetched. -4. Run `melos version --no-git-commit-version` to automatically version packages and update Changelogs. +4. Run `melos version --no-git-commit-version` to automatically version packages and update + Changelogs. 5. Run `melos publish` to dry run and confirm all packages are publishable. -6. After successful dry run, create and checkout to a new branch named `release/[year]-[month]-[day]`. +6. After successful dry run, create and checkout to a new branch named + `release/[year]-[month]-[day]`. 7. Commit all changes with a commit message `chore(release): prepare for release`. 8. Run `git push origin [RELEASE BRANCH NAME]` & open pull request for review on GitHub. -9. After successful review and merge of the pull request, switch to `main` branch locally, & run `git pull origin main`. +9. After successful review and merge of the pull request, switch to `main` branch locally, & run + `git pull origin main`. 10. Run `melos publish --no-dry-run --git-tag-version` to now publish to pub.dev. 11. Run `git push --tags` to push tags to repository. diff --git a/README.md b/README.md index eb77686109..4fe0647eba 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ PlusPlugins is a set of Flutter plugins that is developed based on plugins, whic as a part of [Flutter plugins](https://github.com/flutter/plugins), with extra functionalities, support for more platforms and better maintenance. -[Feedback](https://github.com/fluttercommunity/plus_plugins/issues) and [Pull Requests](https://github.com/fluttercommunity/plus_plugins/pulls) are most welcome! +[Feedback](https://github.com/fluttercommunity/plus_plugins/issues) +and [Pull Requests](https://github.com/fluttercommunity/plus_plugins/pulls) are most welcome! ## Plugins @@ -42,15 +43,16 @@ support for more platforms and better maintenance. > [![battery_plus][battery_plus_badge_pub]][battery_plus] [![pub points][battery_plus_badge_pub_points]][battery_plus_pub_points] -Flutter plugin for accessing information about the battery state(full, charging, discharging) on Android and iOS. +Flutter plugin for accessing information about the battery state(full, charging, discharging) on +Android and iOS. [[readme][battery_plus_readme]] [[code][battery_plus_code]] #### Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | --- @@ -66,8 +68,8 @@ mobile/cellular) connectivity on Android and iOS. #### Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | --- @@ -83,8 +85,8 @@ Flutter plugin providing detailed information about the device #### Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | --- @@ -99,8 +101,8 @@ Flutter plugin for discovering network info. #### Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | --- @@ -116,8 +118,8 @@ package, such as CFBundleVersion on iOS or versionCode on Android. #### Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | --- @@ -132,8 +134,8 @@ Flutter plugin for accessing accelerometer, gyroscope, magnetometer and baromete #### Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | --- @@ -141,15 +143,16 @@ Flutter plugin for accessing accelerometer, gyroscope, magnetometer and baromete > [![share_plus][share_plus_badge_pub]][share_plus] [![pub points][share_plus_badge_pub_points]][share_plus_pub_points] -Flutter plugin for sharing content via the platform share UI, using the ACTION_SEND intent on Android and UIActivityViewController on iOS. +Flutter plugin for sharing content via the platform share UI, using the ACTION_SEND intent on +Android and UIActivityViewController on iOS. [[readme][share_plus_readme]] [[code][share_plus_code]] #### Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | --- @@ -157,15 +160,16 @@ Flutter plugin for sharing content via the platform share UI, using the ACTION_S > [![android_alarm_manager_plus][android_alarm_manager_plus_badge_pub]][android_alarm_manager_plus] [![pub points][android_alarm_manager_plus_badge_pub_points]][android_alarm_manager_plus_pub_points] -Flutter plugin for accessing the Android AlarmManager service, and running Dart code in the background when alarms fire. +Flutter plugin for accessing the Android AlarmManager service, and running Dart code in the +background when alarms fire. [[readme][android_alarm_manager_plus_readme]] [[code][android_alarm_manager_plus_code]] #### Platform Support | Android | -| :-----: | -| ✅ | +|:-------:| +| ✅ | --- @@ -180,16 +184,18 @@ Flutter plugin for launching Android Intents. Not supported on iOS. #### Platform Support | Android | -| :-----: | -| ✅ | +|:-------:| +| ✅ | --- ## Issues -Please file PlusPlugins specific issues, bugs, or feature requests in our [issue tracker](https://github.com/fluttercommunity/plus_plugins/issues/new). +Please file PlusPlugins specific issues, bugs, or feature requests in +our [issue tracker](https://github.com/fluttercommunity/plus_plugins/issues/new). -Plugin issues that are not specific to PlusPlugins can be filed in the [Flutter issue tracker](https://github.com/flutter/flutter/issues/new). +Plugin issues that are not specific to PlusPlugins can be filed in +the [Flutter issue tracker](https://github.com/flutter/flutter/issues/new). ## Contributing @@ -199,59 +205,113 @@ and open a [pull request](https://github.com/fluttercommunity/plus_plugins/pulls ## Status -This repository is maintained by FlutterCommunity authors. Issues here are answered by maintainers and other community members on GitHub on a best-effort basis. +This repository is maintained by FlutterCommunity authors. Issues here are answered by maintainers +and other community members on GitHub on a best-effort basis. [battery_plus]: https://pub.dev/packages/battery_plus + [battery_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus + [battery_plus_readme]: packages/battery_plus/battery_plus/README.md + [battery_plus_pub_points]: https://pub.dev/packages/battery_plus/score + [battery_plus_badge_pub_points]: https://img.shields.io/pub/points/battery_plus?color=2E8B57&label=pub%20points + [battery_plus_badge_pub]: https://img.shields.io/pub/v/battery_plus.svg + [connectivity_plus]: https://pub.dev/packages/connectivity_plus + [connectivity_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/connectivity_plus + [connectivity_plus_readme]: packages/connectivity_plus/connectivity_plus/README.md + [connectivity_plus_pub_points]: https://pub.dev/packages/connectivity_plus/score + [connectivity_plus_badge_pub_points]: https://img.shields.io/pub/points/connectivity_plus?color=2E8B57&label=pub%20points + [connectivity_plus_badge_pub]: https://img.shields.io/pub/v/connectivity_plus.svg + [network_info_plus]: https://pub.dev/packages/network_info_plus + [network_info_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/network_info_plus + [network_info_plus_readme]: packages/network_info_plus/network_info_plus/README.md + [network_info_plus_pub_points]: https://pub.dev/packages/network_info_plus/score + [network_info_plus_badge_pub_points]: https://img.shields.io/pub/points/network_info_plus?color=2E8B57&label=pub%20points + [network_info_plus_badge_pub]: https://img.shields.io/pub/v/network_info_plus.svg + [android_alarm_manager_plus]: https://pub.dev/packages/android_alarm_manager_plus + [android_alarm_manager_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/android_alarm_manager_plus + [android_alarm_manager_plus_readme]: packages/android_alarm_manager_plus/README.md + [android_alarm_manager_plus_pub_points]: https://pub.dev/packages/android_alarm_manager_plus/score + [android_alarm_manager_plus_badge_pub_points]: https://img.shields.io/pub/points/android_alarm_manager_plus?color=2E8B57&label=pub%20points + [android_alarm_manager_plus_badge_pub]: https://img.shields.io/pub/v/android_alarm_manager_plus.svg + [android_intent_plus]: https://pub.dev/packages/android_intent_plus + [android_intent_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/android_intent_plus + [android_intent_plus_readme]: packages/android_intent_plus/README.md + [android_intent_plus_pub_points]: https://pub.dev/packages/android_intent_plus/score + [android_intent_plus_badge_pub_points]: https://img.shields.io/pub/points/android_intent_plus?color=2E8B57&label=pub%20points + [android_intent_plus_badge_pub]: https://img.shields.io/pub/v/android_intent_plus.svg + [device_info_plus]: https://pub.dev/packages/device_info_plus + [device_info_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/device_info_plus + [device_info_plus_readme]: packages/device_info_plus/device_info_plus/README.md + [device_info_plus_pub_points]: https://pub.dev/packages/device_info_plus/score + [device_info_plus_badge_pub_points]: https://img.shields.io/pub/points/device_info_plus?color=2E8B57&label=pub%20points + [device_info_plus_badge_pub]: https://img.shields.io/pub/v/device_info_plus.svg + [package_info_plus]: https://pub.dev/packages/package_info_plus + [package_info_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus -[package_info_plus_readme]: packages/package_info_plus/package_info_plus/README.md + +[package_info_plus_readme]: packages/package_info_plus/package_info_plus/README.md + [package_info_plus_pub_points]: https://pub.dev/packages/package_info_plus/score + [package_info_plus_badge_pub_points]: https://img.shields.io/pub/points/package_info_plus?color=2E8B57&label=pub%20points + [package_info_plus_badge_pub]: https://img.shields.io/pub/v/package_info_plus.svg + [sensors_plus]: https://pub.dev/packages/sensors_plus + [sensors_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/sensors_plus + [sensors_plus_readme]: packages/sensors_plus/sensors_plus/README.md + [sensors_plus_pub_points]: https://pub.dev/packages/sensors_plus/score + [sensors_plus_badge_pub_points]: https://img.shields.io/pub/points/sensors_plus?color=2E8B57&label=pub%20points + [sensors_plus_badge_pub]: https://img.shields.io/pub/v/sensors_plus.svg + [share_plus]: https://pub.dev/packages/share_plus + [share_plus_code]: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/share_plus + [share_plus_readme]: packages/share_plus/share_plus/README.md + [share_plus_pub_points]: https://pub.dev/packages/share_plus/score + [share_plus_badge_pub_points]: https://img.shields.io/pub/points/share_plus?color=2E8B57&label=pub%20points + [share_plus_badge_pub]: https://img.shields.io/pub/v/share_plus.svg diff --git a/packages/android_alarm_manager_plus/CHANGELOG.md b/packages/android_alarm_manager_plus/CHANGELOG.md index b04265932a..617717079b 100644 --- a/packages/android_alarm_manager_plus/CHANGELOG.md +++ b/packages/android_alarm_manager_plus/CHANGELOG.md @@ -1,95 +1,117 @@ ## 4.0.7 - - **FIX**(alarm_manager_plus): removed import that broke build ([#3477](https://github.com/fluttercommunity/plus_plugins/issues/3477)). ([fdac82b0](https://github.com/fluttercommunity/plus_plugins/commit/fdac82b06c8b7f9188656d86155fa041d19a3f2d)) +- **FIX**(alarm_manager_plus): removed import that broke + build ([#3477](https://github.com/fluttercommunity/plus_plugins/issues/3477)). ([fdac82b0](https://github.com/fluttercommunity/plus_plugins/commit/fdac82b06c8b7f9188656d86155fa041d19a3f2d)) ## 4.0.6 - - **FIX**(android_alarm_manager_plus): set correct environment versions ([#3420](https://github.com/fluttercommunity/plus_plugins/issues/3420)). ([c2722f83](https://github.com/fluttercommunity/plus_plugins/commit/c2722f8345407d3bf7c66b99e57fbf5c75da428f)) +- **FIX**(android_alarm_manager_plus): set correct environment + versions ([#3420](https://github.com/fluttercommunity/plus_plugins/issues/3420)). ([c2722f83](https://github.com/fluttercommunity/plus_plugins/commit/c2722f8345407d3bf7c66b99e57fbf5c75da428f)) ## 4.0.5 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 4.0.4 - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 4.0.3 - - **FIX**(android_alarm_manager_plus): Remove references to v1 embedding ([#2864](https://github.com/fluttercommunity/plus_plugins/issues/2864)). ([0bb6a1fd](https://github.com/fluttercommunity/plus_plugins/commit/0bb6a1fd8c77b3ed8ec92ffbd15e426921d1c71a)) +- **FIX**(android_alarm_manager_plus): Remove references to v1 + embedding ([#2864](https://github.com/fluttercommunity/plus_plugins/issues/2864)). ([0bb6a1fd](https://github.com/fluttercommunity/plus_plugins/commit/0bb6a1fd8c77b3ed8ec92ffbd15e426921d1c71a)) ## 4.0.2 - - **REFACTOR**(android_alarm_manager_plus): Migrate Android example to use the new plugins declaration ([#2774](https://github.com/fluttercommunity/plus_plugins/issues/2774)). ([2b8489ca](https://github.com/fluttercommunity/plus_plugins/commit/2b8489cabce6f73d8c16c4206455800a7d003ce1)) - - **FIX**(android_alarm_manager_plus): Fix showIntent not being set correctly in setAlarmClock ([#2778](https://github.com/fluttercommunity/plus_plugins/issues/2778)). ([7d578c36](https://github.com/fluttercommunity/plus_plugins/commit/7d578c364f9f17d932c34113ecdd33667006168d)) +- **REFACTOR**(android_alarm_manager_plus): Migrate Android example to use the new plugins + declaration ([#2774](https://github.com/fluttercommunity/plus_plugins/issues/2774)). ([2b8489ca](https://github.com/fluttercommunity/plus_plugins/commit/2b8489cabce6f73d8c16c4206455800a7d003ce1)) +- **FIX**(android_alarm_manager_plus): Fix showIntent not being set correctly in + setAlarmClock ([#2778](https://github.com/fluttercommunity/plus_plugins/issues/2778)). ([7d578c36](https://github.com/fluttercommunity/plus_plugins/commit/7d578c364f9f17d932c34113ecdd33667006168d)) ## 4.0.1 Plugin now requires the following: -- compileSDK 34 + +- compileSDK 35 - Java 17 - Gradle 8.4 -- **BREAKING** **BUILD**(alarm_manager_plus): Target Java 17 ([#2723](https://github.com/fluttercommunity/plus_plugins/issues/2723)). ([9e187803](https://github.com/fluttercommunity/plus_plugins/commit/9e187803d395bf1d8cbe74a0494ef28989451dde)) -- **BREAKING** **BUILD**(alarm_manager_plus): Update to target and compile SDK 34 ([#2714](https://github.com/fluttercommunity/plus_plugins/pull/2714)). ([0262766](https://github.com/fluttercommunity/plus_plugins/commit/0262766276b4ff695018a08ea398fba30dd881ac)) -- **DOCS**(android_alarm_manager_plus): Update information about SCHEDULE_EXACT_ALARM permission ([#2716](https://github.com/fluttercommunity/plus_plugins/issues/2716)). ([94e454f6](https://github.com/fluttercommunity/plus_plugins/commit/94e454f6e008691608d2c5e6df4d368d32cf0ca9)) +- **BREAKING** **BUILD**(alarm_manager_plus): Target Java + 17 ([#2723](https://github.com/fluttercommunity/plus_plugins/issues/2723)). ([9e187803](https://github.com/fluttercommunity/plus_plugins/commit/9e187803d395bf1d8cbe74a0494ef28989451dde)) +- **BREAKING** **BUILD**(alarm_manager_plus): Update to target and compile SDK + 34 ([#2714](https://github.com/fluttercommunity/plus_plugins/pull/2714)). ([0262766](https://github.com/fluttercommunity/plus_plugins/commit/0262766276b4ff695018a08ea398fba30dd881ac)) +- **DOCS**(android_alarm_manager_plus): Update information about SCHEDULE_EXACT_ALARM + permission ([#2716](https://github.com/fluttercommunity/plus_plugins/issues/2716)). ([94e454f6](https://github.com/fluttercommunity/plus_plugins/commit/94e454f6e008691608d2c5e6df4d368d32cf0ca9)) ## 4.0.0 -> Note: This release was retracted due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). +> Note: This release was retracted due +> to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). ## 3.0.4 - - **FIX**(android_alarm_manager): Add Kotlin dependency and convert AlarmBroadcastReceiver class to Kotlin ([#2271](https://github.com/fluttercommunity/plus_plugins/issues/2271)). ([1ecb676f](https://github.com/fluttercommunity/plus_plugins/commit/1ecb676f4923a54f239b99d18e0f8f819dcc0f15)) +- **FIX**(android_alarm_manager): Add Kotlin dependency and convert AlarmBroadcastReceiver class to + Kotlin ([#2271](https://github.com/fluttercommunity/plus_plugins/issues/2271)). ([1ecb676f](https://github.com/fluttercommunity/plus_plugins/commit/1ecb676f4923a54f239b99d18e0f8f819dcc0f15)) ## 3.0.3 - - **FIX**(alarm_manager_plus): Revert bump compileSDK 34 ([#2235](https://github.com/fluttercommunity/plus_plugins/issues/2235)). ([9dabf257](https://github.com/fluttercommunity/plus_plugins/commit/9dabf257605c73c7d4905838c4b85a360fbae518)) - - **FIX**(android_alarm_manager_plus): Fix documentation typo ([#2046](https://github.com/fluttercommunity/plus_plugins/issues/2046)). ([d98f67ea](https://github.com/fluttercommunity/plus_plugins/commit/d98f67ea61d6b423bef764ed7db8d493044fdab6)) +- **FIX**(alarm_manager_plus): Revert bump compileSDK + 34 ([#2235](https://github.com/fluttercommunity/plus_plugins/issues/2235)). ([9dabf257](https://github.com/fluttercommunity/plus_plugins/commit/9dabf257605c73c7d4905838c4b85a360fbae518)) +- **FIX**(android_alarm_manager_plus): Fix documentation + typo ([#2046](https://github.com/fluttercommunity/plus_plugins/issues/2046)). ([d98f67ea](https://github.com/fluttercommunity/plus_plugins/commit/d98f67ea61d6b423bef764ed7db8d493044fdab6)) ## 3.0.2 - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 3.0.1 - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) ## 3.0.0 > Note: This release has breaking changes. - - **CHORE**(android_alarm_manager_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(android_alarm_manager_plus): Bump min Android version to 4.4 (API 19) (#1785). - - **REFACTOR**(android_alarm_manager_plus): Update example app to use Material 3. +- **CHORE**(android_alarm_manager_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart + to >=2.18.0 <4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(android_alarm_manager_plus): Bump min Android version to 4.4 (API 19) ( + #1785). +- **REFACTOR**(android_alarm_manager_plus): Update example app to use Material 3. ## 2.1.4 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 2.1.3 - - **FIX**(android_alarm_manager_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1698). +- **FIX**(android_alarm_manager_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1698). ## 2.1.2 - - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). - - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). +- **REFACTOR**(all): Remove all manual dependency_overrides (#1628). +- **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). ## 2.1.1 - - **DOCS**: Updates for READMEs and website pages (#1389). +- **DOCS**: Updates for READMEs and website pages (#1389). ## 2.1.0 - - **FEAT**: we can now send extra data to alarm manager and receive it in our callback (#1014). +- **FEAT**: we can now send extra data to alarm manager and receive it in our callback (#1014). ## 2.0.8 - - **FIX**: lint warnings - add missing dependency for tests (#1233). - - **DOCS**: Fix example and docs to explain required annotation (#1229). +- **FIX**: lint warnings - add missing dependency for tests (#1233). +- **DOCS**: Fix example and docs to explain required annotation (#1229). ## 2.0.7+1 @@ -114,7 +136,8 @@ Plugin now requires the following: ## 2.0.4 -- Fix FlutterEngine initialisation to avoid crashes when app is closed and plugin tries to schedule an alarm. +- Fix FlutterEngine initialisation to avoid crashes when app is closed and plugin tries to schedule + an alarm. ## 2.0.3 @@ -187,7 +210,8 @@ Plugin now requires the following: ## 0.4.5+10 -- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). +- Declare API stability and compatibility with `1.0.0` (more details + at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). ## 0.4.5+9 @@ -302,27 +326,27 @@ Plugin now requires the following: - Added support for setting alarms which persist across reboots. - - Both `AndroidAlarmManager.oneShot` and `AndroidAlarmManager.periodic` have - an optional `rescheduleOnReboot` parameter which specifies whether the new - alarm should be rescheduled to run after a reboot (default: false). If set - to false, the alarm will not survive a device reboot. - - Requires AndroidManifest.xml to be updated to include the following - entries: - - ```xml - - - - - - - - - - - ``` + - Both `AndroidAlarmManager.oneShot` and `AndroidAlarmManager.periodic` have + an optional `rescheduleOnReboot` parameter which specifies whether the new + alarm should be rescheduled to run after a reboot (default: false). If set + to false, the alarm will not survive a device reboot. + - Requires AndroidManifest.xml to be updated to include the following + entries: + + ```xml + + + + + + + + + + + ``` ## 0.4.0 diff --git a/packages/android_alarm_manager_plus/CODE_OF_CONDUCT.md b/packages/android_alarm_manager_plus/CODE_OF_CONDUCT.md index c79a563029..07769f6514 100644 --- a/packages/android_alarm_manager_plus/CODE_OF_CONDUCT.md +++ b/packages/android_alarm_manager_plus/CODE_OF_CONDUCT.md @@ -1,4 +1,3 @@ - # Contributor Covenant Code of Conduct ## Our Pledge @@ -107,7 +106,7 @@ Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an +standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within diff --git a/packages/android_alarm_manager_plus/README.md b/packages/android_alarm_manager_plus/README.md index f26975944f..e18d10b8d4 100644 --- a/packages/android_alarm_manager_plus/README.md +++ b/packages/android_alarm_manager_plus/README.md @@ -12,8 +12,8 @@ Dart code in the background when alarms fire. ## Platform Support | Android | -| :-----: | -| ✅ | +|:-------:| +| ✅ | ## Requirements @@ -27,11 +27,19 @@ Dart code in the background when alarms fire. ## Getting Started > [!IMPORTANT] -> You would also need a plugin to request [SCHEDULE_EXACT_ALARM](https://developer.android.com/reference/android/Manifest.permission#SCHEDULE_EXACT_ALARM) permission if your app targets Android 14 and newer. -> Google introduced SCHEDULE_EXACT_ALARM permission in [Android 12](https://developer.android.com/about/versions/12/behavior-changes-12#exact-alarm-permission). In Android 13 it was granted by default. -> Since Android 14 this permission [is denied by default](https://developer.android.com/about/versions/14/changes/schedule-exact-alarms) and apps need to ask user to provide it. -> `android_alarm_manager_plus` does not provide a way to work with this permission, so be sure to handle such logic yourself. -> To do so you would need an additional plugin, like [`permission_handler`](https://pub.dev/packages/permission_handler). +> You would also need a plugin to +> request [SCHEDULE_EXACT_ALARM](https://developer.android.com/reference/android/Manifest.permission#SCHEDULE_EXACT_ALARM) +> permission if your app targets Android 14 and newer. +> Google introduced SCHEDULE_EXACT_ALARM permission +> in [Android 12](https://developer.android.com/about/versions/12/behavior-changes-12#exact-alarm-permission). +> In Android 13 it was granted by default. +> Since Android 14 this +> permission [is denied by default](https://developer.android.com/about/versions/14/changes/schedule-exact-alarms) +> and apps need to ask user to provide it. +> `android_alarm_manager_plus` does not provide a way to work with this permission, so be sure to +> handle such logic yourself. +> To do so you would need an additional plugin, like [ +`permission_handler`](https://pub.dev/packages/permission_handler). After importing this plugin to your project as usual, add the following to your `AndroidManifest.xml` within the `` tags: @@ -90,7 +98,8 @@ main() async { `printHello` will then run (roughly) every minute, even if the main app ends. However, `printHello` will not run in the same isolate as the main application. Unlike threads, isolates do not share -memory and communication between isolates must be done via message passing (see more documentation on +memory and communication between isolates must be done via message passing (see more documentation +on isolates [here](https://api.dart.dev/stable/2.0.0/dart-isolate/dart-isolate-library.html)). ## Using other plugins in alarm callbacks @@ -102,9 +111,18 @@ using. ## Receiving show intents for alarm clocks -If your app is an alarm clock app and sets alarms using the `alarmClock` argument in [`oneShot`](https://pub.dev/documentation/android_alarm_manager_plus/latest/android_alarm_manager_plus/AndroidAlarmManager/oneShot.html) or [`oneShotAt`](https://pub.dev/documentation/android_alarm_manager_plus/latest/android_alarm_manager_plus/AndroidAlarmManager/oneShotAt.html), you can receive [intents](https://developer.android.com/reference/android/content/Intent) when user interacts with system UI that shows the next alarm. An example is the alarm tile in Android [quick-setting tiles](https://developer.android.com/develop/ui/views/quicksettings-tiles). This functionality is to allow you to show users the relevant alarm, or allow them to edit it when they tap on such UIs. +If your app is an alarm clock app and sets alarms using the `alarmClock` argument in [ +`oneShot`](https://pub.dev/documentation/android_alarm_manager_plus/latest/android_alarm_manager_plus/AndroidAlarmManager/oneShot.html) +or [ +`oneShotAt`](https://pub.dev/documentation/android_alarm_manager_plus/latest/android_alarm_manager_plus/AndroidAlarmManager/oneShotAt.html), +you can receive [intents](https://developer.android.com/reference/android/content/Intent) when user +interacts with system UI that shows the next alarm. An example is the alarm tile in +Android [quick-setting tiles](https://developer.android.com/develop/ui/views/quicksettings-tiles). +This functionality is to allow you to show users the relevant alarm, or allow them to edit it when +they tap on such UIs. This intent has the action `android.intent.action.MAIN` and includes the following `extras`: + - `id`: The alarm id that you passed when scheduling the alarm. - `params`: The params argument that you passed when scheduling the alarm, if any. @@ -126,7 +144,8 @@ await AndroidAlarmManager.oneShotAt( ) ``` -To receive this intent in dart, you can use the [receive_intent](https://pub.dev/packages/receive_intent) package: +To receive this intent in dart, you can use +the [receive_intent](https://pub.dev/packages/receive_intent) package: ```dart import 'package:receive_intent/receive_intent.dart'; @@ -146,7 +165,9 @@ if (receivedIntent.action == "android.intent.action.MAIN"){ // navigate user to alarm with given id } ``` -For more information, check out the receive_intent [getting started](https://pub.dev/packages/receive_intent#getting-started). + +For more information, check out the +receive_intent [getting started](https://pub.dev/packages/receive_intent#getting-started). ## FAQ @@ -154,8 +175,9 @@ For more information, check out the receive_intent [getting started](https://pub From the Android AlarmManager documentation: -> Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off -during that time), but will be cleared if it is turned off and rebooted. +> Registered alarms are retained while the device is asleep (and can optionally wake the device up +> if they go off +> during that time), but will be cleared if it is turned off and rebooted. https://developer.android.com/reference/android/app/AlarmManager @@ -163,12 +185,15 @@ https://developer.android.com/reference/android/app/AlarmManager The Android OS will not fire alarms for apps that have been force stopped. -StackOverflow response: https://stackoverflow.com/questions/11241794/alarm-set-in-app-with-alarmmanager-got-removed-when-app-force-stop +StackOverflow +response: https://stackoverflow.com/questions/11241794/alarm-set-in-app-with-alarmmanager-got-removed-when-app-force-stop ### My alarm is not firing on a specific device -Likely the device is running some battery optimization software that is preventing the alarm from firing. -Check out https://dontkillmyapp.com/ to find out about more about optimizations done by different vendors. +Likely the device is running some battery optimization software that is preventing the alarm from +firing. +Check out https://dontkillmyapp.com/ to find out about more about optimizations done by different +vendors. ## Plugin Development diff --git a/packages/android_alarm_manager_plus/android/build.gradle b/packages/android_alarm_manager_plus/android/build.gradle index 9cfc9732ff..8c3cb2c033 100644 --- a/packages/android_alarm_manager_plus/android/build.gradle +++ b/packages/android_alarm_manager_plus/android/build.gradle @@ -2,7 +2,7 @@ group 'dev.fluttercommunity.plus.androidalarmmanager' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.9.23' + ext.kotlin_version = '2.1.10' repositories { google() mavenCentral() @@ -25,7 +25,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.androidalarmmanager' @@ -50,6 +50,6 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - api 'androidx.core:core-ktx:1.13.1' + api 'androidx.core:core:1.15.0' implementation 'androidx.appcompat:appcompat:1.7.0' } diff --git a/packages/android_alarm_manager_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/android_alarm_manager_plus/android/gradle/wrapper/gradle-wrapper.properties index 7825683d62..2e812385d4 100644 --- a/packages/android_alarm_manager_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/android_alarm_manager_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Oct 05 10:00:26 EEST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/AlarmService.java b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/AlarmService.java index 937fcfa7d3..d82c9a28e2 100644 --- a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/AlarmService.java +++ b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/AlarmService.java @@ -13,9 +13,11 @@ import android.os.Build; import android.os.Handler; import android.util.Log; + import androidx.annotation.NonNull; import androidx.core.app.AlarmManagerCompat; import androidx.core.app.JobIntentService; + import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -23,399 +25,410 @@ import java.util.List; import java.util.Set; import java.util.concurrent.CountDownLatch; + import org.json.JSONException; import org.json.JSONObject; public class AlarmService extends JobIntentService { - private static final String TAG = "AlarmService"; - private static final String PERSISTENT_ALARMS_SET_KEY = "persistent_alarm_ids"; - protected static final String SHARED_PREFERENCES_KEY = - "dev.fluttercommunity.plus.android_alarm_manager_plugin"; - private static final int JOB_ID = 1984; // Random job ID. - private static final Object persistentAlarmsLock = new Object(); - - // TODO(mattcarroll): make alarmQueue per-instance, not static. - private static final List alarmQueue = Collections.synchronizedList(new LinkedList<>()); - - /** Background Dart execution context. */ - private static FlutterBackgroundExecutor flutterBackgroundExecutor; - - /** Schedule the alarm to be handled by the {@link AlarmService}. */ - public static void enqueueAlarmProcessing(Context context, Intent alarmContext) { - enqueueWork(context, AlarmService.class, JOB_ID, alarmContext); - } - - /** - * Starts the background isolate for the {@link AlarmService}. - * - *

Preconditions: - * - *

    - *
  • The given {@code callbackHandle} must correspond to a registered Dart callback. If the - * handle does not resolve to a Dart callback then this method does nothing. - *
  • A static {@link #pluginRegistrantCallback} must exist, otherwise a {@link - * PluginRegistrantException} will be thrown. - *
- */ - public static void startBackgroundIsolate(Context context, long callbackHandle) { - if (flutterBackgroundExecutor != null) { - Log.w(TAG, "Attempted to start a duplicate background isolate. Returning..."); - return; - } - flutterBackgroundExecutor = new FlutterBackgroundExecutor(); - flutterBackgroundExecutor.startBackgroundIsolate(context, callbackHandle); - } - - /** - * Called once the Dart isolate ({@code flutterBackgroundExecutor}) has finished initializing. - * - *

Invoked by {@link AndroidAlarmManagerPlugin} when it receives the {@code - * AlarmService.initialized} message. Processes all alarm events that came in while the isolate - * was starting. - */ - /* package */ - static void onInitialized() { - Log.i(TAG, "AlarmService started!"); - synchronized (alarmQueue) { - // Handle all the alarm events received before the Dart isolate was - // initialized, then clear the queue. - for (Intent intent : alarmQueue) { - flutterBackgroundExecutor.executeDartCallbackInBackgroundIsolate(intent, null); - } - alarmQueue.clear(); + protected static final String SHARED_PREFERENCES_KEY = + "dev.fluttercommunity.plus.android_alarm_manager_plugin"; + private static final String TAG = "AlarmService"; + private static final String PERSISTENT_ALARMS_SET_KEY = "persistent_alarm_ids"; + private static final int JOB_ID = 1984; // Random job ID. + private static final Object persistentAlarmsLock = new Object(); + + // TODO(mattcarroll): make alarmQueue per-instance, not static. + private static final List alarmQueue = Collections.synchronizedList(new LinkedList<>()); + + /** + * Background Dart execution context. + */ + private static FlutterBackgroundExecutor flutterBackgroundExecutor; + + /** + * Schedule the alarm to be handled by the {@link AlarmService}. + */ + public static void enqueueAlarmProcessing(Context context, Intent alarmContext) { + enqueueWork(context, AlarmService.class, JOB_ID, alarmContext); } - } - - /** - * Sets the Dart callback handle for the Dart method that is responsible for initializing the - * background Dart isolate, preparing it to receive Dart callback tasks requests. - */ - public static void setCallbackDispatcher(Context context, long callbackHandle) { - FlutterBackgroundExecutor.setCallbackDispatcher(context, callbackHandle); - } - - private static void scheduleAlarm( - Context context, - int requestCode, - boolean alarmClock, - boolean allowWhileIdle, - boolean repeating, - boolean exact, - boolean wakeup, - long startMillis, - long intervalMillis, - boolean rescheduleOnReboot, - long callbackHandle, - JSONObject params) { - if (rescheduleOnReboot) { - addPersistentAlarm( - context, - requestCode, - alarmClock, - allowWhileIdle, - repeating, - exact, - wakeup, - startMillis, - intervalMillis, - callbackHandle, - params); + + /** + * Starts the background isolate for the {@link AlarmService}. + * + *

Preconditions: + * + *

    + *
  • The given {@code callbackHandle} must correspond to a registered Dart callback. If the + * handle does not resolve to a Dart callback then this method does nothing. + *
  • A static {@link #pluginRegistrantCallback} must exist, otherwise a {@link + * PluginRegistrantException} will be thrown. + *
+ */ + public static void startBackgroundIsolate(Context context, long callbackHandle) { + if (flutterBackgroundExecutor != null) { + Log.w(TAG, "Attempted to start a duplicate background isolate. Returning..."); + return; + } + flutterBackgroundExecutor = new FlutterBackgroundExecutor(); + flutterBackgroundExecutor.startBackgroundIsolate(context, callbackHandle); } - // Create an Intent for the alarm and set the desired Dart callback handle. - Intent alarm = new Intent(context, AlarmBroadcastReceiver.class); - alarm.putExtra("id", requestCode); - alarm.putExtra("callbackHandle", callbackHandle); - alarm.putExtra("params", params == null ? null : params.toString()); - PendingIntent pendingIntent = - PendingIntent.getBroadcast( - context, - requestCode, - alarm, - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0) - | PendingIntent.FLAG_UPDATE_CURRENT); - - // Use the appropriate clock. - int clock = AlarmManager.RTC; - if (wakeup) { - clock = AlarmManager.RTC_WAKEUP; + /** + * Called once the Dart isolate ({@code flutterBackgroundExecutor}) has finished initializing. + * + *

Invoked by {@link AndroidAlarmManagerPlugin} when it receives the {@code + * AlarmService.initialized} message. Processes all alarm events that came in while the isolate + * was starting. + */ + /* package */ + static void onInitialized() { + Log.i(TAG, "AlarmService started!"); + synchronized (alarmQueue) { + // Handle all the alarm events received before the Dart isolate was + // initialized, then clear the queue. + for (Intent intent : alarmQueue) { + flutterBackgroundExecutor.executeDartCallbackInBackgroundIsolate(intent, null); + } + alarmQueue.clear(); + } } - // Schedule the alarm. - AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - - if (alarmClock) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !manager.canScheduleExactAlarms()) { - Log.e(TAG, "Can`t schedule exact alarm due to revoked SCHEDULE_EXACT_ALARM permission"); - } else { - PendingIntent showPendingIntent = createShowPendingIntent(context, requestCode, params); - AlarmManagerCompat.setAlarmClock( - manager, startMillis, - showPendingIntent, pendingIntent); - } - return; + /** + * Sets the Dart callback handle for the Dart method that is responsible for initializing the + * background Dart isolate, preparing it to receive Dart callback tasks requests. + */ + public static void setCallbackDispatcher(Context context, long callbackHandle) { + FlutterBackgroundExecutor.setCallbackDispatcher(context, callbackHandle); } - if (exact) { - if (repeating) { - manager.setRepeating(clock, startMillis, intervalMillis, pendingIntent); - } else { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !manager.canScheduleExactAlarms()) { - Log.e(TAG, "Can`t schedule exact alarm due to revoked SCHEDULE_EXACT_ALARM permission"); - } else { - if (allowWhileIdle) { - AlarmManagerCompat.setExactAndAllowWhileIdle( - manager, clock, startMillis, pendingIntent); - } else { - AlarmManagerCompat.setExact(manager, clock, startMillis, pendingIntent); - } + private static void scheduleAlarm( + Context context, + int requestCode, + boolean alarmClock, + boolean allowWhileIdle, + boolean repeating, + boolean exact, + boolean wakeup, + long startMillis, + long intervalMillis, + boolean rescheduleOnReboot, + long callbackHandle, + JSONObject params) { + if (rescheduleOnReboot) { + addPersistentAlarm( + context, + requestCode, + alarmClock, + allowWhileIdle, + repeating, + exact, + wakeup, + startMillis, + intervalMillis, + callbackHandle, + params); } - } - } else { - if (repeating) { - manager.setInexactRepeating(clock, startMillis, intervalMillis, pendingIntent); - } else { - if (allowWhileIdle) { - AlarmManagerCompat.setAndAllowWhileIdle(manager, clock, startMillis, pendingIntent); + + // Create an Intent for the alarm and set the desired Dart callback handle. + Intent alarm = new Intent(context, AlarmBroadcastReceiver.class); + alarm.putExtra("id", requestCode); + alarm.putExtra("callbackHandle", callbackHandle); + alarm.putExtra("params", params == null ? null : params.toString()); + PendingIntent pendingIntent = + PendingIntent.getBroadcast( + context, + requestCode, + alarm, + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0) + | PendingIntent.FLAG_UPDATE_CURRENT); + + // Use the appropriate clock. + int clock = AlarmManager.RTC; + if (wakeup) { + clock = AlarmManager.RTC_WAKEUP; + } + + // Schedule the alarm. + AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + + if (alarmClock) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !manager.canScheduleExactAlarms()) { + Log.e(TAG, "Can`t schedule exact alarm due to revoked SCHEDULE_EXACT_ALARM permission"); + } else { + PendingIntent showPendingIntent = createShowPendingIntent(context, requestCode, params); + AlarmManagerCompat.setAlarmClock( + manager, startMillis, + showPendingIntent, pendingIntent); + } + return; + } + + if (exact) { + if (repeating) { + manager.setRepeating(clock, startMillis, intervalMillis, pendingIntent); + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !manager.canScheduleExactAlarms()) { + Log.e(TAG, "Can`t schedule exact alarm due to revoked SCHEDULE_EXACT_ALARM permission"); + } else { + if (allowWhileIdle) { + AlarmManagerCompat.setExactAndAllowWhileIdle( + manager, clock, startMillis, pendingIntent); + } else { + AlarmManagerCompat.setExact(manager, clock, startMillis, pendingIntent); + } + } + } } else { - manager.set(clock, startMillis, pendingIntent); + if (repeating) { + manager.setInexactRepeating(clock, startMillis, intervalMillis, pendingIntent); + } else { + if (allowWhileIdle) { + AlarmManagerCompat.setAndAllowWhileIdle(manager, clock, startMillis, pendingIntent); + } else { + manager.set(clock, startMillis, pendingIntent); + } + } } - } } - } - - /** Schedules a one-shot alarm to be executed once in the future. */ - public static void setOneShot(Context context, AndroidAlarmManagerPlugin.OneShotRequest request) { - final boolean repeating = false; - scheduleAlarm( - context, - request.requestCode, - request.alarmClock, - request.allowWhileIdle, - repeating, - request.exact, - request.wakeup, - request.startMillis, - 0, - request.rescheduleOnReboot, - request.callbackHandle, - request.params); - } - - /** Schedules a periodic alarm to be executed repeatedly in the future. */ - public static void setPeriodic( - Context context, AndroidAlarmManagerPlugin.PeriodicRequest request) { - final boolean repeating = true; - final boolean alarmClock = false; - scheduleAlarm( - context, - request.requestCode, - alarmClock, - request.allowWhileIdle, - repeating, - request.exact, - request.wakeup, - request.startMillis, - request.intervalMillis, - request.rescheduleOnReboot, - request.callbackHandle, - request.params); - } - - /** Cancels an alarm with ID {@code requestCode}. */ - public static void cancel(Context context, int requestCode) { - // Clear the alarm if it was set to be rescheduled after reboots. - clearPersistentAlarm(context, requestCode); - - // Cancel the alarm with the system alarm service. - Intent alarm = new Intent(context, AlarmBroadcastReceiver.class); - PendingIntent existingIntent = - PendingIntent.getBroadcast( - context, - requestCode, - alarm, - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0) - | PendingIntent.FLAG_NO_CREATE); - if (existingIntent == null) { - Log.i(TAG, "cancel: broadcast receiver not found"); - return; + + /** + * Schedules a one-shot alarm to be executed once in the future. + */ + public static void setOneShot(Context context, AndroidAlarmManagerPlugin.OneShotRequest request) { + final boolean repeating = false; + scheduleAlarm( + context, + request.requestCode, + request.alarmClock, + request.allowWhileIdle, + repeating, + request.exact, + request.wakeup, + request.startMillis, + 0, + request.rescheduleOnReboot, + request.callbackHandle, + request.params); } - AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - manager.cancel(existingIntent); - } - - private static String getPersistentAlarmKey(int requestCode) { - return "android_alarm_manager/persistent_alarm_" + requestCode; - } - - private static void addPersistentAlarm( - Context context, - int requestCode, - boolean alarmClock, - boolean allowWhileIdle, - boolean repeating, - boolean exact, - boolean wakeup, - long startMillis, - long intervalMillis, - long callbackHandle, - JSONObject params) { - HashMap alarmSettings = new HashMap<>(); - alarmSettings.put("alarmClock", alarmClock); - alarmSettings.put("allowWhileIdle", allowWhileIdle); - alarmSettings.put("repeating", repeating); - alarmSettings.put("exact", exact); - alarmSettings.put("wakeup", wakeup); - alarmSettings.put("startMillis", startMillis); - alarmSettings.put("intervalMillis", intervalMillis); - alarmSettings.put("callbackHandle", callbackHandle); - alarmSettings.put("params", params); - JSONObject obj = new JSONObject(alarmSettings); - String key = getPersistentAlarmKey(requestCode); - SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0); - - synchronized (persistentAlarmsLock) { - Set persistentAlarms = - new HashSet<>(prefs.getStringSet(PERSISTENT_ALARMS_SET_KEY, new HashSet<>())); - if (persistentAlarms.isEmpty()) { - RebootBroadcastReceiver.enableRescheduleOnReboot(context); - } - persistentAlarms.add(Integer.toString(requestCode)); - prefs - .edit() - .putString(key, obj.toString()) - .putStringSet(PERSISTENT_ALARMS_SET_KEY, persistentAlarms) - .apply(); + + /** + * Schedules a periodic alarm to be executed repeatedly in the future. + */ + public static void setPeriodic( + Context context, AndroidAlarmManagerPlugin.PeriodicRequest request) { + final boolean repeating = true; + final boolean alarmClock = false; + scheduleAlarm( + context, + request.requestCode, + alarmClock, + request.allowWhileIdle, + repeating, + request.exact, + request.wakeup, + request.startMillis, + request.intervalMillis, + request.rescheduleOnReboot, + request.callbackHandle, + request.params); } - } - - private static void clearPersistentAlarm(Context context, int requestCode) { - SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0); - synchronized (persistentAlarmsLock) { - Set persistentAlarms = - new HashSet<>(prefs.getStringSet(PERSISTENT_ALARMS_SET_KEY, new HashSet<>())); - if (!persistentAlarms.contains(Integer.toString(requestCode))) { - return; - } - persistentAlarms.remove(Integer.toString(requestCode)); - String key = getPersistentAlarmKey(requestCode); - prefs.edit().remove(key).putStringSet(PERSISTENT_ALARMS_SET_KEY, persistentAlarms).apply(); - - if (persistentAlarms.isEmpty()) { - RebootBroadcastReceiver.disableRescheduleOnReboot(context); - } + + /** + * Cancels an alarm with ID {@code requestCode}. + */ + public static void cancel(Context context, int requestCode) { + // Clear the alarm if it was set to be rescheduled after reboots. + clearPersistentAlarm(context, requestCode); + + // Cancel the alarm with the system alarm service. + Intent alarm = new Intent(context, AlarmBroadcastReceiver.class); + PendingIntent existingIntent = + PendingIntent.getBroadcast( + context, + requestCode, + alarm, + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0) + | PendingIntent.FLAG_NO_CREATE); + if (existingIntent == null) { + Log.i(TAG, "cancel: broadcast receiver not found"); + return; + } + AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + manager.cancel(existingIntent); + } + + private static String getPersistentAlarmKey(int requestCode) { + return "android_alarm_manager/persistent_alarm_" + requestCode; } - } - - public static void reschedulePersistentAlarms(Context context) { - synchronized (persistentAlarmsLock) { - SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0); - Set persistentAlarms = prefs.getStringSet(PERSISTENT_ALARMS_SET_KEY, null); - // No alarms to reschedule. - if (persistentAlarms == null) { - return; - } - - for (String persistentAlarm : persistentAlarms) { - int requestCode = Integer.parseInt(persistentAlarm); + + private static void addPersistentAlarm( + Context context, + int requestCode, + boolean alarmClock, + boolean allowWhileIdle, + boolean repeating, + boolean exact, + boolean wakeup, + long startMillis, + long intervalMillis, + long callbackHandle, + JSONObject params) { + HashMap alarmSettings = new HashMap<>(); + alarmSettings.put("alarmClock", alarmClock); + alarmSettings.put("allowWhileIdle", allowWhileIdle); + alarmSettings.put("repeating", repeating); + alarmSettings.put("exact", exact); + alarmSettings.put("wakeup", wakeup); + alarmSettings.put("startMillis", startMillis); + alarmSettings.put("intervalMillis", intervalMillis); + alarmSettings.put("callbackHandle", callbackHandle); + alarmSettings.put("params", params); + JSONObject obj = new JSONObject(alarmSettings); String key = getPersistentAlarmKey(requestCode); - String json = prefs.getString(key, null); - if (json == null) { - Log.e(TAG, "Data for alarm request code " + requestCode + " is invalid."); - continue; + SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0); + + synchronized (persistentAlarmsLock) { + Set persistentAlarms = + new HashSet<>(prefs.getStringSet(PERSISTENT_ALARMS_SET_KEY, new HashSet<>())); + if (persistentAlarms.isEmpty()) { + RebootBroadcastReceiver.enableRescheduleOnReboot(context); + } + persistentAlarms.add(Integer.toString(requestCode)); + prefs + .edit() + .putString(key, obj.toString()) + .putStringSet(PERSISTENT_ALARMS_SET_KEY, persistentAlarms) + .apply(); } - try { - JSONObject alarm = new JSONObject(json); - boolean alarmClock = alarm.getBoolean("alarmClock"); - boolean allowWhileIdle = alarm.getBoolean("allowWhileIdle"); - boolean repeating = alarm.getBoolean("repeating"); - boolean exact = alarm.getBoolean("exact"); - boolean wakeup = alarm.getBoolean("wakeup"); - long startMillis = alarm.getLong("startMillis"); - long intervalMillis = alarm.getLong("intervalMillis"); - long callbackHandle = alarm.getLong("callbackHandle"); - JSONObject params = alarm.getJSONObject("params"); - scheduleAlarm( - context, - requestCode, - alarmClock, - allowWhileIdle, - repeating, - exact, - wakeup, - startMillis, - intervalMillis, - false, - callbackHandle, - params); - } catch (JSONException e) { - Log.e(TAG, "Data for alarm request code " + requestCode + " is invalid: " + json); + } + + private static void clearPersistentAlarm(Context context, int requestCode) { + SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0); + synchronized (persistentAlarmsLock) { + Set persistentAlarms = + new HashSet<>(prefs.getStringSet(PERSISTENT_ALARMS_SET_KEY, new HashSet<>())); + if (!persistentAlarms.contains(Integer.toString(requestCode))) { + return; + } + persistentAlarms.remove(Integer.toString(requestCode)); + String key = getPersistentAlarmKey(requestCode); + prefs.edit().remove(key).putStringSet(PERSISTENT_ALARMS_SET_KEY, persistentAlarms).apply(); + + if (persistentAlarms.isEmpty()) { + RebootBroadcastReceiver.disableRescheduleOnReboot(context); + } } - } } - } - - private static PendingIntent createShowPendingIntent( - Context context, int requestCode, JSONObject params) { - PackageManager packageManager = context.getPackageManager(); - String appId = context.getPackageName(); - Intent launchIntent = packageManager.getLaunchIntentForPackage(appId); - launchIntent.putExtra("id", requestCode); - launchIntent.putExtra("params", params == null ? null : params.toString()); - return PendingIntent.getActivity( - context, - requestCode, - launchIntent, - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0) - | PendingIntent.FLAG_UPDATE_CURRENT); - } - - @Override - public void onCreate() { - super.onCreate(); - if (flutterBackgroundExecutor == null) { - flutterBackgroundExecutor = new FlutterBackgroundExecutor(); + + public static void reschedulePersistentAlarms(Context context) { + synchronized (persistentAlarmsLock) { + SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0); + Set persistentAlarms = prefs.getStringSet(PERSISTENT_ALARMS_SET_KEY, null); + // No alarms to reschedule. + if (persistentAlarms == null) { + return; + } + + for (String persistentAlarm : persistentAlarms) { + int requestCode = Integer.parseInt(persistentAlarm); + String key = getPersistentAlarmKey(requestCode); + String json = prefs.getString(key, null); + if (json == null) { + Log.e(TAG, "Data for alarm request code " + requestCode + " is invalid."); + continue; + } + try { + JSONObject alarm = new JSONObject(json); + boolean alarmClock = alarm.getBoolean("alarmClock"); + boolean allowWhileIdle = alarm.getBoolean("allowWhileIdle"); + boolean repeating = alarm.getBoolean("repeating"); + boolean exact = alarm.getBoolean("exact"); + boolean wakeup = alarm.getBoolean("wakeup"); + long startMillis = alarm.getLong("startMillis"); + long intervalMillis = alarm.getLong("intervalMillis"); + long callbackHandle = alarm.getLong("callbackHandle"); + JSONObject params = alarm.getJSONObject("params"); + scheduleAlarm( + context, + requestCode, + alarmClock, + allowWhileIdle, + repeating, + exact, + wakeup, + startMillis, + intervalMillis, + false, + callbackHandle, + params); + } catch (JSONException e) { + Log.e(TAG, "Data for alarm request code " + requestCode + " is invalid: " + json); + } + } + } + } + + private static PendingIntent createShowPendingIntent( + Context context, int requestCode, JSONObject params) { + PackageManager packageManager = context.getPackageManager(); + String appId = context.getPackageName(); + Intent launchIntent = packageManager.getLaunchIntentForPackage(appId); + launchIntent.putExtra("id", requestCode); + launchIntent.putExtra("params", params == null ? null : params.toString()); + return PendingIntent.getActivity( + context, + requestCode, + launchIntent, + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0) + | PendingIntent.FLAG_UPDATE_CURRENT); } - Context context = getApplicationContext(); - flutterBackgroundExecutor.startBackgroundIsolate(context); - } - - /** - * Executes a Dart callback, as specified within the incoming {@code intent}. - * - *

Invoked by our {@link JobIntentService} superclass after a call to {@link - * JobIntentService#enqueueWork(Context, Class, int, Intent);}. - * - *

If there are no pre-existing callback execution requests, other than the incoming {@code - * intent}, then the desired Dart callback is invoked immediately. - * - *

If there are any pre-existing callback requests that have yet to be executed, the incoming - * {@code intent} is added to the {@link #alarmQueue} to invoked later, after all pre-existing - * callbacks have been executed. - */ - @Override - protected void onHandleWork(@NonNull final Intent intent) { - // If we're in the middle of processing queued alarms, add the incoming - // intent to the queue and return. - synchronized (alarmQueue) { - if (!flutterBackgroundExecutor.isRunning()) { - Log.i(TAG, "AlarmService has not yet started."); - alarmQueue.add(intent); - return; - } + + @Override + public void onCreate() { + super.onCreate(); + if (flutterBackgroundExecutor == null) { + flutterBackgroundExecutor = new FlutterBackgroundExecutor(); + } + Context context = getApplicationContext(); + flutterBackgroundExecutor.startBackgroundIsolate(context); } - // There were no pre-existing callback requests. Execute the callback - // specified by the incoming intent. - final CountDownLatch latch = new CountDownLatch(1); - new Handler(getMainLooper()) - .post( - () -> flutterBackgroundExecutor.executeDartCallbackInBackgroundIsolate(intent, latch)); - - try { - latch.await(); - } catch (InterruptedException ex) { - Log.i(TAG, "Exception waiting to execute Dart callback", ex); + /** + * Executes a Dart callback, as specified within the incoming {@code intent}. + * + *

Invoked by our {@link JobIntentService} superclass after a call to {@link + * JobIntentService#enqueueWork(Context, Class, int, Intent);}. + * + *

If there are no pre-existing callback execution requests, other than the incoming {@code + * intent}, then the desired Dart callback is invoked immediately. + * + *

If there are any pre-existing callback requests that have yet to be executed, the incoming + * {@code intent} is added to the {@link #alarmQueue} to invoked later, after all pre-existing + * callbacks have been executed. + */ + @Override + protected void onHandleWork(@NonNull final Intent intent) { + // If we're in the middle of processing queued alarms, add the incoming + // intent to the queue and return. + synchronized (alarmQueue) { + if (!flutterBackgroundExecutor.isRunning()) { + Log.i(TAG, "AlarmService has not yet started."); + alarmQueue.add(intent); + return; + } + } + + // There were no pre-existing callback requests. Execute the callback + // specified by the incoming intent. + final CountDownLatch latch = new CountDownLatch(1); + new Handler(getMainLooper()) + .post( + () -> flutterBackgroundExecutor.executeDartCallbackInBackgroundIsolate(intent, latch)); + + try { + latch.await(); + } catch (InterruptedException ex) { + Log.i(TAG, "Exception waiting to execute Dart callback", ex); + } } - } } diff --git a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/AndroidAlarmManagerPlugin.java b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/AndroidAlarmManagerPlugin.java index 3483912128..10d30f6052 100644 --- a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/AndroidAlarmManagerPlugin.java +++ b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/AndroidAlarmManagerPlugin.java @@ -6,6 +6,7 @@ import android.content.Context; import android.util.Log; + import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.BinaryMessenger; @@ -14,6 +15,7 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -41,214 +43,219 @@ * */ public class AndroidAlarmManagerPlugin implements FlutterPlugin, MethodCallHandler { - private static final String TAG = "AndroidAlarmManagerPlugin"; - private Context context; - private final Object initializationLock = new Object(); - private MethodChannel alarmManagerPluginChannel; - - @Override - public void onAttachedToEngine(FlutterPluginBinding binding) { - onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger()); - } - - public void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger) { - synchronized (initializationLock) { - if (alarmManagerPluginChannel != null) { - return; - } - - Log.i(TAG, "onAttachedToEngine"); - this.context = applicationContext; - - // alarmManagerPluginChannel is the channel responsible for receiving the following messages - // from the main Flutter app: - // - "AlarmService.start" - // - "Alarm.oneShotAt" - // - "Alarm.periodic" - // - "Alarm.cancel" - alarmManagerPluginChannel = - new MethodChannel( - messenger, - "dev.fluttercommunity.plus/android_alarm_manager", - JSONMethodCodec.INSTANCE); - - // Instantiate a new AndroidAlarmManagerPlugin and connect the primary method channel for - // Android/Flutter communication. - alarmManagerPluginChannel.setMethodCallHandler(this); + private static final String TAG = "AndroidAlarmManagerPlugin"; + private final Object initializationLock = new Object(); + private Context context; + private MethodChannel alarmManagerPluginChannel; + + public AndroidAlarmManagerPlugin() { } - } - - @Override - public void onDetachedFromEngine(FlutterPluginBinding binding) { - Log.i(TAG, "onDetachedFromEngine"); - context = null; - alarmManagerPluginChannel.setMethodCallHandler(null); - alarmManagerPluginChannel = null; - } - - public AndroidAlarmManagerPlugin() {} - - /** Invoked when the Flutter side of this plugin sends a message to the Android side. */ - @Override - public void onMethodCall(MethodCall call, Result result) { - String method = call.method; - Object arguments = call.arguments; - try { - switch (method) { - case "AlarmService.start": - // This message is sent when the Dart side of this plugin is told to initialize. - long callbackHandle = ((JSONArray) arguments).getLong(0); - // In response, this (native) side of the plugin needs to spin up a background - // Dart isolate by using the given callbackHandle, and then setup a background - // method channel to communicate with the new background isolate. Once completed, - // this onMethodCall() method will receive messages from both the primary and background - // method channels. - AlarmService.setCallbackDispatcher(context, callbackHandle); - AlarmService.startBackgroundIsolate(context, callbackHandle); - result.success(true); - break; - case "Alarm.periodic": - // This message indicates that the Flutter app would like to schedule a periodic - // task. - PeriodicRequest periodicRequest = PeriodicRequest.fromJson((JSONArray) arguments); - AlarmService.setPeriodic(context, periodicRequest); - result.success(true); - break; - case "Alarm.oneShotAt": - // This message indicates that the Flutter app would like to schedule a one-time - // task. - OneShotRequest oneShotRequest = OneShotRequest.fromJson((JSONArray) arguments); - AlarmService.setOneShot(context, oneShotRequest); - result.success(true); - break; - case "Alarm.cancel": - // This message indicates that the Flutter app would like to cancel a previously - // scheduled task. - int requestCode = ((JSONArray) arguments).getInt(0); - AlarmService.cancel(context, requestCode); - result.success(true); - break; - default: - result.notImplemented(); - break; - } - } catch (JSONException e) { - result.error("error", "JSON error: " + e.getMessage(), null); - } catch (PluginRegistrantException e) { - result.error("error", "AlarmManager error: " + e.getMessage(), null); + + @Override + public void onAttachedToEngine(FlutterPluginBinding binding) { + onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger()); + } + + public void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger) { + synchronized (initializationLock) { + if (alarmManagerPluginChannel != null) { + return; + } + + Log.i(TAG, "onAttachedToEngine"); + this.context = applicationContext; + + // alarmManagerPluginChannel is the channel responsible for receiving the following messages + // from the main Flutter app: + // - "AlarmService.start" + // - "Alarm.oneShotAt" + // - "Alarm.periodic" + // - "Alarm.cancel" + alarmManagerPluginChannel = + new MethodChannel( + messenger, + "dev.fluttercommunity.plus/android_alarm_manager", + JSONMethodCodec.INSTANCE); + + // Instantiate a new AndroidAlarmManagerPlugin and connect the primary method channel for + // Android/Flutter communication. + alarmManagerPluginChannel.setMethodCallHandler(this); + } } - } - - /** A request to schedule a one-shot Dart task. */ - static final class OneShotRequest { - static OneShotRequest fromJson(JSONArray json) throws JSONException { - int requestCode = json.getInt(0); - boolean alarmClock = json.getBoolean(1); - boolean allowWhileIdle = json.getBoolean(2); - boolean exact = json.getBoolean(3); - boolean wakeup = json.getBoolean(4); - long startMillis = json.getLong(5); - boolean rescheduleOnReboot = json.getBoolean(6); - long callbackHandle = json.getLong(7); - JSONObject params = json.getJSONObject(8); - - return new OneShotRequest( - requestCode, - alarmClock, - allowWhileIdle, - exact, - wakeup, - startMillis, - rescheduleOnReboot, - callbackHandle, - params); + + @Override + public void onDetachedFromEngine(FlutterPluginBinding binding) { + Log.i(TAG, "onDetachedFromEngine"); + context = null; + alarmManagerPluginChannel.setMethodCallHandler(null); + alarmManagerPluginChannel = null; } - final int requestCode; - final boolean alarmClock; - final boolean allowWhileIdle; - final boolean exact; - final boolean wakeup; - final long startMillis; - final boolean rescheduleOnReboot; - final long callbackHandle; - final JSONObject params; - - OneShotRequest( - int requestCode, - boolean alarmClock, - boolean allowWhileIdle, - boolean exact, - boolean wakeup, - long startMillis, - boolean rescheduleOnReboot, - long callbackHandle, - JSONObject params) { - this.requestCode = requestCode; - this.alarmClock = alarmClock; - this.allowWhileIdle = allowWhileIdle; - this.exact = exact; - this.wakeup = wakeup; - this.startMillis = startMillis; - this.rescheduleOnReboot = rescheduleOnReboot; - this.callbackHandle = callbackHandle; - this.params = params; + /** + * Invoked when the Flutter side of this plugin sends a message to the Android side. + */ + @Override + public void onMethodCall(MethodCall call, Result result) { + String method = call.method; + Object arguments = call.arguments; + try { + switch (method) { + case "AlarmService.start": + // This message is sent when the Dart side of this plugin is told to initialize. + long callbackHandle = ((JSONArray) arguments).getLong(0); + // In response, this (native) side of the plugin needs to spin up a background + // Dart isolate by using the given callbackHandle, and then setup a background + // method channel to communicate with the new background isolate. Once completed, + // this onMethodCall() method will receive messages from both the primary and background + // method channels. + AlarmService.setCallbackDispatcher(context, callbackHandle); + AlarmService.startBackgroundIsolate(context, callbackHandle); + result.success(true); + break; + case "Alarm.periodic": + // This message indicates that the Flutter app would like to schedule a periodic + // task. + PeriodicRequest periodicRequest = PeriodicRequest.fromJson((JSONArray) arguments); + AlarmService.setPeriodic(context, periodicRequest); + result.success(true); + break; + case "Alarm.oneShotAt": + // This message indicates that the Flutter app would like to schedule a one-time + // task. + OneShotRequest oneShotRequest = OneShotRequest.fromJson((JSONArray) arguments); + AlarmService.setOneShot(context, oneShotRequest); + result.success(true); + break; + case "Alarm.cancel": + // This message indicates that the Flutter app would like to cancel a previously + // scheduled task. + int requestCode = ((JSONArray) arguments).getInt(0); + AlarmService.cancel(context, requestCode); + result.success(true); + break; + default: + result.notImplemented(); + break; + } + } catch (JSONException e) { + result.error("error", "JSON error: " + e.getMessage(), null); + } catch (PluginRegistrantException e) { + result.error("error", "AlarmManager error: " + e.getMessage(), null); + } } - } - - /** A request to schedule a periodic Dart task. */ - static final class PeriodicRequest { - static PeriodicRequest fromJson(JSONArray json) throws JSONException { - int requestCode = json.getInt(0); - boolean allowWhileIdle = json.getBoolean(1); - boolean exact = json.getBoolean(2); - boolean wakeup = json.getBoolean(3); - long startMillis = json.getLong(4); - long intervalMillis = json.getLong(5); - boolean rescheduleOnReboot = json.getBoolean(6); - long callbackHandle = json.getLong(7); - JSONObject params = json.getJSONObject(8); - return new PeriodicRequest( - requestCode, - allowWhileIdle, - exact, - wakeup, - startMillis, - intervalMillis, - rescheduleOnReboot, - callbackHandle, - params); + + /** + * A request to schedule a one-shot Dart task. + */ + static final class OneShotRequest { + final int requestCode; + final boolean alarmClock; + final boolean allowWhileIdle; + final boolean exact; + final boolean wakeup; + final long startMillis; + final boolean rescheduleOnReboot; + final long callbackHandle; + final JSONObject params; + OneShotRequest( + int requestCode, + boolean alarmClock, + boolean allowWhileIdle, + boolean exact, + boolean wakeup, + long startMillis, + boolean rescheduleOnReboot, + long callbackHandle, + JSONObject params) { + this.requestCode = requestCode; + this.alarmClock = alarmClock; + this.allowWhileIdle = allowWhileIdle; + this.exact = exact; + this.wakeup = wakeup; + this.startMillis = startMillis; + this.rescheduleOnReboot = rescheduleOnReboot; + this.callbackHandle = callbackHandle; + this.params = params; + } + + static OneShotRequest fromJson(JSONArray json) throws JSONException { + int requestCode = json.getInt(0); + boolean alarmClock = json.getBoolean(1); + boolean allowWhileIdle = json.getBoolean(2); + boolean exact = json.getBoolean(3); + boolean wakeup = json.getBoolean(4); + long startMillis = json.getLong(5); + boolean rescheduleOnReboot = json.getBoolean(6); + long callbackHandle = json.getLong(7); + JSONObject params = json.getJSONObject(8); + + return new OneShotRequest( + requestCode, + alarmClock, + allowWhileIdle, + exact, + wakeup, + startMillis, + rescheduleOnReboot, + callbackHandle, + params); + } } - final int requestCode; - final boolean allowWhileIdle; - final boolean exact; - final boolean wakeup; - final long startMillis; - final long intervalMillis; - final boolean rescheduleOnReboot; - final long callbackHandle; - final JSONObject params; - - PeriodicRequest( - int requestCode, - boolean allowWhileIdle, - boolean exact, - boolean wakeup, - long startMillis, - long intervalMillis, - boolean rescheduleOnReboot, - long callbackHandle, - JSONObject params) { - this.requestCode = requestCode; - this.allowWhileIdle = allowWhileIdle; - this.exact = exact; - this.wakeup = wakeup; - this.startMillis = startMillis; - this.intervalMillis = intervalMillis; - this.rescheduleOnReboot = rescheduleOnReboot; - this.callbackHandle = callbackHandle; - this.params = params; + /** + * A request to schedule a periodic Dart task. + */ + static final class PeriodicRequest { + final int requestCode; + final boolean allowWhileIdle; + final boolean exact; + final boolean wakeup; + final long startMillis; + final long intervalMillis; + final boolean rescheduleOnReboot; + final long callbackHandle; + final JSONObject params; + PeriodicRequest( + int requestCode, + boolean allowWhileIdle, + boolean exact, + boolean wakeup, + long startMillis, + long intervalMillis, + boolean rescheduleOnReboot, + long callbackHandle, + JSONObject params) { + this.requestCode = requestCode; + this.allowWhileIdle = allowWhileIdle; + this.exact = exact; + this.wakeup = wakeup; + this.startMillis = startMillis; + this.intervalMillis = intervalMillis; + this.rescheduleOnReboot = rescheduleOnReboot; + this.callbackHandle = callbackHandle; + this.params = params; + } + + static PeriodicRequest fromJson(JSONArray json) throws JSONException { + int requestCode = json.getInt(0); + boolean allowWhileIdle = json.getBoolean(1); + boolean exact = json.getBoolean(2); + boolean wakeup = json.getBoolean(3); + long startMillis = json.getLong(4); + long intervalMillis = json.getLong(5); + boolean rescheduleOnReboot = json.getBoolean(6); + long callbackHandle = json.getLong(7); + JSONObject params = json.getJSONObject(8); + return new PeriodicRequest( + requestCode, + allowWhileIdle, + exact, + wakeup, + startMillis, + intervalMillis, + rescheduleOnReboot, + callbackHandle, + params); + } } - } } diff --git a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/FlutterBackgroundExecutor.java b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/FlutterBackgroundExecutor.java index 20677d95fa..74674baf69 100644 --- a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/FlutterBackgroundExecutor.java +++ b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/FlutterBackgroundExecutor.java @@ -10,6 +10,7 @@ import android.content.res.AssetManager; import android.text.TextUtils; import android.util.Log; + import io.flutter.FlutterInjector; import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.dart.DartExecutor; @@ -21,8 +22,10 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.view.FlutterCallbackInformation; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; + import org.json.JSONException; import org.json.JSONObject; @@ -31,198 +34,197 @@ * callback dispatcher, used to invoke Dart callbacks while backgrounded. */ public class FlutterBackgroundExecutor implements MethodCallHandler { - private static final String TAG = "FlutterBackgroundExecutor"; - private static final String CALLBACK_HANDLE_KEY = "callback_handle"; - - /** - * The {@link MethodChannel} that connects the Android side of this plugin with the background - * Dart isolate that was created by this plugin. - */ - private MethodChannel backgroundChannel; - - private FlutterEngine backgroundFlutterEngine; - - private final AtomicBoolean isCallbackDispatcherReady = new AtomicBoolean(false); - - /** - * Sets the Dart callback handle for the Dart method that is responsible for initializing the - * background Dart isolate, preparing it to receive Dart callback tasks requests. - */ - public static void setCallbackDispatcher(Context context, long callbackHandle) { - SharedPreferences prefs = context.getSharedPreferences(AlarmService.SHARED_PREFERENCES_KEY, 0); - prefs.edit().putLong(CALLBACK_HANDLE_KEY, callbackHandle).apply(); - } - - /** Returns true when the background isolate has started and is ready to handle alarms. */ - public boolean isRunning() { - return isCallbackDispatcherReady.get(); - } - - private void onInitialized() { - isCallbackDispatcherReady.set(true); - AlarmService.onInitialized(); - } - - @Override - public void onMethodCall(MethodCall call, Result result) { - String method = call.method; - Object arguments = call.arguments; - try { - if (method.equals("AlarmService.initialized")) { - // This message is sent by the background method channel as soon as the background isolate - // is running. From this point forward, the Android side of this plugin can send - // callback handles through the background method channel, and the Dart side will execute - // the Dart methods corresponding to those callback handles. - onInitialized(); - result.success(true); - } else { - result.notImplemented(); - } - } catch (PluginRegistrantException e) { - result.error("error", "AlarmManager error: " + e.getMessage(), null); + private static final String TAG = "FlutterBackgroundExecutor"; + private static final String CALLBACK_HANDLE_KEY = "callback_handle"; + private final AtomicBoolean isCallbackDispatcherReady = new AtomicBoolean(false); + /** + * The {@link MethodChannel} that connects the Android side of this plugin with the background + * Dart isolate that was created by this plugin. + */ + private MethodChannel backgroundChannel; + private FlutterEngine backgroundFlutterEngine; + + /** + * Sets the Dart callback handle for the Dart method that is responsible for initializing the + * background Dart isolate, preparing it to receive Dart callback tasks requests. + */ + public static void setCallbackDispatcher(Context context, long callbackHandle) { + SharedPreferences prefs = context.getSharedPreferences(AlarmService.SHARED_PREFERENCES_KEY, 0); + prefs.edit().putLong(CALLBACK_HANDLE_KEY, callbackHandle).apply(); } - } - - /** - * Starts running a background Dart isolate within a new {@link FlutterEngine} using a previously - * used entrypoint. - * - *

The isolate is configured as follows: - * - *

    - *
  • Bundle Path: {@code FlutterMain.findAppBundlePath(context)}. - *
  • Entrypoint: The Dart method used the last time this plugin was initialized in the - * foreground. - *
  • Run args: none. - *
- * - *

Preconditions: - * - *

    - *
  • The given callback must correspond to a registered Dart callback. If the handle does not - * resolve to a Dart callback then this method does nothing. - *
- */ - public void startBackgroundIsolate(Context context) { - if (!isRunning()) { - SharedPreferences p = context.getSharedPreferences(AlarmService.SHARED_PREFERENCES_KEY, 0); - long callbackHandle = p.getLong(CALLBACK_HANDLE_KEY, 0); - startBackgroundIsolate(context, callbackHandle); + + /** + * Returns true when the background isolate has started and is ready to handle alarms. + */ + public boolean isRunning() { + return isCallbackDispatcherReady.get(); } - } - - /** - * Starts running a background Dart isolate within a new {@link FlutterEngine}. - * - *

The isolate is configured as follows: - * - *

    - *
  • Bundle Path: {@code FlutterMain.findAppBundlePath(context)}. - *
  • Entrypoint: The Dart method represented by {@code callbackHandle}. - *
  • Run args: none. - *
- * - *

Preconditions: - * - *

    - *
  • The given {@code callbackHandle} must correspond to a registered Dart callback. If the - * handle does not resolve to a Dart callback then this method does nothing. - *
- */ - public void startBackgroundIsolate(Context context, long callbackHandle) { - if (backgroundFlutterEngine != null) { - Log.e(TAG, "Background isolate already started"); - return; + + private void onInitialized() { + isCallbackDispatcherReady.set(true); + AlarmService.onInitialized(); } - Log.i(TAG, "Starting AlarmService..."); - if (!isRunning()) { - backgroundFlutterEngine = new FlutterEngine(context); + @Override + public void onMethodCall(MethodCall call, Result result) { + String method = call.method; + Object arguments = call.arguments; + try { + if (method.equals("AlarmService.initialized")) { + // This message is sent by the background method channel as soon as the background isolate + // is running. From this point forward, the Android side of this plugin can send + // callback handles through the background method channel, and the Dart side will execute + // the Dart methods corresponding to those callback handles. + onInitialized(); + result.success(true); + } else { + result.notImplemented(); + } + } catch (PluginRegistrantException e) { + result.error("error", "AlarmManager error: " + e.getMessage(), null); + } + } - String appBundlePath = FlutterInjector.instance().flutterLoader().findAppBundlePath(); - AssetManager assets = context.getAssets(); + /** + * Starts running a background Dart isolate within a new {@link FlutterEngine} using a previously + * used entrypoint. + * + *

The isolate is configured as follows: + * + *

    + *
  • Bundle Path: {@code FlutterMain.findAppBundlePath(context)}. + *
  • Entrypoint: The Dart method used the last time this plugin was initialized in the + * foreground. + *
  • Run args: none. + *
+ * + *

Preconditions: + * + *

    + *
  • The given callback must correspond to a registered Dart callback. If the handle does not + * resolve to a Dart callback then this method does nothing. + *
+ */ + public void startBackgroundIsolate(Context context) { + if (!isRunning()) { + SharedPreferences p = context.getSharedPreferences(AlarmService.SHARED_PREFERENCES_KEY, 0); + long callbackHandle = p.getLong(CALLBACK_HANDLE_KEY, 0); + startBackgroundIsolate(context, callbackHandle); + } + } - // We need to create an instance of `FlutterEngine` before looking up the - // callback. If we don't, the callback cache won't be initialized and the - // lookup will fail. - FlutterCallbackInformation flutterCallback = - FlutterCallbackInformation.lookupCallbackInformation(callbackHandle); - if (flutterCallback == null) { - Log.e(TAG, "Fatal: failed to find callback"); - return; - } + /** + * Starts running a background Dart isolate within a new {@link FlutterEngine}. + * + *

The isolate is configured as follows: + * + *

    + *
  • Bundle Path: {@code FlutterMain.findAppBundlePath(context)}. + *
  • Entrypoint: The Dart method represented by {@code callbackHandle}. + *
  • Run args: none. + *
+ * + *

Preconditions: + * + *

    + *
  • The given {@code callbackHandle} must correspond to a registered Dart callback. If the + * handle does not resolve to a Dart callback then this method does nothing. + *
+ */ + public void startBackgroundIsolate(Context context, long callbackHandle) { + if (backgroundFlutterEngine != null) { + Log.e(TAG, "Background isolate already started"); + return; + } + + Log.i(TAG, "Starting AlarmService..."); + if (!isRunning()) { + backgroundFlutterEngine = new FlutterEngine(context); + + String appBundlePath = FlutterInjector.instance().flutterLoader().findAppBundlePath(); + AssetManager assets = context.getAssets(); + + // We need to create an instance of `FlutterEngine` before looking up the + // callback. If we don't, the callback cache won't be initialized and the + // lookup will fail. + FlutterCallbackInformation flutterCallback = + FlutterCallbackInformation.lookupCallbackInformation(callbackHandle); + if (flutterCallback == null) { + Log.e(TAG, "Fatal: failed to find callback"); + return; + } - DartExecutor executor = backgroundFlutterEngine.getDartExecutor(); - initializeMethodChannel(executor); - DartCallback dartCallback = new DartCallback(assets, appBundlePath, flutterCallback); + DartExecutor executor = backgroundFlutterEngine.getDartExecutor(); + initializeMethodChannel(executor); + DartCallback dartCallback = new DartCallback(assets, appBundlePath, flutterCallback); - executor.executeDartCallback(dartCallback); + executor.executeDartCallback(dartCallback); + } } - } - - /** - * Executes the desired Dart callback in a background Dart isolate. - * - *

The given {@code intent} should contain a {@code long} extra called "callbackHandle", which - * corresponds to a callback registered with the Dart VM. - */ - public void executeDartCallbackInBackgroundIsolate(Intent intent, final CountDownLatch latch) { - // Grab the handle for the callback associated with this alarm. Pay close - // attention to the type of the callback handle as storing this value in a - // variable of the wrong size will cause the callback lookup to fail. - long callbackHandle = intent.getLongExtra("callbackHandle", 0); - String paramsJsonString = intent.getStringExtra("params"); - JSONObject params = null; - if (!TextUtils.isEmpty(paramsJsonString)) { - try { - params = new JSONObject(paramsJsonString); - } catch (JSONException e) { - throw new IllegalArgumentException("Can not convert 'params' to JsonObject", e); - } - } - // If another thread is waiting, then wake that thread when the callback returns a result. - MethodChannel.Result result = null; - if (latch != null) { - result = - new MethodChannel.Result() { - @Override - public void success(Object result) { - latch.countDown(); - } - @Override - public void error(String errorCode, String errorMessage, Object errorDetails) { - latch.countDown(); + /** + * Executes the desired Dart callback in a background Dart isolate. + * + *

The given {@code intent} should contain a {@code long} extra called "callbackHandle", which + * corresponds to a callback registered with the Dart VM. + */ + public void executeDartCallbackInBackgroundIsolate(Intent intent, final CountDownLatch latch) { + // Grab the handle for the callback associated with this alarm. Pay close + // attention to the type of the callback handle as storing this value in a + // variable of the wrong size will cause the callback lookup to fail. + long callbackHandle = intent.getLongExtra("callbackHandle", 0); + String paramsJsonString = intent.getStringExtra("params"); + JSONObject params = null; + if (!TextUtils.isEmpty(paramsJsonString)) { + try { + params = new JSONObject(paramsJsonString); + } catch (JSONException e) { + throw new IllegalArgumentException("Can not convert 'params' to JsonObject", e); } - - @Override - public void notImplemented() { - latch.countDown(); - } - }; + } + // If another thread is waiting, then wake that thread when the callback returns a result. + MethodChannel.Result result = null; + if (latch != null) { + result = + new MethodChannel.Result() { + @Override + public void success(Object result) { + latch.countDown(); + } + + @Override + public void error(String errorCode, String errorMessage, Object errorDetails) { + latch.countDown(); + } + + @Override + public void notImplemented() { + latch.countDown(); + } + }; + } + + // Handle the alarm event in Dart. Note that for this plugin, we don't + // care about the method name as we simply lookup and invoke the callback + // provided. + backgroundChannel.invokeMethod( + "invokeAlarmManagerCallback", + new Object[]{callbackHandle, intent.getIntExtra("id", -1), params}, + result); } - // Handle the alarm event in Dart. Note that for this plugin, we don't - // care about the method name as we simply lookup and invoke the callback - // provided. - backgroundChannel.invokeMethod( - "invokeAlarmManagerCallback", - new Object[] {callbackHandle, intent.getIntExtra("id", -1), params}, - result); - } - - private void initializeMethodChannel(BinaryMessenger isolate) { - // backgroundChannel is the channel responsible for receiving the following messages from - // the background isolate that was setup by this plugin: - // - "AlarmService.initialized" - // - // This channel is also responsible for sending requests from Android to Dart to execute Dart - // callbacks in the background isolate. - backgroundChannel = - new MethodChannel( - isolate, - "dev.fluttercommunity.plus/android_alarm_manager_background", - JSONMethodCodec.INSTANCE); - backgroundChannel.setMethodCallHandler(this); - } + private void initializeMethodChannel(BinaryMessenger isolate) { + // backgroundChannel is the channel responsible for receiving the following messages from + // the background isolate that was setup by this plugin: + // - "AlarmService.initialized" + // + // This channel is also responsible for sending requests from Android to Dart to execute Dart + // callbacks in the background isolate. + backgroundChannel = + new MethodChannel( + isolate, + "dev.fluttercommunity.plus/android_alarm_manager_background", + JSONMethodCodec.INSTANCE); + backgroundChannel.setMethodCallHandler(this); + } } diff --git a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/PluginRegistrantException.java b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/PluginRegistrantException.java index d135bcc23e..abdf6256df 100644 --- a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/PluginRegistrantException.java +++ b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/PluginRegistrantException.java @@ -5,9 +5,9 @@ package dev.fluttercommunity.plus.androidalarmmanager; class PluginRegistrantException extends RuntimeException { - public PluginRegistrantException() { - super( - "PluginRegistrantCallback is not set. Did you forget to call " - + "AlarmService.setPluginRegistrant? See the README for instructions."); - } + public PluginRegistrantException() { + super( + "PluginRegistrantCallback is not set. Did you forget to call " + + "AlarmService.setPluginRegistrant? See the README for instructions."); + } } diff --git a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/RebootBroadcastReceiver.java b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/RebootBroadcastReceiver.java index f88489a051..75e7302033 100644 --- a/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/RebootBroadcastReceiver.java +++ b/packages/android_alarm_manager_plus/android/src/main/java/dev/fluttercommunity/plus/androidalarmmanager/RebootBroadcastReceiver.java @@ -23,39 +23,39 @@ * AlarmService} to run on {@code BOOT_COMPLETED} and do the rescheduling. */ public class RebootBroadcastReceiver extends BroadcastReceiver { - /** - * Invoked by the OS whenever a broadcast is received by this app. - * - *

If the broadcast's action is {@code BOOT_COMPLETED} then this {@code - * RebootBroadcastReceiver} reschedules all persistent timer callbacks. That rescheduling work is - * handled by {@link AlarmService#reschedulePersistentAlarms(Context)}. - */ - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { - Log.i("AlarmService", "Rescheduling after boot!"); - AlarmService.reschedulePersistentAlarms(context); + /** + * Schedules this {@code RebootBroadcastReceiver} to be run whenever the Android device reboots. + */ + public static void enableRescheduleOnReboot(Context context) { + scheduleOnReboot(context, PackageManager.COMPONENT_ENABLED_STATE_ENABLED); } - } - /** - * Schedules this {@code RebootBroadcastReceiver} to be run whenever the Android device reboots. - */ - public static void enableRescheduleOnReboot(Context context) { - scheduleOnReboot(context, PackageManager.COMPONENT_ENABLED_STATE_ENABLED); - } + /** + * Unschedules this {@code RebootBroadcastReceiver} to be run whenever the Android device reboots. + * This {@code RebootBroadcastReceiver} will no longer be run upon reboot. + */ + public static void disableRescheduleOnReboot(Context context) { + scheduleOnReboot(context, PackageManager.COMPONENT_ENABLED_STATE_DISABLED); + } - /** - * Unschedules this {@code RebootBroadcastReceiver} to be run whenever the Android device reboots. - * This {@code RebootBroadcastReceiver} will no longer be run upon reboot. - */ - public static void disableRescheduleOnReboot(Context context) { - scheduleOnReboot(context, PackageManager.COMPONENT_ENABLED_STATE_DISABLED); - } + private static void scheduleOnReboot(Context context, int state) { + ComponentName receiver = new ComponentName(context, RebootBroadcastReceiver.class); + PackageManager pm = context.getPackageManager(); + pm.setComponentEnabledSetting(receiver, state, PackageManager.DONT_KILL_APP); + } - private static void scheduleOnReboot(Context context, int state) { - ComponentName receiver = new ComponentName(context, RebootBroadcastReceiver.class); - PackageManager pm = context.getPackageManager(); - pm.setComponentEnabledSetting(receiver, state, PackageManager.DONT_KILL_APP); - } + /** + * Invoked by the OS whenever a broadcast is received by this app. + * + *

If the broadcast's action is {@code BOOT_COMPLETED} then this {@code + * RebootBroadcastReceiver} reschedules all persistent timer callbacks. That rescheduling work is + * handled by {@link AlarmService#reschedulePersistentAlarms(Context)}. + */ + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { + Log.i("AlarmService", "Rescheduling after boot!"); + AlarmService.reschedulePersistentAlarms(context); + } + } } diff --git a/packages/android_alarm_manager_plus/android/src/main/kotlin/dev/fluttercommunity/plus/androidalarmmanager/AlarmBroadcastReceiver.kt b/packages/android_alarm_manager_plus/android/src/main/kotlin/dev/fluttercommunity/plus/androidalarmmanager/AlarmBroadcastReceiver.kt index 8b81bed771..fe1a65c275 100644 --- a/packages/android_alarm_manager_plus/android/src/main/kotlin/dev/fluttercommunity/plus/androidalarmmanager/AlarmBroadcastReceiver.kt +++ b/packages/android_alarm_manager_plus/android/src/main/kotlin/dev/fluttercommunity/plus/androidalarmmanager/AlarmBroadcastReceiver.kt @@ -8,22 +8,22 @@ import android.content.Context import android.content.Intent class AlarmBroadcastReceiver : BroadcastReceiver() { - /** - * Invoked by the OS when a timer goes off. - * - * The associated timer was registered in [AlarmService]. - * - * In Android, timer notifications require a [BroadcastReceiver] as the artifact that is - * notified when the timer goes off. As a result, this method is kept simple, immediately - * offloading any work to [AlarmService.enqueueAlarmProcessing]. - * - * This method is the beginning of an execution path that will eventually execute a desired - * Dart callback function, as registered by the Dart side of the android_alarm_manager plugin. - * However, there may be asynchronous gaps between [onReceive] and the eventual invocation - * of the Dart callback because [AlarmService] may need to spin up a Flutter execution - * context before the callback can be invoked. - */ - override fun onReceive(context: Context, intent: Intent) { - AlarmService.enqueueAlarmProcessing(context, intent) - } -} \ No newline at end of file + /** + * Invoked by the OS when a timer goes off. + * + * The associated timer was registered in [AlarmService]. + * + * In Android, timer notifications require a [BroadcastReceiver] as the artifact that is + * notified when the timer goes off. As a result, this method is kept simple, immediately + * offloading any work to [AlarmService.enqueueAlarmProcessing]. + * + * This method is the beginning of an execution path that will eventually execute a desired + * Dart callback function, as registered by the Dart side of the android_alarm_manager plugin. + * However, there may be asynchronous gaps between [onReceive] and the eventual invocation + * of the Dart callback because [AlarmService] may need to spin up a Flutter execution + * context before the callback can be invoked. + */ + override fun onReceive(context: Context, intent: Intent) { + AlarmService.enqueueAlarmProcessing(context, intent) + } +} diff --git a/packages/android_alarm_manager_plus/example/android/app/build.gradle b/packages/android_alarm_manager_plus/example/android/app/build.gradle index 1c776ac6f2..e1dc16ca7d 100644 --- a/packages/android_alarm_manager_plus/example/android/app/build.gradle +++ b/packages/android_alarm_manager_plus/example/android/app/build.gradle @@ -23,7 +23,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'com.example.example' @@ -48,7 +48,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true diff --git a/packages/android_alarm_manager_plus/example/android/app/src/androidTest/java/io/flutter/plugins/androidalarmmanager/BackgroundExecutionTest.java b/packages/android_alarm_manager_plus/example/android/app/src/androidTest/java/io/flutter/plugins/androidalarmmanager/BackgroundExecutionTest.java index 760f0f705c..e73b206ddc 100644 --- a/packages/android_alarm_manager_plus/example/android/app/src/androidTest/java/io/flutter/plugins/androidalarmmanager/BackgroundExecutionTest.java +++ b/packages/android_alarm_manager_plus/example/android/app/src/androidTest/java/io/flutter/plugins/androidalarmmanager/BackgroundExecutionTest.java @@ -12,11 +12,14 @@ import android.content.Context; import android.content.SharedPreferences; import android.util.Log; + import androidx.test.InstrumentationRegistry; import androidx.test.core.app.ActivityScenario; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; + import com.example.example.MainActivity; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -28,48 +31,47 @@ */ @RunWith(AndroidJUnit4.class) public class BackgroundExecutionTest { - private SharedPreferences prefs; - static final String COUNT_KEY = "flutter.count"; + static final String COUNT_KEY = "flutter.count"; + @Rule + public ActivityTestRule myActivityTestRule = + new ActivityTestRule<>(MainActivity.class, true, false); + private SharedPreferences prefs; - @Rule - public ActivityTestRule myActivityTestRule = - new ActivityTestRule<>(MainActivity.class, true, false); + @Before + public void setUp() throws Exception { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + prefs = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE); + prefs.edit().putLong(COUNT_KEY, 0).apply(); - @Before - public void setUp() throws Exception { - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - prefs = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE); - prefs.edit().putLong(COUNT_KEY, 0).apply(); - - ActivityScenario.launch(MainActivity.class); - } + ActivityScenario.launch(MainActivity.class); + } - @Test - public void startBackgroundIsolate() throws Exception { - Log.d("BackgroundExecutionTest", "Started"); + @Test + public void startBackgroundIsolate() throws Exception { + Log.d("BackgroundExecutionTest", "Started"); - // Register a one shot alarm which will go off in ~5 seconds. - onFlutterWidget(withValueKey("RegisterOneShotAlarm")).perform(click()); + // Register a one shot alarm which will go off in ~5 seconds. + onFlutterWidget(withValueKey("RegisterOneShotAlarm")).perform(click()); - // The alarm count should be 0 after installation. - assertEquals(prefs.getLong(COUNT_KEY, -1), 0); + // The alarm count should be 0 after installation. + assertEquals(prefs.getLong(COUNT_KEY, -1), 0); - // Close the application to background it. - // @miquelbeltran: Original code contained this line, the test pass but never finish if the - // activity is closed - // pressBackUnconditionally(); - // Log.d("BackgroundExecutionTest","App closed"); + // Close the application to background it. + // @miquelbeltran: Original code contained this line, the test pass but never finish if the + // activity is closed + // pressBackUnconditionally(); + // Log.d("BackgroundExecutionTest","App closed"); - // The alarm should eventually fire, wake up the application, create a - // background isolate, and then increment the counter in the shared - // preferences. Timeout after 20s, just to be safe. - int tries = 0; - while ((prefs.getLong(COUNT_KEY, -1) == 0) && (tries < 200)) { - Thread.sleep(100); - ++tries; - Log.d("BackgroundExecutionTest", "Waiting..."); + // The alarm should eventually fire, wake up the application, create a + // background isolate, and then increment the counter in the shared + // preferences. Timeout after 20s, just to be safe. + int tries = 0; + while ((prefs.getLong(COUNT_KEY, -1) == 0) && (tries < 200)) { + Thread.sleep(100); + ++tries; + Log.d("BackgroundExecutionTest", "Waiting..."); + } + assertEquals(prefs.getLong(COUNT_KEY, -1), 1); + Log.d("BackgroundExecutionTest", "Finished"); } - assertEquals(prefs.getLong(COUNT_KEY, -1), 1); - Log.d("BackgroundExecutionTest", "Finished"); - } } diff --git a/packages/android_alarm_manager_plus/example/android/app/src/debug/AndroidManifest.xml b/packages/android_alarm_manager_plus/example/android/app/src/debug/AndroidManifest.xml index c208884f30..4f0878a78f 100644 --- a/packages/android_alarm_manager_plus/example/android/app/src/debug/AndroidManifest.xml +++ b/packages/android_alarm_manager_plus/example/android/app/src/debug/AndroidManifest.xml @@ -3,5 +3,5 @@ - + diff --git a/packages/android_alarm_manager_plus/example/android/app/src/main/AndroidManifest.xml b/packages/android_alarm_manager_plus/example/android/app/src/main/AndroidManifest.xml index 3de573c1df..242a34a97b 100644 --- a/packages/android_alarm_manager_plus/example/android/app/src/main/AndroidManifest.xml +++ b/packages/android_alarm_manager_plus/example/android/app/src/main/AndroidManifest.xml @@ -10,7 +10,7 @@ - + @@ -19,16 +19,16 @@ + android:label="Alarm manager example" + android:usesCleartextTraffic="true"> + android:windowSoftInputMode="adjustResize"> + diff --git a/packages/android_alarm_manager_plus/example/android/app/src/profile/AndroidManifest.xml b/packages/android_alarm_manager_plus/example/android/app/src/profile/AndroidManifest.xml index c208884f30..4f0878a78f 100644 --- a/packages/android_alarm_manager_plus/example/android/app/src/profile/AndroidManifest.xml +++ b/packages/android_alarm_manager_plus/example/android/app/src/profile/AndroidManifest.xml @@ -3,5 +3,5 @@ - + diff --git a/packages/android_alarm_manager_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/android_alarm_manager_plus/example/android/gradle/wrapper/gradle-wrapper.properties index e1bda4fd50..5fe58a5ed3 100644 --- a/packages/android_alarm_manager_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/android_alarm_manager_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Oct 05 12:15:50 EEST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/android_alarm_manager_plus/example/android/settings.gradle b/packages/android_alarm_manager_plus/example/android/settings.gradle index fa3b4d0878..18a751a498 100644 --- a/packages/android_alarm_manager_plus/example/android/settings.gradle +++ b/packages/android_alarm_manager_plus/example/android/settings.gradle @@ -18,8 +18,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false - id "org.jetbrains.kotlin.android" version "1.9.23" apply false + id "com.android.application" version "8.9.0" apply false + id "org.jetbrains.kotlin.android" version "2.1.10" apply false } include ":app" diff --git a/packages/android_alarm_manager_plus/example/integration_test/android_alarm_manager_plus_test.dart b/packages/android_alarm_manager_plus/example/integration_test/android_alarm_manager_plus_test.dart index e9a5e01bc3..f9edae879a 100644 --- a/packages/android_alarm_manager_plus/example/integration_test/android_alarm_manager_plus_test.dart +++ b/packages/android_alarm_manager_plus/example/integration_test/android_alarm_manager_plus_test.dart @@ -125,10 +125,7 @@ Future main() async { // Register the UI isolate's SendPort to allow for communication from the // background isolate. port = ReceivePort(); - IsolateNameServer.registerPortWithName( - port.sendPort, - isolateName, - ); + IsolateNameServer.registerPortWithName(port.sendPort, isolateName); await tester.pumpWidget(const AlarmManagerExampleApp()); await tester.tap(find.byKey(const ValueKey('RegisterOneShotAlarm'))); diff --git a/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2d..e882ab9889 100644 --- a/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon-App-1024x1024@1x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2fd4..781d7cdcac 100644 --- a/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" + "idiom": "universal", + "filename": "LaunchImage.png", + "scale": "1x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" + "idiom": "universal", + "filename": "LaunchImage@2x.png", + "scale": "2x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" + "idiom": "universal", + "filename": "LaunchImage@3x.png", + "scale": "3x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725b70..d880e1f556 100644 --- a/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/packages/android_alarm_manager_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,8 @@ # Launch Screen Assets -You can customize the launch screen with your own desired assets by replacing the image files in this directory. +You can customize the launch screen with your own desired assets by replacing the image files in +this directory. -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file +You can also do it by opening your Flutter project's Xcode project with +`open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and +dropping in the desired images. diff --git a/packages/android_alarm_manager_plus/example/lib/main.dart b/packages/android_alarm_manager_plus/example/lib/main.dart index 2eefbc0353..73f7256cc7 100644 --- a/packages/android_alarm_manager_plus/example/lib/main.dart +++ b/packages/android_alarm_manager_plus/example/lib/main.dart @@ -28,10 +28,7 @@ Future main() async { // Register the UI isolate's SendPort to allow for communication from the // background isolate. - IsolateNameServer.registerPortWithName( - port.sendPort, - isolateName, - ); + IsolateNameServer.registerPortWithName(port.sendPort, isolateName); prefs = await SharedPreferences.getInstance(); if (!prefs!.containsKey(countKey)) { await prefs!.setInt(countKey, 0); @@ -154,32 +151,36 @@ class _AlarmHomePageState extends State<_AlarmHomePage> { ), const SizedBox(height: 32), ElevatedButton( - onPressed: _exactAlarmPermissionStatus.isDenied - ? () async { - await Permission.scheduleExactAlarm - .onGrantedCallback(() => setState(() { + onPressed: + _exactAlarmPermissionStatus.isDenied + ? () async { + await Permission.scheduleExactAlarm + .onGrantedCallback( + () => setState(() { _exactAlarmPermissionStatus = PermissionStatus.granted; - })) - .request(); - } - : null, + }), + ) + .request(); + } + : null, child: const Text('Request exact alarm permission'), ), const SizedBox(height: 32), ElevatedButton( - onPressed: _exactAlarmPermissionStatus.isGranted - ? () async { - await AndroidAlarmManager.oneShot( - const Duration(seconds: 5), - // Ensure we have a unique alarm ID. - Random().nextInt(pow(2, 31) as int), - callback, - exact: true, - wakeup: true, - ); - } - : null, + onPressed: + _exactAlarmPermissionStatus.isGranted + ? () async { + await AndroidAlarmManager.oneShot( + const Duration(seconds: 5), + // Ensure we have a unique alarm ID. + Random().nextInt(pow(2, 31) as int), + callback, + exact: true, + wakeup: true, + ); + } + : null, child: const Text('Schedule OneShot Alarm'), ), const Spacer(), diff --git a/packages/android_alarm_manager_plus/ios/Classes/AndroidAlarmManagerPlusPlugin.m b/packages/android_alarm_manager_plus/ios/Classes/AndroidAlarmManagerPlusPlugin.m index 2cdad43acd..586c1d5921 100644 --- a/packages/android_alarm_manager_plus/ios/Classes/AndroidAlarmManagerPlusPlugin.m +++ b/packages/android_alarm_manager_plus/ios/Classes/AndroidAlarmManagerPlusPlugin.m @@ -5,19 +5,19 @@ #import "AndroidAlarmManagerPlusPlugin.h" @implementation FPPAndroidAlarmManagerPlusPlugin -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *channel = [FlutterMethodChannel - methodChannelWithName:@"dev.fluttercommunity.plus/android_alarm_manager" - binaryMessenger:[registrar messenger] - codec:[FlutterJSONMethodCodec sharedInstance]]; - FPPAndroidAlarmManagerPlusPlugin *instance = - [[FPPAndroidAlarmManagerPlusPlugin alloc] init]; - [registrar addMethodCallDelegate:instance channel:channel]; ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/android_alarm_manager" + binaryMessenger:[registrar messenger] + codec:[FlutterJSONMethodCodec sharedInstance]]; + FPPAndroidAlarmManagerPlusPlugin *instance = + [[FPPAndroidAlarmManagerPlusPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - result(FlutterMethodNotImplemented); + result(FlutterMethodNotImplemented); } @end diff --git a/packages/android_alarm_manager_plus/lib/android_alarm_manager_plus.dart b/packages/android_alarm_manager_plus/lib/android_alarm_manager_plus.dart index 1656dfda05..c36d0037cf 100644 --- a/packages/android_alarm_manager_plus/lib/android_alarm_manager_plus.dart +++ b/packages/android_alarm_manager_plus/lib/android_alarm_manager_plus.dart @@ -71,8 +71,10 @@ typedef GetCallbackHandle = CallbackHandle? Function(Function callback); class AndroidAlarmManager { static const String channelName = 'dev.fluttercommunity.plus/android_alarm_manager'; - static const MethodChannel channel = - MethodChannel(channelName, JSONMethodCodec()); + static const MethodChannel channel = MethodChannel( + channelName, + JSONMethodCodec(), + ); // Function used to get the current time. It's [DateTime.now] by default. // ignore: prefer_function_declarations_over_variables @@ -105,8 +107,9 @@ class AndroidAlarmManager { if (handle == null) { return false; } - final r = await channel.invokeMethod( - 'AlarmService.start', [handle.toRawHandle()]); + final r = await channel.invokeMethod('AlarmService.start', [ + handle.toRawHandle(), + ]); return r ?? false; } @@ -167,18 +170,17 @@ class AndroidAlarmManager { bool wakeup = false, bool rescheduleOnReboot = false, Map params = const {}, - }) => - oneShotAt( - _now().add(delay), - id, - callback, - alarmClock: alarmClock, - allowWhileIdle: allowWhileIdle, - exact: exact, - wakeup: wakeup, - rescheduleOnReboot: rescheduleOnReboot, - params: params, - ); + }) => oneShotAt( + _now().add(delay), + id, + callback, + alarmClock: alarmClock, + allowWhileIdle: allowWhileIdle, + exact: exact, + wakeup: wakeup, + rescheduleOnReboot: rescheduleOnReboot, + params: params, + ); /// Schedules a one-shot timer to run `callback` at `time`. /// @@ -239,9 +241,11 @@ class AndroidAlarmManager { Map params = const {}, }) async { // ignore: inference_failure_on_function_return_type - assert(callback is Function() || - callback is Function(int) || - callback is Function(int, Map)); + assert( + callback is Function() || + callback is Function(int) || + callback is Function(int, Map), + ); assert(id.bitLength < 32); checkIfSerializable(params); final startMillis = time.millisecondsSinceEpoch; @@ -322,9 +326,11 @@ class AndroidAlarmManager { Map params = const {}, }) async { // ignore: inference_failure_on_function_return_type - assert(callback is Function() || - callback is Function(int) || - callback is Function(int, Map)); + assert( + callback is Function() || + callback is Function(int) || + callback is Function(int, Map), + ); assert(id.bitLength < 32); checkIfSerializable(params); final now = _now().millisecondsSinceEpoch; @@ -366,9 +372,10 @@ class AndroidAlarmManager { jsonEncode(params); } on JsonUnsupportedObjectError catch (e) { throw UnsupportedError( - "Cannot convert '${e.unsupportedObject.runtimeType}' class to json." - " Please put objects that can be converted to json into the " - "'params' parameter"); + "Cannot convert '${e.unsupportedObject.runtimeType}' class to json." + " Please put objects that can be converted to json into the " + "'params' parameter", + ); } } } diff --git a/packages/android_alarm_manager_plus/test/android_alarm_manager_test.dart b/packages/android_alarm_manager_plus/test/android_alarm_manager_test.dart index cfbd153a0c..53b308f0f7 100644 --- a/packages/android_alarm_manager_plus/test/android_alarm_manager_test.dart +++ b/packages/android_alarm_manager_plus/test/android_alarm_manager_test.dart @@ -18,26 +18,22 @@ void main() { void validCallbackWithParams(int id, Map params) => null; const testChannel = MethodChannel( - 'dev.fluttercommunity.plus/android_alarm_manager', JSONMethodCodec()); + 'dev.fluttercommunity.plus/android_alarm_manager', + JSONMethodCodec(), + ); TestWidgetsFlutterBinding.ensureInitialized(); setUpAll(() { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - testChannel, - (message) => null, - ); + .setMockMethodCallHandler(testChannel, (message) => null); }); test('${AndroidAlarmManager.initialize}', () async { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - testChannel, - (MethodCall call) async { - assert(call.method == 'AlarmService.start'); - return true; - }, - ); + .setMockMethodCallHandler(testChannel, (MethodCall call) async { + assert(call.method == 'AlarmService.start'); + return true; + }); final initialized = await AndroidAlarmManager.initialize(); @@ -51,37 +47,35 @@ void main() { // Callback should take a single int param. await expectLater( - () => AndroidAlarmManager.oneShotAt( - validTime, - validId, - invalidCallback, - ), - throwsAssertionError); + () => + AndroidAlarmManager.oneShotAt(validTime, validId, invalidCallback), + throwsAssertionError, + ); // Callback should take int as first and Map as second param. await expectLater( - () => AndroidAlarmManager.oneShotAt( - validTime, - validId, - invalidCallbackWithParams, - ), - throwsAssertionError); + () => AndroidAlarmManager.oneShotAt( + validTime, + validId, + invalidCallbackWithParams, + ), + throwsAssertionError, + ); // ID should be less than 32 bits. await expectLater( - () => AndroidAlarmManager.oneShotAt( - validTime, - 2147483648, - validCallback, - ), - throwsAssertionError); + () => + AndroidAlarmManager.oneShotAt(validTime, 2147483648, validCallback), + throwsAssertionError, + ); }); test('sends arguments to the platform', () async { final alarm = DateTime(1993); const rawHandle = 4; AndroidAlarmManager.setTestOverrides( - getCallbackHandle: (_) => CallbackHandle.fromRawHandle(rawHandle)); + getCallbackHandle: (_) => CallbackHandle.fromRawHandle(rawHandle), + ); const id = 1; const alarmClock = true; @@ -92,22 +86,19 @@ void main() { const params = {'title': 'myAlarm'}; TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - testChannel, - (MethodCall call) async { - expect(call.method, 'Alarm.oneShotAt'); - expect(call.arguments[0], id); - expect(call.arguments[1], alarmClock); - expect(call.arguments[2], allowWhileIdle); - expect(call.arguments[3], exact); - expect(call.arguments[4], wakeup); - expect(call.arguments[5], alarm.millisecondsSinceEpoch); - expect(call.arguments[6], rescheduleOnReboot); - expect(call.arguments[7], rawHandle); - expect(call.arguments[8], params); - return true; - }, - ); + .setMockMethodCallHandler(testChannel, (MethodCall call) async { + expect(call.method, 'Alarm.oneShotAt'); + expect(call.arguments[0], id); + expect(call.arguments[1], alarmClock); + expect(call.arguments[2], allowWhileIdle); + expect(call.arguments[3], exact); + expect(call.arguments[4], wakeup); + expect(call.arguments[5], alarm.millisecondsSinceEpoch); + expect(call.arguments[6], rescheduleOnReboot); + expect(call.arguments[7], rawHandle); + expect(call.arguments[8], params); + return true; + }); final result = await AndroidAlarmManager.oneShotAt( alarm, @@ -129,9 +120,10 @@ void main() { final now = DateTime(1993); const rawHandle = 4; AndroidAlarmManager.setTestOverrides( - now: () => now, - getCallbackHandle: (Function _) => - CallbackHandle.fromRawHandle(rawHandle)); + now: () => now, + getCallbackHandle: + (Function _) => CallbackHandle.fromRawHandle(rawHandle), + ); const alarm = Duration(seconds: 1); const id = 1; @@ -142,25 +134,22 @@ void main() { const rescheduleOnReboot = true; const params = {'title': 'myAlarm'}; TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - testChannel, - (MethodCall call) async { - expect(call.method, 'Alarm.oneShotAt'); - expect(call.arguments[0], id); - expect(call.arguments[1], alarmClock); - expect(call.arguments[2], allowWhileIdle); - expect(call.arguments[3], exact); - expect(call.arguments[4], wakeup); - expect( - call.arguments[5], - now.millisecondsSinceEpoch + alarm.inMilliseconds, - ); - expect(call.arguments[6], rescheduleOnReboot); - expect(call.arguments[7], rawHandle); - expect(call.arguments[8], params); - return true; - }, - ); + .setMockMethodCallHandler(testChannel, (MethodCall call) async { + expect(call.method, 'Alarm.oneShotAt'); + expect(call.arguments[0], id); + expect(call.arguments[1], alarmClock); + expect(call.arguments[2], allowWhileIdle); + expect(call.arguments[3], exact); + expect(call.arguments[4], wakeup); + expect( + call.arguments[5], + now.millisecondsSinceEpoch + alarm.inMilliseconds, + ); + expect(call.arguments[6], rescheduleOnReboot); + expect(call.arguments[7], rawHandle); + expect(call.arguments[8], params); + return true; + }); final result = await AndroidAlarmManager.oneShot( alarm, @@ -184,30 +173,33 @@ void main() { // Callback should take a single int param. await expectLater( - () => AndroidAlarmManager.periodic( - validDuration, - validId, - invalidCallback, - ), - throwsAssertionError); + () => AndroidAlarmManager.periodic( + validDuration, + validId, + invalidCallback, + ), + throwsAssertionError, + ); // ID should be less than 32 bits. await expectLater( - () => AndroidAlarmManager.periodic( - validDuration, - 2147483648, - validCallback, - ), - throwsAssertionError); + () => AndroidAlarmManager.periodic( + validDuration, + 2147483648, + validCallback, + ), + throwsAssertionError, + ); }); test('sends arguments through to the platform', () async { final now = DateTime(1993); const rawHandle = 4; AndroidAlarmManager.setTestOverrides( - now: () => now, - getCallbackHandle: (Function _) => - CallbackHandle.fromRawHandle(rawHandle)); + now: () => now, + getCallbackHandle: + (Function _) => CallbackHandle.fromRawHandle(rawHandle), + ); const id = 1; const allowWhileIdle = true; @@ -218,25 +210,22 @@ void main() { const params = {'title': 'myAlarm'}; TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - testChannel, - (MethodCall call) async { - expect(call.method, 'Alarm.periodic'); - expect(call.arguments[0], id); - expect(call.arguments[1], allowWhileIdle); - expect(call.arguments[2], exact); - expect(call.arguments[3], wakeup); - expect( - call.arguments[4], - (now.millisecondsSinceEpoch + period.inMilliseconds), - ); - expect(call.arguments[5], period.inMilliseconds); - expect(call.arguments[6], rescheduleOnReboot); - expect(call.arguments[7], rawHandle); - expect(call.arguments[8], params); - return true; - }, - ); + .setMockMethodCallHandler(testChannel, (MethodCall call) async { + expect(call.method, 'Alarm.periodic'); + expect(call.arguments[0], id); + expect(call.arguments[1], allowWhileIdle); + expect(call.arguments[2], exact); + expect(call.arguments[3], wakeup); + expect( + call.arguments[4], + (now.millisecondsSinceEpoch + period.inMilliseconds), + ); + expect(call.arguments[5], period.inMilliseconds); + expect(call.arguments[6], rescheduleOnReboot); + expect(call.arguments[7], rawHandle); + expect(call.arguments[8], params); + return true; + }); final result = await AndroidAlarmManager.periodic( period, @@ -252,83 +241,77 @@ void main() { expect(result, isTrue); }); - test( - 'throws if params not parsable, works if params parsable', - () async { - final now = DateTime(1993); - const rawHandle = 4; - AndroidAlarmManager.setTestOverrides( - now: () => now, - getCallbackHandle: (Function _) => - CallbackHandle.fromRawHandle(rawHandle), - ); - - const id = 1; - const period = Duration(seconds: 1); - final notParsableParams = { - 'title': 'myAlarm', - 'obj': const NotJsonParsableClass(), - }; - - expectLater( - () => AndroidAlarmManager.periodic( - period, - id, - validCallbackWithParams, - params: notParsableParams, - ), - throwsUnsupportedError, - ); - - final parsableParams = { - 'title': 'myAlarm', - 'obj': const JsonParsableClass('MyName') - }; - - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(testChannel, (MethodCall call) async { - expect(call.method, 'Alarm.periodic'); - expect(call.arguments[0], id); - expect( - call.arguments[4], - (now.millisecondsSinceEpoch + period.inMilliseconds), - ); - expect(call.arguments[5], period.inMilliseconds); - expect(call.arguments[7], rawHandle); - expect(call.arguments[8], isA()); - expect( - JsonParsableClass.fromJson(call.arguments[8]['obj']), - isA(), - ); - expect( - JsonParsableClass.fromJson(call.arguments[8]['obj']), - const JsonParsableClass('MyName'), - ); - return true; - }); + test('throws if params not parsable, works if params parsable', () async { + final now = DateTime(1993); + const rawHandle = 4; + AndroidAlarmManager.setTestOverrides( + now: () => now, + getCallbackHandle: + (Function _) => CallbackHandle.fromRawHandle(rawHandle), + ); + + const id = 1; + const period = Duration(seconds: 1); + final notParsableParams = { + 'title': 'myAlarm', + 'obj': const NotJsonParsableClass(), + }; - final result = await AndroidAlarmManager.periodic( + expectLater( + () => AndroidAlarmManager.periodic( period, id, validCallbackWithParams, - params: parsableParams, - ); + params: notParsableParams, + ), + throwsUnsupportedError, + ); - expect(result, isTrue); - }, - ); + final parsableParams = { + 'title': 'myAlarm', + 'obj': const JsonParsableClass('MyName'), + }; + + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(testChannel, (MethodCall call) async { + expect(call.method, 'Alarm.periodic'); + expect(call.arguments[0], id); + expect( + call.arguments[4], + (now.millisecondsSinceEpoch + period.inMilliseconds), + ); + expect(call.arguments[5], period.inMilliseconds); + expect(call.arguments[7], rawHandle); + expect(call.arguments[8], isA()); + expect( + JsonParsableClass.fromJson(call.arguments[8]['obj']), + isA(), + ); + expect( + JsonParsableClass.fromJson(call.arguments[8]['obj']), + const JsonParsableClass('MyName'), + ); + return true; + }); + + final result = await AndroidAlarmManager.periodic( + period, + id, + validCallbackWithParams, + params: parsableParams, + ); + + expect(result, isTrue); + }); }); test('${AndroidAlarmManager.cancel}', () async { const id = 1; TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - testChannel, - (MethodCall call) async { - assert(call.method == 'Alarm.cancel' && call.arguments[0] == id); - return true; - }, - ); + .setMockMethodCallHandler(testChannel, (MethodCall call) async { + assert(call.method == 'Alarm.cancel' && call.arguments[0] == id); + return true; + }); final canceled = await AndroidAlarmManager.cancel(id); diff --git a/packages/android_intent_plus/CHANGELOG.md b/packages/android_intent_plus/CHANGELOG.md index ede140fe72..d91637a518 100644 --- a/packages/android_intent_plus/CHANGELOG.md +++ b/packages/android_intent_plus/CHANGELOG.md @@ -1,95 +1,116 @@ ## 5.3.0 - - **FIX**(android_intent_plus): adds error catching and forwarding ([#3452](https://github.com/fluttercommunity/plus_plugins/issues/3452)). ([37f533c7](https://github.com/fluttercommunity/plus_plugins/commit/37f533c7a6c16fc55ed743b78108b479fc2565c3)) - - **FEAT**(android_intent_plus): adds sendService method ([#3410](https://github.com/fluttercommunity/plus_plugins/issues/3410)). ([ea72b632](https://github.com/fluttercommunity/plus_plugins/commit/ea72b632486a8f1a3416424017774a0fd9fc1a8d)) +- **FIX**(android_intent_plus): adds error catching and + forwarding ([#3452](https://github.com/fluttercommunity/plus_plugins/issues/3452)). ([37f533c7](https://github.com/fluttercommunity/plus_plugins/commit/37f533c7a6c16fc55ed743b78108b479fc2565c3)) +- **FEAT**(android_intent_plus): adds sendService + method ([#3410](https://github.com/fluttercommunity/plus_plugins/issues/3410)). ([ea72b632](https://github.com/fluttercommunity/plus_plugins/commit/ea72b632486a8f1a3416424017774a0fd9fc1a8d)) ## 5.2.2 - - **FIX**(android_intent_plus): set correct environment versions ([#3421](https://github.com/fluttercommunity/plus_plugins/issues/3421)). ([dc3ba17a](https://github.com/fluttercommunity/plus_plugins/commit/dc3ba17a3948329de546c373aababb2401e556bb)) +- **FIX**(android_intent_plus): set correct environment + versions ([#3421](https://github.com/fluttercommunity/plus_plugins/issues/3421)). ([dc3ba17a](https://github.com/fluttercommunity/plus_plugins/commit/dc3ba17a3948329de546c373aababb2401e556bb)) ## 5.2.1 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 5.2.0 - - **FEAT**(android_intent_plus): add getResolvedActivity method ([#3313](https://github.com/fluttercommunity/plus_plugins/issues/3313)). ([8ad1c6d9](https://github.com/fluttercommunity/plus_plugins/commit/8ad1c6d9e061a59383f82f9b4a7703ef03e4c04c)) +- **FEAT**(android_intent_plus): add getResolvedActivity + method ([#3313](https://github.com/fluttercommunity/plus_plugins/issues/3313)). ([8ad1c6d9](https://github.com/fluttercommunity/plus_plugins/commit/8ad1c6d9e061a59383f82f9b4a7703ef03e4c04c)) ## 5.1.0 - - **FIX**(android_intent_plus): remove package name from AndroidManifest ([#3033](https://github.com/fluttercommunity/plus_plugins/issues/3033)). ([af2f4afa](https://github.com/fluttercommunity/plus_plugins/commit/af2f4afaa419cdd9fb32632ea3ebe9a4e6df0513)) - - **FEAT**(android_intent_plus): support for intent as URI ([#2970](https://github.com/fluttercommunity/plus_plugins/issues/2970)). ([e4530870](https://github.com/fluttercommunity/plus_plugins/commit/e4530870dd2412e04776dcecc0fbed2bb3842187)) - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **FIX**(android_intent_plus): remove package name from + AndroidManifest ([#3033](https://github.com/fluttercommunity/plus_plugins/issues/3033)). ([af2f4afa](https://github.com/fluttercommunity/plus_plugins/commit/af2f4afaa419cdd9fb32632ea3ebe9a4e6df0513)) +- **FEAT**(android_intent_plus): support for intent as + URI ([#2970](https://github.com/fluttercommunity/plus_plugins/issues/2970)). ([e4530870](https://github.com/fluttercommunity/plus_plugins/commit/e4530870dd2412e04776dcecc0fbed2bb3842187)) +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 5.0.2 - - **REFACTOR**(android_intent_plus): Migrate Android example to use the new plugins declaration ([#2773](https://github.com/fluttercommunity/plus_plugins/issues/2773)). ([7c2de04d](https://github.com/fluttercommunity/plus_plugins/commit/7c2de04deffa1dc788d93c12e5cee1fd98821514)) +- **REFACTOR**(android_intent_plus): Migrate Android example to use the new plugins + declaration ([#2773](https://github.com/fluttercommunity/plus_plugins/issues/2773)). ([7c2de04d](https://github.com/fluttercommunity/plus_plugins/commit/7c2de04deffa1dc788d93c12e5cee1fd98821514)) ## 5.0.1 Plugin now requires the following: + - compileSDK 34 - Java 17 - Gradle 8.4 -- **BREAKING** **BUILD**(android_intent_plus): Target Java 17 ([#2724](https://github.com/fluttercommunity/plus_plugins/issues/2724)). ([c66a67d](https://github.com/fluttercommunity/plus_plugins/commit/c66a67da396d088a2e02d4e6b69e0b8802189f9a)) -- **BREAKING** **BUILD**(android_intent_plus): Update to target and compile SDK 34 ([#2711](https://github.com/fluttercommunity/plus_plugins/pull/2711)). ([fd48920](https://github.com/fluttercommunity/plus_plugins/commit/fd489200a714594aad4e2eac5f0e56f43ebd751a)) +- **BREAKING** **BUILD**(android_intent_plus): Target Java + 17 ([#2724](https://github.com/fluttercommunity/plus_plugins/issues/2724)). ([c66a67d](https://github.com/fluttercommunity/plus_plugins/commit/c66a67da396d088a2e02d4e6b69e0b8802189f9a)) +- **BREAKING** **BUILD**(android_intent_plus): Update to target and compile SDK + 34 ([#2711](https://github.com/fluttercommunity/plus_plugins/pull/2711)). ([fd48920](https://github.com/fluttercommunity/plus_plugins/commit/fd489200a714594aad4e2eac5f0e56f43ebd751a)) ## 5.0.0 -> Note: This release was retracted due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). +> Note: This release was retracted due +> to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). ## 4.0.3 - - **FIX**(android_intent_plus): Fix annotation dependency declaration ([#2237](https://github.com/fluttercommunity/plus_plugins/issues/2237)). ([795a3dd8](https://github.com/fluttercommunity/plus_plugins/commit/795a3dd81d8c718344936d65226d051f5fe4a125)) - - **FIX**(android_intent_plus): Revert bump compileSDK to 34 ([#2236](https://github.com/fluttercommunity/plus_plugins/issues/2236)). ([38bba0eb](https://github.com/fluttercommunity/plus_plugins/commit/38bba0ebc0f1db404a673440749e4d1d95dcf26c)) +- **FIX**(android_intent_plus): Fix annotation dependency + declaration ([#2237](https://github.com/fluttercommunity/plus_plugins/issues/2237)). ([795a3dd8](https://github.com/fluttercommunity/plus_plugins/commit/795a3dd81d8c718344936d65226d051f5fe4a125)) +- **FIX**(android_intent_plus): Revert bump compileSDK to + 34 ([#2236](https://github.com/fluttercommunity/plus_plugins/issues/2236)). ([38bba0eb](https://github.com/fluttercommunity/plus_plugins/commit/38bba0ebc0f1db404a673440749e4d1d95dcf26c)) ## 4.0.2 - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 4.0.1 - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) ## 4.0.0 > Note: This release has breaking changes. - - **CHORE**(android_intent_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(android_intent_plus): Bump min Android version to 4.4 (API 19) (#1784). - - **REFACTOR**(android_intent_plus): Update example app to use Material 3. +- **CHORE**(android_intent_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to > + =2.18.0 <4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(android_intent_plus): Bump min Android version to 4.4 (API 19) (#1784). +- **REFACTOR**(android_intent_plus): Update example app to use Material 3. ## 3.1.9 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 3.1.8 - - **FIX**(android_intent_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1699). +- **FIX**(android_intent_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1699). ## 3.1.7 - - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). - - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). +- **REFACTOR**(all): Remove all manual dependency_overrides (#1628). +- **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). ## 3.1.6 - - **DOCS**: Updates for READMEs and website pages (#1389). +- **DOCS**: Updates for READMEs and website pages (#1389). ## 3.1.5 - - **FIX**: lint warnings - add missing dependency for tests (#1233). +- **FIX**: lint warnings - add missing dependency for tests (#1233). ## 3.1.4 - - **DOCS**: Add documentation for canResolveActivity. +- **DOCS**: Add documentation for canResolveActivity. ## 3.1.3 - - **CHORE**: Version tagging using melos. +- **CHORE**: Version tagging using melos. ## 3.1.2 @@ -167,7 +188,8 @@ Plugin now requires the following: ## 0.3.7+2 -- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). +- Declare API stability and compatibility with `1.0.0` (more details + at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). ## 0.3.7+1 @@ -199,7 +221,10 @@ Plugin now requires the following: ## 0.3.5 -- Add support for [setType]() and [setDataAndType]() parameters. +- Add support + for [setType]() + and [setDataAndType]() + parameters. ## 0.3.4+8 @@ -226,7 +251,8 @@ Plugin now requires the following: ## 0.3.4+3 -- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to + support apps that has not been migrated to AndroidX. ## 0.3.4+2 diff --git a/packages/android_intent_plus/CODE_OF_CONDUCT.md b/packages/android_intent_plus/CODE_OF_CONDUCT.md index c79a563029..07769f6514 100644 --- a/packages/android_intent_plus/CODE_OF_CONDUCT.md +++ b/packages/android_intent_plus/CODE_OF_CONDUCT.md @@ -1,4 +1,3 @@ - # Contributor Covenant Code of Conduct ## Our Pledge @@ -107,7 +106,7 @@ Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an +standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within diff --git a/packages/android_intent_plus/README.md b/packages/android_intent_plus/README.md index 4dc7a1ef05..60d2344dc6 100644 --- a/packages/android_intent_plus/README.md +++ b/packages/android_intent_plus/README.md @@ -11,8 +11,8 @@ This plugin allows Flutter apps to launch arbitrary intents when the platform is ## Platform Support | Android | -| :-----: | -| ✅ | +|:-------:| +| ✅ | ## Requirements @@ -27,7 +27,8 @@ This plugin allows Flutter apps to launch arbitrary intents when the platform is > **Warning** > -> If the plugin is invoked on iOS, it will crash your app. In checked mode, we assert that the platform should be Android. +> If the plugin is invoked on iOS, it will crash your app. In checked mode, we assert that the +> platform should be Android. Use it by specifying action, category, data and extra arguments for the intent. It does not support returning the result of the launched activity. Sample usage: @@ -54,7 +55,8 @@ for it in the plugin and use an action constant to refer to it. For instance: `'action_location_source_settings'` translates to `android.settings.LOCATION_SOURCE_SETTINGS` -`'action_application_details_settings'` translates to `android.settings.ACTION_APPLICATION_DETAILS_SETTINGS` +`'action_application_details_settings'` translates to +`android.settings.ACTION_APPLICATION_DETAILS_SETTINGS` ```dart if (platform.isAndroid) { @@ -84,7 +86,9 @@ of integers or strings. > clients to set extra parameters for the intent. ### Querying activities -`canResolveActivity()` and `getResolvedActivity()` can be used to query whether an activity can handle an intent, + +`canResolveActivity()` and `getResolvedActivity()` can be used to query whether an activity can +handle an intent, or get the details of the activity that can handle the intent. ```dart @@ -105,7 +109,8 @@ print(details.packageName); // prints com.google.chrome ## Android 11 package visibility Android 11 introduced new permissions for package visibility. -If you plan to use `canResolveActivity()` method, you need to specify queries in `AndroidManifest.xml` with specific package names: +If you plan to use `canResolveActivity()` method, you need to specify queries in +`AndroidManifest.xml` with specific package names: https://developer.android.com/training/package-visibility/declaring diff --git a/packages/android_intent_plus/android/build.gradle b/packages/android_intent_plus/android/build.gradle index fcc7295eb0..8eba9c846b 100644 --- a/packages/android_intent_plus/android/build.gradle +++ b/packages/android_intent_plus/android/build.gradle @@ -22,7 +22,7 @@ rootProject.allprojects { apply plugin: 'com.android.library' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.androidintent' diff --git a/packages/android_intent_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/android_intent_plus/android/gradle/wrapper/gradle-wrapper.properties index e411586a54..2733ed5dc3 100644 --- a/packages/android_intent_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/android_intent_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/AndroidIntentPlugin.java b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/AndroidIntentPlugin.java index f5fd38176f..e17c6690b3 100644 --- a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/AndroidIntentPlugin.java +++ b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/AndroidIntentPlugin.java @@ -1,6 +1,7 @@ package dev.fluttercommunity.plus.androidintent; import androidx.annotation.NonNull; + import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; @@ -11,50 +12,50 @@ *

Instantiate this in an add to app scenario to gracefully handle activity and context changes. */ public final class AndroidIntentPlugin implements FlutterPlugin, ActivityAware { - private final IntentSender sender; - private final MethodCallHandlerImpl impl; - - /** - * Initialize this within the {@code #configureFlutterEngine} of a Flutter activity or fragment. - * - *

See {@code io.flutter.plugins.androidintentexample.MainActivity} for an example. - */ - public AndroidIntentPlugin() { - sender = new IntentSender(/* activity= */ null, /* applicationContext= */ null); - impl = new MethodCallHandlerImpl(sender); - } - - @Override - public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - sender.setApplicationContext(binding.getApplicationContext()); - sender.setActivity(null); - impl.startListening(binding.getBinaryMessenger()); - } - - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - sender.setApplicationContext(null); - sender.setActivity(null); - impl.stopListening(); - } - - @Override - public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { - sender.setActivity(binding.getActivity()); - } - - @Override - public void onDetachedFromActivity() { - sender.setActivity(null); - } - - @Override - public void onDetachedFromActivityForConfigChanges() { - onDetachedFromActivity(); - } - - @Override - public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { - onAttachedToActivity(binding); - } + private final IntentSender sender; + private final MethodCallHandlerImpl impl; + + /** + * Initialize this within the {@code #configureFlutterEngine} of a Flutter activity or fragment. + * + *

See {@code io.flutter.plugins.androidintentexample.MainActivity} for an example. + */ + public AndroidIntentPlugin() { + sender = new IntentSender(/* activity= */ null, /* applicationContext= */ null); + impl = new MethodCallHandlerImpl(sender); + } + + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { + sender.setApplicationContext(binding.getApplicationContext()); + sender.setActivity(null); + impl.startListening(binding.getBinaryMessenger()); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + sender.setApplicationContext(null); + sender.setActivity(null); + impl.stopListening(); + } + + @Override + public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { + sender.setActivity(binding.getActivity()); + } + + @Override + public void onDetachedFromActivity() { + sender.setActivity(null); + } + + @Override + public void onDetachedFromActivityForConfigChanges() { + onDetachedFromActivity(); + } + + @Override + public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { + onAttachedToActivity(binding); + } } diff --git a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java index 398245cb43..703a806caa 100644 --- a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java +++ b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java @@ -10,229 +10,243 @@ import android.os.Bundle; import android.text.TextUtils; import android.util.Log; + import androidx.annotation.Nullable; + import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; -/** Forms and launches intents. */ +/** + * Forms and launches intents. + */ public final class IntentSender { - private static final String TAG = "IntentSender"; - - @Nullable private Activity activity; - @Nullable private Context applicationContext; - - /** - * Caches the given {@code activity} and {@code applicationContext} to use for sending intents - * later. - * - *

Either may be null initially, but at least {@code applicationContext} should be set before - * calling {@link #send}. - * - *

See also {@link #setActivity}, {@link #setApplicationContext}, and {@link #send}. - */ - public IntentSender(@Nullable Activity activity, @Nullable Context applicationContext) { - this.activity = activity; - this.applicationContext = applicationContext; - } - - /** - * Creates and launches an intent with the given params using the cached {@link Activity} and - * {@link Context}. - * - *

This will fail to create and send the intent if {@code applicationContext} hasn't been set - * at the time of calling. - * - *

This uses {@code activity} to start the intent whenever it's not null. Otherwise it falls - * back to {@code applicationContext} and adds {@link Intent#FLAG_ACTIVITY_NEW_TASK} to the intent - * before launching it. - */ - void send(Intent intent) { - if (applicationContext == null) { - Log.wtf(TAG, "Trying to send an intent before the applicationContext was initialized."); - return; - } - - Log.v(TAG, "Sending intent " + intent); - - if (activity != null) { - activity.startActivity(intent); - } else { - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - applicationContext.startActivity(intent); - } - } - - /** Creates an intent and launches it as a Service. */ - void sendService(Intent intent) { - if (applicationContext == null) { - Log.wtf(TAG, "Trying to send an intent before the applicationContext was initialized."); - return; - } - - Log.v(TAG, "Sending service intent " + intent); - - if (activity != null) { - activity.startService(intent); - } else { - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - applicationContext.startService(intent); - } - } - - /** - * Like with {@code send}, creates and launches an intent with the given params, but wraps the - * {@code Intent} with {@code Intent.createChooser}. - */ - public void launchChooser(Intent intent, String title) { - send(Intent.createChooser(intent, title)); - } - - /** Creates an intent and sends it as Broadcast. */ - public void sendBroadcast(Intent intent) { - if (applicationContext == null) { - Log.wtf(TAG, "Trying to send broadcast before the applicationContext was initialized."); - return; - } - - Log.v(TAG, "Sending broadcast " + intent); - applicationContext.sendBroadcast(intent); - } - - /** - * Verifies the given intent and returns whether the application context class can resolve it. - * - *

This will fail to create and send the intent if {@code applicationContext} hasn't been set * - * at the time of calling. - * - *

This currently only supports resolving activities. - * - * @param intent Fully built intent. - * @return Whether the package manager found {@link android.content.pm.ResolveInfo} using its - * {@link PackageManager#resolveActivity(Intent, int)} method. - * @see #buildIntent(String, Integer, String, Uri, Bundle, String, ComponentName, String) - */ - boolean canResolveActivity(Intent intent) { - if (applicationContext == null) { - Log.wtf(TAG, "Trying to resolve an activity before the applicationContext was initialized."); - return false; - } - - final PackageManager packageManager = applicationContext.getPackageManager(); - return packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null; - } - - /** - * Get the default activity that will resolve the intent - * - *

This will fail to create and send the intent if {@code applicationContext} hasn't been set * - * at the time of calling. - * - *

This currently only supports resolving activities. - * - * @param intent Fully built intent. - * @return Whether the package manager found {@link android.content.pm.ResolveInfo} using its - * {@link PackageManager#resolveActivity(Intent, int)} method. - * @see #buildIntent(String, Integer, String, Uri, Bundle, String, ComponentName, String) - */ - @Nullable - Map getResolvedActivity(Intent intent) { - if (applicationContext == null) { - Log.wtf(TAG, "Trying to resolve an activity before the applicationContext was initialized."); - return null; - } - - final PackageManager packageManager = applicationContext.getPackageManager(); - ResolveInfo resolveInfo = - packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); - - if (resolveInfo != null) { - Map resultMap = new HashMap<>(); - resultMap.put("activityName", resolveInfo.activityInfo.name); - resultMap.put("packageName", resolveInfo.activityInfo.packageName); - resultMap.put("appName", resolveInfo.loadLabel(packageManager)); - return resultMap; - } - - return null; - } - - /** Caches the given {@code activity} to use for {@link #send}. */ - void setActivity(@Nullable Activity activity) { - this.activity = activity; - } - - /** Caches the given {@code applicationContext} to use for {@link #send}. */ - void setApplicationContext(@Nullable Context applicationContext) { - this.applicationContext = applicationContext; - } - - /** - * Constructs a new intent with the data specified. - * - * @param action the Intent action, such as {@code ACTION_VIEW}. - * @param flags forwarded to {@link Intent#addFlags(int)} if non-null. - * @param category forwarded to {@link Intent#addCategory(String)} if non-null. - * @param data forwarded to {@link Intent#setData(Uri)} if non-null and 'type' parameter is null. - * If both 'data' and 'type' is non-null they're forwarded to {@link - * Intent#setDataAndType(Uri, String)} - * @param arguments forwarded to {@link Intent#putExtras(Bundle)} if non-null. - * @param packageName forwarded to {@link Intent#setPackage(String)} if non-null. This is forced - * to null if it can't be resolved. - * @param componentName forwarded to {@link Intent#setComponent(ComponentName)} if non-null. - * @param type forwarded to {@link Intent#setType(String)} if non-null and 'data' parameter is - * null. If both 'data' and 'type' is non-null they're forwarded to {@link - * Intent#setDataAndType(Uri, String)} - * @return Fully built intent. - */ - Intent buildIntent( - @Nullable String action, - @Nullable Integer flags, - @Nullable String category, - @Nullable Uri data, - @Nullable Bundle arguments, - @Nullable String packageName, - @Nullable ComponentName componentName, - @Nullable String type) { - if (applicationContext == null) { - Log.wtf(TAG, "Trying to build an intent before the applicationContext was initialized."); - return null; - } - - Intent intent = new Intent(); - - if (action != null) { - intent.setAction(action); - } - if (flags != null) { - intent.addFlags(flags); + private static final String TAG = "IntentSender"; + + @Nullable + private Activity activity; + @Nullable + private Context applicationContext; + + /** + * Caches the given {@code activity} and {@code applicationContext} to use for sending intents + * later. + * + *

Either may be null initially, but at least {@code applicationContext} should be set before + * calling {@link #send}. + * + *

See also {@link #setActivity}, {@link #setApplicationContext}, and {@link #send}. + */ + public IntentSender(@Nullable Activity activity, @Nullable Context applicationContext) { + this.activity = activity; + this.applicationContext = applicationContext; + } + + /** + * Creates and launches an intent with the given params using the cached {@link Activity} and + * {@link Context}. + * + *

This will fail to create and send the intent if {@code applicationContext} hasn't been set + * at the time of calling. + * + *

This uses {@code activity} to start the intent whenever it's not null. Otherwise it falls + * back to {@code applicationContext} and adds {@link Intent#FLAG_ACTIVITY_NEW_TASK} to the intent + * before launching it. + */ + void send(Intent intent) { + if (applicationContext == null) { + Log.wtf(TAG, "Trying to send an intent before the applicationContext was initialized."); + return; + } + + Log.v(TAG, "Sending intent " + intent); + + if (activity != null) { + activity.startActivity(intent); + } else { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + applicationContext.startActivity(intent); + } + } + + /** + * Creates an intent and launches it as a Service. + */ + void sendService(Intent intent) { + if (applicationContext == null) { + Log.wtf(TAG, "Trying to send an intent before the applicationContext was initialized."); + return; + } + + Log.v(TAG, "Sending service intent " + intent); + + if (activity != null) { + activity.startService(intent); + } else { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + applicationContext.startService(intent); + } + } + + /** + * Like with {@code send}, creates and launches an intent with the given params, but wraps the + * {@code Intent} with {@code Intent.createChooser}. + */ + public void launchChooser(Intent intent, String title) { + send(Intent.createChooser(intent, title)); + } + + /** + * Creates an intent and sends it as Broadcast. + */ + public void sendBroadcast(Intent intent) { + if (applicationContext == null) { + Log.wtf(TAG, "Trying to send broadcast before the applicationContext was initialized."); + return; + } + + Log.v(TAG, "Sending broadcast " + intent); + applicationContext.sendBroadcast(intent); + } + + /** + * Verifies the given intent and returns whether the application context class can resolve it. + * + *

This will fail to create and send the intent if {@code applicationContext} hasn't been set * + * at the time of calling. + * + *

This currently only supports resolving activities. + * + * @param intent Fully built intent. + * @return Whether the package manager found {@link android.content.pm.ResolveInfo} using its + * {@link PackageManager#resolveActivity(Intent, int)} method. + * @see #buildIntent(String, Integer, String, Uri, Bundle, String, ComponentName, String) + */ + boolean canResolveActivity(Intent intent) { + if (applicationContext == null) { + Log.wtf(TAG, "Trying to resolve an activity before the applicationContext was initialized."); + return false; + } + + final PackageManager packageManager = applicationContext.getPackageManager(); + return packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null; + } + + /** + * Get the default activity that will resolve the intent + * + *

This will fail to create and send the intent if {@code applicationContext} hasn't been set * + * at the time of calling. + * + *

This currently only supports resolving activities. + * + * @param intent Fully built intent. + * @return Whether the package manager found {@link android.content.pm.ResolveInfo} using its + * {@link PackageManager#resolveActivity(Intent, int)} method. + * @see #buildIntent(String, Integer, String, Uri, Bundle, String, ComponentName, String) + */ + @Nullable + Map getResolvedActivity(Intent intent) { + if (applicationContext == null) { + Log.wtf(TAG, "Trying to resolve an activity before the applicationContext was initialized."); + return null; + } + + final PackageManager packageManager = applicationContext.getPackageManager(); + ResolveInfo resolveInfo = + packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); + + if (resolveInfo != null) { + Map resultMap = new HashMap<>(); + resultMap.put("activityName", resolveInfo.activityInfo.name); + resultMap.put("packageName", resolveInfo.activityInfo.packageName); + resultMap.put("appName", resolveInfo.loadLabel(packageManager)); + return resultMap; + } + + return null; + } + + /** + * Caches the given {@code activity} to use for {@link #send}. + */ + void setActivity(@Nullable Activity activity) { + this.activity = activity; + } + + /** + * Caches the given {@code applicationContext} to use for {@link #send}. + */ + void setApplicationContext(@Nullable Context applicationContext) { + this.applicationContext = applicationContext; + } + + /** + * Constructs a new intent with the data specified. + * + * @param action the Intent action, such as {@code ACTION_VIEW}. + * @param flags forwarded to {@link Intent#addFlags(int)} if non-null. + * @param category forwarded to {@link Intent#addCategory(String)} if non-null. + * @param data forwarded to {@link Intent#setData(Uri)} if non-null and 'type' parameter is null. + * If both 'data' and 'type' is non-null they're forwarded to {@link + * Intent#setDataAndType(Uri, String)} + * @param arguments forwarded to {@link Intent#putExtras(Bundle)} if non-null. + * @param packageName forwarded to {@link Intent#setPackage(String)} if non-null. This is forced + * to null if it can't be resolved. + * @param componentName forwarded to {@link Intent#setComponent(ComponentName)} if non-null. + * @param type forwarded to {@link Intent#setType(String)} if non-null and 'data' parameter is + * null. If both 'data' and 'type' is non-null they're forwarded to {@link + * Intent#setDataAndType(Uri, String)} + * @return Fully built intent. + */ + Intent buildIntent( + @Nullable String action, + @Nullable Integer flags, + @Nullable String category, + @Nullable Uri data, + @Nullable Bundle arguments, + @Nullable String packageName, + @Nullable ComponentName componentName, + @Nullable String type) { + if (applicationContext == null) { + Log.wtf(TAG, "Trying to build an intent before the applicationContext was initialized."); + return null; + } + + Intent intent = new Intent(); + + if (action != null) { + intent.setAction(action); + } + if (flags != null) { + intent.addFlags(flags); + } + if (!TextUtils.isEmpty(category)) { + intent.addCategory(category); + } + if (data != null && type == null) { + intent.setData(data); + } + if (type != null && data == null) { + intent.setType(type); + } + if (type != null && data != null) { + intent.setDataAndType(data, type); + } + if (arguments != null) { + intent.putExtras(arguments); + } + if (!TextUtils.isEmpty(packageName)) { + intent.setPackage(packageName); + if (componentName != null) { + intent.setComponent(componentName); + } + } + + return intent; + } + + public Intent parse(String uri) throws URISyntaxException { + return Intent.parseUri(uri, Intent.URI_INTENT_SCHEME); } - if (!TextUtils.isEmpty(category)) { - intent.addCategory(category); - } - if (data != null && type == null) { - intent.setData(data); - } - if (type != null && data == null) { - intent.setType(type); - } - if (type != null && data != null) { - intent.setDataAndType(data, type); - } - if (arguments != null) { - intent.putExtras(arguments); - } - if (!TextUtils.isEmpty(packageName)) { - intent.setPackage(packageName); - if (componentName != null) { - intent.setComponent(componentName); - } - } - - return intent; - } - - public Intent parse(String uri) throws URISyntaxException { - return Intent.parseUri(uri, Intent.URI_INTENT_SCHEME); - } } diff --git a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java index 70eaddb7d1..a150410d7c 100644 --- a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java +++ b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java @@ -7,260 +7,266 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.Log; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; + import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; + import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Map; -/** Forwards incoming {@link MethodCall}s to {@link IntentSender#send}. */ +/** + * Forwards incoming {@link MethodCall}s to {@link IntentSender#send}. + */ public final class MethodCallHandlerImpl implements MethodCallHandler { - private static final String TAG = "MethodCallHandlerImpl"; - private final IntentSender sender; - @Nullable private MethodChannel methodChannel; + private static final String TAG = "MethodCallHandlerImpl"; + private final IntentSender sender; + @Nullable + private MethodChannel methodChannel; - /** - * Uses the given {@code sender} for all incoming calls. - * - *

This assumes that the sender's context and activity state are managed elsewhere and - * correctly initialized before being sent here. - */ - MethodCallHandlerImpl(IntentSender sender) { - this.sender = sender; - } - - /** - * Registers this instance as a method call handler on the given {@code messenger}. - * - *

Stops any previously started and unstopped calls. - * - *

This should be cleaned with {@link #stopListening} once the messenger is disposed of. - */ - void startListening(BinaryMessenger messenger) { - if (methodChannel != null) { - Log.wtf(TAG, "Setting a method call handler before the last was disposed."); - stopListening(); + /** + * Uses the given {@code sender} for all incoming calls. + * + *

This assumes that the sender's context and activity state are managed elsewhere and + * correctly initialized before being sent here. + */ + MethodCallHandlerImpl(IntentSender sender) { + this.sender = sender; } - methodChannel = new MethodChannel(messenger, "dev.fluttercommunity.plus/android_intent"); - methodChannel.setMethodCallHandler(this); - } - - /** - * Clears this instance from listening to method calls. - * - *

Does nothing is {@link #startListening} hasn't been called, or if we're already stopped. - */ - void stopListening() { - if (methodChannel == null) { - Log.d(TAG, "Tried to stop listening when no methodChannel had been initialized."); - return; - } - - methodChannel.setMethodCallHandler(null); - methodChannel = null; - } - - /** - * Parses the incoming call and forwards it to the cached {@link IntentSender}. - * - *

Always calls {@code result#success}. - */ - @Override - public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { - try { - String action = convertAction((String) call.argument("action")); - Integer flags = call.argument("flags"); - String category = call.argument("category"); - Uri data = call.argument("data") != null ? Uri.parse((String) call.argument("data")) : null; - Bundle arguments = convertArguments((Map) call.argument("arguments")); - Bundle arrayArguments = - convertArrayArguments((Map) call.argument("arrayArguments")); - arguments.putAll(arrayArguments); - String packageName = call.argument("package"); - ComponentName componentName = - (!TextUtils.isEmpty(packageName) - && !TextUtils.isEmpty((String) call.argument("componentName"))) - ? new ComponentName(packageName, (String) call.argument("componentName")) - : null; - String type = call.argument("type"); - - Intent intent = - sender.buildIntent( - action, flags, category, data, arguments, packageName, componentName, type); - - if ("parseAndLaunch".equalsIgnoreCase(call.method)) { - try { - intent = sender.parse(call.argument("uri")); - sender.send(intent); - result.success(null); - } catch (URISyntaxException e) { - result.error("parse_error", "Failed to parse URI", e.getMessage()); + private static String convertAction(String action) { + if (action == null) { + return null; } - } else if ("launch".equalsIgnoreCase(call.method)) { - if (intent != null && !sender.canResolveActivity(intent)) { - Log.i(TAG, "Cannot resolve explicit intent, falling back to implicit"); - intent.setPackage(null); + switch (action) { + case "action_view": + return Intent.ACTION_VIEW; + case "action_voice": + return Intent.ACTION_VOICE_COMMAND; + case "settings": + return Settings.ACTION_SETTINGS; + case "action_location_source_settings": + return Settings.ACTION_LOCATION_SOURCE_SETTINGS; + case "action_application_details_settings": + return Settings.ACTION_APPLICATION_DETAILS_SETTINGS; + default: + return action; } - - sender.send(intent); - result.success(null); - } else if ("launchChooser".equalsIgnoreCase(call.method)) { - String title = call.argument("chooserTitle"); - - sender.launchChooser(intent, title); - result.success(null); - } else if ("sendBroadcast".equalsIgnoreCase(call.method)) { - sender.sendBroadcast(intent); - result.success(null); - } else if ("sendService".equalsIgnoreCase(call.method)) { - sender.sendService(intent); - result.success(null); - } else if ("canResolveActivity".equalsIgnoreCase(call.method)) { - result.success(sender.canResolveActivity(intent)); - } else if ("getResolvedActivity".equalsIgnoreCase(call.method)) { - result.success(sender.getResolvedActivity(intent)); - } else { - result.notImplemented(); - } - } catch (Throwable e) { - result.error("error", e.getMessage(), null); } - } - private static String convertAction(String action) { - if (action == null) { - return null; - } - - switch (action) { - case "action_view": - return Intent.ACTION_VIEW; - case "action_voice": - return Intent.ACTION_VOICE_COMMAND; - case "settings": - return Settings.ACTION_SETTINGS; - case "action_location_source_settings": - return Settings.ACTION_LOCATION_SOURCE_SETTINGS; - case "action_application_details_settings": - return Settings.ACTION_APPLICATION_DETAILS_SETTINGS; - default: - return action; + private static Bundle convertArguments(Map arguments) { + Bundle bundle = new Bundle(); + if (arguments == null) { + return bundle; + } + for (String key : arguments.keySet()) { + Object value = arguments.get(key); + if (value instanceof Integer) { + bundle.putInt(key, (Integer) value); + } else if (value instanceof String) { + bundle.putString(key, (String) value); + } else if (value instanceof Boolean) { + bundle.putBoolean(key, (Boolean) value); + } else if (value instanceof Double) { + bundle.putDouble(key, (Double) value); + } else if (value instanceof Long) { + bundle.putLong(key, (Long) value); + } else if (value instanceof byte[]) { + bundle.putByteArray(key, (byte[]) value); + } else if (value instanceof int[]) { + bundle.putIntArray(key, (int[]) value); + } else if (value instanceof long[]) { + bundle.putLongArray(key, (long[]) value); + } else if (value instanceof double[]) { + bundle.putDoubleArray(key, (double[]) value); + } else if (isTypedArrayList(value, Integer.class)) { + bundle.putIntegerArrayList(key, (ArrayList) value); + } else if (isTypedArrayList(value, String.class)) { + bundle.putStringArrayList(key, (ArrayList) value); + } else if (isStringKeyedMap(value)) { + bundle.putBundle(key, convertArguments((Map) value)); + } else { + throw new UnsupportedOperationException("Unsupported type " + value); + } + } + return bundle; } - } - private static Bundle convertArguments(Map arguments) { - Bundle bundle = new Bundle(); - if (arguments == null) { - return bundle; - } - for (String key : arguments.keySet()) { - Object value = arguments.get(key); - if (value instanceof Integer) { - bundle.putInt(key, (Integer) value); - } else if (value instanceof String) { - bundle.putString(key, (String) value); - } else if (value instanceof Boolean) { - bundle.putBoolean(key, (Boolean) value); - } else if (value instanceof Double) { - bundle.putDouble(key, (Double) value); - } else if (value instanceof Long) { - bundle.putLong(key, (Long) value); - } else if (value instanceof byte[]) { - bundle.putByteArray(key, (byte[]) value); - } else if (value instanceof int[]) { - bundle.putIntArray(key, (int[]) value); - } else if (value instanceof long[]) { - bundle.putLongArray(key, (long[]) value); - } else if (value instanceof double[]) { - bundle.putDoubleArray(key, (double[]) value); - } else if (isTypedArrayList(value, Integer.class)) { - bundle.putIntegerArrayList(key, (ArrayList) value); - } else if (isTypedArrayList(value, String.class)) { - bundle.putStringArrayList(key, (ArrayList) value); - } else if (isStringKeyedMap(value)) { - bundle.putBundle(key, convertArguments((Map) value)); - } else { - throw new UnsupportedOperationException("Unsupported type " + value); - } + private static Bundle convertArrayArguments(Map arrayArguments) { + Bundle bundle = new Bundle(); + if (arrayArguments == null) { + return bundle; + } + for (String key : arrayArguments.keySet()) { + Object value = arrayArguments.get(key); + if (isTypedArrayList(value, Boolean.class)) { + ArrayList list = (ArrayList) value; + boolean[] array = new boolean[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + bundle.putBooleanArray(key, array); + } else if (isTypedArrayList(value, Integer.class)) { + ArrayList list = (ArrayList) value; + int[] array = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + bundle.putIntArray(key, array); + } else if (isTypedArrayList(value, Long.class)) { + ArrayList list = (ArrayList) value; + long[] array = new long[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + bundle.putLongArray(key, array); + } else if (isTypedArrayList(value, Double.class)) { + ArrayList list = (ArrayList) value; + double[] array = new double[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + bundle.putDoubleArray(key, array); + } else if (isTypedArrayList(value, String.class)) { + ArrayList list = (ArrayList) value; + bundle.putStringArray(key, list.toArray(new String[list.size()])); + } else { + throw new UnsupportedOperationException("Unsupported type " + value); + } + } + return bundle; } - return bundle; - } - private static Bundle convertArrayArguments(Map arrayArguments) { - Bundle bundle = new Bundle(); - if (arrayArguments == null) { - return bundle; - } - for (String key : arrayArguments.keySet()) { - Object value = arrayArguments.get(key); - if (isTypedArrayList(value, Boolean.class)) { - ArrayList list = (ArrayList) value; - boolean[] array = new boolean[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); + private static boolean isTypedArrayList(Object value, Class type) { + if (!(value instanceof ArrayList)) { + return false; } - bundle.putBooleanArray(key, array); - } else if (isTypedArrayList(value, Integer.class)) { - ArrayList list = (ArrayList) value; - int[] array = new int[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); + ArrayList list = (ArrayList) value; + for (Object o : list) { + if (!(o == null || type.isInstance(o))) { + return false; + } } - bundle.putIntArray(key, array); - } else if (isTypedArrayList(value, Long.class)) { - ArrayList list = (ArrayList) value; - long[] array = new long[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); + return true; + } + + private static boolean isStringKeyedMap(Object value) { + if (!(value instanceof Map)) { + return false; } - bundle.putLongArray(key, array); - } else if (isTypedArrayList(value, Double.class)) { - ArrayList list = (ArrayList) value; - double[] array = new double[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); + Map map = (Map) value; + for (Object key : map.keySet()) { + if (!(key == null || key instanceof String)) { + return false; + } } - bundle.putDoubleArray(key, array); - } else if (isTypedArrayList(value, String.class)) { - ArrayList list = (ArrayList) value; - bundle.putStringArray(key, list.toArray(new String[list.size()])); - } else { - throw new UnsupportedOperationException("Unsupported type " + value); - } + return true; } - return bundle; - } - private static boolean isTypedArrayList(Object value, Class type) { - if (!(value instanceof ArrayList)) { - return false; - } - ArrayList list = (ArrayList) value; - for (Object o : list) { - if (!(o == null || type.isInstance(o))) { - return false; - } + /** + * Registers this instance as a method call handler on the given {@code messenger}. + * + *

Stops any previously started and unstopped calls. + * + *

This should be cleaned with {@link #stopListening} once the messenger is disposed of. + */ + void startListening(BinaryMessenger messenger) { + if (methodChannel != null) { + Log.wtf(TAG, "Setting a method call handler before the last was disposed."); + stopListening(); + } + + methodChannel = new MethodChannel(messenger, "dev.fluttercommunity.plus/android_intent"); + methodChannel.setMethodCallHandler(this); } - return true; - } - private static boolean isStringKeyedMap(Object value) { - if (!(value instanceof Map)) { - return false; + /** + * Clears this instance from listening to method calls. + * + *

Does nothing is {@link #startListening} hasn't been called, or if we're already stopped. + */ + void stopListening() { + if (methodChannel == null) { + Log.d(TAG, "Tried to stop listening when no methodChannel had been initialized."); + return; + } + + methodChannel.setMethodCallHandler(null); + methodChannel = null; } - Map map = (Map) value; - for (Object key : map.keySet()) { - if (!(key == null || key instanceof String)) { - return false; - } + + /** + * Parses the incoming call and forwards it to the cached {@link IntentSender}. + * + *

Always calls {@code result#success}. + */ + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { + try { + String action = convertAction((String) call.argument("action")); + Integer flags = call.argument("flags"); + String category = call.argument("category"); + Uri data = call.argument("data") != null ? Uri.parse((String) call.argument("data")) : null; + Bundle arguments = convertArguments((Map) call.argument("arguments")); + Bundle arrayArguments = + convertArrayArguments((Map) call.argument("arrayArguments")); + arguments.putAll(arrayArguments); + String packageName = call.argument("package"); + ComponentName componentName = + (!TextUtils.isEmpty(packageName) + && !TextUtils.isEmpty((String) call.argument("componentName"))) + ? new ComponentName(packageName, (String) call.argument("componentName")) + : null; + String type = call.argument("type"); + + Intent intent = + sender.buildIntent( + action, flags, category, data, arguments, packageName, componentName, type); + + if ("parseAndLaunch".equalsIgnoreCase(call.method)) { + try { + intent = sender.parse(call.argument("uri")); + sender.send(intent); + result.success(null); + } catch (URISyntaxException e) { + result.error("parse_error", "Failed to parse URI", e.getMessage()); + } + } else if ("launch".equalsIgnoreCase(call.method)) { + + if (intent != null && !sender.canResolveActivity(intent)) { + Log.i(TAG, "Cannot resolve explicit intent, falling back to implicit"); + intent.setPackage(null); + } + + sender.send(intent); + result.success(null); + } else if ("launchChooser".equalsIgnoreCase(call.method)) { + String title = call.argument("chooserTitle"); + + sender.launchChooser(intent, title); + result.success(null); + } else if ("sendBroadcast".equalsIgnoreCase(call.method)) { + sender.sendBroadcast(intent); + result.success(null); + } else if ("sendService".equalsIgnoreCase(call.method)) { + sender.sendService(intent); + result.success(null); + } else if ("canResolveActivity".equalsIgnoreCase(call.method)) { + result.success(sender.canResolveActivity(intent)); + } else if ("getResolvedActivity".equalsIgnoreCase(call.method)) { + result.success(sender.getResolvedActivity(intent)); + } else { + result.notImplemented(); + } + } catch (Throwable e) { + result.error("error", e.getMessage(), null); + } } - return true; - } } diff --git a/packages/android_intent_plus/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java b/packages/android_intent_plus/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java index e9854974ce..63c1d5c220 100644 --- a/packages/android_intent_plus/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java +++ b/packages/android_intent_plus/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java @@ -17,13 +17,17 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; + import androidx.test.core.app.ApplicationProvider; + import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel.Result; + import java.util.HashMap; import java.util.Map; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,255 +36,255 @@ @RunWith(RobolectricTestRunner.class) public class MethodCallHandlerImplTest { - private static final String CHANNEL_NAME = "dev.fluttercommunity.plus/android_intent"; - private Context context; - private IntentSender sender; - private MethodCallHandlerImpl methodCallHandler; - - @Before - public void setUp() { - context = ApplicationProvider.getApplicationContext(); - sender = new IntentSender(null, null); - methodCallHandler = new MethodCallHandlerImpl(sender); - } - - @Test - public void startListening_registersChannel() { - BinaryMessenger messenger = mock(BinaryMessenger.class); - - methodCallHandler.startListening(messenger); - - verify(messenger, times(1)) - .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); - } - - @Test - public void startListening_unregistersExistingChannel() { - BinaryMessenger firstMessenger = mock(BinaryMessenger.class); - BinaryMessenger secondMessenger = mock(BinaryMessenger.class); - methodCallHandler.startListening(firstMessenger); - - methodCallHandler.startListening(secondMessenger); - - // Unregisters the first and then registers the second. - verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null); - verify(secondMessenger, times(1)) - .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); - } - - @Test - public void stopListening_unregistersExistingChannel() { - BinaryMessenger messenger = mock(BinaryMessenger.class); - methodCallHandler.startListening(messenger); - - methodCallHandler.stopListening(); - - verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null); - } - - @Test - public void stopListening_doesNothingWhenUnset() { - BinaryMessenger messenger = mock(BinaryMessenger.class); - - methodCallHandler.stopListening(); - - verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null); - } - - @Test - public void onMethodCall_doesNothingWhenContextIsNull() { - Result result = mock(Result.class); - Map args = new HashMap<>(); - args.put("action", "foo"); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - // No matter what, should always succeed. - verify(result, times(1)).success(null); - assertNull(shadowOf((Application) context).getNextStartedActivity()); - } - - @Test - public void onMethodCall_setsAction() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - args.put("action", "foo"); - Result result = mock(Result.class); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertEquals("foo", intent.getAction()); - } - - @Test - public void onMethodCall_setsNewTaskFlagWithApplicationContext() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - args.put("action", "foo"); - Result result = mock(Result.class); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK, intent.getFlags()); - } - - @Test - public void onMethodCall_addsFlags() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - args.put("action", "foo"); - Integer requestFlags = Intent.FLAG_FROM_BACKGROUND; - args.put("flags", requestFlags); - Result result = mock(Result.class); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK | requestFlags, intent.getFlags()); - } - - @Test - public void onMethodCall_addsCategory() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - args.put("action", "foo"); - String category = "bar"; - args.put("category", category); - Result result = mock(Result.class); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertTrue(intent.getCategories().contains(category)); - } - - @Test - public void onMethodCall_setsData() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - args.put("action", "foo"); - Uri data = Uri.parse("http://flutter.dev"); - args.put("data", data.toString()); - Result result = mock(Result.class); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertEquals(data, intent.getData()); - } - - @Test - public void onMethodCall_clearsInvalidPackageNames() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - args.put("action", "foo"); - args.put("packageName", "invalid"); - Result result = mock(Result.class); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertNull(intent.getPackage()); - } - - @Test - public void onMethodCall_setsComponentName() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - ComponentName expectedComponent = - new ComponentName("io.flutter.plugins.androidintent", "MainActivity"); - args.put("action", "foo"); - args.put("package", expectedComponent.getPackageName()); - args.put("componentName", expectedComponent.getClassName()); - Result result = mock(Result.class); - ShadowPackageManager shadowPm = - shadowOf(ApplicationProvider.getApplicationContext().getPackageManager()); - shadowPm.addActivityIfNotPresent(expectedComponent); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertNotNull(intent.getComponent()); - assertEquals("foo", intent.getAction()); - assertEquals("io.flutter.plugins.androidintent", intent.getPackage()); - assertEquals( - "io.flutter.plugins.androidintent/MainActivity", intent.getComponent().flattenToString()); - } - - @Test - public void onMethodCall_setsOnlyComponentName() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - ComponentName expectedComponent = - new ComponentName("io.flutter.plugins.androidintent", "MainActivity"); - args.put("package", expectedComponent.getPackageName()); - args.put("componentName", expectedComponent.getClassName()); - Result result = mock(Result.class); - ShadowPackageManager shadowPm = - shadowOf(ApplicationProvider.getApplicationContext().getPackageManager()); - shadowPm.addActivityIfNotPresent(expectedComponent); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertNotNull(intent.getComponent()); - assertEquals("io.flutter.plugins.androidintent", intent.getPackage()); - assertEquals( - "io.flutter.plugins.androidintent/MainActivity", intent.getComponent().flattenToString()); - } - - @Test - public void onMethodCall_setsType() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - args.put("action", "foo"); - String type = "video/*"; - args.put("type", type); - Result result = mock(Result.class); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertEquals(type, intent.getType()); - } - - @Test - public void onMethodCall_setsDataAndType() { - sender.setApplicationContext(context); - Map args = new HashMap<>(); - args.put("action", "foo"); - Uri data = Uri.parse("http://flutter.dev"); - args.put("data", data.toString()); - String type = "video/*"; - args.put("type", type); - Result result = mock(Result.class); - - methodCallHandler.onMethodCall(new MethodCall("launch", args), result); - - verify(result, times(1)).success(null); - Intent intent = shadowOf((Application) context).getNextStartedActivity(); - assertNotNull(intent); - assertEquals(type, intent.getType()); - assertEquals(data, intent.getData()); - } + private static final String CHANNEL_NAME = "dev.fluttercommunity.plus/android_intent"; + private Context context; + private IntentSender sender; + private MethodCallHandlerImpl methodCallHandler; + + @Before + public void setUp() { + context = ApplicationProvider.getApplicationContext(); + sender = new IntentSender(null, null); + methodCallHandler = new MethodCallHandlerImpl(sender); + } + + @Test + public void startListening_registersChannel() { + BinaryMessenger messenger = mock(BinaryMessenger.class); + + methodCallHandler.startListening(messenger); + + verify(messenger, times(1)) + .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + } + + @Test + public void startListening_unregistersExistingChannel() { + BinaryMessenger firstMessenger = mock(BinaryMessenger.class); + BinaryMessenger secondMessenger = mock(BinaryMessenger.class); + methodCallHandler.startListening(firstMessenger); + + methodCallHandler.startListening(secondMessenger); + + // Unregisters the first and then registers the second. + verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + verify(secondMessenger, times(1)) + .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + } + + @Test + public void stopListening_unregistersExistingChannel() { + BinaryMessenger messenger = mock(BinaryMessenger.class); + methodCallHandler.startListening(messenger); + + methodCallHandler.stopListening(); + + verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + } + + @Test + public void stopListening_doesNothingWhenUnset() { + BinaryMessenger messenger = mock(BinaryMessenger.class); + + methodCallHandler.stopListening(); + + verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null); + } + + @Test + public void onMethodCall_doesNothingWhenContextIsNull() { + Result result = mock(Result.class); + Map args = new HashMap<>(); + args.put("action", "foo"); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + // No matter what, should always succeed. + verify(result, times(1)).success(null); + assertNull(shadowOf((Application) context).getNextStartedActivity()); + } + + @Test + public void onMethodCall_setsAction() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + args.put("action", "foo"); + Result result = mock(Result.class); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertEquals("foo", intent.getAction()); + } + + @Test + public void onMethodCall_setsNewTaskFlagWithApplicationContext() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + args.put("action", "foo"); + Result result = mock(Result.class); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK, intent.getFlags()); + } + + @Test + public void onMethodCall_addsFlags() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + args.put("action", "foo"); + Integer requestFlags = Intent.FLAG_FROM_BACKGROUND; + args.put("flags", requestFlags); + Result result = mock(Result.class); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK | requestFlags, intent.getFlags()); + } + + @Test + public void onMethodCall_addsCategory() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + args.put("action", "foo"); + String category = "bar"; + args.put("category", category); + Result result = mock(Result.class); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertTrue(intent.getCategories().contains(category)); + } + + @Test + public void onMethodCall_setsData() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + args.put("action", "foo"); + Uri data = Uri.parse("http://flutter.dev"); + args.put("data", data.toString()); + Result result = mock(Result.class); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertEquals(data, intent.getData()); + } + + @Test + public void onMethodCall_clearsInvalidPackageNames() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + args.put("action", "foo"); + args.put("packageName", "invalid"); + Result result = mock(Result.class); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertNull(intent.getPackage()); + } + + @Test + public void onMethodCall_setsComponentName() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + ComponentName expectedComponent = + new ComponentName("io.flutter.plugins.androidintent", "MainActivity"); + args.put("action", "foo"); + args.put("package", expectedComponent.getPackageName()); + args.put("componentName", expectedComponent.getClassName()); + Result result = mock(Result.class); + ShadowPackageManager shadowPm = + shadowOf(ApplicationProvider.getApplicationContext().getPackageManager()); + shadowPm.addActivityIfNotPresent(expectedComponent); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertNotNull(intent.getComponent()); + assertEquals("foo", intent.getAction()); + assertEquals("io.flutter.plugins.androidintent", intent.getPackage()); + assertEquals( + "io.flutter.plugins.androidintent/MainActivity", intent.getComponent().flattenToString()); + } + + @Test + public void onMethodCall_setsOnlyComponentName() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + ComponentName expectedComponent = + new ComponentName("io.flutter.plugins.androidintent", "MainActivity"); + args.put("package", expectedComponent.getPackageName()); + args.put("componentName", expectedComponent.getClassName()); + Result result = mock(Result.class); + ShadowPackageManager shadowPm = + shadowOf(ApplicationProvider.getApplicationContext().getPackageManager()); + shadowPm.addActivityIfNotPresent(expectedComponent); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertNotNull(intent.getComponent()); + assertEquals("io.flutter.plugins.androidintent", intent.getPackage()); + assertEquals( + "io.flutter.plugins.androidintent/MainActivity", intent.getComponent().flattenToString()); + } + + @Test + public void onMethodCall_setsType() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + args.put("action", "foo"); + String type = "video/*"; + args.put("type", type); + Result result = mock(Result.class); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertEquals(type, intent.getType()); + } + + @Test + public void onMethodCall_setsDataAndType() { + sender.setApplicationContext(context); + Map args = new HashMap<>(); + args.put("action", "foo"); + Uri data = Uri.parse("http://flutter.dev"); + args.put("data", data.toString()); + String type = "video/*"; + args.put("type", type); + Result result = mock(Result.class); + + methodCallHandler.onMethodCall(new MethodCall("launch", args), result); + + verify(result, times(1)).success(null); + Intent intent = shadowOf((Application) context).getNextStartedActivity(); + assertNotNull(intent); + assertEquals(type, intent.getType()); + assertEquals(data, intent.getData()); + } } diff --git a/packages/android_intent_plus/example/android/app/build.gradle b/packages/android_intent_plus/example/android/app/build.gradle index ed42698bfe..a704f1bec9 100644 --- a/packages/android_intent_plus/example/android/app/build.gradle +++ b/packages/android_intent_plus/example/android/app/build.gradle @@ -23,7 +23,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'io.flutter.plugins.androidintentexample' @@ -39,7 +39,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.androidintentexample" minSdk 21 - targetSdk 34 + targetSdk 35 multiDexEnabled true versionCode flutterVersionCode.toInteger() @@ -70,7 +70,7 @@ dependencies { } } implementation 'androidx.multidex:multidex:2.0.1' - implementation 'androidx.core:core-ktx:1.13.1' + implementation 'androidx.core:core:1.15.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test:runner:1.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' diff --git a/packages/android_intent_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties b/packages/android_intent_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties index e411586a54..2733ed5dc3 100644 --- a/packages/android_intent_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties +++ b/packages/android_intent_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/android_intent_plus/example/android/app/src/androidTestDebug/java/io/flutter/plugins/androidintentexample/MainActivityTest.java b/packages/android_intent_plus/example/android/app/src/androidTestDebug/java/io/flutter/plugins/androidintentexample/MainActivityTest.java index d390dcd749..6ebd921462 100644 --- a/packages/android_intent_plus/example/android/app/src/androidTestDebug/java/io/flutter/plugins/androidintentexample/MainActivityTest.java +++ b/packages/android_intent_plus/example/android/app/src/androidTestDebug/java/io/flutter/plugins/androidintentexample/MainActivityTest.java @@ -1,11 +1,14 @@ package io.flutter.plugins.androidintentexample; import androidx.test.rule.ActivityTestRule; + import dev.flutter.plugins.e2e.FlutterRunner; + import org.junit.Rule; import org.junit.runner.RunWith; @RunWith(FlutterRunner.class) public class MainActivityTest { - @Rule public ActivityTestRule rule = new ActivityTestRule<>(MainActivity.class); + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(MainActivity.class); } diff --git a/packages/android_intent_plus/example/android/app/src/main/AndroidManifest.xml b/packages/android_intent_plus/example/android/app/src/main/AndroidManifest.xml index 20f0667b3e..86791dbad9 100644 --- a/packages/android_intent_plus/example/android/app/src/main/AndroidManifest.xml +++ b/packages/android_intent_plus/example/android/app/src/main/AndroidManifest.xml @@ -1,58 +1,59 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + package="io.flutter.plugins.androidintentexample"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/android_intent_plus/example/android/app/src/main/java/io/flutter/plugins/androidintentexample/MainActivity.java b/packages/android_intent_plus/example/android/app/src/main/java/io/flutter/plugins/androidintentexample/MainActivity.java index 125227d3ed..36153efa9f 100644 --- a/packages/android_intent_plus/example/android/app/src/main/java/io/flutter/plugins/androidintentexample/MainActivity.java +++ b/packages/android_intent_plus/example/android/app/src/main/java/io/flutter/plugins/androidintentexample/MainActivity.java @@ -3,18 +3,20 @@ import android.annotation.SuppressLint; import android.content.IntentFilter; import android.os.Bundle; + import androidx.core.content.ContextCompat; + import io.flutter.embedding.android.FlutterActivity; public class MainActivity extends FlutterActivity { - @SuppressLint("WrongConstant") - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @SuppressLint("WrongConstant") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); - IntentFilter filter = new IntentFilter("com.example.broadcast"); - MyBroadcastReceiver receiver = new MyBroadcastReceiver(); - ContextCompat.registerReceiver(this, receiver, filter, ContextCompat.RECEIVER_EXPORTED); - } + IntentFilter filter = new IntentFilter("com.example.broadcast"); + MyBroadcastReceiver receiver = new MyBroadcastReceiver(); + ContextCompat.registerReceiver(this, receiver, filter, ContextCompat.RECEIVER_EXPORTED); + } } diff --git a/packages/android_intent_plus/example/android/app/src/main/java/io/flutter/plugins/androidintentexample/MyBroadcastReceiver.java b/packages/android_intent_plus/example/android/app/src/main/java/io/flutter/plugins/androidintentexample/MyBroadcastReceiver.java index ab66f6759f..c6c563d0da 100644 --- a/packages/android_intent_plus/example/android/app/src/main/java/io/flutter/plugins/androidintentexample/MyBroadcastReceiver.java +++ b/packages/android_intent_plus/example/android/app/src/main/java/io/flutter/plugins/androidintentexample/MyBroadcastReceiver.java @@ -7,9 +7,9 @@ import android.widget.Toast; public class MyBroadcastReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Log.d("MyBroadcastReceiver", "Got Intent: " + intent.toString()); - Toast.makeText(context, "Broadcast Received!", Toast.LENGTH_LONG).show(); - } + @Override + public void onReceive(Context context, Intent intent) { + Log.d("MyBroadcastReceiver", "Got Intent: " + intent.toString()); + Toast.makeText(context, "Broadcast Received!", Toast.LENGTH_LONG).show(); + } } diff --git a/packages/android_intent_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/android_intent_plus/example/android/gradle/wrapper/gradle-wrapper.properties index 8dee89d1a6..2fddc3d201 100644 --- a/packages/android_intent_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/android_intent_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Oct 02 17:46:54 EEST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/android_intent_plus/example/android/settings.gradle b/packages/android_intent_plus/example/android/settings.gradle index 5133de22fb..18a751a498 100644 --- a/packages/android_intent_plus/example/android/settings.gradle +++ b/packages/android_intent_plus/example/android/settings.gradle @@ -18,8 +18,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false - id "org.jetbrains.kotlin.android" version "1.7.22" apply false + id "com.android.application" version "8.9.0" apply false + id "org.jetbrains.kotlin.android" version "2.1.10" apply false } include ":app" diff --git a/packages/android_intent_plus/example/integration_test/android_intent_plus_test.dart b/packages/android_intent_plus/example/integration_test/android_intent_plus_test.dart index 341cac544a..ccbd9bc3e3 100644 --- a/packages/android_intent_plus/example/integration_test/android_intent_plus_test.dart +++ b/packages/android_intent_plus/example/integration_test/android_intent_plus_test.dart @@ -39,20 +39,25 @@ void main() { } }); - testWidgets('Launch throws when no Activity is found', - (WidgetTester tester) async { + testWidgets('Launch throws when no Activity is found', ( + WidgetTester tester, + ) async { // We can't test that any of this is really working, this is mostly just // checking that the plugin API is registered. Only works on Android. const intent = AndroidIntent(action: 'LAUNCH', package: 'foobar'); - await expectLater(() async => await intent.launch(), throwsA((Exception e) { - return e is PlatformException && - e.message!.contains('No Activity found to handle Intent'); - })); + await expectLater( + () async => await intent.launch(), + throwsA((Exception e) { + return e is PlatformException && + e.message!.contains('No Activity found to handle Intent'); + }), + ); }, skip: !Platform.isAndroid); - testWidgets('Set an alarm on weekdays at 9:30pm should not throw', - (WidgetTester tester) async { - const intent = AndroidIntent( + testWidgets( + 'Set an alarm on weekdays at 9:30pm should not throw', + (WidgetTester tester) async { + const intent = AndroidIntent( action: 'android.intent.action.SET_ALARM', arguments: { 'android.intent.extra.alarm.DAYS': [2, 3, 4, 5, 6], @@ -60,12 +65,16 @@ void main() { 'android.intent.extra.alarm.MINUTES': 30, 'android.intent.extra.alarm.SKIP_UI': true, 'android.intent.extra.alarm.MESSAGE': 'Just for Integration test', - }); - await intent.launch(); - }, skip: !Platform.isAndroid); + }, + ); + await intent.launch(); + }, + skip: !Platform.isAndroid, + ); testWidgets('Parse and Launch should not throw', (WidgetTester tester) async { - const intent = 'intent:#Intent;' + const intent = + 'intent:#Intent;' 'action=android.intent.action.SET_ALARM;' 'B.android.intent.extra.alarm.SKIP_UI=true;' 'S.android.intent.extra.alarm.MESSAGE=Create%20a%20Flutter%20app;' @@ -86,51 +95,58 @@ void main() { }, skip: !Platform.isAndroid); testWidgets('sendService should not throw', (WidgetTester tester) async { - const intent = AndroidIntent( - action: 'com.example.service', - ); + const intent = AndroidIntent(action: 'com.example.service'); await intent.sendService(); }, skip: !Platform.isAndroid); testWidgets('SendBroadcast should not throw', (WidgetTester tester) async { - const intent = AndroidIntent( - action: 'com.example.broadcast', - ); + const intent = AndroidIntent(action: 'com.example.broadcast'); await intent.sendBroadcast(); }, skip: !Platform.isAndroid); - testWidgets('CanResolveActivity returns true when example Activity is found', - (WidgetTester tester) async { - const intent = AndroidIntent( - action: 'action_view', - package: 'io.flutter.plugins.androidintentexample', - componentName: 'io.flutter.plugins.androidintentexample.MainActivity', - ); - await expectLater(await intent.canResolveActivity(), isTrue); - }, skip: !Platform.isAndroid); + testWidgets( + 'CanResolveActivity returns true when example Activity is found', + (WidgetTester tester) async { + const intent = AndroidIntent( + action: 'action_view', + package: 'io.flutter.plugins.androidintentexample', + componentName: 'io.flutter.plugins.androidintentexample.MainActivity', + ); + await expectLater(await intent.canResolveActivity(), isTrue); + }, + skip: !Platform.isAndroid, + ); - testWidgets('CanResolveActivity returns false when no Activity is found', - (WidgetTester tester) async { - const intent = AndroidIntent(action: 'LAUNCH', package: 'foobar'); - await expectLater(await intent.canResolveActivity(), isFalse); - }, skip: !Platform.isAndroid); + testWidgets( + 'CanResolveActivity returns false when no Activity is found', + (WidgetTester tester) async { + const intent = AndroidIntent(action: 'LAUNCH', package: 'foobar'); + await expectLater(await intent.canResolveActivity(), isFalse); + }, + skip: !Platform.isAndroid, + ); testWidgets( - 'getResolvedActivity return activity details when example Activity is found', - (WidgetTester tester) async { - final intent = AndroidIntent( - action: 'action_view', - data: Uri.encodeFull('http://'), - ); - await expectLater(await intent.getResolvedActivity(), isNotNull); - }, skip: !Platform.isAndroid); + 'getResolvedActivity return activity details when example Activity is found', + (WidgetTester tester) async { + final intent = AndroidIntent( + action: 'action_view', + data: Uri.encodeFull('http://'), + ); + await expectLater(await intent.getResolvedActivity(), isNotNull); + }, + skip: !Platform.isAndroid, + ); - testWidgets('getResolvedActivity returns null when no Activity is found', - (WidgetTester tester) async { - final intent = AndroidIntent( - action: 'action_view', - data: Uri.encodeFull('mycustomscheme://'), - ); - await expectLater(await intent.getResolvedActivity(), isNull); - }, skip: !Platform.isAndroid); + testWidgets( + 'getResolvedActivity returns null when no Activity is found', + (WidgetTester tester) async { + final intent = AndroidIntent( + action: 'action_view', + data: Uri.encodeFull('mycustomscheme://'), + ); + await expectLater(await intent.getResolvedActivity(), isNull); + }, + skip: !Platform.isAndroid, + ); } diff --git a/packages/android_intent_plus/example/ios/Runner/AppDelegate.m b/packages/android_intent_plus/example/ios/Runner/AppDelegate.m index 26c653a8ea..54a549ff8a 100644 --- a/packages/android_intent_plus/example/ios/Runner/AppDelegate.m +++ b/packages/android_intent_plus/example/ios/Runner/AppDelegate.m @@ -7,12 +7,12 @@ @implementation AppDelegate -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - // Override point for customization after application launch. - return [super application:application - didFinishLaunchingWithOptions:launchOptions]; +- (BOOL) application:(UIApplication *)application +didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + // Override point for customization after application launch. + return [super application:application +didFinishLaunchingWithOptions:launchOptions]; } @end diff --git a/packages/android_intent_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/android_intent_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d22f10b2ab..8ed7b0f6b5 100644 --- a/packages/android_intent_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/android_intent_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,116 +1,116 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/android_intent_plus/example/ios/Runner/main.m b/packages/android_intent_plus/example/ios/Runner/main.m index b7fe28c73a..e574c83b0d 100644 --- a/packages/android_intent_plus/example/ios/Runner/main.m +++ b/packages/android_intent_plus/example/ios/Runner/main.m @@ -7,8 +7,8 @@ #import int main(int argc, char *argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, - NSStringFromClass([AppDelegate class])); - } + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, + NSStringFromClass([AppDelegate class])); + } } diff --git a/packages/android_intent_plus/example/lib/main.dart b/packages/android_intent_plus/example/lib/main.dart index ce48c1305c..a50084883d 100644 --- a/packages/android_intent_plus/example/lib/main.dart +++ b/packages/android_intent_plus/example/lib/main.dart @@ -26,8 +26,8 @@ class MyApp extends StatelessWidget { ), home: const MyHomePage(), routes: { - ExplicitIntentsWidget.routeName: (BuildContext context) => - const ExplicitIntentsWidget() + ExplicitIntentsWidget.routeName: + (BuildContext context) => const ExplicitIntentsWidget(), }, ); } @@ -67,7 +67,8 @@ class MyHomePage extends StatelessWidget { ElevatedButton( onPressed: _createAlarm, child: const Text( - 'Tap here to set an alarm\non weekdays at 9:30pm.'), + 'Tap here to set an alarm\non weekdays at 9:30pm.', + ), ), ElevatedButton( onPressed: _parseAndLaunch, @@ -110,14 +111,13 @@ class MyHomePage extends StatelessWidget { } void _sendBroadcast() { - const intent = AndroidIntent( - action: 'com.example.broadcast', - ); + const intent = AndroidIntent(action: 'com.example.broadcast'); intent.sendBroadcast(); } void _parseAndLaunch() { - const intent = 'intent:#Intent;' + const intent = + 'intent:#Intent;' 'action=android.intent.action.SET_ALARM;' 'B.android.intent.extra.alarm.SKIP_UI=true;' 'S.android.intent.extra.alarm.MESSAGE=Create%20a%20Flutter%20app;' @@ -139,34 +139,39 @@ class ExplicitIntentsWidget extends StatelessWidget { void _openGoogleMapsStreetView() { final intent = AndroidIntent( - action: 'action_view', - data: Uri.encodeFull('google.streetview:cbll=46.414382,10.013988'), - package: 'com.google.android.apps.maps'); + action: 'action_view', + data: Uri.encodeFull('google.streetview:cbll=46.414382,10.013988'), + package: 'com.google.android.apps.maps', + ); intent.launch(); } void _displayMapInGoogleMaps({int zoomLevel = 12}) { final intent = AndroidIntent( - action: 'action_view', - data: Uri.encodeFull('geo:37.7749,-122.4194?z=$zoomLevel'), - package: 'com.google.android.apps.maps'); + action: 'action_view', + data: Uri.encodeFull('geo:37.7749,-122.4194?z=$zoomLevel'), + package: 'com.google.android.apps.maps', + ); intent.launch(); } void _launchTurnByTurnNavigationInGoogleMaps() { final intent = AndroidIntent( - action: 'action_view', - data: Uri.encodeFull( - 'google.navigation:q=Taronga+Zoo,+Sydney+Australia&avoid=tf'), - package: 'com.google.android.apps.maps'); + action: 'action_view', + data: Uri.encodeFull( + 'google.navigation:q=Taronga+Zoo,+Sydney+Australia&avoid=tf', + ), + package: 'com.google.android.apps.maps', + ); intent.launch(); } void _openLinkInGoogleChrome() { final intent = AndroidIntent( - action: 'action_view', - data: Uri.encodeFull('https://flutter.dev'), - package: 'com.android.chrome'); + action: 'action_view', + data: Uri.encodeFull('https://flutter.dev'), + package: 'com.android.chrome', + ); intent.launch(); } @@ -181,9 +186,10 @@ class ExplicitIntentsWidget extends StatelessWidget { void _testExplicitIntentFallback() { final intent = AndroidIntent( - action: 'action_view', - data: Uri.encodeFull('https://flutter.dev'), - package: 'com.android.chrome.implicit.fallback'); + action: 'action_view', + data: Uri.encodeFull('https://flutter.dev'), + package: 'com.android.chrome.implicit.fallback', + ); intent.launch(); } @@ -234,10 +240,7 @@ class ExplicitIntentsWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Test explicit intents'), - elevation: 4, - ), + appBar: AppBar(title: const Text('Test explicit intents'), elevation: 4), body: Center( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(vertical: 15.0), @@ -247,7 +250,8 @@ class ExplicitIntentsWidget extends StatelessWidget { ElevatedButton( onPressed: _openGoogleMapsStreetView, child: const Text( - 'Tap here to display panorama\nimagery in Google Street View.'), + 'Tap here to display panorama\nimagery in Google Street View.', + ), ), const SizedBox(height: 16), ElevatedButton( @@ -258,7 +262,8 @@ class ExplicitIntentsWidget extends StatelessWidget { ElevatedButton( onPressed: _launchTurnByTurnNavigationInGoogleMaps, child: const Text( - 'Tap here to launch turn-by-turn\nnavigation in Google Maps.'), + 'Tap here to launch turn-by-turn\nnavigation in Google Maps.', + ), ), const SizedBox(height: 16), ElevatedButton( @@ -274,7 +279,8 @@ class ExplicitIntentsWidget extends StatelessWidget { ElevatedButton( onPressed: _testExplicitIntentFallback, child: const Text( - 'Tap here to test explicit intent fallback to implicit.'), + 'Tap here to test explicit intent fallback to implicit.', + ), ), const SizedBox(height: 16), ElevatedButton( @@ -286,23 +292,17 @@ class ExplicitIntentsWidget extends StatelessWidget { const SizedBox(height: 16), ElevatedButton( onPressed: _openApplicationDetails, - child: const Text( - 'Tap here to open Application Details', - ), + child: const Text('Tap here to open Application Details'), ), const SizedBox(height: 16), ElevatedButton( onPressed: () => _getResolvedActivity(context), - child: const Text( - 'Tap here to get default resolved activity', - ), + child: const Text('Tap here to get default resolved activity'), ), const SizedBox(height: 16), ElevatedButton( onPressed: _openGmail, - child: const Text( - 'Tap here to open gmail app with details', - ), + child: const Text('Tap here to open gmail app with details'), ), ], ), diff --git a/packages/android_intent_plus/lib/android_intent.dart b/packages/android_intent_plus/lib/android_intent.dart index d6e2fff3f1..c676e671dd 100644 --- a/packages/android_intent_plus/lib/android_intent.dart +++ b/packages/android_intent_plus/lib/android_intent.dart @@ -41,10 +41,12 @@ class AndroidIntent { this.componentName, Platform? platform, this.type, - }) : assert(action != null || componentName != null, - 'action or component (or both) must be specified'), - _channel = const MethodChannel(_kChannelName), - _platform = platform ?? const LocalPlatform(); + }) : assert( + action != null || componentName != null, + 'action or component (or both) must be specified', + ), + _channel = const MethodChannel(_kChannelName), + _platform = platform ?? const LocalPlatform(); /// This constructor is only exposed for unit testing. Do not rely on this in /// app code, it may break without warning. @@ -61,10 +63,12 @@ class AndroidIntent { this.package, this.componentName, this.type, - }) : assert(action != null || componentName != null, - 'action or component (or both) must be specified'), - _channel = channel, - _platform = platform; + }) : assert( + action != null || componentName != null, + 'action or component (or both) must be specified', + ), + _channel = channel, + _platform = platform; /// This is the general verb that the intent should attempt to do. This /// includes constants like `ACTION_VIEW`. @@ -159,8 +163,9 @@ class AndroidIntent { return; } - await const MethodChannel(_kChannelName) - .invokeMethod('parseAndLaunch', {'uri': uri}); + await const MethodChannel( + _kChannelName, + ).invokeMethod('parseAndLaunch', {'uri': uri}); } /// Launch the intent with 'createChooser(intent, title)'. @@ -173,10 +178,7 @@ class AndroidIntent { final buildArguments = _buildArguments(); buildArguments['chooserTitle'] = title; - await _channel.invokeMethod( - 'launchChooser', - buildArguments, - ); + await _channel.invokeMethod('launchChooser', buildArguments); } /// Starts intent as service. @@ -187,10 +189,7 @@ class AndroidIntent { return; } - await _channel.invokeMethod( - 'sendService', - _buildArguments(), - ); + await _channel.invokeMethod('sendService', _buildArguments()); } /// Sends intent as broadcast. @@ -201,10 +200,7 @@ class AndroidIntent { return; } - await _channel.invokeMethod( - 'sendBroadcast', - _buildArguments(), - ); + await _channel.invokeMethod('sendBroadcast', _buildArguments()); } /// Check whether the intent can be resolved to an activity. diff --git a/packages/android_intent_plus/test/android_intent_test.dart b/packages/android_intent_plus/test/android_intent_test.dart index ce6fd3d4c5..d7478dc14b 100644 --- a/packages/android_intent_plus/test/android_intent_test.dart +++ b/packages/android_intent_plus/test/android_intent_test.dart @@ -31,20 +31,24 @@ void main() { group('launch', () { test('pass right params', () async { androidIntent = AndroidIntent.private( - action: 'action_view', - data: Uri.encodeFull('https://flutter.dev'), - flags: [Flag.FLAG_ACTIVITY_NEW_TASK], - channel: mockChannel, - platform: FakePlatform(operatingSystem: 'android'), - type: 'video/*'); + action: 'action_view', + data: Uri.encodeFull('https://flutter.dev'), + flags: [Flag.FLAG_ACTIVITY_NEW_TASK], + channel: mockChannel, + platform: FakePlatform(operatingSystem: 'android'), + type: 'video/*', + ); await androidIntent.launch(); - verify(mockChannel.invokeMethod('launch', { - 'action': 'action_view', - 'data': Uri.encodeFull('https://flutter.dev'), - 'flags': - androidIntent.convertFlags([Flag.FLAG_ACTIVITY_NEW_TASK]), - 'type': 'video/*', - })); + verify( + mockChannel.invokeMethod('launch', { + 'action': 'action_view', + 'data': Uri.encodeFull('https://flutter.dev'), + 'flags': androidIntent.convertFlags([ + Flag.FLAG_ACTIVITY_NEW_TASK, + ]), + 'type': 'video/*', + }), + ); }); test('can send Intent with an action and no component', () async { @@ -54,9 +58,11 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.launch(); - verify(mockChannel.invokeMethod('launch', { - 'action': 'action_view', - })); + verify( + mockChannel.invokeMethod('launch', { + 'action': 'action_view', + }), + ); }); test('can send Intent with a component and no action', () async { @@ -67,17 +73,20 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.launch(); - verify(mockChannel.invokeMethod('launch', { - 'package': 'packageName', - 'componentName': 'componentName', - })); + verify( + mockChannel.invokeMethod('launch', { + 'package': 'packageName', + 'componentName': 'componentName', + }), + ); }); test('call in ios platform', () async { androidIntent = AndroidIntent.private( - action: 'action_view', - channel: mockChannel, - platform: FakePlatform(operatingSystem: 'ios')); + action: 'action_view', + channel: mockChannel, + platform: FakePlatform(operatingSystem: 'ios'), + ); await androidIntent.launch(); verifyZeroInteractions(mockChannel); }); @@ -86,21 +95,24 @@ void main() { group('canResolveActivity', () { test('pass right params', () async { androidIntent = AndroidIntent.private( - action: 'action_view', - data: Uri.encodeFull('https://flutter.dev'), - flags: [Flag.FLAG_ACTIVITY_NEW_TASK], - channel: mockChannel, - platform: FakePlatform(operatingSystem: 'android'), - type: 'video/*'); + action: 'action_view', + data: Uri.encodeFull('https://flutter.dev'), + flags: [Flag.FLAG_ACTIVITY_NEW_TASK], + channel: mockChannel, + platform: FakePlatform(operatingSystem: 'android'), + type: 'video/*', + ); await androidIntent.canResolveActivity(); - verify(mockChannel - .invokeMethod('canResolveActivity', { - 'action': 'action_view', - 'data': Uri.encodeFull('https://flutter.dev'), - 'flags': - androidIntent.convertFlags([Flag.FLAG_ACTIVITY_NEW_TASK]), - 'type': 'video/*', - })); + verify( + mockChannel.invokeMethod('canResolveActivity', { + 'action': 'action_view', + 'data': Uri.encodeFull('https://flutter.dev'), + 'flags': androidIntent.convertFlags([ + Flag.FLAG_ACTIVITY_NEW_TASK, + ]), + 'type': 'video/*', + }), + ); }); test('can send Intent with an action and no component', () async { @@ -110,10 +122,11 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.canResolveActivity(); - verify(mockChannel - .invokeMethod('canResolveActivity', { - 'action': 'action_view', - })); + verify( + mockChannel.invokeMethod('canResolveActivity', { + 'action': 'action_view', + }), + ); }); test('can send Intent with a component and no action', () async { @@ -124,18 +137,20 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.canResolveActivity(); - verify(mockChannel - .invokeMethod('canResolveActivity', { - 'package': 'packageName', - 'componentName': 'componentName', - })); + verify( + mockChannel.invokeMethod('canResolveActivity', { + 'package': 'packageName', + 'componentName': 'componentName', + }), + ); }); test('call in ios platform', () async { androidIntent = AndroidIntent.private( - action: 'action_view', - channel: mockChannel, - platform: FakePlatform(operatingSystem: 'ios')); + action: 'action_view', + channel: mockChannel, + platform: FakePlatform(operatingSystem: 'ios'), + ); await androidIntent.canResolveActivity(); verifyZeroInteractions(mockChannel); }); @@ -144,21 +159,27 @@ void main() { group('getResolvedActivity', () { test('pass right params', () async { androidIntent = AndroidIntent.private( - action: 'action_view', - data: Uri.encodeFull('https://flutter.dev'), - flags: [Flag.FLAG_ACTIVITY_NEW_TASK], - channel: mockChannel, - platform: FakePlatform(operatingSystem: 'android'), - type: 'video/*'); + action: 'action_view', + data: Uri.encodeFull('https://flutter.dev'), + flags: [Flag.FLAG_ACTIVITY_NEW_TASK], + channel: mockChannel, + platform: FakePlatform(operatingSystem: 'android'), + type: 'video/*', + ); await androidIntent.getResolvedActivity(); - verify(mockChannel - .invokeMethod('getResolvedActivity', { - 'action': 'action_view', - 'data': Uri.encodeFull('https://flutter.dev'), - 'flags': - androidIntent.convertFlags([Flag.FLAG_ACTIVITY_NEW_TASK]), - 'type': 'video/*', - })); + verify( + mockChannel.invokeMethod( + 'getResolvedActivity', + { + 'action': 'action_view', + 'data': Uri.encodeFull('https://flutter.dev'), + 'flags': androidIntent.convertFlags([ + Flag.FLAG_ACTIVITY_NEW_TASK, + ]), + 'type': 'video/*', + }, + ), + ); }); test('returns a ResolvedActivity', () async { @@ -169,12 +190,13 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); - when(mockChannel.invokeMethod("getResolvedActivity", any)) - .thenAnswer((_) async => { - "activityName": "activity name", - "appName": "App Name", - "packageName": "com.packagename", - }); + when(mockChannel.invokeMethod("getResolvedActivity", any)).thenAnswer( + (_) async => { + "activityName": "activity name", + "appName": "App Name", + "packageName": "com.packagename", + }, + ); final result = await androidIntent.getResolvedActivity(); @@ -190,10 +212,12 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.getResolvedActivity(); - verify(mockChannel - .invokeMethod('getResolvedActivity', { - 'action': 'action_view', - })); + verify( + mockChannel.invokeMethod( + 'getResolvedActivity', + {'action': 'action_view'}, + ), + ); }); test('can send Intent with a component and no action', () async { @@ -204,18 +228,23 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.getResolvedActivity(); - verify(mockChannel - .invokeMethod('getResolvedActivity', { - 'package': 'packageName', - 'componentName': 'componentName', - })); + verify( + mockChannel.invokeMethod( + 'getResolvedActivity', + { + 'package': 'packageName', + 'componentName': 'componentName', + }, + ), + ); }); test('call in ios platform', () async { androidIntent = AndroidIntent.private( - action: 'action_view', - channel: mockChannel, - platform: FakePlatform(operatingSystem: 'ios')); + action: 'action_view', + channel: mockChannel, + platform: FakePlatform(operatingSystem: 'ios'), + ); await androidIntent.getResolvedActivity(); verifyZeroInteractions(mockChannel); }); @@ -229,10 +258,12 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.launchChooser('title'); - verify(mockChannel.invokeMethod('launchChooser', { - 'action': 'action_view', - 'chooserTitle': 'title', - })); + verify( + mockChannel.invokeMethod('launchChooser', { + 'action': 'action_view', + 'chooserTitle': 'title', + }), + ); }); }); @@ -244,9 +275,11 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.sendService(); - verify(mockChannel.invokeMethod('sendService', { - 'action': 'com.example.service', - })); + verify( + mockChannel.invokeMethod('sendService', { + 'action': 'com.example.service', + }), + ); }); }); @@ -258,41 +291,32 @@ void main() { platform: FakePlatform(operatingSystem: 'android'), ); await androidIntent.sendBroadcast(); - verify(mockChannel.invokeMethod('sendBroadcast', { - 'action': 'com.example.broadcast', - })); + verify( + mockChannel.invokeMethod('sendBroadcast', { + 'action': 'com.example.broadcast', + }), + ); }); }); }); group('convertFlags ', () { - androidIntent = const AndroidIntent( - action: 'action_view', - ); + androidIntent = const AndroidIntent(action: 'action_view'); test('add filled flag list', () async { final flags = []; flags.add(Flag.FLAG_ACTIVITY_NEW_TASK); flags.add(Flag.FLAG_ACTIVITY_NEW_DOCUMENT); - expect( - androidIntent.convertFlags(flags), - 268959744, - ); + expect(androidIntent.convertFlags(flags), 268959744); }); test('add flags whose values are not power of 2', () async { final flags = []; flags.add(100); flags.add(10); - expect( - () => androidIntent.convertFlags(flags), - throwsArgumentError, - ); + expect(() => androidIntent.convertFlags(flags), throwsArgumentError); }); test('add empty flag list', () async { final flags = []; - expect( - androidIntent.convertFlags(flags), - 0, - ); + expect(androidIntent.convertFlags(flags), 0); }); }); } @@ -301,8 +325,9 @@ void main() { class MockMethodChannel extends Mock implements MethodChannel { @override Future invokeMethod(String method, [dynamic arguments]) async { - return super - .noSuchMethod(Invocation.method(#invokeMethod, [method, arguments])) + return super.noSuchMethod( + Invocation.method(#invokeMethod, [method, arguments]), + ) as dynamic; } } diff --git a/packages/battery_plus/battery_plus/CHANGELOG.md b/packages/battery_plus/battery_plus/CHANGELOG.md index fb8db48c65..6298833b2b 100644 --- a/packages/battery_plus/battery_plus/CHANGELOG.md +++ b/packages/battery_plus/battery_plus/CHANGELOG.md @@ -1,37 +1,51 @@ ## 6.2.1 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) - - **FIX**(battery_plus): Incorrect minimum version configuration. ([#3364](https://github.com/fluttercommunity/plus_plugins/issues/3364)). ([56fc9847](https://github.com/fluttercommunity/plus_plugins/commit/56fc98473d29f97ed4a014b85585d06d2356fd9e)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **FIX**(battery_plus): Incorrect minimum version + configuration. ([#3364](https://github.com/fluttercommunity/plus_plugins/issues/3364)). ([56fc9847](https://github.com/fluttercommunity/plus_plugins/commit/56fc98473d29f97ed4a014b85585d06d2356fd9e)) ## 6.2.0 - - **FEAT**(battery_plus): Add battery save mode check on MacOS ([#3332](https://github.com/fluttercommunity/plus_plugins/issues/3332)). ([0e8c9223](https://github.com/fluttercommunity/plus_plugins/commit/0e8c9223f00f801abeb203c25a79b8f19259a11c)) +- **FEAT**(battery_plus): Add battery save mode check on + MacOS ([#3332](https://github.com/fluttercommunity/plus_plugins/issues/3332)). ([0e8c9223](https://github.com/fluttercommunity/plus_plugins/commit/0e8c9223f00f801abeb203c25a79b8f19259a11c)) ## 6.1.0 - - **FEAT**(battery_plus): Add Swift Package Manager support ([#3154](https://github.com/fluttercommunity/plus_plugins/issues/3154)). ([cba3279a](https://github.com/fluttercommunity/plus_plugins/commit/cba3279abf0faaa0b62323af0a33e118186b30fc)) +- **FEAT**(battery_plus): Add Swift Package Manager + support ([#3154](https://github.com/fluttercommunity/plus_plugins/issues/3154)). ([cba3279a](https://github.com/fluttercommunity/plus_plugins/commit/cba3279abf0faaa0b62323af0a33e118186b30fc)) ## 6.0.4 - - **FIX**(all): Clean up macOS Privacy Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) - - **FIX**(all): Add macOS Privacy Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) +- **FIX**(all): Clean up macOS Privacy + Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) +- **FIX**(all): Add macOS Privacy + Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) ## 6.0.3 - - **CHORE**(battery_plus): Update to package:web to ^1.0.0 ([#3103](https://github.com/fluttercommunity/plus_plugins/pull/3103)). ([cf534eec](https://github.com/fluttercommunity/plus_plugins/commit/cf534eec402b57b70ffe96bf5351afcdfa8c7c7e)) - - **FIX**(battery_plus): Fix type conversion ([#3159](https://github.com/fluttercommunity/plus_plugins/issues/3159)). ([1145af14](https://github.com/fluttercommunity/plus_plugins/commit/1145af14298ecab7d7be57bfa9a32c628b9acdf3)) - - **FIX**(battery_plus): Fix crash when retrieving battery level on desktop Mac. ([#3155](https://github.com/fluttercommunity/plus_plugins/issues/3155)). ([36e7dd16](https://github.com/fluttercommunity/plus_plugins/commit/36e7dd16de3ac43d83eeece7e682b265c93f2fbe)) - - **DOCS**(battery_plus): Update plugin requirements ([#3158](https://github.com/fluttercommunity/plus_plugins/issues/3158)). ([c0353107](https://github.com/fluttercommunity/plus_plugins/commit/c0353107f17e5e32ca33e44742343ccd2c391a0c)) +- **CHORE**(battery_plus): Update to package:web to + ^1.0.0 ([#3103](https://github.com/fluttercommunity/plus_plugins/pull/3103)). ([cf534eec](https://github.com/fluttercommunity/plus_plugins/commit/cf534eec402b57b70ffe96bf5351afcdfa8c7c7e)) +- **FIX**(battery_plus): Fix type + conversion ([#3159](https://github.com/fluttercommunity/plus_plugins/issues/3159)). ([1145af14](https://github.com/fluttercommunity/plus_plugins/commit/1145af14298ecab7d7be57bfa9a32c628b9acdf3)) +- **FIX**(battery_plus): Fix crash when retrieving battery level on desktop + Mac. ([#3155](https://github.com/fluttercommunity/plus_plugins/issues/3155)). ([36e7dd16](https://github.com/fluttercommunity/plus_plugins/commit/36e7dd16de3ac43d83eeece7e682b265c93f2fbe)) +- **DOCS**(battery_plus): Update plugin + requirements ([#3158](https://github.com/fluttercommunity/plus_plugins/issues/3158)). ([c0353107](https://github.com/fluttercommunity/plus_plugins/commit/c0353107f17e5e32ca33e44742343ccd2c391a0c)) ## 6.0.2 - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 6.0.1 - - **REFACTOR**(battery_plus): Migrate Android example to use the new plugins declaration ([#2772](https://github.com/fluttercommunity/plus_plugins/issues/2772)). ([740a5df2](https://github.com/fluttercommunity/plus_plugins/commit/740a5df21fb84df2b88cea822d53302ce61a6dc2)) - - **FIX**(battery_plus): Fix return value of getBattery to be nullable ([#2745](https://github.com/fluttercommunity/plus_plugins/issues/2745)). ([4d5b950e](https://github.com/fluttercommunity/plus_plugins/commit/4d5b950ed1c74f801f621ef0c07b44f496a7465b)) +- **REFACTOR**(battery_plus): Migrate Android example to use the new plugins + declaration ([#2772](https://github.com/fluttercommunity/plus_plugins/issues/2772)). ([740a5df2](https://github.com/fluttercommunity/plus_plugins/commit/740a5df21fb84df2b88cea822d53302ce61a6dc2)) +- **FIX**(battery_plus): Fix return value of getBattery to be + nullable ([#2745](https://github.com/fluttercommunity/plus_plugins/issues/2745)). ([4d5b950e](https://github.com/fluttercommunity/plus_plugins/commit/4d5b950ed1c74f801f621ef0c07b44f496a7465b)) ## 6.0.0 @@ -40,106 +54,136 @@ In this release plugin migrated to package:web, meaning that it now supports WASM! Plugin now requires the following: + - Flutter >=3.19.0 - Dart >=3.3.0 - compileSDK 34 for Android part - Java 17 for Android part - Gradle 8.4 for Android part -- **BREAKING** **FEAT**(battery_plus): Migrate to package:web ([#2720](https://github.com/fluttercommunity/plus_plugins/issues/2720)). ([21ccfa45](https://github.com/fluttercommunity/plus_plugins/commit/21ccfa459fcfb0609da46299fed6e10c9e77332b)) -- **BREAKING** **BUILD**(battery_plus): Target Java 17 on Android ([#2727](https://github.com/fluttercommunity/plus_plugins/issues/2727)). ([ca2c35ab](https://github.com/fluttercommunity/plus_plugins/commit/ca2c35abc464b26e741ace6e53e319dfa674b630)) -- **BREAKING** **BUILD**(battery_plus): Update to target and compile SDK 34 ([#2702](https://github.com/fluttercommunity/plus_plugins/pull/2702)). ([fc59745](https://github.com/fluttercommunity/plus_plugins/commit/fc59745d0a8650cc32f6e4d949887c4cdbffe547)) -- **BREAKING** **REFACTOR**(battery_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2592](https://github.com/fluttercommunity/plus_plugins/issues/2592)). ([fe07964b](https://github.com/fluttercommunity/plus_plugins/commit/fe07964b03997db73f22f3c30b7d09ea2c0adc93)) - - **FIX**(battery_plus): Add iOS Privacy Info ([#2580](https://github.com/fluttercommunity/plus_plugins/issues/2580)). ([9f36a001](https://github.com/fluttercommunity/plus_plugins/commit/9f36a0018daa08e3f3ebb59cebcd4149fae7c4bc)) +- **BREAKING** **FEAT**(battery_plus): Migrate to package: + web ([#2720](https://github.com/fluttercommunity/plus_plugins/issues/2720)). ([21ccfa45](https://github.com/fluttercommunity/plus_plugins/commit/21ccfa459fcfb0609da46299fed6e10c9e77332b)) +- **BREAKING** **BUILD**(battery_plus): Target Java 17 on + Android ([#2727](https://github.com/fluttercommunity/plus_plugins/issues/2727)). ([ca2c35ab](https://github.com/fluttercommunity/plus_plugins/commit/ca2c35abc464b26e741ace6e53e319dfa674b630)) +- **BREAKING** **BUILD**(battery_plus): Update to target and compile SDK + 34 ([#2702](https://github.com/fluttercommunity/plus_plugins/pull/2702)). ([fc59745](https://github.com/fluttercommunity/plus_plugins/commit/fc59745d0a8650cc32f6e4d949887c4cdbffe547)) +- **BREAKING** **REFACTOR**(battery_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to + 10.14 ([#2592](https://github.com/fluttercommunity/plus_plugins/issues/2592)). ([fe07964b](https://github.com/fluttercommunity/plus_plugins/commit/fe07964b03997db73f22f3c30b7d09ea2c0adc93)) +- **FIX**(battery_plus): Add iOS Privacy + Info ([#2580](https://github.com/fluttercommunity/plus_plugins/issues/2580)). ([9f36a001](https://github.com/fluttercommunity/plus_plugins/commit/9f36a0018daa08e3f3ebb59cebcd4149fae7c4bc)) ## 5.0.3 - - **FIX**(battery_plus): battery state always unknown on iOS ([#2481](https://github.com/fluttercommunity/plus_plugins/issues/2481)). ([ea892fb9](https://github.com/fluttercommunity/plus_plugins/commit/ea892fb96d06dcd685fa7953a468c377cc133ecc)) +- **FIX**(battery_plus): battery state always unknown on + iOS ([#2481](https://github.com/fluttercommunity/plus_plugins/issues/2481)). ([ea892fb9](https://github.com/fluttercommunity/plus_plugins/commit/ea892fb96d06dcd685fa7953a468c377cc133ecc)) ## 5.0.2 - - **FIX**(battery_plus): Return correct state enum value on Android for not charging state ([#2451](https://github.com/fluttercommunity/plus_plugins/issues/2451)). ([68ddda39](https://github.com/fluttercommunity/plus_plugins/commit/68ddda39f0fa8e7ac950c13721403d49d0d97a65)) +- **FIX**(battery_plus): Return correct state enum value on Android for not charging + state ([#2451](https://github.com/fluttercommunity/plus_plugins/issues/2451)). ([68ddda39](https://github.com/fluttercommunity/plus_plugins/commit/68ddda39f0fa8e7ac950c13721403d49d0d97a65)) ## 5.0.1 -> Note: This release has breaking changes. There is a new state for battery available on Android, MacOS and Linux platforms. -> Also, MacOS implementation was updated to provide more accurate battery status. Be sure to test if it affects your MacOS app. - - - **BREAKING** **FIX**(battery_plus): Implement not_charging battery state ([#2275](https://github.com/fluttercommunity/plus_plugins/issues/2275)). ([6595e035](https://github.com/fluttercommunity/plus_plugins/commit/6595e035fd113b4a75651c9d471cc098d5798de3)) - - **BREAKING** **FEAT**(battery_plus): Introduce connected_not_charging state on MacOS ([#2399](https://github.com/fluttercommunity/plus_plugins/issues/2399)). ([78f44bf4](https://github.com/fluttercommunity/plus_plugins/commit/78f44bf41a7e8349240bacae2dd70598ba22e97a)) - - **BREAKING** **FEAT**(battery_plus): Introduce not_charging state on Linux ([#2400](https://github.com/fluttercommunity/plus_plugins/issues/2400)). ([42ef02bd](https://github.com/fluttercommunity/plus_plugins/commit/42ef02bd6de219fef1b2d9db2eebe9775a6ac751)) - - **DOCS**(battery_plus): Improve documentation on battery states ([#2402](https://github.com/fluttercommunity/plus_plugins/issues/2402)). ([baeb886f](https://github.com/fluttercommunity/plus_plugins/commit/baeb886fcc587f72662ce177ab4922496bb1db46)) - - **BREAKING** **FIX**(battery_plus): Bump iOS min target to 12 and update example app ([#2401](https://github.com/fluttercommunity/plus_plugins/issues/2401)). ([25ef7928](https://github.com/fluttercommunity/plus_plugins/commit/25ef7928cd57ca17d6107ed839711ea166d451a6)) +> Note: This release has breaking changes. There is a new state for battery available on Android, +> MacOS and Linux platforms. +> Also, MacOS implementation was updated to provide more accurate battery status. Be sure to test if +> it affects your MacOS app. + +- **BREAKING** **FIX**(battery_plus): Implement not_charging battery + state ([#2275](https://github.com/fluttercommunity/plus_plugins/issues/2275)). ([6595e035](https://github.com/fluttercommunity/plus_plugins/commit/6595e035fd113b4a75651c9d471cc098d5798de3)) +- **BREAKING** **FEAT**(battery_plus): Introduce connected_not_charging state on + MacOS ([#2399](https://github.com/fluttercommunity/plus_plugins/issues/2399)). ([78f44bf4](https://github.com/fluttercommunity/plus_plugins/commit/78f44bf41a7e8349240bacae2dd70598ba22e97a)) +- **BREAKING** **FEAT**(battery_plus): Introduce not_charging state on + Linux ([#2400](https://github.com/fluttercommunity/plus_plugins/issues/2400)). ([42ef02bd](https://github.com/fluttercommunity/plus_plugins/commit/42ef02bd6de219fef1b2d9db2eebe9775a6ac751)) +- **DOCS**(battery_plus): Improve documentation on battery + states ([#2402](https://github.com/fluttercommunity/plus_plugins/issues/2402)). ([baeb886f](https://github.com/fluttercommunity/plus_plugins/commit/baeb886fcc587f72662ce177ab4922496bb1db46)) +- **BREAKING** **FIX**(battery_plus): Bump iOS min target to 12 and update example + app ([#2401](https://github.com/fluttercommunity/plus_plugins/issues/2401)). ([25ef7928](https://github.com/fluttercommunity/plus_plugins/commit/25ef7928cd57ca17d6107ed839711ea166d451a6)) ## 5.0.0 -This release was retracted due to due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). +This release was retracted due to due +to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). ## 4.1.0 -> Info: This release is a replacement for release 5.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. +> Info: This release is a replacement for release 5.0.0, which was retracted due to +> issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change +> was reverted the major release was also reverted in favor of this one. - - **FIX**(battery_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2257](https://github.com/fluttercommunity/plus_plugins/issues/2257)). ([f5244e36](https://github.com/fluttercommunity/plus_plugins/commit/f5244e368c74d8b6e7bdd0062a4a2250dcabe540)) - - **FIX**(battery_plus): Revert bump of compileSDK to 34 ([#2228](https://github.com/fluttercommunity/plus_plugins/issues/2228)). ([e834f582](https://github.com/fluttercommunity/plus_plugins/commit/e834f582b85d5fb5a18aefc49b11b039ae600c78)) - - **FEAT**(battery_plus): Remove deprecated VALID_ARCHS iOS property ([#2025](https://github.com/fluttercommunity/plus_plugins/issues/2025)). ([09318317](https://github.com/fluttercommunity/plus_plugins/commit/0931831758dfc829e5649d880a616840a9b1d21f)) +- **FIX**(battery_plus): Change Kotlin version from 1.9.10 to + 1.7.22 ([#2257](https://github.com/fluttercommunity/plus_plugins/issues/2257)). ([f5244e36](https://github.com/fluttercommunity/plus_plugins/commit/f5244e368c74d8b6e7bdd0062a4a2250dcabe540)) +- **FIX**(battery_plus): Revert bump of compileSDK to + 34 ([#2228](https://github.com/fluttercommunity/plus_plugins/issues/2228)). ([e834f582](https://github.com/fluttercommunity/plus_plugins/commit/e834f582b85d5fb5a18aefc49b11b039ae600c78)) +- **FEAT**(battery_plus): Remove deprecated VALID_ARCHS iOS + property ([#2025](https://github.com/fluttercommunity/plus_plugins/issues/2025)). ([09318317](https://github.com/fluttercommunity/plus_plugins/commit/0931831758dfc829e5649d880a616840a9b1d21f)) ## 4.0.2 - - **FIX**(battery_plus): Regenerate iOS and MacOS example apps ([#1873](https://github.com/fluttercommunity/plus_plugins/issues/1873)). ([18deeff3](https://github.com/fluttercommunity/plus_plugins/commit/18deeff3c68f312e2dae0de80273e1991ef97f45)) - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **FIX**(battery_plus): Regenerate iOS and MacOS example + apps ([#1873](https://github.com/fluttercommunity/plus_plugins/issues/1873)). ([18deeff3](https://github.com/fluttercommunity/plus_plugins/commit/18deeff3c68f312e2dae0de80273e1991ef97f45)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 4.0.1 - - **FIX**(battery_plus): Use ContextCompat on Android to register broadcast receiver ([#1811](https://github.com/fluttercommunity/plus_plugins/issues/1811)). ([b901615c](https://github.com/fluttercommunity/plus_plugins/commit/b901615cdc12d4bc5140ba9713d16f5a85fa6198)) - - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **FIX**(battery_plus): Use ContextCompat on Android to register broadcast + receiver ([#1811](https://github.com/fluttercommunity/plus_plugins/issues/1811)). ([b901615c](https://github.com/fluttercommunity/plus_plugins/commit/b901615cdc12d4bc5140ba9713d16f5a85fa6198)) +- **FIX**: Add jvm target compatibility to Kotlin + plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) ## 4.0.0 > Note: This release has breaking changes. - - **CHORE**(battery_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(battery_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1783). - - **REFACTOR**(battery_plus): Update example app to use Material 3. - - **FIX**(battery_plus): Close StreamController on Web and Linux when done (#1744). +- **CHORE**(battery_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 < + 4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(battery_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update + podspec file (#1783). +- **REFACTOR**(battery_plus): Update example app to use Material 3. +- **FIX**(battery_plus): Close StreamController on Web and Linux when done (#1744). ## 3.0.6 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 3.0.5 - - **FIX**(battery_plus): Huawei power save mode check (#1708). - - **FIX**(battery_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1700). +- **FIX**(battery_plus): Huawei power save mode check (#1708). +- **FIX**(battery_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1700). ## 3.0.4 - - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). - - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). +- **REFACTOR**(all): Remove all manual dependency_overrides (#1628). +- **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). ## 3.0.3 - - **FIX**: broadcast stream (#1479). - - **DOCS**: Updates for READMEs and website pages (#1389). +- **FIX**: broadcast stream (#1479). +- **DOCS**: Updates for READMEs and website pages (#1389). ## 3.0.2 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 3.0.1 - - **FIX**: lint warnings - add missing dependency for tests (#1233). +- **FIX**: lint warnings - add missing dependency for tests (#1233). ## 3.0.0 > Note: This release has breaking changes. - - **BREAKING** **REFACTOR**: platform implementation refactor into a single package (#1169). +- **BREAKING** **REFACTOR**: platform implementation refactor into a single package (#1169). ## 2.2.2 - - **FIX**: batteryState always return unknown on API < 26 (#1120). +- **FIX**: batteryState always return unknown on API < 26 (#1120). ## 2.2.1 @@ -271,7 +315,8 @@ This release was retracted due to due to ([#2251](https://github.com/fluttercomm ## 0.3.1+9 -- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). +- Declare API stability and compatibility with `1.0.0` (more details + at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). ## 0.3.1+8 @@ -306,7 +351,8 @@ This release was retracted due to due to ([#2251](https://github.com/fluttercomm ## 0.3.1+1 -- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to + support apps that has not been migrated to AndroidX. ## 0.3.1 diff --git a/packages/battery_plus/battery_plus/README.md b/packages/battery_plus/battery_plus/README.md index 6e9ee13c25..ca11e4cd83 100644 --- a/packages/battery_plus/battery_plus/README.md +++ b/packages/battery_plus/battery_plus/README.md @@ -6,13 +6,14 @@ [](https://flutter.dev/docs/development/packages-and-plugins/favorites) -A Flutter plugin to access various information about the battery of the device the app is running on. +A Flutter plugin to access various information about the battery of the device the app is running +on. ## Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :----: | -| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ## Requirements diff --git a/packages/battery_plus/battery_plus/android/build.gradle b/packages/battery_plus/battery_plus/android/build.gradle index c7c0c92c07..b9c5314b93 100644 --- a/packages/battery_plus/battery_plus/android/build.gradle +++ b/packages/battery_plus/battery_plus/android/build.gradle @@ -2,7 +2,7 @@ group 'dev.fluttercommunity.plus.battery' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.7.22' + ext.kotlin_version = '2.1.10' repositories { google() mavenCentral() @@ -24,7 +24,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.battery' @@ -49,5 +49,5 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "androidx.core:core-ktx:1.13.1" + implementation "androidx.core:core:1.15.0" } diff --git a/packages/battery_plus/battery_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/battery_plus/battery_plus/android/gradle/wrapper/gradle-wrapper.properties index fce403e45e..2733ed5dc3 100644 --- a/packages/battery_plus/battery_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/battery_plus/battery_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/battery_plus/battery_plus/android/src/main/AndroidManifest.xml b/packages/battery_plus/battery_plus/android/src/main/AndroidManifest.xml index da40a4e70a..8c97527089 100644 --- a/packages/battery_plus/battery_plus/android/src/main/AndroidManifest.xml +++ b/packages/battery_plus/battery_plus/android/src/main/AndroidManifest.xml @@ -1,2 +1 @@ - - + diff --git a/packages/battery_plus/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt b/packages/battery_plus/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt index f7618902af..b5aa622bc3 100644 --- a/packages/battery_plus/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt +++ b/packages/battery_plus/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt @@ -103,7 +103,10 @@ class BatteryPlusPlugin : MethodCallHandler, EventChannel.StreamHandler, Flutter val status: Int = if (VERSION.SDK_INT >= VERSION_CODES.O) { getBatteryProperty(BatteryManager.BATTERY_PROPERTY_STATUS) } else { - val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + val intent = ContextWrapper(applicationContext).registerReceiver( + null, + IntentFilter(Intent.ACTION_BATTERY_CHANGED) + ) intent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1 } return convertBatteryStatus(status) @@ -113,7 +116,10 @@ class BatteryPlusPlugin : MethodCallHandler, EventChannel.StreamHandler, Flutter return if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { getBatteryProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) } else { - val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + val intent = ContextWrapper(applicationContext).registerReceiver( + null, + IntentFilter(Intent.ACTION_BATTERY_CHANGED) + ) val level = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1) (level * 100 / scale) @@ -136,7 +142,10 @@ class BatteryPlusPlugin : MethodCallHandler, EventChannel.StreamHandler, Flutter } private fun isSamsungPowerSaveModeActive(): Boolean { - val mode = Settings.System.getString(applicationContext!!.contentResolver, POWER_SAVE_MODE_SAMSUNG_NAME) + val mode = Settings.System.getString( + applicationContext!!.contentResolver, + POWER_SAVE_MODE_SAMSUNG_NAME + ) return if (mode == null && VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { checkPowerServiceSaveMode() } else { @@ -146,7 +155,11 @@ class BatteryPlusPlugin : MethodCallHandler, EventChannel.StreamHandler, Flutter @RequiresApi(VERSION_CODES.LOLLIPOP) private fun isHuaweiPowerSaveModeActive(): Boolean { - val mode = Settings.System.getInt(applicationContext!!.contentResolver, POWER_SAVE_MODE_HUAWEI_NAME, -1) + val mode = Settings.System.getInt( + applicationContext!!.contentResolver, + POWER_SAVE_MODE_HUAWEI_NAME, + -1 + ) return if (mode != -1) { mode == POWER_SAVE_MODE_HUAWEI_VALUE } else { @@ -157,7 +170,11 @@ class BatteryPlusPlugin : MethodCallHandler, EventChannel.StreamHandler, Flutter } private fun isXiaomiPowerSaveModeActive(): Boolean? { - val mode = Settings.System.getInt(applicationContext!!.contentResolver, POWER_SAVE_MODE_XIAOMI_NAME, -1) + val mode = Settings.System.getInt( + applicationContext!!.contentResolver, + POWER_SAVE_MODE_XIAOMI_NAME, + -1 + ) return if (mode != -1) { mode == POWER_SAVE_MODE_XIAOMI_VALUE } else { @@ -174,7 +191,8 @@ class BatteryPlusPlugin : MethodCallHandler, EventChannel.StreamHandler, Flutter @RequiresApi(api = VERSION_CODES.LOLLIPOP) private fun getBatteryProperty(property: Int): Int { - val batteryManager = applicationContext!!.getSystemService(Context.BATTERY_SERVICE) as BatteryManager + val batteryManager = + applicationContext!!.getSystemService(Context.BATTERY_SERVICE) as BatteryManager return batteryManager.getIntProperty(property) } diff --git a/packages/battery_plus/battery_plus/example/android/app/build.gradle b/packages/battery_plus/battery_plus/example/android/app/build.gradle index 52b4b07259..12953e44b2 100644 --- a/packages/battery_plus/battery_plus/example/android/app/build.gradle +++ b/packages/battery_plus/battery_plus/example/android/app/build.gradle @@ -23,7 +23,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'io.flutter.plugins.batteryexample.example' @@ -48,7 +48,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "io.flutter.plugins.batteryexample.example" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/packages/battery_plus/battery_plus/example/android/app/src/debug/AndroidManifest.xml b/packages/battery_plus/battery_plus/example/android/app/src/debug/AndroidManifest.xml index f094cef4d3..a04359269a 100644 --- a/packages/battery_plus/battery_plus/example/android/app/src/debug/AndroidManifest.xml +++ b/packages/battery_plus/battery_plus/example/android/app/src/debug/AndroidManifest.xml @@ -3,5 +3,5 @@ - + diff --git a/packages/battery_plus/battery_plus/example/android/app/src/main/AndroidManifest.xml b/packages/battery_plus/battery_plus/example/android/app/src/main/AndroidManifest.xml index dd87ee3a64..0120e8889f 100644 --- a/packages/battery_plus/battery_plus/example/android/app/src/main/AndroidManifest.xml +++ b/packages/battery_plus/battery_plus/example/android/app/src/main/AndroidManifest.xml @@ -7,36 +7,34 @@ FlutterApplication and put your custom class here. --> + android:icon="@mipmap/ic_launcher" + android:label="example"> + android:launchMode="singleTop" + android:theme="@style/LaunchTheme" + android:windowSoftInputMode="adjustResize"> + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" /> + android:name="io.flutter.embedding.android.SplashScreenDrawable" + android:resource="@drawable/launch_background" /> - - + + + diff --git a/packages/battery_plus/battery_plus/example/android/app/src/profile/AndroidManifest.xml b/packages/battery_plus/battery_plus/example/android/app/src/profile/AndroidManifest.xml index f094cef4d3..a04359269a 100644 --- a/packages/battery_plus/battery_plus/example/android/app/src/profile/AndroidManifest.xml +++ b/packages/battery_plus/battery_plus/example/android/app/src/profile/AndroidManifest.xml @@ -3,5 +3,5 @@ - + diff --git a/packages/battery_plus/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/battery_plus/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties index 825c34f1c4..03a32d076a 100644 --- a/packages/battery_plus/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/battery_plus/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Oct 05 14:03:03 CEST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/battery_plus/battery_plus/example/android/settings.gradle b/packages/battery_plus/battery_plus/example/android/settings.gradle index fa3b4d0878..18a751a498 100644 --- a/packages/battery_plus/battery_plus/example/android/settings.gradle +++ b/packages/battery_plus/battery_plus/example/android/settings.gradle @@ -18,8 +18,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false - id "org.jetbrains.kotlin.android" version "1.9.23" apply false + id "com.android.application" version "8.9.0" apply false + id "org.jetbrains.kotlin.android" version "2.1.10" apply false } include ":app" diff --git a/packages/battery_plus/battery_plus/example/integration_test/battery_plus_test.dart b/packages/battery_plus/battery_plus/example/integration_test/battery_plus_test.dart index 04c0855dbf..5ac1b0a7bd 100644 --- a/packages/battery_plus/battery_plus/example/integration_test/battery_plus_test.dart +++ b/packages/battery_plus/battery_plus/example/integration_test/battery_plus_test.dart @@ -12,12 +12,14 @@ void main() { final bool batteryLevelIsImplemented = Platform.isAndroid || Platform.isMacOS || Platform.isLinux; - final bool batteryStateIsImplemented = Platform.isAndroid || + final bool batteryStateIsImplemented = + Platform.isAndroid || Platform.isIOS || Platform.isMacOS || Platform.isWindows || Platform.isLinux; - final bool isInBatterySaveModeIsImplemented = Platform.isAndroid || + final bool isInBatterySaveModeIsImplemented = + Platform.isAndroid || Platform.isIOS || Platform.isMacOS || Platform.isWindows; @@ -34,9 +36,12 @@ void main() { expect(batteryState, isNotNull); }, skip: !batteryStateIsImplemented); - testWidgets('Can get if device is in battery save mode', - (WidgetTester tester) async { - final isInBatterySaveMode = await Battery().isInBatterySaveMode; - expect(isInBatterySaveMode, false); - }, skip: !isInBatterySaveModeIsImplemented); + testWidgets( + 'Can get if device is in battery save mode', + (WidgetTester tester) async { + final isInBatterySaveMode = await Battery().isInBatterySaveMode; + expect(isInBatterySaveMode, false); + }, + skip: !isInBatterySaveModeIsImplemented, + ); } diff --git a/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2d..e882ab9889 100644 --- a/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon-App-1024x1024@1x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2fd4..781d7cdcac 100644 --- a/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" + "idiom": "universal", + "filename": "LaunchImage.png", + "scale": "1x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" + "idiom": "universal", + "filename": "LaunchImage@2x.png", + "scale": "2x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" + "idiom": "universal", + "filename": "LaunchImage@3x.png", + "scale": "3x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725b70..d880e1f556 100644 --- a/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/packages/battery_plus/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,8 @@ # Launch Screen Assets -You can customize the launch screen with your own desired assets by replacing the image files in this directory. +You can customize the launch screen with your own desired assets by replacing the image files in +this directory. -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file +You can also do it by opening your Flutter project's Xcode project with +`open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and +dropping in the desired images. diff --git a/packages/battery_plus/battery_plus/example/lib/main.dart b/packages/battery_plus/battery_plus/example/lib/main.dart index a6f348224d..8026269467 100644 --- a/packages/battery_plus/battery_plus/example/lib/main.dart +++ b/packages/battery_plus/battery_plus/example/lib/main.dart @@ -43,8 +43,9 @@ class _MyHomePageState extends State { void initState() { super.initState(); _battery.batteryState.then(_updateBatteryState); - _batteryStateSubscription = - _battery.onBatteryStateChanged.listen(_updateBatteryState); + _batteryStateSubscription = _battery.onBatteryStateChanged.listen( + _updateBatteryState, + ); } void _updateBatteryState(BatteryState state) { @@ -77,58 +78,56 @@ class _MyHomePageState extends State { const SizedBox(height: 24), ElevatedButton( onPressed: () { - _battery.batteryLevel.then( - (batteryLevel) { - showDialog( - context: context, - builder: (_) => AlertDialog( - content: Text('Battery: $batteryLevel%'), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: const Text('OK'), - ) - ], - ), - ); - }, - ); + _battery.batteryLevel.then((batteryLevel) { + showDialog( + context: context, + builder: + (_) => AlertDialog( + content: Text('Battery: $batteryLevel%'), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text('OK'), + ), + ], + ), + ); + }); }, child: const Text('Get battery level'), ), const SizedBox(height: 24), ElevatedButton( onPressed: () { - _battery.isInBatterySaveMode.then( - (isInPowerSaveMode) { - showDialog( - context: context, - builder: (_) => AlertDialog( - title: const Text( - 'Is in Battery Save mode?', - style: TextStyle(fontSize: 20), + _battery.isInBatterySaveMode.then((isInPowerSaveMode) { + showDialog( + context: context, + builder: + (_) => AlertDialog( + title: const Text( + 'Is in Battery Save mode?', + style: TextStyle(fontSize: 20), + ), + content: Text( + "$isInPowerSaveMode", + style: const TextStyle(fontSize: 18), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text('Close'), + ), + ], ), - content: Text( - "$isInPowerSaveMode", - style: const TextStyle(fontSize: 18), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: const Text('Close'), - ) - ], - ), - ); - }, - ); + ); + }); }, child: const Text('Is in Battery Save mode?'), - ) + ), ], ), ), diff --git a/packages/battery_plus/battery_plus/example/linux/CMakeLists.txt b/packages/battery_plus/battery_plus/example/linux/CMakeLists.txt index 386893d7de..c3b27f8d20 100644 --- a/packages/battery_plus/battery_plus/example/linux/CMakeLists.txt +++ b/packages/battery_plus/battery_plus/example/linux/CMakeLists.txt @@ -9,19 +9,19 @@ cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif () # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -37,9 +37,9 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") # Application build add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) target_link_libraries(${BINARY_NAME} PRIVATE flutter) @@ -50,8 +50,8 @@ add_dependencies(${BINARY_NAME} flutter_assemble) # people trying to run the unbundled copy, put it in a subdirectory instead of # the default top-level location. set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) # Generated plugin build rules, which manage building the plugins and adding @@ -63,9 +63,9 @@ include(flutter/generated_plugins.cmake) # By default, "installing" just makes a relocatable bundle in the build # directory. set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () # Start with a clean build bundle directory every time. install(CODE " @@ -76,19 +76,19 @@ set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -97,10 +97,10 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () diff --git a/packages/battery_plus/battery_plus/example/linux/flutter/CMakeLists.txt b/packages/battery_plus/battery_plus/example/linux/flutter/CMakeLists.txt index 5b465c7ecf..03e4a7fe4a 100644 --- a/packages/battery_plus/battery_plus/example/linux/flutter/CMakeLists.txt +++ b/packages/battery_plus/battery_plus/example/linux/flutter/CMakeLists.txt @@ -12,9 +12,9 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # which isn't available in 3.10. function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) + foreach (element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) + endforeach (element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() @@ -35,38 +35,38 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO - PkgConfig::BLKID + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID ) add_dependencies(flutter flutter_assemble) @@ -75,15 +75,15 @@ add_dependencies(flutter flutter_assemble) # since currently there's no way to get a full input/output list from the # flutter tool. add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} ) diff --git a/packages/battery_plus/battery_plus/example/linux/main.cc b/packages/battery_plus/battery_plus/example/linux/main.cc index 8bc1561588..dbe6db8472 100644 --- a/packages/battery_plus/battery_plus/example/linux/main.cc +++ b/packages/battery_plus/battery_plus/example/linux/main.cc @@ -1,11 +1,12 @@ #include "my_application.h" int main(int argc, char **argv) { - // Only X11 is currently supported. - // Wayland support is being developed: - // https://github.com/flutter/flutter/issues/57932. - gdk_set_allowed_backends("x11"); + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); + g_autoptr(MyApplication) + app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); } diff --git a/packages/battery_plus/battery_plus/example/linux/my_application.cc b/packages/battery_plus/battery_plus/example/linux/my_application.cc index cef2f77145..20cf1fa128 100644 --- a/packages/battery_plus/battery_plus/example/linux/my_application.cc +++ b/packages/battery_plus/battery_plus/example/linux/my_application.cc @@ -5,41 +5,43 @@ #include "flutter/generated_plugin_registrant.h" struct _MyApplication { - GtkApplication parent_instance; + GtkApplication parent_instance; }; -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION +) // Implements GApplication::activate. static void my_application_activate(GApplication *application) { - GtkWindow *window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - - FlView *view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) + project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); } static void my_application_class_init(MyApplicationClass *klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->activate = my_application_activate; } -static void my_application_init(MyApplication *self) {} +static void my_application_init(MyApplication * self) {} MyApplication *my_application_new() { - return MY_APPLICATION(g_object_new( - my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); } diff --git a/packages/battery_plus/battery_plus/example/linux/my_application.h b/packages/battery_plus/battery_plus/example/linux/my_application.h index 3258a73cf4..5b081e77c6 100644 --- a/packages/battery_plus/battery_plus/example/linux/my_application.h +++ b/packages/battery_plus/battery_plus/example/linux/my_application.h @@ -4,7 +4,8 @@ #include G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) + GtkApplication +) /** * my_application_new: diff --git a/packages/battery_plus/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/battery_plus/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f19f..60e60c947e 100644 --- a/packages/battery_plus/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/battery_plus/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ + "images": [ { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" }, { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/battery_plus/battery_plus/example/web/index.html b/packages/battery_plus/battery_plus/example/web/index.html index a0c14606fc..62362982b9 100644 --- a/packages/battery_plus/battery_plus/example/web/index.html +++ b/packages/battery_plus/battery_plus/example/web/index.html @@ -1,33 +1,33 @@ - - - + + + - - - - - + + + + + - - + + - example - + example + - - - + + diff --git a/packages/battery_plus/battery_plus/example/web/manifest.json b/packages/battery_plus/battery_plus/example/web/manifest.json index 8c012917da..037463cc72 100644 --- a/packages/battery_plus/battery_plus/example/web/manifest.json +++ b/packages/battery_plus/battery_plus/example/web/manifest.json @@ -1,23 +1,23 @@ { - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] } diff --git a/packages/battery_plus/battery_plus/example/windows/CMakeLists.txt b/packages/battery_plus/battery_plus/example/windows/CMakeLists.txt index abf90408ef..5d3a4fe2dc 100644 --- a/packages/battery_plus/battery_plus/example/windows/CMakeLists.txt +++ b/packages/battery_plus/battery_plus/example/windows/CMakeLists.txt @@ -9,17 +9,17 @@ set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() +if (IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else () + if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif () +endif () set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") @@ -31,11 +31,11 @@ add_definitions(-DUNICODE -D_UNICODE) # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -58,27 +58,27 @@ include(flutter/generated_plugins.cmake) set(BUILD_BUNDLE_DIR "$") # Make the "install" step default, as it's required to run. set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -87,9 +87,9 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/battery_plus/battery_plus/example/windows/flutter/CMakeLists.txt b/packages/battery_plus/battery_plus/example/windows/flutter/CMakeLists.txt index 744f08a938..bc1c2f9f44 100644 --- a/packages/battery_plus/battery_plus/example/windows/flutter/CMakeLists.txt +++ b/packages/battery_plus/battery_plus/example/windows/flutter/CMakeLists.txt @@ -19,60 +19,60 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") add_dependencies(flutter flutter_assemble) # === Wrapper === list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" + "core_implementations.cc" + "standard_codec.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" + "plugin_registrar.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" + "flutter_engine.cc" + "flutter_view_controller.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") # Wrapper sources needed for a plugin. add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} ) apply_standard_settings(flutter_wrapper_plugin) set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_plugin flutter_assemble) # Wrapper sources needed for the runner. add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} ) apply_standard_settings(flutter_wrapper_app) target_link_libraries(flutter_wrapper_app PUBLIC flutter) target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_app flutter_assemble) @@ -83,20 +83,20 @@ add_dependencies(flutter_wrapper_app flutter_assemble) set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} ) diff --git a/packages/battery_plus/battery_plus/example/windows/runner/CMakeLists.txt b/packages/battery_plus/battery_plus/example/windows/runner/CMakeLists.txt index 977e38b5d1..3fdcb0dd27 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/CMakeLists.txt +++ b/packages/battery_plus/battery_plus/example/windows/runner/CMakeLists.txt @@ -2,14 +2,14 @@ cmake_minimum_required(VERSION 3.15) project(runner LANGUAGES CXX) add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "run_loop.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" ) apply_standard_settings(${BINARY_NAME}) target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") diff --git a/packages/battery_plus/battery_plus/example/windows/runner/Runner.rc b/packages/battery_plus/battery_plus/example/windows/runner/Runner.rc index 9b0221d35d..8f8ae073f4 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/Runner.rc +++ b/packages/battery_plus/battery_plus/example/windows/runner/Runner.rc @@ -1,6 +1,7 @@ // Microsoft Visual C++ generated resource script. // #pragma code_page(65001) + #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS @@ -20,27 +21,27 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// + ///////////////////////////////////////////////////////////////////////////// + // + // TEXTINCLUDE + // -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END + 1 TEXTINCLUDE + BEGIN + "resource.h\0" + END -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END + 2 TEXTINCLUDE + BEGIN + "#include ""winres.h""\r\n" + "\0" + END -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END + 3 TEXTINCLUDE + BEGIN + "\r\n" + "\0" + END #endif // APSTUDIO_INVOKED @@ -73,37 +74,41 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEVERSION VERSION_AS_NUMBER +PRODUCTVERSION VERSION_AS_NUMBER +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG +FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L +FILEFLAGS 0x0L #endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0x0L BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "io.flutter.plugins.batteryexample" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2020 io.flutter.plugins.batteryexample. All rights reserved." "\0" - VALUE "OriginalFilename", "example.exe" "\0" - VALUE "ProductName", "example" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" + BLOCK +"StringFileInfo" +BEGIN + BLOCK +"040904e4" +BEGIN + VALUE +"CompanyName", "io.flutter.plugins.batteryexample" "\0" +VALUE "FileDescription", "A new Flutter project." "\0" +VALUE "FileVersion", VERSION_AS_STRING "\0" +VALUE "InternalName", "example" "\0" +VALUE "LegalCopyright", "Copyright (C) 2020 io.flutter.plugins.batteryexample. All rights reserved." "\0" +VALUE "OriginalFilename", "example.exe" "\0" +VALUE "ProductName", "example" "\0" +VALUE "ProductVersion", VERSION_AS_STRING "\0" +END END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END +BLOCK "VarFileInfo" +BEGIN + VALUE +"Translation", 0x409, 1252 END + END #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/packages/battery_plus/battery_plus/example/windows/runner/flutter_window.cpp b/packages/battery_plus/battery_plus/example/windows/runner/flutter_window.cpp index 0f0105d995..c0ae50a354 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/flutter_window.cpp +++ b/packages/battery_plus/battery_plus/example/windows/runner/flutter_window.cpp @@ -6,59 +6,64 @@ FlutterWindow::FlutterWindow(RunLoop *run_loop, const flutter::DartProject &project) - : run_loop_(run_loop), project_(project) {} + : run_loop_(run_loop), project_(project) {} FlutterWindow::~FlutterWindow() {} bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } + if (!Win32Window::OnCreate()) { + return false; + } - RECT frame = GetClientArea(); + RECT frame = GetClientArea(); - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - return true; + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; } void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); - flutter_controller_ = nullptr; - } + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } - Win32Window::OnDestroy(); + Win32Window::OnDestroy(); } LRESULT FlutterWindow::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opporutunity to handle window messages. - if (flutter_controller_) { - std::optional result = + LPARAM const lparam) + +noexcept { +// Give Flutter, including plugins, an opporutunity to handle window messages. +if (flutter_controller_) { +std::optional result = flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, lparam); - if (result) { - return *result; - } - } +if (result) { +return * +result; +} +} - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } +switch (message) { +case WM_FONTCHANGE: +flutter_controller_->engine()->ReloadSystemFonts(); +break; +} - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +return +Win32Window::MessageHandler(hwnd, message, wparam, lparam +); } diff --git a/packages/battery_plus/battery_plus/example/windows/runner/flutter_window.h b/packages/battery_plus/battery_plus/example/windows/runner/flutter_window.h index 69234d4f5e..da91a8f3f2 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/flutter_window.h +++ b/packages/battery_plus/battery_plus/example/windows/runner/flutter_window.h @@ -12,28 +12,33 @@ // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: - // Creates a new FlutterWindow driven by the |run_loop|, hosting a - // Flutter view running |project|. - explicit FlutterWindow(RunLoop *run_loop, - const flutter::DartProject &project); - virtual ~FlutterWindow(); + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + + virtual ~FlutterWindow(); protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; + // Win32Window: + bool OnCreate() override; + + void OnDestroy() override; + + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) + + noexcept override; private: - // The run loop driving events for this window. - RunLoop *run_loop_; + // The run loop driving events for this window. + RunLoop *run_loop_; - // The project to run. - flutter::DartProject project_; + // The project to run. + flutter::DartProject project_; - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; }; #endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/battery_plus/battery_plus/example/windows/runner/main.cpp b/packages/battery_plus/battery_plus/example/windows/runner/main.cpp index fc17fec614..b2218a2c48 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/main.cpp +++ b/packages/battery_plus/battery_plus/example/windows/runner/main.cpp @@ -6,31 +6,45 @@ #include "run_loop.h" #include "utils.h" -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - RunLoop run_loop; - - flutter::DartProject project(L"data"); - FlutterWindow window(&run_loop, project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"example", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - run_loop.Run(); - - ::CoUninitialize(); - return EXIT_SUCCESS; +int APIENTRY +wWinMain(_In_ +HINSTANCE instance, _In_opt_ +HINSTANCE prev, + _In_ +wchar_t *command_line, _In_ +int show_command +) { +// Attach to console when present (e.g., 'flutter run') or create a +// new console when running with a debugger. +if (! +::AttachConsole(ATTACH_PARENT_PROCESS) +&& ::IsDebuggerPresent()) { +CreateAndAttachConsole(); + +} + +// Initialize COM, so that it is available for use in the library and/or +// plugins. +::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED +); + +RunLoop run_loop; + +flutter::DartProject project(L"data"); +FlutterWindow window(&run_loop, project); +Win32Window::Point origin(10, 10); +Win32Window::Size size(1280, 720); +if (!window.CreateAndShow(L"example", origin, size)) { +return +EXIT_FAILURE; +} +window.SetQuitOnClose(true); + +run_loop. + +Run(); + +::CoUninitialize(); +return +EXIT_SUCCESS; } diff --git a/packages/battery_plus/battery_plus/example/windows/runner/run_loop.cpp b/packages/battery_plus/battery_plus/example/windows/runner/run_loop.cpp index 31b89f6229..6ee4580c2e 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/run_loop.cpp +++ b/packages/battery_plus/battery_plus/example/windows/runner/run_loop.cpp @@ -9,58 +9,58 @@ RunLoop::RunLoop() {} RunLoop::~RunLoop() {} void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - } } void RunLoop::RegisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.insert(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); } void RunLoop::UnregisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.erase(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); } RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { - TimePoint next_event_time = TimePoint::max(); - for (auto instance : flutter_instances_) { - std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); - if (wait_duration != std::chrono::nanoseconds::max()) { - next_event_time = - std::min(next_event_time, TimePoint::clock::now() + wait_duration); + TimePoint next_event_time = TimePoint::max(); + for (auto instance: flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } } - } - return next_event_time; + return next_event_time; } diff --git a/packages/battery_plus/battery_plus/example/windows/runner/run_loop.h b/packages/battery_plus/battery_plus/example/windows/runner/run_loop.h index 7fe1aaccc2..5105e29d76 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/run_loop.h +++ b/packages/battery_plus/battery_plus/example/windows/runner/run_loop.h @@ -10,29 +10,31 @@ // as native messages. class RunLoop { public: - RunLoop(); - ~RunLoop(); + RunLoop(); - // Prevent copying - RunLoop(RunLoop const &) = delete; - RunLoop &operator=(RunLoop const &) = delete; + ~RunLoop(); - // Runs the run loop until the application quits. - void Run(); + // Prevent copying + RunLoop(RunLoop const &) = delete; - // Registers the given Flutter instance for event servicing. - void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + RunLoop &operator=(RunLoop const &) = delete; - // Unregisters the given Flutter instance from event servicing. - void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); private: - using TimePoint = std::chrono::steady_clock::time_point; + using TimePoint = std::chrono::steady_clock::time_point; - // Processes all currently pending messages for registered Flutter instances. - TimePoint ProcessFlutterMessages(); + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); - std::set flutter_instances_; + std::set flutter_instances_; }; #endif // RUNNER_RUN_LOOP_H_ diff --git a/packages/battery_plus/battery_plus/example/windows/runner/utils.cpp b/packages/battery_plus/battery_plus/example/windows/runner/utils.cpp index 37501e5db7..9ac126b9aa 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/utils.cpp +++ b/packages/battery_plus/battery_plus/example/windows/runner/utils.cpp @@ -8,15 +8,15 @@ #include void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } } diff --git a/packages/battery_plus/battery_plus/example/windows/runner/win32_window.cpp b/packages/battery_plus/battery_plus/example/windows/runner/win32_window.cpp index 9669d7fc6b..d2ac7322dd 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/win32_window.cpp +++ b/packages/battery_plus/battery_plus/example/windows/runner/win32_window.cpp @@ -6,33 +6,36 @@ namespace { -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; // The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; + static int g_active_window_count = 0; -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + using EnableNonClientDpiScaling = + BOOL __stdcall(HWND + hwnd); // Scale helper to convert logical scaler values to physical using passed in // scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} + int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); + } // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. // This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { + void EnableFullDpiSupportIfAvailable(HWND + hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); - } +} +auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); +if (enable_non_client_dpi_scaling != nullptr) { +enable_non_client_dpi_scaling(hwnd); +FreeLibrary(user32_module); +} } } // namespace @@ -40,197 +43,227 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { // Manages the Win32Window's window class registration. class WindowClassRegistrar { public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registar instance. - static WindowClassRegistrar *GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; } - return instance_; - } - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t *GetWindowClass(); + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); private: - WindowClassRegistrar() = default; + WindowClassRegistrar() = default; - static WindowClassRegistrar *instance_; + static WindowClassRegistrar *instance_; - bool class_registered_ = false; + bool class_registered_ = false; }; WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; const wchar_t *WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; } void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; } Win32Window::Win32Window() { ++g_active_window_count; } Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); + --g_active_window_count; + Destroy(); } bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, const Size &size) { - Destroy(); + Destroy(); - const wchar_t *window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); - if (!window) { - return false; - } + if (!window) { + return false; + } - return OnCreate(); + return OnCreate(); } // static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window *that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } +LRESULT CALLBACK +Win32Window::WndProc(HWND +const window, +UINT const message, + WPARAM +const wparam, +LPARAM const lparam +) noexcept { +if (message == WM_NCCREATE) { +auto window_struct = reinterpret_cast(lparam); +SetWindowLongPtr(window, GWLP_USERDATA, +reinterpret_cast +(window_struct +->lpCreateParams)); + +auto that = static_cast(window_struct->lpCreateParams); +EnableFullDpiSupportIfAvailable(window); +that-> +window_handle_ = window; +} else if ( +Win32Window *that = GetThisFromHandle(window) +) { +return that-> +MessageHandler(window, message, wparam, lparam +); +} - return DefWindowProc(window, message, wparam, lparam); +return +DefWindowProc(window, message, wparam, lparam +); } LRESULT -Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; + Win32Window::MessageHandler(HWND +hwnd, +UINT const message, WPARAM +const wparam, +LPARAM const lparam +) noexcept { +switch (message) { +case WM_DESTROY: +window_handle_ = nullptr; + +Destroy(); + +if (quit_on_close_) { +PostQuitMessage(0); +} +return 0; - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - } +case WM_DPICHANGED: { +auto newRectSize = reinterpret_cast(lparam); +LONG newWidth = newRectSize->right - newRectSize->left; +LONG newHeight = newRectSize->bottom - newRectSize->top; + +SetWindowPos(hwnd, nullptr, newRectSize +->left, newRectSize->top, newWidth, +newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - return DefWindowProc(window_handle_, message, wparam, lparam); +return 0; +} +case WM_SIZE: +RECT rect = GetClientArea(); +if (child_content_ != nullptr) { +// Size and position the child window. +MoveWindow(child_content_, rect +.left, rect.top, rect.right - rect.left, +rect.bottom - rect.top, TRUE); +} +return 0; + +case WM_ACTIVATE: +if (child_content_ != nullptr) { +SetFocus(child_content_); +} +return 0; +} + +return +DefWindowProc(window_handle_, message, wparam, lparam +); } void Win32Window::Destroy() { - OnDestroy(); + OnDestroy(); - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } } -Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); +Win32Window *Win32Window::GetThisFromHandle(HWND const window) + +noexcept { +return reinterpret_cast( +GetWindowLongPtr(window, GWLP_USERDATA +)); } -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); +void Win32Window::SetChildContent(HWND +content) { +child_content_ = content; +SetParent(content, window_handle_ +); +RECT frame = GetClientArea(); - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); +MoveWindow(content, frame +.left, frame.top, frame.right - frame.left, +frame.bottom - frame.top, true); - SetFocus(child_content_); +SetFocus(child_content_); } RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; } HWND Win32Window::GetHandle() { return window_handle_; } void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; + quit_on_close_ = quit_on_close; } bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; + // No-op; provided for subclasses. + return true; } void Win32Window::OnDestroy() { - // No-op; provided for subclasses. + // No-op; provided for subclasses. } diff --git a/packages/battery_plus/battery_plus/example/windows/runner/win32_window.h b/packages/battery_plus/battery_plus/example/windows/runner/win32_window.h index 7b518125bb..f8b5225436 100644 --- a/packages/battery_plus/battery_plus/example/windows/runner/win32_window.h +++ b/packages/battery_plus/battery_plus/example/windows/runner/win32_window.h @@ -12,84 +12,97 @@ // rendering and input handling class Win32Window { public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates and shows a win32 window with |title| and position and size using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring &title, const Point &origin, - const Size &size); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); + struct Point { + unsigned int x; + unsigned int y; -protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); + struct Size { + unsigned int width; + unsigned int height; - // Called when Destroy is called. - virtual void OnDestroy(); + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; -private: - friend class WindowClassRegistrar; + Win32Window(); + + virtual ~Win32Window(); - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); - // Retrieves a class instance pointer for |window| - static Win32Window *GetThisFromHandle(HWND const window) noexcept; + // Release OS resources associated with window. + void Destroy(); - bool quit_on_close_ = false; + // Inserts |content| into the window tree. + void SetChildContent(HWND content); - // window handle for top level window. - HWND window_handle_ = nullptr; + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); - // window handle for hosted content. - HWND child_content_ = nullptr; + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) + + noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK + WndProc(HWND + const window, + UINT const message, + WPARAM + const wparam, + LPARAM const lparam + ) + noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) + + noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; }; #endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/battery_plus/battery_plus/ios/battery_plus/Sources/battery_plus/FPPBatteryPlusPlugin.m b/packages/battery_plus/battery_plus/ios/battery_plus/Sources/battery_plus/FPPBatteryPlusPlugin.m index 81e95d01bb..80fec07b46 100644 --- a/packages/battery_plus/battery_plus/ios/battery_plus/Sources/battery_plus/FPPBatteryPlusPlugin.m +++ b/packages/battery_plus/battery_plus/ios/battery_plus/Sources/battery_plus/FPPBatteryPlusPlugin.m @@ -8,114 +8,114 @@ @interface FPPBatteryPlusPlugin () @end @implementation FPPBatteryPlusPlugin { - FlutterEventSink _eventSink; + FlutterEventSink _eventSink; } -+ (void)registerWithRegistrar:(NSObject *)registrar { - FPPBatteryPlusPlugin *instance = [[FPPBatteryPlusPlugin alloc] init]; ++ (void)registerWithRegistrar:(NSObject *)registrar { + FPPBatteryPlusPlugin *instance = [[FPPBatteryPlusPlugin alloc] init]; - FlutterMethodChannel *channel = [FlutterMethodChannel - methodChannelWithName:@"dev.fluttercommunity.plus/battery" - binaryMessenger:[registrar messenger]]; + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/battery" + binaryMessenger:[registrar messenger]]; - [registrar addMethodCallDelegate:instance channel:channel]; - FlutterEventChannel *chargingChannel = [FlutterEventChannel - eventChannelWithName:@"dev.fluttercommunity.plus/charging" - binaryMessenger:[registrar messenger]]; - [chargingChannel setStreamHandler:instance]; + [registrar addMethodCallDelegate:instance channel:channel]; + FlutterEventChannel *chargingChannel = [FlutterEventChannel + eventChannelWithName:@"dev.fluttercommunity.plus/charging" + binaryMessenger:[registrar messenger]]; + [chargingChannel setStreamHandler:instance]; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - if ([@"getBatteryLevel" isEqualToString:call.method]) { - int batteryLevel = [self getBatteryLevel]; - if (batteryLevel == -1) { - result([FlutterError errorWithCode:@"UNAVAILABLE" - message:@"Battery info unavailable" - details:nil]); + if ([@"getBatteryLevel" isEqualToString:call.method]) { + int batteryLevel = [self getBatteryLevel]; + if (batteryLevel == -1) { + result([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Battery info unavailable" + details:nil]); + } else { + result(@(batteryLevel)); + } + } else if ([@"getBatteryState" isEqualToString:call.method]) { + NSString *state = [self getBatteryState]; + if (state) { + result(state); + } else { + result([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Charging status unavailable" + details:nil]); + } + } else if ([@"isInBatterySaveMode" isEqualToString:call.method]) { + result(@([[NSProcessInfo processInfo] isLowPowerModeEnabled])); } else { - result(@(batteryLevel)); + result(FlutterMethodNotImplemented); } - } else if ([@"getBatteryState" isEqualToString:call.method]) { - NSString *state = [self getBatteryState]; - if (state) { - result(state); - } else { - result([FlutterError errorWithCode:@"UNAVAILABLE" - message:@"Charging status unavailable" - details:nil]); - } - } else if ([@"isInBatterySaveMode" isEqualToString:call.method]) { - result(@([[NSProcessInfo processInfo] isLowPowerModeEnabled])); - } else { - result(FlutterMethodNotImplemented); - } } - (void)onBatteryStateDidChange:(NSNotification *)notification { - [self sendBatteryStateEvent]; + [self sendBatteryStateEvent]; } - (void)sendBatteryStateEvent { - if (!_eventSink) - return; - NSString *state = [self getBatteryState]; - if (state) { - _eventSink(state); - } else { - _eventSink([FlutterError errorWithCode:@"UNAVAILABLE" - message:@"Charging status unavailable" - details:nil]); - } + if (!_eventSink) + return; + NSString *state = [self getBatteryState]; + if (state) { + _eventSink(state); + } else { + _eventSink([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Charging status unavailable" + details:nil]); + } } - (NSString *)getBatteryState { - UIDevice *device = UIDevice.currentDevice; - device.batteryMonitoringEnabled = YES; - UIDeviceBatteryState state = [device batteryState]; - switch (state) { - case UIDeviceBatteryStateUnknown: - return @"unknown"; - case UIDeviceBatteryStateFull: - return @"full"; - case UIDeviceBatteryStateCharging: - return @"charging"; - case UIDeviceBatteryStateUnplugged: - return @"discharging"; - default: - return nil; - } + UIDevice *device = UIDevice.currentDevice; + device.batteryMonitoringEnabled = YES; + UIDeviceBatteryState state = [device batteryState]; + switch (state) { + case UIDeviceBatteryStateUnknown: + return @"unknown"; + case UIDeviceBatteryStateFull: + return @"full"; + case UIDeviceBatteryStateCharging: + return @"charging"; + case UIDeviceBatteryStateUnplugged: + return @"discharging"; + default: + return nil; + } } - (int)getBatteryLevel { - UIDevice *device = UIDevice.currentDevice; - device.batteryMonitoringEnabled = YES; - if (device.batteryState == UIDeviceBatteryStateUnknown) { - return -1; - } else { - return ((int)(device.batteryLevel * 100)); - } + UIDevice *device = UIDevice.currentDevice; + device.batteryMonitoringEnabled = YES; + if (device.batteryState == UIDeviceBatteryStateUnknown) { + return -1; + } else { + return ((int) (device.batteryLevel * 100)); + } } #pragma mark FlutterStreamHandler impl - (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { - _eventSink = eventSink; - [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES]; - [self sendBatteryStateEvent]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(onBatteryStateDidChange:) - name:UIDeviceBatteryStateDidChangeNotification - object:nil]; - return nil; + _eventSink = eventSink; + [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES]; + [self sendBatteryStateEvent]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onBatteryStateDidChange:) + name:UIDeviceBatteryStateDidChangeNotification + object:nil]; + return nil; } - (FlutterError *)onCancelWithArguments:(id)arguments { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - _eventSink = nil; - return nil; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + _eventSink = nil; + return nil; } @end diff --git a/packages/battery_plus/battery_plus/lib/src/battery_plus_linux.dart b/packages/battery_plus/battery_plus/lib/src/battery_plus_linux.dart index 89ab9b778f..0a9680a1d5 100644 --- a/packages/battery_plus/battery_plus/lib/src/battery_plus_linux.dart +++ b/packages/battery_plus/battery_plus/lib/src/battery_plus_linux.dart @@ -80,9 +80,9 @@ class BatteryPlusLinuxPlugin extends BatteryPlatform { Future _startListenState() async { _stateClient ??= createClient(); - await _stateClient! - .connect() - .then((_) => _addState(_stateClient!.displayDevice.state)); + await _stateClient!.connect().then( + (_) => _addState(_stateClient!.displayDevice.state), + ); _stateClient!.displayDevice.propertiesChanged.listen((properties) { if (properties.contains('State')) { _addState(_stateClient!.displayDevice.state); diff --git a/packages/battery_plus/battery_plus/lib/src/battery_plus_web.dart b/packages/battery_plus/battery_plus/lib/src/battery_plus_web.dart index f179ad289a..660fc050cc 100644 --- a/packages/battery_plus/battery_plus/lib/src/battery_plus_web.dart +++ b/packages/battery_plus/battery_plus/lib/src/battery_plus_web.dart @@ -80,11 +80,12 @@ class BatteryPlusWebPlugin extends BatteryPlatform { _checkBatteryChargingState(batteryManager.charging), ); - batteryManager.onchargingchange = (Event _) { - _batteryChangeStreamController?.add( - _checkBatteryChargingState(batteryManager.charging), - ); - }.toJS; + batteryManager.onchargingchange = + (Event _) { + _batteryChangeStreamController?.add( + _checkBatteryChargingState(batteryManager.charging), + ); + }.toJS; _batteryChangeStreamController?.onCancel = () { _batteryChangeStreamController?.close(); diff --git a/packages/battery_plus/battery_plus/test/battery_plus_linux_test.dart b/packages/battery_plus/battery_plus/test/battery_plus_linux_test.dart index 7f86b691eb..7895adcbd0 100644 --- a/packages/battery_plus/battery_plus/test/battery_plus_linux_test.dart +++ b/packages/battery_plus/battery_plus/test/battery_plus_linux_test.dart @@ -41,8 +41,10 @@ void main() { return client; }; expect(battery.onBatteryStateChanged.isBroadcast, isTrue); - expect(battery.onBatteryStateChanged, - emitsInOrder([BatteryState.charging, BatteryState.full])); + expect( + battery.onBatteryStateChanged, + emitsInOrder([BatteryState.charging, BatteryState.full]), + ); }); } diff --git a/packages/battery_plus/battery_plus/test/battery_plus_linux_test.mocks.dart b/packages/battery_plus/battery_plus/test/battery_plus_linux_test.mocks.dart index 4d1a2e7d96..ee395f8710 100644 --- a/packages/battery_plus/battery_plus/test/battery_plus_linux_test.mocks.dart +++ b/packages/battery_plus/battery_plus/test/battery_plus_linux_test.mocks.dart @@ -32,63 +32,103 @@ class MockUPowerClient extends _i1.Mock implements _i2.UPowerClient { @override _i2.UPowerKbdBacklight get kbdBacklight => - (super.noSuchMethod(Invocation.getter(#kbdBacklight), - returnValue: _FakeUPowerKbdBacklight_0()) as _i2.UPowerKbdBacklight); + (super.noSuchMethod( + Invocation.getter(#kbdBacklight), + returnValue: _FakeUPowerKbdBacklight_0(), + ) + as _i2.UPowerKbdBacklight); + @override - set kbdBacklight(_i2.UPowerKbdBacklight? _kbdBacklight) => - super.noSuchMethod(Invocation.setter(#kbdBacklight, _kbdBacklight), - returnValueForMissingStub: null); + set kbdBacklight(_i2.UPowerKbdBacklight? _kbdBacklight) => super.noSuchMethod( + Invocation.setter(#kbdBacklight, _kbdBacklight), + returnValueForMissingStub: null, + ); + @override String get daemonVersion => (super.noSuchMethod(Invocation.getter(#daemonVersion), returnValue: '') as String); + @override bool get onBattery => (super.noSuchMethod(Invocation.getter(#onBattery), returnValue: false) as bool); + @override bool get lidIsPresent => (super.noSuchMethod(Invocation.getter(#lidIsPresent), returnValue: false) as bool); + @override bool get lidIsClosed => (super.noSuchMethod(Invocation.getter(#lidIsClosed), returnValue: false) as bool); + @override List<_i2.UPowerDevice> get devices => - (super.noSuchMethod(Invocation.getter(#devices), - returnValue: <_i2.UPowerDevice>[]) as List<_i2.UPowerDevice>); + (super.noSuchMethod( + Invocation.getter(#devices), + returnValue: <_i2.UPowerDevice>[], + ) + as List<_i2.UPowerDevice>); + @override _i2.UPowerDevice get displayDevice => - (super.noSuchMethod(Invocation.getter(#displayDevice), - returnValue: _FakeUPowerDevice_1()) as _i2.UPowerDevice); + (super.noSuchMethod( + Invocation.getter(#displayDevice), + returnValue: _FakeUPowerDevice_1(), + ) + as _i2.UPowerDevice); + @override _i3.Stream<_i2.UPowerDevice> get deviceAdded => - (super.noSuchMethod(Invocation.getter(#deviceAdded), - returnValue: Stream<_i2.UPowerDevice>.empty()) + (super.noSuchMethod( + Invocation.getter(#deviceAdded), + returnValue: Stream<_i2.UPowerDevice>.empty(), + ) as _i3.Stream<_i2.UPowerDevice>); + @override _i3.Stream<_i2.UPowerDevice> get deviceRemoved => - (super.noSuchMethod(Invocation.getter(#deviceRemoved), - returnValue: Stream<_i2.UPowerDevice>.empty()) + (super.noSuchMethod( + Invocation.getter(#deviceRemoved), + returnValue: Stream<_i2.UPowerDevice>.empty(), + ) as _i3.Stream<_i2.UPowerDevice>); + @override - _i3.Stream> get propertiesChanged => (super.noSuchMethod( - Invocation.getter(#propertiesChanged), - returnValue: Stream>.empty()) as _i3.Stream>); + _i3.Stream> get propertiesChanged => + (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty(), + ) + as _i3.Stream>); + @override _i3.Future connect() => - (super.noSuchMethod(Invocation.method(#connect, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); + (super.noSuchMethod( + Invocation.method(#connect, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); + @override _i3.Future getCriticalAction() => - (super.noSuchMethod(Invocation.method(#getCriticalAction, []), - returnValue: Future.value('')) as _i3.Future); + (super.noSuchMethod( + Invocation.method(#getCriticalAction, []), + returnValue: Future.value(''), + ) + as _i3.Future); + @override - _i3.Future close() => (super.noSuchMethod(Invocation.method(#close, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); + _i3.Future close() => + (super.noSuchMethod( + Invocation.method(#close, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); } /// A class which mocks [UPowerDevice]. @@ -103,143 +143,212 @@ class MockUPowerDevice extends _i1.Mock implements _i2.UPowerDevice { String get nativePath => (super.noSuchMethod(Invocation.getter(#nativePath), returnValue: '') as String); + @override String get vendor => (super.noSuchMethod(Invocation.getter(#vendor), returnValue: '') as String); + @override String get model => (super.noSuchMethod(Invocation.getter(#model), returnValue: '') as String); + @override String get serial => (super.noSuchMethod(Invocation.getter(#serial), returnValue: '') as String); + @override int get updateTime => (super.noSuchMethod(Invocation.getter(#updateTime), returnValue: 0) as int); + @override - _i2.UPowerDeviceType get type => (super.noSuchMethod(Invocation.getter(#type), - returnValue: _i2.UPowerDeviceType.unknown) as _i2.UPowerDeviceType); + _i2.UPowerDeviceType get type => + (super.noSuchMethod( + Invocation.getter(#type), + returnValue: _i2.UPowerDeviceType.unknown, + ) + as _i2.UPowerDeviceType); + @override bool get powerSupply => (super.noSuchMethod(Invocation.getter(#powerSupply), returnValue: false) as bool); + @override bool get hasHistory => (super.noSuchMethod(Invocation.getter(#hasHistory), returnValue: false) as bool); + @override bool get hasStatistics => (super.noSuchMethod(Invocation.getter(#hasStatistics), returnValue: false) as bool); + @override bool get online => (super.noSuchMethod(Invocation.getter(#online), returnValue: false) as bool); + @override double get energy => (super.noSuchMethod(Invocation.getter(#energy), returnValue: 0.0) as double); + @override double get energyEmpty => (super.noSuchMethod(Invocation.getter(#energyEmpty), returnValue: 0.0) as double); + @override double get energyFull => (super.noSuchMethod(Invocation.getter(#energyFull), returnValue: 0.0) as double); + @override - double get energyFullDesign => (super - .noSuchMethod(Invocation.getter(#energyFullDesign), returnValue: 0.0) - as double); + double get energyFullDesign => + (super.noSuchMethod( + Invocation.getter(#energyFullDesign), + returnValue: 0.0, + ) + as double); + @override double get energyRate => (super.noSuchMethod(Invocation.getter(#energyRate), returnValue: 0.0) as double); + @override double get voltage => (super.noSuchMethod(Invocation.getter(#voltage), returnValue: 0.0) as double); + @override double get luminosity => (super.noSuchMethod(Invocation.getter(#luminosity), returnValue: 0.0) as double); + @override int get timeToEmpty => (super.noSuchMethod(Invocation.getter(#timeToEmpty), returnValue: 0) as int); + @override int get timeToFull => (super.noSuchMethod(Invocation.getter(#timeToFull), returnValue: 0) as int); + @override double get percentage => (super.noSuchMethod(Invocation.getter(#percentage), returnValue: 0.0) as double); + @override double get temperature => (super.noSuchMethod(Invocation.getter(#temperature), returnValue: 0.0) as double); + @override bool get isPresent => (super.noSuchMethod(Invocation.getter(#isPresent), returnValue: false) as bool); + @override _i2.UPowerDeviceState get state => - (super.noSuchMethod(Invocation.getter(#state), - returnValue: _i2.UPowerDeviceState.unknown) as _i2.UPowerDeviceState); + (super.noSuchMethod( + Invocation.getter(#state), + returnValue: _i2.UPowerDeviceState.unknown, + ) + as _i2.UPowerDeviceState); + @override - bool get isRechargeable => (super - .noSuchMethod(Invocation.getter(#isRechargeable), returnValue: false) - as bool); + bool get isRechargeable => + (super.noSuchMethod( + Invocation.getter(#isRechargeable), + returnValue: false, + ) + as bool); + @override double get capacity => (super.noSuchMethod(Invocation.getter(#capacity), returnValue: 0.0) as double); + @override _i2.UPowerDeviceTechnology get technology => - (super.noSuchMethod(Invocation.getter(#technology), - returnValue: _i2.UPowerDeviceTechnology.unknown) + (super.noSuchMethod( + Invocation.getter(#technology), + returnValue: _i2.UPowerDeviceTechnology.unknown, + ) as _i2.UPowerDeviceTechnology); + @override _i2.UPowerDeviceWarningLevel get warningLevel => - (super.noSuchMethod(Invocation.getter(#warningLevel), - returnValue: _i2.UPowerDeviceWarningLevel.unknown) + (super.noSuchMethod( + Invocation.getter(#warningLevel), + returnValue: _i2.UPowerDeviceWarningLevel.unknown, + ) as _i2.UPowerDeviceWarningLevel); + @override _i2.UPowerDeviceBatteryLevel get batteryLevel => - (super.noSuchMethod(Invocation.getter(#batteryLevel), - returnValue: _i2.UPowerDeviceBatteryLevel.unknown) + (super.noSuchMethod( + Invocation.getter(#batteryLevel), + returnValue: _i2.UPowerDeviceBatteryLevel.unknown, + ) as _i2.UPowerDeviceBatteryLevel); + @override String get iconName => (super.noSuchMethod(Invocation.getter(#iconName), returnValue: '') as String); + @override - _i3.Stream> get propertiesChanged => (super.noSuchMethod( - Invocation.getter(#propertiesChanged), - returnValue: Stream>.empty()) as _i3.Stream>); + _i3.Stream> get propertiesChanged => + (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty(), + ) + as _i3.Stream>); + @override _i3.Future refresh() => - (super.noSuchMethod(Invocation.method(#refresh, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); + (super.noSuchMethod( + Invocation.method(#refresh, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); + @override _i3.Future> getHistory( - String? type, int? resolution, {int? timespan = 0}) => + String? type, + int? resolution, { + int? timespan = 0, + }) => (super.noSuchMethod( - Invocation.method( - #getHistory, [type, resolution], {#timespan: timespan}), - returnValue: Future>.value( - <_i2.UPowerDeviceHistoryRecord>[])) + Invocation.method( + #getHistory, + [type, resolution], + {#timespan: timespan}, + ), + returnValue: Future>.value( + <_i2.UPowerDeviceHistoryRecord>[], + ), + ) as _i3.Future>); + @override _i3.Future> getStatistics( - String? type) => - (super.noSuchMethod(Invocation.method(#getStatistics, [type]), - returnValue: Future>.value( - <_i2.UPowerDeviceStatisticsRecord>[])) + String? type, + ) => + (super.noSuchMethod( + Invocation.method(#getStatistics, [type]), + returnValue: Future>.value( + <_i2.UPowerDeviceStatisticsRecord>[], + ), + ) as _i3.Future>); } diff --git a/packages/battery_plus/battery_plus/test/battery_test.dart b/packages/battery_plus/battery_plus/test/battery_test.dart index fb1a7683e3..0eb3de3707 100644 --- a/packages/battery_plus/battery_plus/test/battery_test.dart +++ b/packages/battery_plus/battery_plus/test/battery_test.dart @@ -21,11 +21,11 @@ class MockBatteryPlatform @override Stream get onBatteryStateChanged => Stream.fromIterable([ - BatteryState.unknown, - BatteryState.charging, - BatteryState.full, - BatteryState.discharging - ]); + BatteryState.unknown, + BatteryState.charging, + BatteryState.full, + BatteryState.discharging, + ]); @override Future get isInBatterySaveMode => Future.value(true); diff --git a/packages/battery_plus/battery_plus/windows/CMakeLists.txt b/packages/battery_plus/battery_plus/windows/CMakeLists.txt index b8f1d4096a..051fffa6b8 100644 --- a/packages/battery_plus/battery_plus/windows/CMakeLists.txt +++ b/packages/battery_plus/battery_plus/windows/CMakeLists.txt @@ -5,19 +5,19 @@ project(${PROJECT_NAME} LANGUAGES CXX) set(PLUGIN_NAME "${PROJECT_NAME}_plugin") add_library(${PLUGIN_NAME} SHARED - "${PLUGIN_NAME}.cpp" - "system_battery.cpp" + "${PLUGIN_NAME}.cpp" + "system_battery.cpp" ) apply_standard_settings(${PLUGIN_NAME}) set_target_properties(${PLUGIN_NAME} PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") + "${CMAKE_CURRENT_SOURCE_DIR}/include") target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) # List of absolute paths to libraries that should be bundled with the plugin set(battery_plus_bundled_libraries - "" - PARENT_SCOPE + "" + PARENT_SCOPE ) diff --git a/packages/battery_plus/battery_plus/windows/battery_plus_plugin.cpp b/packages/battery_plus/battery_plus/windows/battery_plus_plugin.cpp index 868e584710..73502cefc7 100644 --- a/packages/battery_plus/battery_plus/windows/battery_plus_plugin.cpp +++ b/packages/battery_plus/battery_plus/windows/battery_plus_plugin.cpp @@ -15,162 +15,164 @@ namespace { -typedef flutter::EventChannel FlEventChannel; -typedef flutter::EventSink FlEventSink; -typedef flutter::MethodCall FlMethodCall; -typedef flutter::MethodResult FlMethodResult; -typedef flutter::MethodChannel FlMethodChannel; -typedef flutter::StreamHandler FlStreamHandler; -typedef flutter::StreamHandlerError - FlStreamHandlerError; - -class BatteryPlusWindowsPlugin : public flutter::Plugin { -public: - static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); - - BatteryPlusWindowsPlugin(flutter::PluginRegistrarWindows *registrar); - ~BatteryPlusWindowsPlugin(); - -private: - void HandleMethodCall(const FlMethodCall &method_call, - std::unique_ptr result); - std::unique_ptr _methodChannel; - std::unique_ptr _eventChannel; -}; - -class BatteryStatusStreamHandler : public FlStreamHandler { -public: - BatteryStatusStreamHandler(flutter::PluginRegistrarWindows *registrar); - -protected: - void AddStatusEvent(BatteryStatus status); - - std::unique_ptr - OnListenInternal(const flutter::EncodableValue *arguments, - std::unique_ptr &&events) override; - - std::unique_ptr - OnCancelInternal(const flutter::EncodableValue *arguments) override; - -private: - int _delegate = -1; - SystemBattery _battery; - std::unique_ptr _events; - flutter::PluginRegistrarWindows *_registrar = nullptr; -}; - -void BatteryPlusWindowsPlugin::RegisterWithRegistrar( - flutter::PluginRegistrarWindows *registrar) { - registrar->AddPlugin(std::make_unique(registrar)); -} - -BatteryPlusWindowsPlugin::BatteryPlusWindowsPlugin( - flutter::PluginRegistrarWindows *registrar) { - _methodChannel = std::make_unique( - registrar->messenger(), "dev.fluttercommunity.plus/battery", - &flutter::StandardMethodCodec::GetInstance()); + typedef flutter::EventChannel FlEventChannel; + typedef flutter::EventSink FlEventSink; + typedef flutter::MethodCall FlMethodCall; + typedef flutter::MethodResult FlMethodResult; + typedef flutter::MethodChannel FlMethodChannel; + typedef flutter::StreamHandler FlStreamHandler; + typedef flutter::StreamHandlerError + FlStreamHandlerError; + + class BatteryPlusWindowsPlugin : public flutter::Plugin { + public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + + BatteryPlusWindowsPlugin(flutter::PluginRegistrarWindows *registrar); + + ~BatteryPlusWindowsPlugin(); + + private: + void HandleMethodCall(const FlMethodCall &method_call, + std::unique_ptr result); + + std::unique_ptr _methodChannel; + std::unique_ptr _eventChannel; + }; + + class BatteryStatusStreamHandler : public FlStreamHandler { + public: + BatteryStatusStreamHandler(flutter::PluginRegistrarWindows *registrar); + + protected: + void AddStatusEvent(BatteryStatus status); + + std::unique_ptr + OnListenInternal(const flutter::EncodableValue *arguments, + std::unique_ptr &&events) override; + + std::unique_ptr + OnCancelInternal(const flutter::EncodableValue *arguments) override; + + private: + int _delegate = -1; + SystemBattery _battery; + std::unique_ptr _events; + flutter::PluginRegistrarWindows *_registrar = nullptr; + }; + + void BatteryPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + registrar->AddPlugin(std::make_unique(registrar)); + } - _methodChannel->SetMethodCallHandler([this](const auto &call, auto result) { - HandleMethodCall(call, std::move(result)); - }); + BatteryPlusWindowsPlugin::BatteryPlusWindowsPlugin( + flutter::PluginRegistrarWindows *registrar) { + _methodChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/battery", + &flutter::StandardMethodCodec::GetInstance()); - _eventChannel = std::make_unique( - registrar->messenger(), "dev.fluttercommunity.plus/charging", - &flutter::StandardMethodCodec::GetInstance()); + _methodChannel->SetMethodCallHandler([this](const auto &call, auto result) { + HandleMethodCall(call, std::move(result)); + }); - _eventChannel->SetStreamHandler( - std::make_unique(registrar)); -} + _eventChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/charging", + &flutter::StandardMethodCodec::GetInstance()); -BatteryPlusWindowsPlugin::~BatteryPlusWindowsPlugin() {} + _eventChannel->SetStreamHandler( + std::make_unique(registrar)); + } -BatteryStatusStreamHandler::BatteryStatusStreamHandler( - flutter::PluginRegistrarWindows *registrar) - : _registrar(registrar) {} + BatteryPlusWindowsPlugin::~BatteryPlusWindowsPlugin() {} -void BatteryStatusStreamHandler::AddStatusEvent(BatteryStatus status) { - if (status != BatteryStatus::Error) { - _events->Success(_battery.GetStatusString()); - } else { - _events->Error(std::to_string(_battery.GetError()), - _battery.GetErrorString()); - } -} + BatteryStatusStreamHandler::BatteryStatusStreamHandler( + flutter::PluginRegistrarWindows *registrar) + : _registrar(registrar) {} -std::unique_ptr -BatteryStatusStreamHandler::OnListenInternal( - const flutter::EncodableValue *arguments, - std::unique_ptr &&events) { - _events = std::move(events); - - HWND hwnd = _registrar->GetView()->GetNativeWindow(); - BatteryStatusCallback callback = std::bind( - &BatteryStatusStreamHandler::AddStatusEvent, this, std::placeholders::_1); - - if (!_battery.StartListen(hwnd, callback)) { - return std::make_unique( - std::to_string(_battery.GetError()), _battery.GetErrorString(), - nullptr); - } - - _delegate = _registrar->RegisterTopLevelWindowProcDelegate( - [this](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - _battery.ProcessMsg(hwnd, message, wparam, lparam); - return std::nullopt; - }); - - AddStatusEvent(_battery.GetStatus()); - return nullptr; -} + void BatteryStatusStreamHandler::AddStatusEvent(BatteryStatus status) { + if (status != BatteryStatus::Error) { + _events->Success(_battery.GetStatusString()); + } else { + _events->Error(std::to_string(_battery.GetError()), + _battery.GetErrorString()); + } + } -std::unique_ptr -BatteryStatusStreamHandler::OnCancelInternal( - const flutter::EncodableValue *arguments) { - _registrar->UnregisterTopLevelWindowProcDelegate(_delegate); - if (!_battery.StopListen()) { - return std::make_unique( - std::to_string(_battery.GetError()), _battery.GetErrorString(), - nullptr); - } - _delegate = -1; - _events.reset(); - return nullptr; -} + std::unique_ptr + BatteryStatusStreamHandler::OnListenInternal( + const flutter::EncodableValue *arguments, + std::unique_ptr &&events) { + _events = std::move(events); + + HWND hwnd = _registrar->GetView()->GetNativeWindow(); + BatteryStatusCallback callback = std::bind( + &BatteryStatusStreamHandler::AddStatusEvent, this, std::placeholders::_1); + + if (!_battery.StartListen(hwnd, callback)) { + return std::make_unique( + std::to_string(_battery.GetError()), _battery.GetErrorString(), + nullptr); + } + + _delegate = _registrar->RegisterTopLevelWindowProcDelegate( + [this](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + _battery.ProcessMsg(hwnd, message, wparam, lparam); + return std::nullopt; + }); + + AddStatusEvent(_battery.GetStatus()); + return nullptr; + } -void BatteryPlusWindowsPlugin::HandleMethodCall( - const FlMethodCall &method_call, std::unique_ptr result) { - if (method_call.method_name().compare("isInBatterySaveMode") == 0) { - SystemBattery battery; - int batteryStatus = battery.GetBatterySaveMode(); - if (batteryStatus == 0 || batteryStatus == 1) { - bool isBatteryMode = batteryStatus == 1; - result->Success(flutter::EncodableValue(isBatteryMode)); - } else { - result->Error(std::to_string(battery.GetError()), - battery.GetErrorString()); + std::unique_ptr + BatteryStatusStreamHandler::OnCancelInternal( + const flutter::EncodableValue *arguments) { + _registrar->UnregisterTopLevelWindowProcDelegate(_delegate); + if (!_battery.StopListen()) { + return std::make_unique( + std::to_string(_battery.GetError()), _battery.GetErrorString(), + nullptr); + } + _delegate = -1; + _events.reset(); + return nullptr; } - } else if (method_call.method_name().compare("getBatteryLevel") == 0) { - SystemBattery battery; - int level = battery.GetLevel(); - if (level >= 0) { - result->Success(flutter::EncodableValue(level)); - } else { - result->Error(std::to_string(battery.GetError()), - battery.GetErrorString()); + + void BatteryPlusWindowsPlugin::HandleMethodCall( + const FlMethodCall &method_call, std::unique_ptr result) { + if (method_call.method_name().compare("isInBatterySaveMode") == 0) { + SystemBattery battery; + int batteryStatus = battery.GetBatterySaveMode(); + if (batteryStatus == 0 || batteryStatus == 1) { + bool isBatteryMode = batteryStatus == 1; + result->Success(flutter::EncodableValue(isBatteryMode)); + } else { + result->Error(std::to_string(battery.GetError()), + battery.GetErrorString()); + } + } else if (method_call.method_name().compare("getBatteryLevel") == 0) { + SystemBattery battery; + int level = battery.GetLevel(); + if (level >= 0) { + result->Success(flutter::EncodableValue(level)); + } else { + result->Error(std::to_string(battery.GetError()), + battery.GetErrorString()); + } + } else if (method_call.method_name().compare("getBatteryState") == 0) { + SystemBattery battery; + result->Success(flutter::EncodableValue(battery.GetStatusString())); + } else { + result->NotImplemented(); + } } - } else if (method_call.method_name().compare("getBatteryState") == 0) { - SystemBattery battery; - result->Success(flutter::EncodableValue(battery.GetStatusString())); - } else { - result->NotImplemented(); - } -} } // namespace void BatteryPlusWindowsPluginRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar) { - BatteryPlusWindowsPlugin::RegisterWithRegistrar( - flutter::PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar)); + FlutterDesktopPluginRegistrarRef registrar) { + BatteryPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); } diff --git a/packages/battery_plus/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h b/packages/battery_plus/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h index 9d8d922670..81cc3aaae0 100644 --- a/packages/battery_plus/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h +++ b/packages/battery_plus/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h @@ -14,7 +14,7 @@ extern "C" { #endif FLUTTER_PLUGIN_EXPORT void BatteryPlusWindowsPluginRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar); + FlutterDesktopPluginRegistrarRef registrar); #if defined(__cplusplus) } // extern "C" diff --git a/packages/battery_plus/battery_plus/windows/include/battery_plus/system_battery.h b/packages/battery_plus/battery_plus/windows/include/battery_plus/system_battery.h index 9e58f0e21c..ca2e8a1c41 100644 --- a/packages/battery_plus/battery_plus/windows/include/battery_plus/system_battery.h +++ b/packages/battery_plus/battery_plus/windows/include/battery_plus/system_battery.h @@ -7,31 +7,39 @@ #include #include -enum class BatteryStatus { Full, Charging, Discharging, Error, Unknown }; +enum class BatteryStatus { + Full, Charging, Discharging, Error, Unknown +}; typedef std::function BatteryStatusCallback; class SystemBattery { public: - SystemBattery(); - ~SystemBattery(); + SystemBattery(); + + ~SystemBattery(); + + int GetBatterySaveMode() const; + + int GetLevel() const; + + BatteryStatus GetStatus() const; + + std::string GetStatusString() const; + + int GetError() const; - int GetBatterySaveMode() const; - int GetLevel() const; + std::string GetErrorString() const; - BatteryStatus GetStatus() const; - std::string GetStatusString() const; + bool StartListen(HWND hwnd, BatteryStatusCallback callback); - int GetError() const; - std::string GetErrorString() const; + void ProcessMsg(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); - bool StartListen(HWND hwnd, BatteryStatusCallback callback); - void ProcessMsg(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); - bool StopListen(); + bool StopListen(); private: - HPOWERNOTIFY _notifier = nullptr; - BatteryStatusCallback _callback = nullptr; + HPOWERNOTIFY _notifier = nullptr; + BatteryStatusCallback _callback = nullptr; }; #endif // FLUTTER_PLUGIN_BATTERY_PLUS_SYSTEM_BATTERY_H_ diff --git a/packages/battery_plus/battery_plus/windows/system_battery.cpp b/packages/battery_plus/battery_plus/windows/system_battery.cpp index b769196bea..c6e21a874b 100644 --- a/packages/battery_plus/battery_plus/windows/system_battery.cpp +++ b/packages/battery_plus/battery_plus/windows/system_battery.cpp @@ -3,33 +3,33 @@ #include namespace { -enum ACLineStatus { - Offline = 0, - Online = 1, -}; - -enum BatteryLevel { - Empty = 0, - Full = 100, - Unknown = 255, -}; - -enum BatteryFlag { - High = 1, // the battery capacity is at more than 66 percent - Low = 2, // the battery capacity is at less than 33 percent - Critical = 4, // the battery capacity is at less than five percent - Charging = 8, - NoBattery = 128 // no system battery -}; - -bool GetBatteryStatus(LPSYSTEM_POWER_STATUS lpStatus) { - return GetSystemPowerStatus(lpStatus) != 0; -} + enum ACLineStatus { + Offline = 0, + Online = 1, + }; + + enum BatteryLevel { + Empty = 0, + Full = 100, + Unknown = 255, + }; + + enum BatteryFlag { + High = 1, // the battery capacity is at more than 66 percent + Low = 2, // the battery capacity is at less than 33 percent + Critical = 4, // the battery capacity is at less than five percent + Charging = 8, + NoBattery = 128 // no system battery + }; + + bool GetBatteryStatus(LPSYSTEM_POWER_STATUS lpStatus) { + return GetSystemPowerStatus(lpStatus) != 0; + } -bool IsValidBatteryStatus(LPSYSTEM_POWER_STATUS lpStatus) { - return lpStatus->BatteryFlag != NoBattery && - lpStatus->BatteryLifePercent != Unknown; -} + bool IsValidBatteryStatus(LPSYSTEM_POWER_STATUS lpStatus) { + return lpStatus->BatteryFlag != NoBattery && + lpStatus->BatteryLifePercent != Unknown; + } } // namespace SystemBattery::SystemBattery() {} @@ -37,89 +37,89 @@ SystemBattery::SystemBattery() {} SystemBattery::~SystemBattery() { StopListen(); } int SystemBattery::GetBatterySaveMode() const { - SYSTEM_POWER_STATUS status; - if (!GetBatteryStatus(&status)) { - return -1; - } - return status.SystemStatusFlag; + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status)) { + return -1; + } + return status.SystemStatusFlag; } int SystemBattery::GetLevel() const { - SYSTEM_POWER_STATUS status; - if (!GetBatteryStatus(&status) || !IsValidBatteryStatus(&status)) { - return -1; - } - return status.BatteryLifePercent; + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status) || !IsValidBatteryStatus(&status)) { + return -1; + } + return status.BatteryLifePercent; } BatteryStatus SystemBattery::GetStatus() const { - SYSTEM_POWER_STATUS status; - if (!GetBatteryStatus(&status)) { - return BatteryStatus::Error; - } - if (IsValidBatteryStatus(&status)) { - if (status.ACLineStatus == Online) { - if (status.BatteryLifePercent == Full) { - return BatteryStatus::Full; - } else if (status.BatteryFlag & Charging) { - return BatteryStatus::Charging; - } - } else if (status.ACLineStatus == Offline) { - if (!(status.BatteryFlag & Charging)) { - return BatteryStatus::Discharging; - } + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status)) { + return BatteryStatus::Error; } - } - return BatteryStatus::Unknown; + if (IsValidBatteryStatus(&status)) { + if (status.ACLineStatus == Online) { + if (status.BatteryLifePercent == Full) { + return BatteryStatus::Full; + } else if (status.BatteryFlag & Charging) { + return BatteryStatus::Charging; + } + } else if (status.ACLineStatus == Offline) { + if (!(status.BatteryFlag & Charging)) { + return BatteryStatus::Discharging; + } + } + } + return BatteryStatus::Unknown; } std::string SystemBattery::GetStatusString() const { - switch (GetStatus()) { - case BatteryStatus::Charging: - return "charging"; - case BatteryStatus::Discharging: - return "discharging"; - case BatteryStatus::Full: - return "full"; - case BatteryStatus::Unknown: - default: - return "unknown"; - } + switch (GetStatus()) { + case BatteryStatus::Charging: + return "charging"; + case BatteryStatus::Discharging: + return "discharging"; + case BatteryStatus::Full: + return "full"; + case BatteryStatus::Unknown: + default: + return "unknown"; + } } int SystemBattery::GetError() const { return GetLastError(); } std::string SystemBattery::GetErrorString() const { - // ### TODO: FormatMessage() - return "GetSystemPowerStatus() failed"; + // ### TODO: FormatMessage() + return "GetSystemPowerStatus() failed"; } bool SystemBattery::StartListen(HWND hwnd, BatteryStatusCallback callback) { - if (_notifier) { - return false; - } - _callback = callback; - _notifier = RegisterPowerSettingNotification(hwnd, &GUID_ACDC_POWER_SOURCE, - DEVICE_NOTIFY_WINDOW_HANDLE); - return _notifier != nullptr; + if (_notifier) { + return false; + } + _callback = callback; + _notifier = RegisterPowerSettingNotification(hwnd, &GUID_ACDC_POWER_SOURCE, + DEVICE_NOTIFY_WINDOW_HANDLE); + return _notifier != nullptr; } void SystemBattery::ProcessMsg(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - if (!_callback) { - return; - } - if (message == WM_POWERBROADCAST && wparam == PBT_APMPOWERSTATUSCHANGE) { - _callback(GetStatus()); - } + if (!_callback) { + return; + } + if (message == WM_POWERBROADCAST && wparam == PBT_APMPOWERSTATUSCHANGE) { + _callback(GetStatus()); + } } bool SystemBattery::StopListen() { - if (!_notifier) { - return false; - } - HPOWERNOTIFY notifier = nullptr; - std::swap(notifier, _notifier); - _callback = nullptr; - return UnregisterPowerSettingNotification(notifier) != 0; + if (!_notifier) { + return false; + } + HPOWERNOTIFY notifier = nullptr; + std::swap(notifier, _notifier); + _callback = nullptr; + return UnregisterPowerSettingNotification(notifier) != 0; } diff --git a/packages/battery_plus/battery_plus_platform_interface/CHANGELOG.md b/packages/battery_plus/battery_plus_platform_interface/CHANGELOG.md index 2622243459..bbe24bfe5e 100644 --- a/packages/battery_plus/battery_plus_platform_interface/CHANGELOG.md +++ b/packages/battery_plus/battery_plus_platform_interface/CHANGELOG.md @@ -1,18 +1,22 @@ ## 2.0.1 - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 2.0.0 > Note: This release has breaking changes. - - **FIX**(battery_plus): Implement not charging battery state ([#2275](https://github.com/fluttercommunity/plus_plugins/issues/2275)). ([6595e035](https://github.com/fluttercommunity/plus_plugins/commit/6595e035fd113b4a75651c9d471cc098d5798de3)) - - **FEAT**(battery_plus): Introduce not_charging state on Linux ([#2400](https://github.com/fluttercommunity/plus_plugins/issues/2400)). ([42ef02bd](https://github.com/fluttercommunity/plus_plugins/commit/42ef02bd6de219fef1b2d9db2eebe9775a6ac751)) - - **BREAKING** **FEAT**(battery_plus): Introduce connected_not_charging state on MacOS ([#2399](https://github.com/fluttercommunity/plus_plugins/issues/2399)). ([78f44bf4](https://github.com/fluttercommunity/plus_plugins/commit/78f44bf41a7e8349240bacae2dd70598ba22e97a)) +- **FIX**(battery_plus): Implement not charging battery + state ([#2275](https://github.com/fluttercommunity/plus_plugins/issues/2275)). ([6595e035](https://github.com/fluttercommunity/plus_plugins/commit/6595e035fd113b4a75651c9d471cc098d5798de3)) +- **FEAT**(battery_plus): Introduce not_charging state on + Linux ([#2400](https://github.com/fluttercommunity/plus_plugins/issues/2400)). ([42ef02bd](https://github.com/fluttercommunity/plus_plugins/commit/42ef02bd6de219fef1b2d9db2eebe9775a6ac751)) +- **BREAKING** **FEAT**(battery_plus): Introduce connected_not_charging state on + MacOS ([#2399](https://github.com/fluttercommunity/plus_plugins/issues/2399)). ([78f44bf4](https://github.com/fluttercommunity/plus_plugins/commit/78f44bf41a7e8349240bacae2dd70598ba22e97a)) ## 1.2.2 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 1.2.2 diff --git a/packages/battery_plus/battery_plus_platform_interface/lib/battery_plus_platform_interface.dart b/packages/battery_plus/battery_plus_platform_interface/lib/battery_plus_platform_interface.dart index 6d91d295b1..ea902244ad 100644 --- a/packages/battery_plus/battery_plus_platform_interface/lib/battery_plus_platform_interface.dart +++ b/packages/battery_plus/battery_plus_platform_interface/lib/battery_plus_platform_interface.dart @@ -55,6 +55,7 @@ abstract class BatteryPlatform extends PlatformInterface { /// Returns a Stream of BatteryState changes. Stream get onBatteryStateChanged { throw UnimplementedError( - 'get onBatteryStateChanged has not been implemented.'); + 'get onBatteryStateChanged has not been implemented.', + ); } } diff --git a/packages/battery_plus/battery_plus_platform_interface/lib/method_channel_battery_plus.dart b/packages/battery_plus/battery_plus_platform_interface/lib/method_channel_battery_plus.dart index 1f69c9cf40..bc123e8800 100644 --- a/packages/battery_plus/battery_plus_platform_interface/lib/method_channel_battery_plus.dart +++ b/packages/battery_plus/battery_plus_platform_interface/lib/method_channel_battery_plus.dart @@ -14,13 +14,15 @@ import 'src/utils.dart'; class MethodChannelBattery extends BatteryPlatform { /// The method channel used to interact with the native platform. @visibleForTesting - MethodChannel methodChannel = - const MethodChannel('dev.fluttercommunity.plus/battery'); + MethodChannel methodChannel = const MethodChannel( + 'dev.fluttercommunity.plus/battery', + ); /// The event channel used to receive BatteryState changes from the native platform. @visibleForTesting - EventChannel eventChannel = - const EventChannel('dev.fluttercommunity.plus/charging'); + EventChannel eventChannel = const EventChannel( + 'dev.fluttercommunity.plus/charging', + ); Stream? _onBatteryStateChanged; @@ -45,9 +47,9 @@ class MethodChannelBattery extends BatteryPlatform { /// Fires whenever the battery state changes. @override Stream get onBatteryStateChanged { - _onBatteryStateChanged ??= eventChannel - .receiveBroadcastStream() - .map((dynamic event) => parseBatteryState(event)); + _onBatteryStateChanged ??= eventChannel.receiveBroadcastStream().map( + (dynamic event) => parseBatteryState(event), + ); return _onBatteryStateChanged!; } } diff --git a/packages/battery_plus/battery_plus_platform_interface/lib/src/enums.dart b/packages/battery_plus/battery_plus_platform_interface/lib/src/enums.dart index ca790d5dfc..28252ed385 100644 --- a/packages/battery_plus/battery_plus_platform_interface/lib/src/enums.dart +++ b/packages/battery_plus/battery_plus_platform_interface/lib/src/enums.dart @@ -18,5 +18,5 @@ enum BatteryState { discharging, /// The state of the battery is unknown. - unknown; + unknown, } diff --git a/packages/battery_plus/battery_plus_platform_interface/test/battery_plus_platform_interface_test.dart b/packages/battery_plus/battery_plus_platform_interface/test/battery_plus_platform_interface_test.dart index c967f8bfc0..6627c9057a 100644 --- a/packages/battery_plus/battery_plus_platform_interface/test/battery_plus_platform_interface_test.dart +++ b/packages/battery_plus/battery_plus_platform_interface/test/battery_plus_platform_interface_test.dart @@ -14,46 +14,46 @@ void main() { methodChannelBattery = MethodChannelBattery(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - methodChannelBattery.methodChannel, - (MethodCall methodCall) async { - log.add(methodCall); - switch (methodCall.method) { - case 'getBatteryLevel': - return 100; - case 'isInBatterySaveMode': - return true; - case 'getBatteryState': - return 'charging'; - default: - return null; - } - }, - ); + .setMockMethodCallHandler(methodChannelBattery.methodChannel, ( + MethodCall methodCall, + ) async { + log.add(methodCall); + switch (methodCall.method) { + case 'getBatteryLevel': + return 100; + case 'isInBatterySaveMode': + return true; + case 'getBatteryState': + return 'charging'; + default: + return null; + } + }); log.clear(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler( - MethodChannel(methodChannelBattery.eventChannel.name), - (MethodCall methodCall) async { - switch (methodCall.method) { - case 'listen': - await TestDefaultBinaryMessengerBinding - .instance.defaultBinaryMessenger - .handlePlatformMessage( - methodChannelBattery.eventChannel.name, - methodChannelBattery.eventChannel.codec - .encodeSuccessEnvelope('full'), - (_) {}, - ); - break; - case 'cancel': - default: + MethodChannel(methodChannelBattery.eventChannel.name), + (MethodCall methodCall) async { + switch (methodCall.method) { + case 'listen': + await TestDefaultBinaryMessengerBinding + .instance + .defaultBinaryMessenger + .handlePlatformMessage( + methodChannelBattery.eventChannel.name, + methodChannelBattery.eventChannel.codec + .encodeSuccessEnvelope('full'), + (_) {}, + ); + break; + case 'cancel': + default: + return null; + } return null; - } - return null; - }, - ); + }, + ); }); test('onBatteryChanged', () async { @@ -64,43 +64,21 @@ void main() { test('getBatteryLevel', () async { final result = await methodChannelBattery.batteryLevel; expect(result, 100); - expect( - log, - [ - isMethodCall( - 'getBatteryLevel', - arguments: null, - ), - ], - ); + expect(log, [isMethodCall('getBatteryLevel', arguments: null)]); }); test('isInBatterySaveMode', () async { final result = await methodChannelBattery.isInBatterySaveMode; expect(result, true); - expect( - log, - [ - isMethodCall( - 'isInBatterySaveMode', - arguments: null, - ), - ], - ); + expect(log, [ + isMethodCall('isInBatterySaveMode', arguments: null), + ]); }); test('getBatteryState', () async { final result = await methodChannelBattery.batteryState; expect(result, BatteryState.charging); - expect( - log, - [ - isMethodCall( - 'getBatteryState', - arguments: null, - ), - ], - ); + expect(log, [isMethodCall('getBatteryState', arguments: null)]); }); }); } diff --git a/packages/connectivity_plus/connectivity_plus/CHANGELOG.md b/packages/connectivity_plus/connectivity_plus/CHANGELOG.md index a8369c396a..3e9a640cd9 100644 --- a/packages/connectivity_plus/connectivity_plus/CHANGELOG.md +++ b/packages/connectivity_plus/connectivity_plus/CHANGELOG.md @@ -1,44 +1,61 @@ ## 6.1.3 - - **FIX**(connectivity_plus): Resolve missing privacy manifest issue for iOS and MacOS ([#3458](https://github.com/fluttercommunity/plus_plugins/issues/3458)). ([dab92074](https://github.com/fluttercommunity/plus_plugins/commit/dab92074cbf7dece71a64854b4357eb5b62e2f4f)) +- **FIX**(connectivity_plus): Resolve missing privacy manifest issue for iOS and + MacOS ([#3458](https://github.com/fluttercommunity/plus_plugins/issues/3458)). ([dab92074](https://github.com/fluttercommunity/plus_plugins/commit/dab92074cbf7dece71a64854b4357eb5b62e2f4f)) ## 6.1.2 - - **DOCS**(connectivity_plus): update package requirements ([#3409](https://github.com/fluttercommunity/plus_plugins/issues/3409)). ([cb8c5ead](https://github.com/fluttercommunity/plus_plugins/commit/cb8c5ead41bf8f1d5042a1109eac3e23305d3016)) +- **DOCS**(connectivity_plus): update package + requirements ([#3409](https://github.com/fluttercommunity/plus_plugins/issues/3409)). ([cb8c5ead](https://github.com/fluttercommunity/plus_plugins/commit/cb8c5ead41bf8f1d5042a1109eac3e23305d3016)) ## 6.1.1 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) - - **FIX**(connectivity_plus): macOS Privacy Manifest ([#3390](https://github.com/fluttercommunity/plus_plugins/issues/3390)). ([170703b5](https://github.com/fluttercommunity/plus_plugins/commit/170703b525c5390682fb558235ce699d29923b29)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **FIX**(connectivity_plus): macOS Privacy + Manifest ([#3390](https://github.com/fluttercommunity/plus_plugins/issues/3390)). ([170703b5](https://github.com/fluttercommunity/plus_plugins/commit/170703b525c5390682fb558235ce699d29923b29)) ## 6.1.0 - - **FEAT**(connectivity_plus): Add Swift Package Manager support ([#3173](https://github.com/fluttercommunity/plus_plugins/issues/3173)). ([036afeeb](https://github.com/fluttercommunity/plus_plugins/commit/036afeeb549f24813256f5049def6a6a3740a4f2)) +- **FEAT**(connectivity_plus): Add Swift Package Manager + support ([#3173](https://github.com/fluttercommunity/plus_plugins/issues/3173)). ([036afeeb](https://github.com/fluttercommunity/plus_plugins/commit/036afeeb549f24813256f5049def6a6a3740a4f2)) ## 6.0.5 - - **DOCS**(connectivity_plus): Update plugin requirements in README ([#3160](https://github.com/fluttercommunity/plus_plugins/issues/3160)). ([277f8b6b](https://github.com/fluttercommunity/plus_plugins/commit/277f8b6ba9ee6e7e5e3b1cce3e5eb8416830ba6b)) +- **DOCS**(connectivity_plus): Update plugin requirements in + README ([#3160](https://github.com/fluttercommunity/plus_plugins/issues/3160)). ([277f8b6b](https://github.com/fluttercommunity/plus_plugins/commit/277f8b6ba9ee6e7e5e3b1cce3e5eb8416830ba6b)) ## 6.0.4 - - **CHORE**(connectivity_plus): Use `>=0.5.0 < 2.0.0` version range for package:web. - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **CHORE**(connectivity_plus): Use `>=0.5.0 < 2.0.0` version range for package:web. +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 6.0.3 - - **FIX**(connectivity_plus): Ensure Connectivity on Android is correctly reported when lost ([#2836](https://github.com/fluttercommunity/plus_plugins/issues/2836)). ([2aa6ad7a](https://github.com/fluttercommunity/plus_plugins/commit/2aa6ad7a1c05d35b894e6cef515bd9dfa49351dd)) +- **FIX**(connectivity_plus): Ensure Connectivity on Android is correctly reported when + lost ([#2836](https://github.com/fluttercommunity/plus_plugins/issues/2836)). ([2aa6ad7a](https://github.com/fluttercommunity/plus_plugins/commit/2aa6ad7a1c05d35b894e6cef515bd9dfa49351dd)) ## 6.0.2 - - **REFACTOR**(connectivity_plus): remove ReachabilityConnectivityProvider and ReachabilitySwift dependency ([#2813](https://github.com/fluttercommunity/plus_plugins/issues/2813)). ([f9ad927f](https://github.com/fluttercommunity/plus_plugins/commit/f9ad927f5c18f8ed8d4c22a24476430239c13492)) - - **REFACTOR**(connectivity_plus): Migrate Android example to use the new plugins declaration ([#2771](https://github.com/fluttercommunity/plus_plugins/issues/2771)). ([04200c23](https://github.com/fluttercommunity/plus_plugins/commit/04200c2311e8dd581980ed19f8ebd24d0afd1512)) - - **FIX**(connectivity_plus): WASM-compatible conditional imports ([#2825](https://github.com/fluttercommunity/plus_plugins/issues/2825)). ([6bee4a7e](https://github.com/fluttercommunity/plus_plugins/commit/6bee4a7e02d681ce94d8bd95c4399d844b0ceb27)) - - **FIX**(connectivity_plus): Improve iOS PathMonitorConnectivityProvider implementation and documentation ([#2763](https://github.com/fluttercommunity/plus_plugins/issues/2763)). ([c850d58e](https://github.com/fluttercommunity/plus_plugins/commit/c850d58ed9f422182c8f77583a43bcb13d5d979f)) - - **DOCS**(connectivity_plus): Document supported ConnectivityResult per platform ([#2780](https://github.com/fluttercommunity/plus_plugins/issues/2780)). ([1c4aec01](https://github.com/fluttercommunity/plus_plugins/commit/1c4aec019e74433a2b1174d75522b5abb0c9d9b4)) - - **DOCS**(connectivity_plus): Update README for more clarity ([#2770](https://github.com/fluttercommunity/plus_plugins/issues/2770)). ([8fb738e2](https://github.com/fluttercommunity/plus_plugins/commit/8fb738e2b8f5534db8f1c0fbbeae1a51cf03d099)) - - **DOCS**(connectivity_plus): Specify behavior when there is no connectivity ([#2753](https://github.com/fluttercommunity/plus_plugins/issues/2753)). ([8f132a23](https://github.com/fluttercommunity/plus_plugins/commit/8f132a23a0424299c5e9b946171164bc66710540)) - - **DOCS**(connectivity_plus): Improve documentation onConnectivityChanged method ([#2746](https://github.com/fluttercommunity/plus_plugins/issues/2746)). ([9ea21fbd](https://github.com/fluttercommunity/plus_plugins/commit/9ea21fbdbb9974077375f803f5bb3c57abcb6488)) +- **REFACTOR**(connectivity_plus): remove ReachabilityConnectivityProvider and ReachabilitySwift + dependency ([#2813](https://github.com/fluttercommunity/plus_plugins/issues/2813)). ([f9ad927f](https://github.com/fluttercommunity/plus_plugins/commit/f9ad927f5c18f8ed8d4c22a24476430239c13492)) +- **REFACTOR**(connectivity_plus): Migrate Android example to use the new plugins + declaration ([#2771](https://github.com/fluttercommunity/plus_plugins/issues/2771)). ([04200c23](https://github.com/fluttercommunity/plus_plugins/commit/04200c2311e8dd581980ed19f8ebd24d0afd1512)) +- **FIX**(connectivity_plus): WASM-compatible conditional + imports ([#2825](https://github.com/fluttercommunity/plus_plugins/issues/2825)). ([6bee4a7e](https://github.com/fluttercommunity/plus_plugins/commit/6bee4a7e02d681ce94d8bd95c4399d844b0ceb27)) +- **FIX**(connectivity_plus): Improve iOS PathMonitorConnectivityProvider implementation and + documentation ([#2763](https://github.com/fluttercommunity/plus_plugins/issues/2763)). ([c850d58e](https://github.com/fluttercommunity/plus_plugins/commit/c850d58ed9f422182c8f77583a43bcb13d5d979f)) +- **DOCS**(connectivity_plus): Document supported ConnectivityResult per + platform ([#2780](https://github.com/fluttercommunity/plus_plugins/issues/2780)). ([1c4aec01](https://github.com/fluttercommunity/plus_plugins/commit/1c4aec019e74433a2b1174d75522b5abb0c9d9b4)) +- **DOCS**(connectivity_plus): Update README for more + clarity ([#2770](https://github.com/fluttercommunity/plus_plugins/issues/2770)). ([8fb738e2](https://github.com/fluttercommunity/plus_plugins/commit/8fb738e2b8f5534db8f1c0fbbeae1a51cf03d099)) +- **DOCS**(connectivity_plus): Specify behavior when there is no + connectivity ([#2753](https://github.com/fluttercommunity/plus_plugins/issues/2753)). ([8f132a23](https://github.com/fluttercommunity/plus_plugins/commit/8f132a23a0424299c5e9b946171164bc66710540)) +- **DOCS**(connectivity_plus): Improve documentation onConnectivityChanged + method ([#2746](https://github.com/fluttercommunity/plus_plugins/issues/2746)). ([9ea21fbd](https://github.com/fluttercommunity/plus_plugins/commit/9ea21fbdbb9974077375f803f5bb3c57abcb6488)) ## 6.0.1 @@ -53,17 +70,28 @@ In this release plugin migrated to package:web, meaning that it now supports WASM! -- **BREAKING** **FEAT**(connectivity_plus): support multiple connectivity types at the same time ([#2599](https://github.com/fluttercommunity/plus_plugins/issues/2599)). ([5b477468](https://github.com/fluttercommunity/plus_plugins/commit/5b4774683d6e186fbd69cf4208302221f52aa54d)) -- **BREAKING** **FEAT**(connectivity_plus): Migrate to package:web ([#2621](https://github.com/fluttercommunity/plus_plugins/issues/2621)). ([fbc8e61c](https://github.com/fluttercommunity/plus_plugins/commit/fbc8e61c4f8996d6ba47622de191a83dc2fe1882)) -- **BREAKING** **BUILD**(connectivity_plus): Target Java 17 on Android ([2413e45e](https://github.com/fluttercommunity/plus_plugins/commit/2413e45e88fa6a431c29f8e6240780e20c405453)) -- **BREAKING** **BUILD**(connectivity_plus): Update to target and compile SDK 34 ([#2701](https://github.com/fluttercommunity/plus_plugins/pull/2701)). ([7ddd749](https://github.com/fluttercommunity/plus_plugins/commit/7ddd74989d2921af706f5e7a1aa32e41159ce13f)) -- **BREAKING** **REFACTOR**(connectivity_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2588](https://github.com/fluttercommunity/plus_plugins/issues/2588)). ([f6fe62d5](https://github.com/fluttercommunity/plus_plugins/commit/f6fe62d5f4d87c93e0f974e96bbd47ff453937d9)) -- **FIX**(connectivity_plus): Emit event with types on Android when subscribing to onConnectivityChanged ([#2721](https://github.com/fluttercommunity/plus_plugins/issues/2721)). ([5a81e7ef](https://github.com/fluttercommunity/plus_plugins/commit/5a81e7ef75d75852935f7a095e5b426d534edff9)) -- **FIX**(connectivity_plus): Fix connectivity state update on Android when network is lost ([#2673](https://github.com/fluttercommunity/plus_plugins/issues/2673)). ([21191682](https://github.com/fluttercommunity/plus_plugins/commit/2119168267e436e5900ea09cf68dd110e51b01e0)) -- **FIX**(connectivity_plus): Return valid connection type when only one available ([#2668](https://github.com/fluttercommunity/plus_plugins/issues/2668)). ([81026a4c](https://github.com/fluttercommunity/plus_plugins/commit/81026a4c6c07cb610299a8f17db69c518475a675)) -- **FIX**(connectivity_plus): Add iOS Privacy Info ([#2581](https://github.com/fluttercommunity/plus_plugins/issues/2581)). ([707fab70](https://github.com/fluttercommunity/plus_plugins/commit/707fab70eb1dd262226158be97586a67eec03dd0)) -- **FIX**(connectivity_plus): Fix iOS example app name ([#2722](https://github.com/fluttercommunity/plus_plugins/issues/2722)). ([2441accd](https://github.com/fluttercommunity/plus_plugins/commit/2441accdffc3bc86f5e74db6c682d0dd4fbd6813)) -- **DOCS**(connectivity_plus): Update documentation to address API changes ([#2719](https://github.com/fluttercommunity/plus_plugins/issues/2719)). ([59b9b341](https://github.com/fluttercommunity/plus_plugins/commit/59b9b3417cd0387d8a5f9e857eb350b4048dc68c)) +- **BREAKING** **FEAT**(connectivity_plus): support multiple connectivity types at the same + time ([#2599](https://github.com/fluttercommunity/plus_plugins/issues/2599)). ([5b477468](https://github.com/fluttercommunity/plus_plugins/commit/5b4774683d6e186fbd69cf4208302221f52aa54d)) +- **BREAKING** **FEAT**(connectivity_plus): Migrate to package: + web ([#2621](https://github.com/fluttercommunity/plus_plugins/issues/2621)). ([fbc8e61c](https://github.com/fluttercommunity/plus_plugins/commit/fbc8e61c4f8996d6ba47622de191a83dc2fe1882)) +- **BREAKING** **BUILD**(connectivity_plus): Target Java 17 on + Android ([2413e45e](https://github.com/fluttercommunity/plus_plugins/commit/2413e45e88fa6a431c29f8e6240780e20c405453)) +- **BREAKING** **BUILD**(connectivity_plus): Update to target and compile SDK + 34 ([#2701](https://github.com/fluttercommunity/plus_plugins/pull/2701)). ([7ddd749](https://github.com/fluttercommunity/plus_plugins/commit/7ddd74989d2921af706f5e7a1aa32e41159ce13f)) +- **BREAKING** **REFACTOR**(connectivity_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to + 10.14 ([#2588](https://github.com/fluttercommunity/plus_plugins/issues/2588)). ([f6fe62d5](https://github.com/fluttercommunity/plus_plugins/commit/f6fe62d5f4d87c93e0f974e96bbd47ff453937d9)) +- **FIX**(connectivity_plus): Emit event with types on Android when subscribing to + onConnectivityChanged ([#2721](https://github.com/fluttercommunity/plus_plugins/issues/2721)). ([5a81e7ef](https://github.com/fluttercommunity/plus_plugins/commit/5a81e7ef75d75852935f7a095e5b426d534edff9)) +- **FIX**(connectivity_plus): Fix connectivity state update on Android when network is + lost ([#2673](https://github.com/fluttercommunity/plus_plugins/issues/2673)). ([21191682](https://github.com/fluttercommunity/plus_plugins/commit/2119168267e436e5900ea09cf68dd110e51b01e0)) +- **FIX**(connectivity_plus): Return valid connection type when only one + available ([#2668](https://github.com/fluttercommunity/plus_plugins/issues/2668)). ([81026a4c](https://github.com/fluttercommunity/plus_plugins/commit/81026a4c6c07cb610299a8f17db69c518475a675)) +- **FIX**(connectivity_plus): Add iOS Privacy + Info ([#2581](https://github.com/fluttercommunity/plus_plugins/issues/2581)). ([707fab70](https://github.com/fluttercommunity/plus_plugins/commit/707fab70eb1dd262226158be97586a67eec03dd0)) +- **FIX**(connectivity_plus): Fix iOS example app + name ([#2722](https://github.com/fluttercommunity/plus_plugins/issues/2722)). ([2441accd](https://github.com/fluttercommunity/plus_plugins/commit/2441accdffc3bc86f5e74db6c682d0dd4fbd6813)) +- **DOCS**(connectivity_plus): Update documentation to address API + changes ([#2719](https://github.com/fluttercommunity/plus_plugins/issues/2719)). ([59b9b341](https://github.com/fluttercommunity/plus_plugins/commit/59b9b3417cd0387d8a5f9e857eb350b4048dc68c)) ## 6.0.0 @@ -71,75 +99,87 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 5.0.2 - - **FIX**(connectivity_plus): Return correct connection state on Linux ([#2371](https://github.com/fluttercommunity/plus_plugins/issues/2371)). ([26576d83](https://github.com/fluttercommunity/plus_plugins/commit/26576d838be3b39121fd77ab33f49fc1fff1a97f)) +- **FIX**(connectivity_plus): Return correct connection state on + Linux ([#2371](https://github.com/fluttercommunity/plus_plugins/issues/2371)). ([26576d83](https://github.com/fluttercommunity/plus_plugins/commit/26576d838be3b39121fd77ab33f49fc1fff1a97f)) ## 5.0.1 - - **FIX**(connectivity_plus): Fix CHANGELOG to not mention Kotlin requirement ([#2246](https://github.com/fluttercommunity/plus_plugins/issues/2246)). ([e489d4aa](https://github.com/fluttercommunity/plus_plugins/commit/e489d4aa7a223b152b89b6c33ae994e8a73679bd)) +- **FIX**(connectivity_plus): Fix CHANGELOG to not mention Kotlin + requirement ([#2246](https://github.com/fluttercommunity/plus_plugins/issues/2246)). ([e489d4aa](https://github.com/fluttercommunity/plus_plugins/commit/e489d4aa7a223b152b89b6c33ae994e8a73679bd)) ## 5.0.0 > Note: This release has breaking changes. - - **BREAKING** **FIX**(connectivity_plus): Bump min iOS to 12 to not crash after builds with Xcode 15 ([#2169](https://github.com/fluttercommunity/plus_plugins/issues/2169)). ([cf7d93fb](https://github.com/fluttercommunity/plus_plugins/commit/cf7d93fbfc76830acf2db755543cf4235a49df60)) - - **FIX**(connectivity_plus): Revert bump compileSDK to 34 ([#2229](https://github.com/fluttercommunity/plus_plugins/issues/2229)). ([01df65ce](https://github.com/fluttercommunity/plus_plugins/commit/01df65ce0268093de5dd381c84d251668dc95984)) - - **FEAT**(connectivity_plus): Remove deprecated VALID_ARCHS iOS property ([#2021](https://github.com/fluttercommunity/plus_plugins/issues/2021)). ([ee89d583](https://github.com/fluttercommunity/plus_plugins/commit/ee89d5836c7e598fce07d89e82a2d127ddfacbf8)) - +- **BREAKING** **FIX**(connectivity_plus): Bump min iOS to 12 to not crash after builds with Xcode + 15 ([#2169](https://github.com/fluttercommunity/plus_plugins/issues/2169)). ([cf7d93fb](https://github.com/fluttercommunity/plus_plugins/commit/cf7d93fbfc76830acf2db755543cf4235a49df60)) +- **FIX**(connectivity_plus): Revert bump compileSDK to + 34 ([#2229](https://github.com/fluttercommunity/plus_plugins/issues/2229)). ([01df65ce](https://github.com/fluttercommunity/plus_plugins/commit/01df65ce0268093de5dd381c84d251668dc95984)) +- **FEAT**(connectivity_plus): Remove deprecated VALID_ARCHS iOS + property ([#2021](https://github.com/fluttercommunity/plus_plugins/issues/2021)). ([ee89d583](https://github.com/fluttercommunity/plus_plugins/commit/ee89d5836c7e598fce07d89e82a2d127ddfacbf8)) ## 4.0.2 - - **FIX**(connectivity_plus): Downgrade js version to work with Flutter 3.3.10 ([#1989](https://github.com/fluttercommunity/plus_plugins/issues/1989)). ([42938c0c](https://github.com/fluttercommunity/plus_plugins/commit/42938c0c03132f7f50fa047c2970660d2720d320)) - - **FIX**(connectivity_plus): Regenerate iOS and MacOS example apps ([#1874](https://github.com/fluttercommunity/plus_plugins/issues/1874)). ([fc22e54e](https://github.com/fluttercommunity/plus_plugins/commit/fc22e54ec166d37d4326a9271677054fd34ccc3c)) - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **FIX**(connectivity_plus): Downgrade js version to work with Flutter + 3.3.10 ([#1989](https://github.com/fluttercommunity/plus_plugins/issues/1989)). ([42938c0c](https://github.com/fluttercommunity/plus_plugins/commit/42938c0c03132f7f50fa047c2970660d2720d320)) +- **FIX**(connectivity_plus): Regenerate iOS and MacOS example + apps ([#1874](https://github.com/fluttercommunity/plus_plugins/issues/1874)). ([fc22e54e](https://github.com/fluttercommunity/plus_plugins/commit/fc22e54ec166d37d4326a9271677054fd34ccc3c)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 4.0.1 - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) ## 4.0.0 > Note: This release has breaking changes. - - **CHORE**(connectivity_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(connectivity_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1782). +- **CHORE**(connectivity_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to > + =2.18.0 <4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(connectivity_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update + podspec file (#1782). ## 3.0.6 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 3.0.5 - - **FIX**(connectivity_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1701). +- **FIX**(connectivity_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1701). ## 3.0.4 - - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). - - **DOCS**(connectivity_plus): Documentation added for the missing network interface enums (#1524). +- **REFACTOR**(all): Remove all manual dependency_overrides (#1628). +- **DOCS**(connectivity_plus): Documentation added for the missing network interface enums (#1524). ## 3.0.3 - - **FIX**: Do not return ConnectivityResult.none on iOS and MacOS with VPN (#1335). - - **DOCS**: Updates for READMEs and website pages (#1389). +- **FIX**: Do not return ConnectivityResult.none on iOS and MacOS with VPN (#1335). +- **DOCS**: Updates for READMEs and website pages (#1389). ## 3.0.2 - - **FIX**: Add connectivity_plus_web export (#1278). +- **FIX**: Add connectivity_plus_web export (#1278). ## 3.0.1 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 3.0.0 > Note: This release has breaking changes. - - **FIX**: lint warnings - add missing dependency for tests (#1233). - - **BREAKING** **REFACTOR**: two-package federated architecture (#1227). +- **FIX**: lint warnings - add missing dependency for tests (#1233). +- **BREAKING** **REFACTOR**: two-package federated architecture (#1227). ## 2.3.9 - - **CHORE**: Version tagging using melos. +- **CHORE**: Version tagging using melos. ## 2.3.8 @@ -236,7 +276,8 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 1.0.8 -- Web: Fix to show `ConnectivityResult.mobile` instead of `ConnectivityResult.wifi` when the network is connected to 4g +- Web: Fix to show `ConnectivityResult.mobile` instead of `ConnectivityResult.wifi` when the network + is connected to 4g ## 1.0.7 @@ -285,10 +326,10 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 0.7.2 - Deprecated the following members (use network_info_plus instead): - - getWifiBSSID() - - getWifiIP() - - requestLocationServiceAuthorization() - - getLocationServiceAuthorization() + - getWifiBSSID() + - getWifiIP() + - requestLocationServiceAuthorization() + - getLocationServiceAuthorization() ## 0.7.1 @@ -326,7 +367,8 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 0.4.8+5 -- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). +- Declare API stability and compatibility with `1.0.0` (more details + at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). ## 0.4.8+4 @@ -353,7 +395,8 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 0.4.7 -- Migrate the plugin to use the ConnectivityPlatform.instance defined in the connectivity_plus_platform_interface package. +- Migrate the plugin to use the ConnectivityPlatform.instance defined in the + connectivity_plus_platform_interface package. ## 0.4.6+2 @@ -401,7 +444,8 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 0.4.5+1 -- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to + support apps that has not been migrated to AndroidX. ## 0.4.5 diff --git a/packages/connectivity_plus/connectivity_plus/README.md b/packages/connectivity_plus/connectivity_plus/README.md index 644b63f8c9..bb5e5e5d83 100644 --- a/packages/connectivity_plus/connectivity_plus/README.md +++ b/packages/connectivity_plus/connectivity_plus/README.md @@ -10,15 +10,20 @@ This plugin allows Flutter apps to discover network connectivity types that can > **Note** > -> You should not rely on the current connectivity status to decide whether you can reliably make a network request. Always guard your app code against timeouts and errors that might come from the network layer. -> Connection type availability does not guarantee that there is an Internet access. For example, the plugin might return Wi-Fi connection type, but it might be a connection with no Internet access due to network requirements (like on hotel Wi-Fi networks where user often needs to go through a captive portal to authorize first). +> You should not rely on the current connectivity status to decide whether you can reliably make a +> network request. Always guard your app code against timeouts and errors that might come from the +> network layer. +> Connection type availability does not guarantee that there is an Internet access. For example, the +> plugin might return Wi-Fi connection type, but it might be a connection with no Internet access due +> to network requirements (like on hotel Wi-Fi networks where user often needs to go through a captive +> portal to authorize first). > ## Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ## Requirements @@ -93,8 +98,8 @@ dispose() { The following table shows which `ConnectivityResult` values are supported per platform. -| | Android | iOS | Web | MacOS | Windows | Linux | -|-----------|:-------:|:---:|:---:|:-----:|:-------:|:-----:| +| | Android | iOS | Web | MacOS | Windows | Linux | +|-----------|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:| | wifi | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | bluetooth | :white_check_mark: | | | | | :white_check_mark: | | ethernet | :white_check_mark: | :white_check_mark: | | :white_check_mark: | :white_check_mark: | :white_check_mark: | @@ -106,33 +111,51 @@ _`none` is supported on all platforms by default._ ### Android -Connectivity changes are no longer communicated to Android apps in the background starting with Android O (8.0). You should always check for connectivity status when your app is resumed. The broadcast is only useful when your application is in the foreground. +Connectivity changes are no longer communicated to Android apps in the background starting with +Android O (8.0). You should always check for connectivity status when your app is resumed. The +broadcast is only useful when your application is in the foreground. ### iOS & MacOS -On iOS simulators, the connectivity types stream might not update when Wi-Fi status changes. This is a known issue. +On iOS simulators, the connectivity types stream might not update when Wi-Fi status changes. This is +a known issue. -Starting with iOS 12 and MacOS 10.14, the implementation uses `NWPathMonitor` to obtain the enabled connectivity types. We noticed that this observer can give multiple or unreliable results. For example, reporting connectivity "none" followed by connectivity "wifi" right after reconnecting. +Starting with iOS 12 and MacOS 10.14, the implementation uses `NWPathMonitor` to obtain the enabled +connectivity types. We noticed that this observer can give multiple or unreliable results. For +example, reporting connectivity "none" followed by connectivity "wifi" right after reconnecting. -We recommend to use the `onConnectivityChanged` with this limitation in mind, as the method doesn't filter events, nor it ensures distinct values. +We recommend to use the `onConnectivityChanged` with this limitation in mind, as the method doesn't +filter events, nor it ensures distinct values. ### Web -In order to retrieve information about the quality/speed of a browser's connection, the web implementation of the `connectivity` plugin uses the browser's [**NetworkInformation** Web API](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation), which as of this writing (June 2020) is still "experimental", and not available in all browsers: +In order to retrieve information about the quality/speed of a browser's connection, the web +implementation of the `connectivity` plugin uses the browser's [**NetworkInformation +** Web API](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation), which as of this +writing (June 2020) is still "experimental", and not available in all browsers: ![Data on support for the netinfo feature across the major browsers from caniuse.com](https://caniuse.bitsofco.de/image/netinfo.png) -On desktop browsers, this API only returns a very broad set of connectivity statuses (One of `'slow-2g', '2g', '3g', or '4g'`), and may _not_ provide a Stream of changes. Firefox still hasn't enabled this feature by default. +On desktop browsers, this API only returns a very broad set of connectivity statuses (One of +`'slow-2g', '2g', '3g', or '4g'`), and may _not_ provide a Stream of changes. Firefox still hasn't +enabled this feature by default. **Fallback to `navigator.onLine`** -For those browsers where the NetworkInformation Web API is not available, the plugin falls back to the [**NavigatorOnLine** Web API](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine), which is more broadly supported: +For those browsers where the NetworkInformation Web API is not available, the plugin falls back to +the [**NavigatorOnLine** Web API](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine), +which is more broadly supported: ![Data on support for the online-status feature across the major browsers from caniuse.com](https://caniuse.bitsofco.de/image/online-status.png) -The NavigatorOnLine API is [provided by `dart:html`](https://api.dart.dev/stable/2.7.2/dart-html/Navigator/onLine.html), and only supports a boolean connectivity status (either online or offline), with no network speed information. In those cases the plugin will return either `wifi` (when the browser is online) or `none` (when it's not). +The NavigatorOnLine API is [provided by +`dart:html`](https://api.dart.dev/stable/2.7.2/dart-html/Navigator/onLine.html), and only supports a +boolean connectivity status (either online or offline), with no network speed information. In those +cases the plugin will return either `wifi` (when the browser is online) or `none` (when it's not). -Other than the approximate "downlink" speed, where available, and due to security and privacy concerns, **no Web browser will provide** any specific information about the actual network your users' device is connected to, like **the SSID on a Wi-Fi, or the MAC address of their device.** +Other than the approximate "downlink" speed, where available, and due to security and privacy +concerns, **no Web browser will provide** any specific information about the actual network your +users' device is connected to, like **the SSID on a Wi-Fi, or the MAC address of their device.** ## Learn more diff --git a/packages/connectivity_plus/connectivity_plus/android/build.gradle b/packages/connectivity_plus/connectivity_plus/android/build.gradle index 6d8c5881be..b9347d8eae 100644 --- a/packages/connectivity_plus/connectivity_plus/android/build.gradle +++ b/packages/connectivity_plus/connectivity_plus/android/build.gradle @@ -22,13 +22,13 @@ rootProject.allprojects { apply plugin: 'com.android.library' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.connectivity' compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } defaultConfig { diff --git a/packages/connectivity_plus/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/connectivity_plus/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties index cae4528dfb..c0bc428bc1 100644 --- a/packages/connectivity_plus/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/connectivity_plus/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/connectivity_plus/connectivity_plus/android/src/main/AndroidManifest.xml b/packages/connectivity_plus/connectivity_plus/android/src/main/AndroidManifest.xml index 6435d2cb74..527986591e 100644 --- a/packages/connectivity_plus/connectivity_plus/android/src/main/AndroidManifest.xml +++ b/packages/connectivity_plus/connectivity_plus/android/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ - + package="dev.fluttercommunity.plus.connectivity"> + + diff --git a/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java b/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java index d5e5cbbde2..71b0ec99c0 100644 --- a/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java +++ b/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java @@ -8,114 +8,118 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.os.Build; + import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; + import java.util.ArrayList; import java.util.List; -/** Reports connectivity related information such as connectivity type and wifi information. */ +/** + * Reports connectivity related information such as connectivity type and wifi information. + */ public class Connectivity { - static final String CONNECTIVITY_NONE = "none"; - static final String CONNECTIVITY_WIFI = "wifi"; - static final String CONNECTIVITY_MOBILE = "mobile"; - static final String CONNECTIVITY_ETHERNET = "ethernet"; - static final String CONNECTIVITY_BLUETOOTH = "bluetooth"; - static final String CONNECTIVITY_VPN = "vpn"; - static final String CONNECTIVITY_OTHER = "other"; - private final ConnectivityManager connectivityManager; + static final String CONNECTIVITY_NONE = "none"; + static final String CONNECTIVITY_WIFI = "wifi"; + static final String CONNECTIVITY_MOBILE = "mobile"; + static final String CONNECTIVITY_ETHERNET = "ethernet"; + static final String CONNECTIVITY_BLUETOOTH = "bluetooth"; + static final String CONNECTIVITY_VPN = "vpn"; + static final String CONNECTIVITY_OTHER = "other"; + private final ConnectivityManager connectivityManager; - public Connectivity(ConnectivityManager connectivityManager) { - this.connectivityManager = connectivityManager; - } - - List getNetworkTypes() { - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - Network network = connectivityManager.getActiveNetwork(); - return getCapabilitiesFromNetwork(network); - } else { - // For legacy versions, return a single type as before or adapt similarly if multiple types - // need to be supported - return getNetworkTypesLegacy(); + public Connectivity(ConnectivityManager connectivityManager) { + this.connectivityManager = connectivityManager; } - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - List getCapabilitiesFromNetwork(Network network) { - NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network); - return getCapabilitiesList(capabilities); - } - @NonNull - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - List getCapabilitiesList(NetworkCapabilities capabilities) { - List types = new ArrayList<>(); - if (capabilities == null - || !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { - types.add(CONNECTIVITY_NONE); - return types; - } - if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) - || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) { - types.add(CONNECTIVITY_WIFI); - } - if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { - types.add(CONNECTIVITY_ETHERNET); - } - if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { - types.add(CONNECTIVITY_VPN); + List getNetworkTypes() { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Network network = connectivityManager.getActiveNetwork(); + return getCapabilitiesFromNetwork(network); + } else { + // For legacy versions, return a single type as before or adapt similarly if multiple types + // need to be supported + return getNetworkTypesLegacy(); + } } - if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { - types.add(CONNECTIVITY_MOBILE); - } - if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) { - types.add(CONNECTIVITY_BLUETOOTH); - } - if (types.isEmpty() - && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { - types.add(CONNECTIVITY_OTHER); - } - if (types.isEmpty()) { - types.add(CONNECTIVITY_NONE); + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + List getCapabilitiesFromNetwork(Network network) { + NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network); + return getCapabilitiesList(capabilities); } - return types; - } - @SuppressWarnings("deprecation") - private List getNetworkTypesLegacy() { - // handle type for Android versions less than Android 6 - android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo(); - List types = new ArrayList<>(); - if (info == null || !info.isConnected()) { - types.add(CONNECTIVITY_NONE); - return types; + @NonNull + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + List getCapabilitiesList(NetworkCapabilities capabilities) { + List types = new ArrayList<>(); + if (capabilities == null + || !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + types.add(CONNECTIVITY_NONE); + return types; + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) { + types.add(CONNECTIVITY_WIFI); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { + types.add(CONNECTIVITY_ETHERNET); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { + types.add(CONNECTIVITY_VPN); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + types.add(CONNECTIVITY_MOBILE); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) { + types.add(CONNECTIVITY_BLUETOOTH); + } + if (types.isEmpty() + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + types.add(CONNECTIVITY_OTHER); + } + if (types.isEmpty()) { + types.add(CONNECTIVITY_NONE); + } + return types; } - int type = info.getType(); - switch (type) { - case ConnectivityManager.TYPE_BLUETOOTH: - types.add(CONNECTIVITY_BLUETOOTH); - break; - case ConnectivityManager.TYPE_ETHERNET: - types.add(CONNECTIVITY_ETHERNET); - break; - case ConnectivityManager.TYPE_WIFI: - case ConnectivityManager.TYPE_WIMAX: - types.add(CONNECTIVITY_WIFI); - break; - case ConnectivityManager.TYPE_VPN: - types.add(CONNECTIVITY_VPN); - break; - case ConnectivityManager.TYPE_MOBILE: - case ConnectivityManager.TYPE_MOBILE_DUN: - case ConnectivityManager.TYPE_MOBILE_HIPRI: - types.add(CONNECTIVITY_MOBILE); - break; - default: - types.add(CONNECTIVITY_OTHER); + + @SuppressWarnings("deprecation") + private List getNetworkTypesLegacy() { + // handle type for Android versions less than Android 6 + android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo(); + List types = new ArrayList<>(); + if (info == null || !info.isConnected()) { + types.add(CONNECTIVITY_NONE); + return types; + } + int type = info.getType(); + switch (type) { + case ConnectivityManager.TYPE_BLUETOOTH: + types.add(CONNECTIVITY_BLUETOOTH); + break; + case ConnectivityManager.TYPE_ETHERNET: + types.add(CONNECTIVITY_ETHERNET); + break; + case ConnectivityManager.TYPE_WIFI: + case ConnectivityManager.TYPE_WIMAX: + types.add(CONNECTIVITY_WIFI); + break; + case ConnectivityManager.TYPE_VPN: + types.add(CONNECTIVITY_VPN); + break; + case ConnectivityManager.TYPE_MOBILE: + case ConnectivityManager.TYPE_MOBILE_DUN: + case ConnectivityManager.TYPE_MOBILE_HIPRI: + types.add(CONNECTIVITY_MOBILE); + break; + default: + types.add(CONNECTIVITY_OTHER); + } + return types; } - return types; - } - public ConnectivityManager getConnectivityManager() { - return connectivityManager; - } + public ConnectivityManager getConnectivityManager() { + return connectivityManager; + } } diff --git a/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java b/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java index 324d3d234d..1053e14c8b 100644 --- a/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java +++ b/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java @@ -14,7 +14,9 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; + import io.flutter.plugin.common.EventChannel; + import java.util.List; /** @@ -26,96 +28,96 @@ * to set up the receiver. */ public class ConnectivityBroadcastReceiver extends BroadcastReceiver - implements EventChannel.StreamHandler { - private final Context context; - private final Connectivity connectivity; - private EventChannel.EventSink events; - private final Handler mainHandler = new Handler(Looper.getMainLooper()); - private ConnectivityManager.NetworkCallback networkCallback; - public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + implements EventChannel.StreamHandler { + public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + private final Context context; + private final Connectivity connectivity; + private final Handler mainHandler = new Handler(Looper.getMainLooper()); + private EventChannel.EventSink events; + private ConnectivityManager.NetworkCallback networkCallback; - public ConnectivityBroadcastReceiver(Context context, Connectivity connectivity) { - this.context = context; - this.connectivity = connectivity; - } + public ConnectivityBroadcastReceiver(Context context, Connectivity connectivity) { + this.context = context; + this.connectivity = connectivity; + } - @Override - public void onListen(Object arguments, EventChannel.EventSink events) { - this.events = events; - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - networkCallback = - new ConnectivityManager.NetworkCallback() { - @Override - public void onAvailable(Network network) { - // onAvailable is called when the phone switches to a new network - // e.g. the phone was offline and gets wifi connection - // or the phone was on wifi and now switches to mobile. - // The plugin sends the current capability connection to the users. - sendEvent(connectivity.getCapabilitiesFromNetwork(network)); - } + @Override + public void onListen(Object arguments, EventChannel.EventSink events) { + this.events = events; + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + networkCallback = + new ConnectivityManager.NetworkCallback() { + @Override + public void onAvailable(Network network) { + // onAvailable is called when the phone switches to a new network + // e.g. the phone was offline and gets wifi connection + // or the phone was on wifi and now switches to mobile. + // The plugin sends the current capability connection to the users. + sendEvent(connectivity.getCapabilitiesFromNetwork(network)); + } - @Override - public void onCapabilitiesChanged( - Network network, NetworkCapabilities networkCapabilities) { - // This callback is called multiple times after a call to onAvailable - // this also causes multiple callbacks to the Flutter layer. - sendEvent(connectivity.getCapabilitiesList(networkCapabilities)); - } + @Override + public void onCapabilitiesChanged( + Network network, NetworkCapabilities networkCapabilities) { + // This callback is called multiple times after a call to onAvailable + // this also causes multiple callbacks to the Flutter layer. + sendEvent(connectivity.getCapabilitiesList(networkCapabilities)); + } - @Override - public void onLost(Network network) { - // This callback is called when a capability is lost. - // - // The provided Network object contains information about the - // network capability that has been lost, so we cannot use it. - // - // Instead, post the current network but with a delay long enough - // that we avoid a race condition. - sendCurrentStatusWithDelay(); - } - }; - connectivity.getConnectivityManager().registerDefaultNetworkCallback(networkCallback); - } else { - context.registerReceiver(this, new IntentFilter(CONNECTIVITY_ACTION)); + @Override + public void onLost(Network network) { + // This callback is called when a capability is lost. + // + // The provided Network object contains information about the + // network capability that has been lost, so we cannot use it. + // + // Instead, post the current network but with a delay long enough + // that we avoid a race condition. + sendCurrentStatusWithDelay(); + } + }; + connectivity.getConnectivityManager().registerDefaultNetworkCallback(networkCallback); + } else { + context.registerReceiver(this, new IntentFilter(CONNECTIVITY_ACTION)); + } + // Need to emit first event with connectivity types without waiting for first change in system + // that might happen much later + sendEvent(connectivity.getNetworkTypes()); } - // Need to emit first event with connectivity types without waiting for first change in system - // that might happen much later - sendEvent(connectivity.getNetworkTypes()); - } - @Override - public void onCancel(Object arguments) { - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - if (networkCallback != null) { - connectivity.getConnectivityManager().unregisterNetworkCallback(networkCallback); - networkCallback = null; - } - } else { - try { - context.unregisterReceiver(this); - } catch (Exception e) { - // listen never called, ignore the error - } + @Override + public void onCancel(Object arguments) { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (networkCallback != null) { + connectivity.getConnectivityManager().unregisterNetworkCallback(networkCallback); + networkCallback = null; + } + } else { + try { + context.unregisterReceiver(this); + } catch (Exception e) { + // listen never called, ignore the error + } + } } - } - @Override - public void onReceive(Context context, Intent intent) { - if (events != null) { - events.success(connectivity.getNetworkTypes()); + @Override + public void onReceive(Context context, Intent intent) { + if (events != null) { + events.success(connectivity.getNetworkTypes()); + } } - } - private void sendEvent(List networkTypes) { - Runnable runnable = () -> events.success(networkTypes); - // Emit events on main thread - mainHandler.post(runnable); - } + private void sendEvent(List networkTypes) { + Runnable runnable = () -> events.success(networkTypes); + // Emit events on main thread + mainHandler.post(runnable); + } - private void sendCurrentStatusWithDelay() { - Runnable runnable = () -> events.success(connectivity.getNetworkTypes()); - // Emit events on main thread - // 500 milliseconds to avoid race conditions - mainHandler.postDelayed(runnable, 500); - } + private void sendCurrentStatusWithDelay() { + Runnable runnable = () -> events.success(connectivity.getNetworkTypes()); + // Emit events on main thread + // 500 milliseconds to avoid race conditions + mainHandler.postDelayed(runnable, 500); + } } diff --git a/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java b/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java index e6cfbf1c2f..fb3f1d2b9e 100644 --- a/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java +++ b/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java @@ -5,6 +5,7 @@ package dev.fluttercommunity.plus.connectivity; import androidx.annotation.NonNull; + import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; @@ -15,23 +16,23 @@ */ class ConnectivityMethodChannelHandler implements MethodChannel.MethodCallHandler { - private final Connectivity connectivity; + private final Connectivity connectivity; - /** - * Construct the ConnectivityMethodChannelHandler with a {@code connectivity}. The {@code - * connectivity} must not be null. - */ - ConnectivityMethodChannelHandler(Connectivity connectivity) { - assert (connectivity != null); - this.connectivity = connectivity; - } + /** + * Construct the ConnectivityMethodChannelHandler with a {@code connectivity}. The {@code + * connectivity} must not be null. + */ + ConnectivityMethodChannelHandler(Connectivity connectivity) { + assert (connectivity != null); + this.connectivity = connectivity; + } - @Override - public void onMethodCall(MethodCall call, @NonNull MethodChannel.Result result) { - if ("check".equals(call.method)) { - result.success(connectivity.getNetworkTypes()); - } else { - result.notImplemented(); + @Override + public void onMethodCall(MethodCall call, @NonNull MethodChannel.Result result) { + if ("check".equals(call.method)) { + result.success(connectivity.getNetworkTypes()); + } else { + result.notImplemented(); + } } - } } diff --git a/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java b/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java index 666cfb837e..6a8b52225d 100644 --- a/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java +++ b/packages/connectivity_plus/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java @@ -6,51 +6,55 @@ import android.content.Context; import android.net.ConnectivityManager; + import androidx.annotation.NonNull; + import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.MethodChannel; -/** ConnectivityPlugin */ +/** + * ConnectivityPlugin + */ public class ConnectivityPlugin implements FlutterPlugin { - private MethodChannel methodChannel; - private EventChannel eventChannel; - private ConnectivityBroadcastReceiver receiver; - - @Override - public void onAttachedToEngine(FlutterPluginBinding binding) { - setupChannels(binding.getBinaryMessenger(), binding.getApplicationContext()); - } - - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - teardownChannels(); - } - - private void setupChannels(BinaryMessenger messenger, Context context) { - methodChannel = new MethodChannel(messenger, "dev.fluttercommunity.plus/connectivity"); - eventChannel = new EventChannel(messenger, "dev.fluttercommunity.plus/connectivity_status"); - ConnectivityManager connectivityManager = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - - Connectivity connectivity = new Connectivity(connectivityManager); - - ConnectivityMethodChannelHandler methodChannelHandler = - new ConnectivityMethodChannelHandler(connectivity); - receiver = new ConnectivityBroadcastReceiver(context, connectivity); - - methodChannel.setMethodCallHandler(methodChannelHandler); - eventChannel.setStreamHandler(receiver); - } - - private void teardownChannels() { - methodChannel.setMethodCallHandler(null); - eventChannel.setStreamHandler(null); - receiver.onCancel(null); - methodChannel = null; - eventChannel = null; - receiver = null; - } + private MethodChannel methodChannel; + private EventChannel eventChannel; + private ConnectivityBroadcastReceiver receiver; + + @Override + public void onAttachedToEngine(FlutterPluginBinding binding) { + setupChannels(binding.getBinaryMessenger(), binding.getApplicationContext()); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + teardownChannels(); + } + + private void setupChannels(BinaryMessenger messenger, Context context) { + methodChannel = new MethodChannel(messenger, "dev.fluttercommunity.plus/connectivity"); + eventChannel = new EventChannel(messenger, "dev.fluttercommunity.plus/connectivity_status"); + ConnectivityManager connectivityManager = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + + Connectivity connectivity = new Connectivity(connectivityManager); + + ConnectivityMethodChannelHandler methodChannelHandler = + new ConnectivityMethodChannelHandler(connectivity); + receiver = new ConnectivityBroadcastReceiver(context, connectivity); + + methodChannel.setMethodCallHandler(methodChannelHandler); + eventChannel.setStreamHandler(receiver); + } + + private void teardownChannels() { + methodChannel.setMethodCallHandler(null); + eventChannel.setStreamHandler(null); + receiver.onCancel(null); + methodChannel = null; + eventChannel = null; + receiver = null; + } } diff --git a/packages/connectivity_plus/connectivity_plus/example/analysis_options.yaml b/packages/connectivity_plus/connectivity_plus/example/analysis_options.yaml index 61b6c4de17..ae08714cb1 100644 --- a/packages/connectivity_plus/connectivity_plus/example/analysis_options.yaml +++ b/packages/connectivity_plus/connectivity_plus/example/analysis_options.yaml @@ -22,8 +22,8 @@ linter: # `// ignore_for_file: name_of_lint` syntax on the line or in the file # producing the lint. rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options diff --git a/packages/connectivity_plus/connectivity_plus/example/android/app/build.gradle b/packages/connectivity_plus/connectivity_plus/example/android/app/build.gradle index 3efaaa1a6e..a4cf6e7a01 100644 --- a/packages/connectivity_plus/connectivity_plus/example/android/app/build.gradle +++ b/packages/connectivity_plus/connectivity_plus/example/android/app/build.gradle @@ -27,7 +27,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'io.flutter.plugins.connectivityexample' @@ -43,7 +43,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.connectivityexample" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/packages/connectivity_plus/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java b/packages/connectivity_plus/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java index 0f0dcf2555..feb081653d 100644 --- a/packages/connectivity_plus/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java +++ b/packages/connectivity_plus/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java @@ -5,13 +5,15 @@ package io.flutter.plugins.connectivityexample; import androidx.test.rule.ActivityTestRule; + import dev.flutter.plugins.integration_test.FlutterTestRunner; import io.flutter.embedding.android.FlutterActivity; + import org.junit.Rule; import org.junit.runner.RunWith; @RunWith(FlutterTestRunner.class) public class FlutterActivityTest { - @Rule - public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); } diff --git a/packages/connectivity_plus/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/connectivity_plus/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties index 032437da60..3641ebded3 100644 --- a/packages/connectivity_plus/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/connectivity_plus/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Oct 05 14:43:11 CEST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/connectivity_plus/connectivity_plus/example/android/settings.gradle b/packages/connectivity_plus/connectivity_plus/example/android/settings.gradle index 5fad357a02..c45c7624c3 100644 --- a/packages/connectivity_plus/connectivity_plus/example/android/settings.gradle +++ b/packages/connectivity_plus/connectivity_plus/example/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false + id "com.android.application" version "8.9.0" apply false } include ":app" diff --git a/packages/connectivity_plus/connectivity_plus/example/integration_test/connectivity_plus_test.dart b/packages/connectivity_plus/connectivity_plus/example/integration_test/connectivity_plus_test.dart index fe8cd72f8e..71a7a99262 100644 --- a/packages/connectivity_plus/connectivity_plus/example/integration_test/connectivity_plus_test.dart +++ b/packages/connectivity_plus/connectivity_plus/example/integration_test/connectivity_plus_test.dart @@ -22,33 +22,41 @@ void main() { expect(result, isNotNull); }); - testWidgets('connectivity on Android newer than 5 (API 21) should be wifi', - (WidgetTester tester) async { - final result = await connectivity.checkConnectivity(); + testWidgets( + 'connectivity on Android newer than 5 (API 21) should be wifi', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); - expect(result, [ConnectivityResult.wifi]); - }, - skip: !Platform.isAndroid || - Platform.operatingSystemVersion.contains('5.0.2')); + expect(result, [ConnectivityResult.wifi]); + }, + skip: + !Platform.isAndroid || + Platform.operatingSystemVersion.contains('5.0.2'), + ); - testWidgets('connectivity on Android 5 (API 21) should be mobile', - (WidgetTester tester) async { - final result = await connectivity.checkConnectivity(); + testWidgets( + 'connectivity on Android 5 (API 21) should be mobile', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); - expect(result, [ConnectivityResult.mobile]); - }, - skip: !Platform.isAndroid || - !Platform.operatingSystemVersion.contains('5.0.2')); + expect(result, [ConnectivityResult.mobile]); + }, + skip: + !Platform.isAndroid || + !Platform.operatingSystemVersion.contains('5.0.2'), + ); - testWidgets('connectivity on MacOS should be ethernet', - (WidgetTester tester) async { + testWidgets('connectivity on MacOS should be ethernet', ( + WidgetTester tester, + ) async { final result = await connectivity.checkConnectivity(); expect(result, [ConnectivityResult.ethernet]); }, skip: !Platform.isMacOS); - testWidgets('connectivity on Linux should be none', - (WidgetTester tester) async { + testWidgets('connectivity on Linux should be none', ( + WidgetTester tester, + ) async { final result = await connectivity.checkConnectivity(); expect(result, [ConnectivityResult.other]); diff --git a/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2d..e882ab9889 100644 --- a/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon-App-1024x1024@1x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2fd4..781d7cdcac 100644 --- a/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" + "idiom": "universal", + "filename": "LaunchImage.png", + "scale": "1x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" + "idiom": "universal", + "filename": "LaunchImage@2x.png", + "scale": "2x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" + "idiom": "universal", + "filename": "LaunchImage@3x.png", + "scale": "3x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725b70..d880e1f556 100644 --- a/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/packages/connectivity_plus/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,8 @@ # Launch Screen Assets -You can customize the launch screen with your own desired assets by replacing the image files in this directory. +You can customize the launch screen with your own desired assets by replacing the image files in +this directory. -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file +You can also do it by opening your Flutter project's Xcode project with +`open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and +dropping in the desired images. diff --git a/packages/connectivity_plus/connectivity_plus/example/lib/main.dart b/packages/connectivity_plus/connectivity_plus/example/lib/main.dart index 29927da5dc..5bf298be8a 100644 --- a/packages/connectivity_plus/connectivity_plus/example/lib/main.dart +++ b/packages/connectivity_plus/connectivity_plus/example/lib/main.dart @@ -51,8 +51,9 @@ class _MyHomePageState extends State { super.initState(); initConnectivity(); - _connectivitySubscription = - _connectivity.onConnectivityChanged.listen(_updateConnectionStatus); + _connectivitySubscription = _connectivity.onConnectivityChanged.listen( + _updateConnectionStatus, + ); } @override @@ -109,13 +110,14 @@ class _MyHomePageState extends State { ListView( shrinkWrap: true, children: List.generate( - _connectionStatus.length, - (index) => Center( - child: Text( - _connectionStatus[index].toString(), - style: Theme.of(context).textTheme.headlineSmall, - ), - )), + _connectionStatus.length, + (index) => Center( + child: Text( + _connectionStatus[index].toString(), + style: Theme.of(context).textTheme.headlineSmall, + ), + ), + ), ), const Spacer(flex: 2), ], diff --git a/packages/connectivity_plus/connectivity_plus/example/linux/CMakeLists.txt b/packages/connectivity_plus/connectivity_plus/example/linux/CMakeLists.txt index 279007eb35..c460a20abe 100644 --- a/packages/connectivity_plus/connectivity_plus/example/linux/CMakeLists.txt +++ b/packages/connectivity_plus/connectivity_plus/example/linux/CMakeLists.txt @@ -9,19 +9,19 @@ cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif () # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -37,9 +37,9 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") # Application build add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) target_link_libraries(${BINARY_NAME} PRIVATE flutter) @@ -50,8 +50,8 @@ add_dependencies(${BINARY_NAME} flutter_assemble) # people trying to run the unbundled copy, put it in a subdirectory instead of # the default top-level location. set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) # Generated plugin build rules, which manage building the plugins and adding @@ -63,9 +63,9 @@ include(flutter/generated_plugins.cmake) # By default, "installing" just makes a relocatable bundle in the build # directory. set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () # Start with a clean build bundle directory every time. install(CODE " @@ -76,19 +76,19 @@ set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -97,10 +97,10 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () diff --git a/packages/connectivity_plus/connectivity_plus/example/linux/flutter/CMakeLists.txt b/packages/connectivity_plus/connectivity_plus/example/linux/flutter/CMakeLists.txt index 5b465c7ecf..03e4a7fe4a 100644 --- a/packages/connectivity_plus/connectivity_plus/example/linux/flutter/CMakeLists.txt +++ b/packages/connectivity_plus/connectivity_plus/example/linux/flutter/CMakeLists.txt @@ -12,9 +12,9 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # which isn't available in 3.10. function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) + foreach (element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) + endforeach (element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() @@ -35,38 +35,38 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO - PkgConfig::BLKID + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID ) add_dependencies(flutter flutter_assemble) @@ -75,15 +75,15 @@ add_dependencies(flutter flutter_assemble) # since currently there's no way to get a full input/output list from the # flutter tool. add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} ) diff --git a/packages/connectivity_plus/connectivity_plus/example/linux/main.cc b/packages/connectivity_plus/connectivity_plus/example/linux/main.cc index 8bc1561588..dbe6db8472 100644 --- a/packages/connectivity_plus/connectivity_plus/example/linux/main.cc +++ b/packages/connectivity_plus/connectivity_plus/example/linux/main.cc @@ -1,11 +1,12 @@ #include "my_application.h" int main(int argc, char **argv) { - // Only X11 is currently supported. - // Wayland support is being developed: - // https://github.com/flutter/flutter/issues/57932. - gdk_set_allowed_backends("x11"); + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); + g_autoptr(MyApplication) + app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); } diff --git a/packages/connectivity_plus/connectivity_plus/example/linux/my_application.cc b/packages/connectivity_plus/connectivity_plus/example/linux/my_application.cc index cef2f77145..20cf1fa128 100644 --- a/packages/connectivity_plus/connectivity_plus/example/linux/my_application.cc +++ b/packages/connectivity_plus/connectivity_plus/example/linux/my_application.cc @@ -5,41 +5,43 @@ #include "flutter/generated_plugin_registrant.h" struct _MyApplication { - GtkApplication parent_instance; + GtkApplication parent_instance; }; -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION +) // Implements GApplication::activate. static void my_application_activate(GApplication *application) { - GtkWindow *window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - - FlView *view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) + project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); } static void my_application_class_init(MyApplicationClass *klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->activate = my_application_activate; } -static void my_application_init(MyApplication *self) {} +static void my_application_init(MyApplication * self) {} MyApplication *my_application_new() { - return MY_APPLICATION(g_object_new( - my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); } diff --git a/packages/connectivity_plus/connectivity_plus/example/linux/my_application.h b/packages/connectivity_plus/connectivity_plus/example/linux/my_application.h index 3258a73cf4..5b081e77c6 100644 --- a/packages/connectivity_plus/connectivity_plus/example/linux/my_application.h +++ b/packages/connectivity_plus/connectivity_plus/example/linux/my_application.h @@ -4,7 +4,8 @@ #include G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) + GtkApplication +) /** * my_application_new: diff --git a/packages/connectivity_plus/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/connectivity_plus/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f19f..60e60c947e 100644 --- a/packages/connectivity_plus/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/connectivity_plus/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ + "images": [ { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" }, { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/connectivity_plus/connectivity_plus/example/web/index.html b/packages/connectivity_plus/connectivity_plus/example/web/index.html index 9b7a438f82..b37ec9aceb 100644 --- a/packages/connectivity_plus/connectivity_plus/example/web/index.html +++ b/packages/connectivity_plus/connectivity_plus/example/web/index.html @@ -1,33 +1,33 @@ - - - + + + - - - - - + + + + + - - + + - example - + example + - - - + + diff --git a/packages/connectivity_plus/connectivity_plus/example/web/manifest.json b/packages/connectivity_plus/connectivity_plus/example/web/manifest.json index 8c012917da..037463cc72 100644 --- a/packages/connectivity_plus/connectivity_plus/example/web/manifest.json +++ b/packages/connectivity_plus/connectivity_plus/example/web/manifest.json @@ -1,23 +1,23 @@ { - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] } diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/CMakeLists.txt b/packages/connectivity_plus/connectivity_plus/example/windows/CMakeLists.txt index abf90408ef..5d3a4fe2dc 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/CMakeLists.txt +++ b/packages/connectivity_plus/connectivity_plus/example/windows/CMakeLists.txt @@ -9,17 +9,17 @@ set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() +if (IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else () + if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif () +endif () set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") @@ -31,11 +31,11 @@ add_definitions(-DUNICODE -D_UNICODE) # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -58,27 +58,27 @@ include(flutter/generated_plugins.cmake) set(BUILD_BUNDLE_DIR "$") # Make the "install" step default, as it's required to run. set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -87,9 +87,9 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/flutter/CMakeLists.txt b/packages/connectivity_plus/connectivity_plus/example/windows/flutter/CMakeLists.txt index b02c5485c9..33bff4bf3c 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/flutter/CMakeLists.txt +++ b/packages/connectivity_plus/connectivity_plus/example/windows/flutter/CMakeLists.txt @@ -19,61 +19,61 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") add_dependencies(flutter flutter_assemble) # === Wrapper === list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" + "core_implementations.cc" + "standard_codec.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" + "plugin_registrar.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" + "flutter_engine.cc" + "flutter_view_controller.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") # Wrapper sources needed for a plugin. add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} ) apply_standard_settings(flutter_wrapper_plugin) set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_plugin flutter_assemble) # Wrapper sources needed for the runner. add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} ) apply_standard_settings(flutter_wrapper_app) target_link_libraries(flutter_wrapper_app PUBLIC flutter) target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_app flutter_assemble) @@ -84,20 +84,20 @@ add_dependencies(flutter_wrapper_app flutter_assemble) set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} ) diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/CMakeLists.txt b/packages/connectivity_plus/connectivity_plus/example/windows/runner/CMakeLists.txt index 977e38b5d1..3fdcb0dd27 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/CMakeLists.txt +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/CMakeLists.txt @@ -2,14 +2,14 @@ cmake_minimum_required(VERSION 3.15) project(runner LANGUAGES CXX) add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "run_loop.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" ) apply_standard_settings(${BINARY_NAME}) target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/Runner.rc b/packages/connectivity_plus/connectivity_plus/example/windows/runner/Runner.rc index f414c2d849..5458a8b9bc 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/Runner.rc +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/Runner.rc @@ -1,6 +1,7 @@ // Microsoft Visual C++ generated resource script. // #pragma code_page(65001) + #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS @@ -20,27 +21,27 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// + ///////////////////////////////////////////////////////////////////////////// + // + // TEXTINCLUDE + // -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END + 1 TEXTINCLUDE + BEGIN + "resource.h\0" + END -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END + 2 TEXTINCLUDE + BEGIN + "#include ""winres.h""\r\n" + "\0" + END -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END + 3 TEXTINCLUDE + BEGIN + "\r\n" + "\0" + END #endif // APSTUDIO_INVOKED @@ -73,37 +74,41 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEVERSION VERSION_AS_NUMBER +PRODUCTVERSION VERSION_AS_NUMBER +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG +FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L +FILEFLAGS 0x0L #endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0x0L BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "io.flutter.plugins" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2021 io.flutter.plugins. All rights reserved." "\0" - VALUE "OriginalFilename", "example.exe" "\0" - VALUE "ProductName", "example" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" + BLOCK +"StringFileInfo" +BEGIN + BLOCK +"040904e4" +BEGIN + VALUE +"CompanyName", "io.flutter.plugins" "\0" +VALUE "FileDescription", "A new Flutter project." "\0" +VALUE "FileVersion", VERSION_AS_STRING "\0" +VALUE "InternalName", "example" "\0" +VALUE "LegalCopyright", "Copyright (C) 2021 io.flutter.plugins. All rights reserved." "\0" +VALUE "OriginalFilename", "example.exe" "\0" +VALUE "ProductName", "example" "\0" +VALUE "ProductVersion", VERSION_AS_STRING "\0" +END END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END +BLOCK "VarFileInfo" +BEGIN + VALUE +"Translation", 0x409, 1252 END + END #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/flutter_window.cpp b/packages/connectivity_plus/connectivity_plus/example/windows/runner/flutter_window.cpp index 0f0105d995..c0ae50a354 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/flutter_window.cpp +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/flutter_window.cpp @@ -6,59 +6,64 @@ FlutterWindow::FlutterWindow(RunLoop *run_loop, const flutter::DartProject &project) - : run_loop_(run_loop), project_(project) {} + : run_loop_(run_loop), project_(project) {} FlutterWindow::~FlutterWindow() {} bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } + if (!Win32Window::OnCreate()) { + return false; + } - RECT frame = GetClientArea(); + RECT frame = GetClientArea(); - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - return true; + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; } void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); - flutter_controller_ = nullptr; - } + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } - Win32Window::OnDestroy(); + Win32Window::OnDestroy(); } LRESULT FlutterWindow::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opporutunity to handle window messages. - if (flutter_controller_) { - std::optional result = + LPARAM const lparam) + +noexcept { +// Give Flutter, including plugins, an opporutunity to handle window messages. +if (flutter_controller_) { +std::optional result = flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, lparam); - if (result) { - return *result; - } - } +if (result) { +return * +result; +} +} - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } +switch (message) { +case WM_FONTCHANGE: +flutter_controller_->engine()->ReloadSystemFonts(); +break; +} - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +return +Win32Window::MessageHandler(hwnd, message, wparam, lparam +); } diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/flutter_window.h b/packages/connectivity_plus/connectivity_plus/example/windows/runner/flutter_window.h index 69234d4f5e..da91a8f3f2 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/flutter_window.h +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/flutter_window.h @@ -12,28 +12,33 @@ // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: - // Creates a new FlutterWindow driven by the |run_loop|, hosting a - // Flutter view running |project|. - explicit FlutterWindow(RunLoop *run_loop, - const flutter::DartProject &project); - virtual ~FlutterWindow(); + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + + virtual ~FlutterWindow(); protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; + // Win32Window: + bool OnCreate() override; + + void OnDestroy() override; + + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) + + noexcept override; private: - // The run loop driving events for this window. - RunLoop *run_loop_; + // The run loop driving events for this window. + RunLoop *run_loop_; - // The project to run. - flutter::DartProject project_; + // The project to run. + flutter::DartProject project_; - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; }; #endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/main.cpp b/packages/connectivity_plus/connectivity_plus/example/windows/runner/main.cpp index 098956860e..c92ebc79c9 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/main.cpp +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/main.cpp @@ -6,36 +6,52 @@ #include "run_loop.h" #include "utils.h" -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } +int APIENTRY +wWinMain(_In_ +HINSTANCE instance, _In_opt_ +HINSTANCE prev, + _In_ +wchar_t *command_line, _In_ +int show_command +) { +// Attach to console when present (e.g., 'flutter run') or create a +// new console when running with a debugger. +if (! +::AttachConsole(ATTACH_PARENT_PROCESS) +&& ::IsDebuggerPresent()) { +CreateAndAttachConsole(); - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); +} + +// Initialize COM, so that it is available for use in the library and/or +// plugins. +::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED +); - RunLoop run_loop; +RunLoop run_loop; - flutter::DartProject project(L"data"); +flutter::DartProject project(L"data"); - std::vector command_line_arguments = GetCommandLineArguments(); +std::vector command_line_arguments = GetCommandLineArguments(); - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); +project. +set_dart_entrypoint_arguments(std::move(command_line_arguments) +); + +FlutterWindow window(&run_loop, project); +Win32Window::Point origin(10, 10); +Win32Window::Size size(1280, 720); +if (!window.CreateAndShow(L"example", origin, size)) { +return +EXIT_FAILURE; +} +window.SetQuitOnClose(true); - FlutterWindow window(&run_loop, project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"example", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); +run_loop. - run_loop.Run(); +Run(); - ::CoUninitialize(); - return EXIT_SUCCESS; +::CoUninitialize(); +return +EXIT_SUCCESS; } diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/run_loop.cpp b/packages/connectivity_plus/connectivity_plus/example/windows/runner/run_loop.cpp index 31b89f6229..6ee4580c2e 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/run_loop.cpp +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/run_loop.cpp @@ -9,58 +9,58 @@ RunLoop::RunLoop() {} RunLoop::~RunLoop() {} void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - } } void RunLoop::RegisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.insert(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); } void RunLoop::UnregisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.erase(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); } RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { - TimePoint next_event_time = TimePoint::max(); - for (auto instance : flutter_instances_) { - std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); - if (wait_duration != std::chrono::nanoseconds::max()) { - next_event_time = - std::min(next_event_time, TimePoint::clock::now() + wait_duration); + TimePoint next_event_time = TimePoint::max(); + for (auto instance: flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } } - } - return next_event_time; + return next_event_time; } diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/run_loop.h b/packages/connectivity_plus/connectivity_plus/example/windows/runner/run_loop.h index 7fe1aaccc2..5105e29d76 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/run_loop.h +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/run_loop.h @@ -10,29 +10,31 @@ // as native messages. class RunLoop { public: - RunLoop(); - ~RunLoop(); + RunLoop(); - // Prevent copying - RunLoop(RunLoop const &) = delete; - RunLoop &operator=(RunLoop const &) = delete; + ~RunLoop(); - // Runs the run loop until the application quits. - void Run(); + // Prevent copying + RunLoop(RunLoop const &) = delete; - // Registers the given Flutter instance for event servicing. - void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + RunLoop &operator=(RunLoop const &) = delete; - // Unregisters the given Flutter instance from event servicing. - void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); private: - using TimePoint = std::chrono::steady_clock::time_point; + using TimePoint = std::chrono::steady_clock::time_point; - // Processes all currently pending messages for registered Flutter instances. - TimePoint ProcessFlutterMessages(); + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); - std::set flutter_instances_; + std::set flutter_instances_; }; #endif // RUNNER_RUN_LOOP_H_ diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/utils.cpp b/packages/connectivity_plus/connectivity_plus/example/windows/runner/utils.cpp index 7758aabf38..7113aa377e 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/utils.cpp +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/utils.cpp @@ -8,56 +8,56 @@ #include void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } } -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } - std::vector command_line_arguments; + std::vector command_line_arguments; - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } - ::LocalFree(argv); + ::LocalFree(argv); - return command_line_arguments; + return command_line_arguments; } std::string Utf8FromUtf16(const wchar_t *utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - int target_length = - ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, - nullptr, 0, nullptr, nullptr); - if (target_length == 0) { - return std::string(); - } - std::string utf8_string; - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), - target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; } diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/utils.h b/packages/connectivity_plus/connectivity_plus/example/windows/runner/utils.h index ff43ce2ce5..2deec25811 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/utils.h +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/utils.h @@ -14,6 +14,6 @@ std::string Utf8FromUtf16(const wchar_t *utf16_string); // Gets the command line arguments passed in as a std::vector, // encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); +std::vector GetCommandLineArguments(); #endif // RUNNER_UTILS_H_ diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/win32_window.cpp b/packages/connectivity_plus/connectivity_plus/example/windows/runner/win32_window.cpp index 90ff01e592..b87e3eb19d 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/win32_window.cpp +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/win32_window.cpp @@ -6,33 +6,36 @@ namespace { -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; // The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; + static int g_active_window_count = 0; -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + using EnableNonClientDpiScaling = + BOOL __stdcall(HWND + hwnd); // Scale helper to convert logical scaler values to physical using passed in // scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} + int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); + } // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. // This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { + void EnableFullDpiSupportIfAvailable(HWND + hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); - } +} +auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); +if (enable_non_client_dpi_scaling != nullptr) { +enable_non_client_dpi_scaling(hwnd); +FreeLibrary(user32_module); +} } } // namespace @@ -40,198 +43,228 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { // Manages the Win32Window's window class registration. class WindowClassRegistrar { public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registar instance. - static WindowClassRegistrar *GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; } - return instance_; - } - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t *GetWindowClass(); + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); private: - WindowClassRegistrar() = default; + WindowClassRegistrar() = default; - static WindowClassRegistrar *instance_; + static WindowClassRegistrar *instance_; - bool class_registered_ = false; + bool class_registered_ = false; }; WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; const wchar_t *WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; } void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; } Win32Window::Win32Window() { ++g_active_window_count; } Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); + --g_active_window_count; + Destroy(); } bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, const Size &size) { - Destroy(); + Destroy(); - const wchar_t *window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); - if (!window) { - return false; - } + if (!window) { + return false; + } - return OnCreate(); + return OnCreate(); } // static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window *that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } +LRESULT CALLBACK +Win32Window::WndProc(HWND +const window, +UINT const message, + WPARAM +const wparam, +LPARAM const lparam +) noexcept { +if (message == WM_NCCREATE) { +auto window_struct = reinterpret_cast(lparam); +SetWindowLongPtr(window, GWLP_USERDATA, +reinterpret_cast +(window_struct +->lpCreateParams)); + +auto that = static_cast(window_struct->lpCreateParams); +EnableFullDpiSupportIfAvailable(window); +that-> +window_handle_ = window; +} else if ( +Win32Window *that = GetThisFromHandle(window) +) { +return that-> +MessageHandler(window, message, wparam, lparam +); +} - return DefWindowProc(window, message, wparam, lparam); +return +DefWindowProc(window, message, wparam, lparam +); } LRESULT -Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } + Win32Window::MessageHandler(HWND +hwnd, +UINT const message, WPARAM +const wparam, +LPARAM const lparam +) noexcept { +switch (message) { +case WM_DESTROY: +window_handle_ = nullptr; + +Destroy(); + +if (quit_on_close_) { +PostQuitMessage(0); +} +return 0; - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - } +case WM_DPICHANGED: { +auto newRectSize = reinterpret_cast(lparam); +LONG newWidth = newRectSize->right - newRectSize->left; +LONG newHeight = newRectSize->bottom - newRectSize->top; - return DefWindowProc(window_handle_, message, wparam, lparam); +SetWindowPos(hwnd, nullptr, newRectSize +->left, newRectSize->top, newWidth, +newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + +return 0; +} +case WM_SIZE: { +RECT rect = GetClientArea(); +if (child_content_ != nullptr) { +// Size and position the child window. +MoveWindow(child_content_, rect +.left, rect.top, rect.right - rect.left, +rect.bottom - rect.top, TRUE); +} +return 0; +} + +case WM_ACTIVATE: +if (child_content_ != nullptr) { +SetFocus(child_content_); +} +return 0; +} + +return +DefWindowProc(window_handle_, message, wparam, lparam +); } void Win32Window::Destroy() { - OnDestroy(); + OnDestroy(); - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } } -Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); +Win32Window *Win32Window::GetThisFromHandle(HWND const window) + +noexcept { +return reinterpret_cast( +GetWindowLongPtr(window, GWLP_USERDATA +)); } -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); +void Win32Window::SetChildContent(HWND +content) { +child_content_ = content; +SetParent(content, window_handle_ +); +RECT frame = GetClientArea(); - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); +MoveWindow(content, frame +.left, frame.top, frame.right - frame.left, +frame.bottom - frame.top, true); - SetFocus(child_content_); +SetFocus(child_content_); } RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; } HWND Win32Window::GetHandle() { return window_handle_; } void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; + quit_on_close_ = quit_on_close; } bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; + // No-op; provided for subclasses. + return true; } void Win32Window::OnDestroy() { - // No-op; provided for subclasses. + // No-op; provided for subclasses. } diff --git a/packages/connectivity_plus/connectivity_plus/example/windows/runner/win32_window.h b/packages/connectivity_plus/connectivity_plus/example/windows/runner/win32_window.h index 7b518125bb..f8b5225436 100644 --- a/packages/connectivity_plus/connectivity_plus/example/windows/runner/win32_window.h +++ b/packages/connectivity_plus/connectivity_plus/example/windows/runner/win32_window.h @@ -12,84 +12,97 @@ // rendering and input handling class Win32Window { public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates and shows a win32 window with |title| and position and size using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring &title, const Point &origin, - const Size &size); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); + struct Point { + unsigned int x; + unsigned int y; -protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); + struct Size { + unsigned int width; + unsigned int height; - // Called when Destroy is called. - virtual void OnDestroy(); + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; -private: - friend class WindowClassRegistrar; + Win32Window(); + + virtual ~Win32Window(); - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); - // Retrieves a class instance pointer for |window| - static Win32Window *GetThisFromHandle(HWND const window) noexcept; + // Release OS resources associated with window. + void Destroy(); - bool quit_on_close_ = false; + // Inserts |content| into the window tree. + void SetChildContent(HWND content); - // window handle for top level window. - HWND window_handle_ = nullptr; + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); - // window handle for hosted content. - HWND child_content_ = nullptr; + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) + + noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK + WndProc(HWND + const window, + UINT const message, + WPARAM + const wparam, + LPARAM const lparam + ) + noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) + + noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; }; #endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/connectivity_plus/connectivity_plus/lib/src/web/utils/connectivity_result.dart b/packages/connectivity_plus/connectivity_plus/lib/src/web/utils/connectivity_result.dart index c3250f194c..b1636943fd 100644 --- a/packages/connectivity_plus/connectivity_plus/lib/src/web/utils/connectivity_result.dart +++ b/packages/connectivity_plus/connectivity_plus/lib/src/web/utils/connectivity_result.dart @@ -19,7 +19,8 @@ List networkInformationToConnectivityResult( } List _effectiveTypeToConnectivityResult( - String effectiveType) { + String effectiveType, +) { // Possible values: /*'2g'|'3g'|'4g'|'slow-2g'*/ switch (effectiveType) { diff --git a/packages/connectivity_plus/connectivity_plus/test/connectivity_plus_linux_test.dart b/packages/connectivity_plus/connectivity_plus/test/connectivity_plus_linux_test.dart index b7ecf03cab..dcc4f10574 100644 --- a/packages/connectivity_plus/connectivity_plus/test/connectivity_plus_linux_test.dart +++ b/packages/connectivity_plus/connectivity_plus/test/connectivity_plus_linux_test.dart @@ -18,8 +18,9 @@ void main() { final linux = ConnectivityPlusLinuxPlugin(); linux.createClient = () { final client = MockNetworkManagerClient(); - when(client.connectivity) - .thenReturn(NetworkManagerConnectivityState.full); + when( + client.connectivity, + ).thenReturn(NetworkManagerConnectivityState.full); when(client.primaryConnectionType).thenReturn('bluetooth'); return client; }; @@ -33,8 +34,9 @@ void main() { final linux = ConnectivityPlusLinuxPlugin(); linux.createClient = () { final client = MockNetworkManagerClient(); - when(client.connectivity) - .thenReturn(NetworkManagerConnectivityState.full); + when( + client.connectivity, + ).thenReturn(NetworkManagerConnectivityState.full); when(client.primaryConnectionType).thenReturn('ethernet'); return client; }; @@ -48,8 +50,9 @@ void main() { final linux = ConnectivityPlusLinuxPlugin(); linux.createClient = () { final client = MockNetworkManagerClient(); - when(client.connectivity) - .thenReturn(NetworkManagerConnectivityState.full); + when( + client.connectivity, + ).thenReturn(NetworkManagerConnectivityState.full); when(client.primaryConnectionType).thenReturn('wireless'); return client; }; @@ -63,8 +66,9 @@ void main() { final linux = ConnectivityPlusLinuxPlugin(); linux.createClient = () { final client = MockNetworkManagerClient(); - when(client.connectivity) - .thenReturn(NetworkManagerConnectivityState.full); + when( + client.connectivity, + ).thenReturn(NetworkManagerConnectivityState.full); when(client.primaryConnectionType).thenReturn('vpn'); return client; }; @@ -78,8 +82,9 @@ void main() { final linux = ConnectivityPlusLinuxPlugin(); linux.createClient = () { final client = MockNetworkManagerClient(); - when(client.connectivity) - .thenReturn(NetworkManagerConnectivityState.full); + when( + client.connectivity, + ).thenReturn(NetworkManagerConnectivityState.full); when(client.primaryConnectionType).thenReturn('wireless,vpn'); return client; }; @@ -93,33 +98,39 @@ void main() { final linux = ConnectivityPlusLinuxPlugin(); linux.createClient = () { final client = MockNetworkManagerClient(); - when(client.connectivity) - .thenReturn(NetworkManagerConnectivityState.none); + when( + client.connectivity, + ).thenReturn(NetworkManagerConnectivityState.none); return client; }; - expect(linux.checkConnectivity(), - completion(equals([ConnectivityResult.none]))); + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.none])), + ); }); test('connectivity changes', () { final linux = ConnectivityPlusLinuxPlugin(); linux.createClient = () { final client = MockNetworkManagerClient(); - when(client.connectivity) - .thenReturn(NetworkManagerConnectivityState.full); + when( + client.connectivity, + ).thenReturn(NetworkManagerConnectivityState.full); when(client.primaryConnectionType).thenReturn('wireless'); when(client.propertiesChanged).thenAnswer((_) { - when(client.connectivity) - .thenReturn(NetworkManagerConnectivityState.none); + when( + client.connectivity, + ).thenReturn(NetworkManagerConnectivityState.none); return Stream.value(['Connectivity']); }); return client; }; expect( - linux.onConnectivityChanged, - emitsInOrder([ - [ConnectivityResult.wifi], - [ConnectivityResult.none] - ])); + linux.onConnectivityChanged, + emitsInOrder([ + [ConnectivityResult.wifi], + [ConnectivityResult.none], + ]), + ); }); } diff --git a/packages/connectivity_plus/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart b/packages/connectivity_plus/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart index 9e1ffbcf94..b622939059 100644 --- a/packages/connectivity_plus/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart +++ b/packages/connectivity_plus/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart @@ -38,168 +38,276 @@ class MockNetworkManagerClient extends _i1.Mock @override _i3.Stream<_i2.NetworkManagerDevice> get deviceAdded => - (super.noSuchMethod(Invocation.getter(#deviceAdded), - returnValue: Stream<_i2.NetworkManagerDevice>.empty()) + (super.noSuchMethod( + Invocation.getter(#deviceAdded), + returnValue: Stream<_i2.NetworkManagerDevice>.empty(), + ) as _i3.Stream<_i2.NetworkManagerDevice>); + @override _i3.Stream<_i2.NetworkManagerDevice> get deviceRemoved => - (super.noSuchMethod(Invocation.getter(#deviceRemoved), - returnValue: Stream<_i2.NetworkManagerDevice>.empty()) + (super.noSuchMethod( + Invocation.getter(#deviceRemoved), + returnValue: Stream<_i2.NetworkManagerDevice>.empty(), + ) as _i3.Stream<_i2.NetworkManagerDevice>); + @override _i3.Stream<_i2.NetworkManagerActiveConnection> get activeConnectionAdded => - (super.noSuchMethod(Invocation.getter(#activeConnectionAdded), - returnValue: Stream<_i2.NetworkManagerActiveConnection>.empty()) + (super.noSuchMethod( + Invocation.getter(#activeConnectionAdded), + returnValue: Stream<_i2.NetworkManagerActiveConnection>.empty(), + ) as _i3.Stream<_i2.NetworkManagerActiveConnection>); + @override _i3.Stream<_i2.NetworkManagerActiveConnection> get activeConnectionRemoved => - (super.noSuchMethod(Invocation.getter(#activeConnectionRemoved), - returnValue: Stream<_i2.NetworkManagerActiveConnection>.empty()) + (super.noSuchMethod( + Invocation.getter(#activeConnectionRemoved), + returnValue: Stream<_i2.NetworkManagerActiveConnection>.empty(), + ) as _i3.Stream<_i2.NetworkManagerActiveConnection>); + @override - _i3.Stream> get propertiesChanged => (super.noSuchMethod( - Invocation.getter(#propertiesChanged), - returnValue: Stream>.empty()) as _i3.Stream>); + _i3.Stream> get propertiesChanged => + (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty(), + ) + as _i3.Stream>); + @override List<_i2.NetworkManagerDevice> get devices => - (super.noSuchMethod(Invocation.getter(#devices), - returnValue: <_i2.NetworkManagerDevice>[]) + (super.noSuchMethod( + Invocation.getter(#devices), + returnValue: <_i2.NetworkManagerDevice>[], + ) as List<_i2.NetworkManagerDevice>); + @override List<_i2.NetworkManagerDevice> get allDevices => - (super.noSuchMethod(Invocation.getter(#allDevices), - returnValue: <_i2.NetworkManagerDevice>[]) + (super.noSuchMethod( + Invocation.getter(#allDevices), + returnValue: <_i2.NetworkManagerDevice>[], + ) as List<_i2.NetworkManagerDevice>); + @override bool get networkingEnabled => - (super.noSuchMethod(Invocation.getter(#networkingEnabled), - returnValue: false) as bool); + (super.noSuchMethod( + Invocation.getter(#networkingEnabled), + returnValue: false, + ) + as bool); + @override - bool get wirelessEnabled => (super - .noSuchMethod(Invocation.getter(#wirelessEnabled), returnValue: false) - as bool); + bool get wirelessEnabled => + (super.noSuchMethod( + Invocation.getter(#wirelessEnabled), + returnValue: false, + ) + as bool); + @override bool get wirelessHardwareEnabled => - (super.noSuchMethod(Invocation.getter(#wirelessHardwareEnabled), - returnValue: false) as bool); + (super.noSuchMethod( + Invocation.getter(#wirelessHardwareEnabled), + returnValue: false, + ) + as bool); + @override bool get wwanEnabled => (super.noSuchMethod(Invocation.getter(#wwanEnabled), returnValue: false) as bool); + @override bool get wwanHardwareEnabled => - (super.noSuchMethod(Invocation.getter(#wwanHardwareEnabled), - returnValue: false) as bool); + (super.noSuchMethod( + Invocation.getter(#wwanHardwareEnabled), + returnValue: false, + ) + as bool); + @override List<_i2.NetworkManagerActiveConnection> get activeConnections => - (super.noSuchMethod(Invocation.getter(#activeConnections), - returnValue: <_i2.NetworkManagerActiveConnection>[]) + (super.noSuchMethod( + Invocation.getter(#activeConnections), + returnValue: <_i2.NetworkManagerActiveConnection>[], + ) as List<_i2.NetworkManagerActiveConnection>); + @override String get primaryConnectionType => - (super.noSuchMethod(Invocation.getter(#primaryConnectionType), - returnValue: '') as String); + (super.noSuchMethod( + Invocation.getter(#primaryConnectionType), + returnValue: '', + ) + as String); + @override _i2.NetworkManagerMetered get metered => - (super.noSuchMethod(Invocation.getter(#metered), - returnValue: _i2.NetworkManagerMetered.unknown) + (super.noSuchMethod( + Invocation.getter(#metered), + returnValue: _i2.NetworkManagerMetered.unknown, + ) as _i2.NetworkManagerMetered); + @override bool get startup => (super.noSuchMethod(Invocation.getter(#startup), returnValue: false) as bool); + @override String get version => (super.noSuchMethod(Invocation.getter(#version), returnValue: '') as String); + @override _i2.NetworkManagerConnectivityState get connectivity => - (super.noSuchMethod(Invocation.getter(#connectivity), - returnValue: _i2.NetworkManagerConnectivityState.unknown) + (super.noSuchMethod( + Invocation.getter(#connectivity), + returnValue: _i2.NetworkManagerConnectivityState.unknown, + ) as _i2.NetworkManagerConnectivityState); + @override bool get connectivityCheckAvailable => - (super.noSuchMethod(Invocation.getter(#connectivityCheckAvailable), - returnValue: false) as bool); + (super.noSuchMethod( + Invocation.getter(#connectivityCheckAvailable), + returnValue: false, + ) + as bool); + @override bool get connectivityCheckEnabled => - (super.noSuchMethod(Invocation.getter(#connectivityCheckEnabled), - returnValue: false) as bool); + (super.noSuchMethod( + Invocation.getter(#connectivityCheckEnabled), + returnValue: false, + ) + as bool); + @override String get connectivityCheckUri => - (super.noSuchMethod(Invocation.getter(#connectivityCheckUri), - returnValue: '') as String); + (super.noSuchMethod( + Invocation.getter(#connectivityCheckUri), + returnValue: '', + ) + as String); + @override - _i2.NetworkManagerState get state => (super.noSuchMethod( - Invocation.getter(#state), - returnValue: _i2.NetworkManagerState.unknown) as _i2.NetworkManagerState); + _i2.NetworkManagerState get state => + (super.noSuchMethod( + Invocation.getter(#state), + returnValue: _i2.NetworkManagerState.unknown, + ) + as _i2.NetworkManagerState); + @override _i2.NetworkManagerSettings get settings => - (super.noSuchMethod(Invocation.getter(#settings), - returnValue: _FakeNetworkManagerSettings_0()) + (super.noSuchMethod( + Invocation.getter(#settings), + returnValue: _FakeNetworkManagerSettings_0(), + ) as _i2.NetworkManagerSettings); + @override _i2.NetworkManagerDnsManager get dnsManager => - (super.noSuchMethod(Invocation.getter(#dnsManager), - returnValue: _FakeNetworkManagerDnsManager_1()) + (super.noSuchMethod( + Invocation.getter(#dnsManager), + returnValue: _FakeNetworkManagerDnsManager_1(), + ) as _i2.NetworkManagerDnsManager); + @override _i3.Future connect() => - (super.noSuchMethod(Invocation.method(#connect, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); + (super.noSuchMethod( + Invocation.method(#connect, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); + @override _i3.Future setWirelessEnabled(bool? value) => - (super.noSuchMethod(Invocation.method(#setWirelessEnabled, [value]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); + (super.noSuchMethod( + Invocation.method(#setWirelessEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); + @override _i3.Future setWwanEnabled(bool? value) => - (super.noSuchMethod(Invocation.method(#setWwanEnabled, [value]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); - @override - _i3.Future setConnectivityCheckEnabled(bool? value) => (super - .noSuchMethod(Invocation.method(#setConnectivityCheckEnabled, [value]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); - @override - _i3.Future<_i2.NetworkManagerActiveConnection> addAndActivateConnection( - {Map>? connection = const {}, - _i2.NetworkManagerDevice? device, - _i2.NetworkManagerAccessPoint? accessPoint}) => - (super.noSuchMethod( - Invocation.method(#addAndActivateConnection, [], { - #connection: connection, - #device: device, - #accessPoint: accessPoint - }), - returnValue: Future<_i2.NetworkManagerActiveConnection>.value( - _FakeNetworkManagerActiveConnection_2())) + (super.noSuchMethod( + Invocation.method(#setWwanEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); + + @override + _i3.Future setConnectivityCheckEnabled(bool? value) => + (super.noSuchMethod( + Invocation.method(#setConnectivityCheckEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); + + @override + _i3.Future<_i2.NetworkManagerActiveConnection> addAndActivateConnection({ + Map>? connection = const {}, + _i2.NetworkManagerDevice? device, + _i2.NetworkManagerAccessPoint? accessPoint, + }) => + (super.noSuchMethod( + Invocation.method(#addAndActivateConnection, [], { + #connection: connection, + #device: device, + #accessPoint: accessPoint, + }), + returnValue: Future<_i2.NetworkManagerActiveConnection>.value( + _FakeNetworkManagerActiveConnection_2(), + ), + ) as _i3.Future<_i2.NetworkManagerActiveConnection>); + @override - _i3.Future<_i2.NetworkManagerActiveConnection> activateConnection( - {_i2.NetworkManagerDevice? device, - _i2.NetworkManagerSettingsConnection? connection, - _i2.NetworkManagerAccessPoint? accessPoint}) => - (super.noSuchMethod( - Invocation.method(#activateConnection, [], { - #device: device, - #connection: connection, - #accessPoint: accessPoint - }), - returnValue: Future<_i2.NetworkManagerActiveConnection>.value( - _FakeNetworkManagerActiveConnection_2())) + _i3.Future<_i2.NetworkManagerActiveConnection> activateConnection({ + _i2.NetworkManagerDevice? device, + _i2.NetworkManagerSettingsConnection? connection, + _i2.NetworkManagerAccessPoint? accessPoint, + }) => + (super.noSuchMethod( + Invocation.method(#activateConnection, [], { + #device: device, + #connection: connection, + #accessPoint: accessPoint, + }), + returnValue: Future<_i2.NetworkManagerActiveConnection>.value( + _FakeNetworkManagerActiveConnection_2(), + ), + ) as _i3.Future<_i2.NetworkManagerActiveConnection>); + @override _i3.Future deactivateConnection( - _i2.NetworkManagerActiveConnection? connection) => + _i2.NetworkManagerActiveConnection? connection, + ) => (super.noSuchMethod( - Invocation.method(#deactivateConnection, [connection]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); + Invocation.method(#deactivateConnection, [connection]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); + @override - _i3.Future close() => (super.noSuchMethod(Invocation.method(#close, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i3.Future); + _i3.Future close() => + (super.noSuchMethod( + Invocation.method(#close, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value(), + ) + as _i3.Future); } diff --git a/packages/connectivity_plus/connectivity_plus/test/connectivity_test.dart b/packages/connectivity_plus/connectivity_plus/test/connectivity_test.dart index 4f177c0f31..0700ceaece 100644 --- a/packages/connectivity_plus/connectivity_plus/test/connectivity_test.dart +++ b/packages/connectivity_plus/connectivity_plus/test/connectivity_test.dart @@ -9,7 +9,7 @@ import 'package:plugin_platform_interface/plugin_platform_interface.dart'; import 'package:mockito/mockito.dart'; const List kCheckConnectivityResult = [ - ConnectivityResult.wifi + ConnectivityResult.wifi, ]; void main() { diff --git a/packages/connectivity_plus/connectivity_plus/windows/CMakeLists.txt b/packages/connectivity_plus/connectivity_plus/windows/CMakeLists.txt index ac315ccdc9..7a8aa0bfc0 100644 --- a/packages/connectivity_plus/connectivity_plus/windows/CMakeLists.txt +++ b/packages/connectivity_plus/connectivity_plus/windows/CMakeLists.txt @@ -7,23 +7,23 @@ project(${PROJECT_NAME} LANGUAGES CXX) set(PLUGIN_NAME "connectivity_plus_plugin") add_library(${PLUGIN_NAME} SHARED - "connectivity_plus_plugin.cpp" - "network_manager.cpp" + "connectivity_plus_plugin.cpp" + "network_manager.cpp" ) apply_standard_settings(${PLUGIN_NAME}) set_target_properties(${PLUGIN_NAME} PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") + "${CMAKE_CURRENT_SOURCE_DIR}/include") target_link_libraries(${PLUGIN_NAME} PRIVATE - flutter - flutter_wrapper_plugin - iphlpapi + flutter + flutter_wrapper_plugin + iphlpapi ) # List of absolute paths to libraries that should be bundled with the plugin set(connectivity_plus_bundled_libraries - "" - PARENT_SCOPE + "" + PARENT_SCOPE ) diff --git a/packages/connectivity_plus/connectivity_plus/windows/connectivity_plus_plugin.cpp b/packages/connectivity_plus/connectivity_plus/windows/connectivity_plus_plugin.cpp index cb6ae1f936..58680ae8cb 100644 --- a/packages/connectivity_plus/connectivity_plus/windows/connectivity_plus_plugin.cpp +++ b/packages/connectivity_plus/connectivity_plus/windows/connectivity_plus_plugin.cpp @@ -15,175 +15,177 @@ namespace { -typedef flutter::EventChannel FlEventChannel; -typedef flutter::EventSink FlEventSink; -typedef flutter::MethodCall FlMethodCall; -typedef flutter::MethodResult FlMethodResult; -typedef flutter::MethodChannel FlMethodChannel; -typedef flutter::StreamHandler FlStreamHandler; -typedef flutter::StreamHandlerError - FlStreamHandlerError; - -class ConnectivityPlusWindowsPlugin : public flutter::Plugin { -public: - ConnectivityPlusWindowsPlugin(); - virtual ~ConnectivityPlusWindowsPlugin(); - - std::shared_ptr GetManager() const; - - static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); - -private: - void HandleMethodCall(const FlMethodCall &method_call, - std::unique_ptr result); - - std::shared_ptr manager; -}; - -class ConnectivityStreamHandler : public FlStreamHandler { -public: - ConnectivityStreamHandler(std::shared_ptr manager); - virtual ~ConnectivityStreamHandler(); - -protected: - void AddConnectivityEvent(); - - std::unique_ptr - OnListenInternal(const flutter::EncodableValue *arguments, - std::unique_ptr &&sink) override; - - std::unique_ptr - OnCancelInternal(const flutter::EncodableValue *arguments) override; - -private: - std::shared_ptr manager; - std::unique_ptr sink; -}; - -ConnectivityPlusWindowsPlugin::ConnectivityPlusWindowsPlugin() { - manager = std::make_shared(); - manager->Init(); -} - -ConnectivityPlusWindowsPlugin::~ConnectivityPlusWindowsPlugin() { - manager->Cleanup(); -} - -std::shared_ptr -ConnectivityPlusWindowsPlugin::GetManager() const { - return manager; -} - -void ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( - flutter::PluginRegistrarWindows *registrar) { - auto plugin = std::make_unique(); - - auto methodChannel = - std::make_unique>( - registrar->messenger(), "dev.fluttercommunity.plus/connectivity", - &flutter::StandardMethodCodec::GetInstance()); - - methodChannel->SetMethodCallHandler( - [plugin_pointer = plugin.get()](const auto &call, auto result) { - plugin_pointer->HandleMethodCall(call, std::move(result)); - }); - - auto eventChannel = std::make_unique( - registrar->messenger(), "dev.fluttercommunity.plus/connectivity_status", - &flutter::StandardMethodCodec::GetInstance()); - - eventChannel->SetStreamHandler( - std::make_unique(plugin->GetManager())); - - registrar->AddPlugin(std::move(plugin)); -} - -static std::string ConnectivityToString(ConnectivityType connectivityType) { - switch (connectivityType) { - case ConnectivityType::WiFi: - return "wifi"; - case ConnectivityType::Ethernet: - return "ethernet"; - case ConnectivityType::VPN: - return "vpn"; - case ConnectivityType::Other: - return "other"; - case ConnectivityType::None: - default: - return "none"; - } -} - -static flutter::EncodableList -EncodeConnectivityTypes(std::set connectivityTypes) { - flutter::EncodableList encodedList; - - if (connectivityTypes.empty()) { - encodedList.push_back( - flutter::EncodableValue(ConnectivityToString(ConnectivityType::None))); - return encodedList; - } - - for (const auto &type : connectivityTypes) { - std::string connectivityString = ConnectivityToString(type); - encodedList.push_back(flutter::EncodableValue(connectivityString)); - } - - return encodedList; -} - -void ConnectivityPlusWindowsPlugin::HandleMethodCall( - const flutter::MethodCall &method_call, - std::unique_ptr> result) { - if (method_call.method_name().compare("check") == 0) { - result->Success(EncodeConnectivityTypes(manager->GetConnectivityTypes())); - } else { - result->NotImplemented(); - } -} - -ConnectivityStreamHandler::ConnectivityStreamHandler( - std::shared_ptr manager) - : manager(manager) {} - -ConnectivityStreamHandler::~ConnectivityStreamHandler() {} - -void ConnectivityStreamHandler::AddConnectivityEvent() { - sink->Success(EncodeConnectivityTypes(manager->GetConnectivityTypes())); -} - -std::unique_ptr -ConnectivityStreamHandler::OnListenInternal( - const flutter::EncodableValue *arguments, - std::unique_ptr &&events) { - sink = std::move(events); - - auto callback = - std::bind(&ConnectivityStreamHandler::AddConnectivityEvent, this); - - if (!manager->StartListen(callback)) { - return std::make_unique( - std::to_string(manager->GetError()), "NetworkManager::StartListen", - nullptr); - } - - AddConnectivityEvent(); - return nullptr; -} - -std::unique_ptr -ConnectivityStreamHandler::OnCancelInternal( - const flutter::EncodableValue *arguments) { - manager->StopListen(); - sink.reset(); - return nullptr; -} + typedef flutter::EventChannel FlEventChannel; + typedef flutter::EventSink FlEventSink; + typedef flutter::MethodCall FlMethodCall; + typedef flutter::MethodResult FlMethodResult; + typedef flutter::MethodChannel FlMethodChannel; + typedef flutter::StreamHandler FlStreamHandler; + typedef flutter::StreamHandlerError + FlStreamHandlerError; + + class ConnectivityPlusWindowsPlugin : public flutter::Plugin { + public: + ConnectivityPlusWindowsPlugin(); + + virtual ~ConnectivityPlusWindowsPlugin(); + + std::shared_ptr GetManager() const; + + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + + private: + void HandleMethodCall(const FlMethodCall &method_call, + std::unique_ptr result); + + std::shared_ptr manager; + }; + + class ConnectivityStreamHandler : public FlStreamHandler { + public: + ConnectivityStreamHandler(std::shared_ptr manager); + + virtual ~ConnectivityStreamHandler(); + + protected: + void AddConnectivityEvent(); + + std::unique_ptr + OnListenInternal(const flutter::EncodableValue *arguments, + std::unique_ptr &&sink) override; + + std::unique_ptr + OnCancelInternal(const flutter::EncodableValue *arguments) override; + + private: + std::shared_ptr manager; + std::unique_ptr sink; + }; + + ConnectivityPlusWindowsPlugin::ConnectivityPlusWindowsPlugin() { + manager = std::make_shared(); + manager->Init(); + } + + ConnectivityPlusWindowsPlugin::~ConnectivityPlusWindowsPlugin() { + manager->Cleanup(); + } + + std::shared_ptr + ConnectivityPlusWindowsPlugin::GetManager() const { + return manager; + } + + void ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + auto plugin = std::make_unique(); + + auto methodChannel = + std::make_unique < flutter::MethodChannel < flutter::EncodableValue >> ( + registrar->messenger(), "dev.fluttercommunity.plus/connectivity", + &flutter::StandardMethodCodec::GetInstance()); + + methodChannel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + + auto eventChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/connectivity_status", + &flutter::StandardMethodCodec::GetInstance()); + + eventChannel->SetStreamHandler( + std::make_unique(plugin->GetManager())); + + registrar->AddPlugin(std::move(plugin)); + } + + static std::string ConnectivityToString(ConnectivityType connectivityType) { + switch (connectivityType) { + case ConnectivityType::WiFi: + return "wifi"; + case ConnectivityType::Ethernet: + return "ethernet"; + case ConnectivityType::VPN: + return "vpn"; + case ConnectivityType::Other: + return "other"; + case ConnectivityType::None: + default: + return "none"; + } + } + + static flutter::EncodableList + EncodeConnectivityTypes(std::set connectivityTypes) { + flutter::EncodableList encodedList; + + if (connectivityTypes.empty()) { + encodedList.push_back( + flutter::EncodableValue(ConnectivityToString(ConnectivityType::None))); + return encodedList; + } + + for (const auto &type: connectivityTypes) { + std::string connectivityString = ConnectivityToString(type); + encodedList.push_back(flutter::EncodableValue(connectivityString)); + } + + return encodedList; + } + + void ConnectivityPlusWindowsPlugin::HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr > result) { + if (method_call.method_name().compare("check") == 0) { + result->Success(EncodeConnectivityTypes(manager->GetConnectivityTypes())); + } else { + result->NotImplemented(); + } + } + + ConnectivityStreamHandler::ConnectivityStreamHandler( + std::shared_ptr manager) + : manager(manager) {} + + ConnectivityStreamHandler::~ConnectivityStreamHandler() {} + + void ConnectivityStreamHandler::AddConnectivityEvent() { + sink->Success(EncodeConnectivityTypes(manager->GetConnectivityTypes())); + } + + std::unique_ptr + ConnectivityStreamHandler::OnListenInternal( + const flutter::EncodableValue *arguments, + std::unique_ptr &&events) { + sink = std::move(events); + + auto callback = + std::bind(&ConnectivityStreamHandler::AddConnectivityEvent, this); + + if (!manager->StartListen(callback)) { + return std::make_unique( + std::to_string(manager->GetError()), "NetworkManager::StartListen", + nullptr); + } + + AddConnectivityEvent(); + return nullptr; + } + + std::unique_ptr + ConnectivityStreamHandler::OnCancelInternal( + const flutter::EncodableValue *arguments) { + manager->StopListen(); + sink.reset(); + return nullptr; + } } // namespace void ConnectivityPlusWindowsPluginRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar) { - ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( - flutter::PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar)); + FlutterDesktopPluginRegistrarRef registrar) { + ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); } diff --git a/packages/connectivity_plus/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h b/packages/connectivity_plus/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h index 17af447443..72debed11b 100644 --- a/packages/connectivity_plus/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h +++ b/packages/connectivity_plus/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h @@ -14,7 +14,7 @@ extern "C" { #endif FLUTTER_PLUGIN_EXPORT void ConnectivityPlusWindowsPluginRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar); + FlutterDesktopPluginRegistrarRef registrar); #if defined(__cplusplus) } // extern "C" diff --git a/packages/connectivity_plus/connectivity_plus/windows/include/connectivity_plus/network_manager.h b/packages/connectivity_plus/connectivity_plus/windows/include/connectivity_plus/network_manager.h index 19394fec82..ade4d659bd 100644 --- a/packages/connectivity_plus/connectivity_plus/windows/include/connectivity_plus/network_manager.h +++ b/packages/connectivity_plus/connectivity_plus/windows/include/connectivity_plus/network_manager.h @@ -10,9 +10,12 @@ #include #include -enum class ConnectivityType { None, Ethernet, WiFi, Other, VPN }; +enum class ConnectivityType { + None, Ethernet, WiFi, Other, VPN +}; class NetworkListener; + struct IConnectionPoint; struct IConnectionPointContainer; struct INetworkListManager; @@ -22,29 +25,33 @@ typedef std::function NetworkCallback; class NetworkManager { public: - NetworkManager(); - ~NetworkManager(); + NetworkManager(); + + ~NetworkManager(); + + bool Init(); + + void Cleanup(); + + std::set GetConnectivityTypes() const; - bool Init(); - void Cleanup(); + bool StartListen(NetworkCallback pCallback); - std::set GetConnectivityTypes() const; + void StopListen(); - bool StartListen(NetworkCallback pCallback); - void StopListen(); + bool HasError() const; - bool HasError() const; - int GetError() const; + int GetError() const; private: - std::vector GetConnectedAdapterIds() const; - - DWORD dwCookie = 0; - IUnknown *pUnknown = NULL; - INetworkListManager *pNetworkListManager = NULL; - IConnectionPointContainer *pCPContainer = NULL; - IConnectionPoint *pConnectPoint = NULL; - NetworkListener *pListener = NULL; + std::vector GetConnectedAdapterIds() const; + + DWORD dwCookie = 0; + IUnknown *pUnknown = NULL; + INetworkListManager *pNetworkListManager = NULL; + IConnectionPointContainer *pCPContainer = NULL; + IConnectionPoint *pConnectPoint = NULL; + NetworkListener *pListener = NULL; }; #endif // NETWORK_MANAGER_H diff --git a/packages/connectivity_plus/connectivity_plus/windows/network_manager.cpp b/packages/connectivity_plus/connectivity_plus/windows/network_manager.cpp index 31822c5590..aa7368a506 100644 --- a/packages/connectivity_plus/connectivity_plus/windows/network_manager.cpp +++ b/packages/connectivity_plus/connectivity_plus/windows/network_manager.cpp @@ -20,231 +20,250 @@ class NetworkListener final : public INetworkEvents { public: - NetworkListener(NetworkCallback pCb) : pCallback(pCb) {} - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { - AddRef(); - - HRESULT hr = S_OK; - if (IsEqualIID(riid, IID_IUnknown)) { - *ppvObject = (IUnknown *)this; - } else if (IsEqualIID(riid, IID_INetworkEvents)) { - *ppvObject = (INetworkEvents *)this; - } else { - hr = E_NOINTERFACE; + NetworkListener(NetworkCallback pCb) : pCallback(pCb) {} + + HRESULT STDMETHODCALLTYPE + QueryInterface(REFIID + riid, + void **ppvObject + ) { + AddRef(); + + HRESULT hr = S_OK; + if (IsEqualIID(riid, IID_IUnknown)) { + *ppvObject = (IUnknown *) this; + } else if (IsEqualIID(riid, IID_INetworkEvents)) { + *ppvObject = (INetworkEvents * ) + this; + } else { + hr = E_NOINTERFACE; + } + return hr; } - return hr; - } - ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&lRef); } + ULONG STDMETHODCALLTYPE - ULONG STDMETHODCALLTYPE Release() { - LONG lAddend = InterlockedDecrement(&lRef); - if (lRef == 0) { - delete this; - } - return lAddend; - } + AddRef() { return InterlockedIncrement(&lRef); } - HRESULT STDMETHODCALLTYPE NetworkAdded(GUID networkId) { return S_OK; } + ULONG STDMETHODCALLTYPE - HRESULT STDMETHODCALLTYPE - NetworkConnectivityChanged(GUID networkId, NLM_CONNECTIVITY newConnectivity) { - Callback(); - return S_OK; - } + Release() { + LONG lAddend = InterlockedDecrement(&lRef); + if (lRef == 0) { + delete this; + } + return lAddend; + } - HRESULT STDMETHODCALLTYPE NetworkDeleted(GUID networkId) { return S_OK; } + HRESULT STDMETHODCALLTYPE + NetworkAdded(GUID + networkId) { return S_OK; } + + HRESULT STDMETHODCALLTYPE + NetworkConnectivityChanged(GUID + networkId, + NLM_CONNECTIVITY newConnectivity + ) { + Callback(); + return S_OK; + } - HRESULT STDMETHODCALLTYPE - NetworkPropertyChanged(GUID networkId, NLM_NETWORK_PROPERTY_CHANGE flags) { - if (flags & NLM_NETWORK_PROPERTY_CHANGE_CONNECTION) { - Callback(); + HRESULT STDMETHODCALLTYPE + NetworkDeleted(GUID + networkId) { return S_OK; } + + HRESULT STDMETHODCALLTYPE + NetworkPropertyChanged(GUID + networkId, + NLM_NETWORK_PROPERTY_CHANGE flags + ) { + if (flags & NLM_NETWORK_PROPERTY_CHANGE_CONNECTION) { + Callback(); + } + return S_OK; } - return S_OK; - } - void Callback() { - assert(pCallback); - pCallback(); - } + void Callback() { + assert(pCallback); + pCallback(); + } private: - volatile LONG lRef = 1; - NetworkCallback pCallback = nullptr; + volatile LONG lRef = 1; + NetworkCallback pCallback = nullptr; }; NetworkManager::NetworkManager() {} NetworkManager::~NetworkManager() { - StopListen(); - Cleanup(); + StopListen(); + Cleanup(); } bool NetworkManager::Init() { - CoInitialize(NULL); - - HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, - IID_IUnknown, (void **)&pUnknown); - if (SUCCEEDED(hr)) { - hr = pUnknown->QueryInterface(IID_INetworkListManager, - (void **)&pNetworkListManager); - } - return SUCCEEDED(hr); + CoInitialize(NULL); + + HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, + IID_IUnknown, (void **) &pUnknown); + if (SUCCEEDED(hr)) { + hr = pUnknown->QueryInterface(IID_INetworkListManager, + (void **) &pNetworkListManager); + } + return SUCCEEDED(hr); } void NetworkManager::Cleanup() { - if (pNetworkListManager) { - pNetworkListManager->Release(); - pNetworkListManager = NULL; - } + if (pNetworkListManager) { + pNetworkListManager->Release(); + pNetworkListManager = NULL; + } - if (pUnknown) { - pUnknown->Release(); - pUnknown = NULL; - } + if (pUnknown) { + pUnknown->Release(); + pUnknown = NULL; + } - CoUninitialize(); + CoUninitialize(); } -std::vector NetworkManager::GetConnectedAdapterIds() const { - std::vector adapterIds; - - IEnumNetworkConnections *connections = NULL; - HRESULT hr = pNetworkListManager->GetNetworkConnections(&connections); - if (hr == S_OK) { - while (true) { - INetworkConnection *connection = NULL; - hr = connections->Next(1, &connection, NULL); - if (hr != S_OK) { - break; - } - - VARIANT_BOOL isConnected = VARIANT_FALSE; - hr = connection->get_IsConnectedToInternet(&isConnected); - if (hr == S_OK && isConnected == VARIANT_TRUE) { - GUID guid; - hr = connection->GetAdapterId(&guid); - if (hr == S_OK) { - adapterIds.push_back(std::move(guid)); +std::vector NetworkManager::GetConnectedAdapterIds() const { + std::vector adapterIds; + + IEnumNetworkConnections *connections = NULL; + HRESULT hr = pNetworkListManager->GetNetworkConnections(&connections); + if (hr == S_OK) { + while (true) { + INetworkConnection *connection = NULL; + hr = connections->Next(1, &connection, NULL); + if (hr != S_OK) { + break; + } + + VARIANT_BOOL isConnected = VARIANT_FALSE; + hr = connection->get_IsConnectedToInternet(&isConnected); + if (hr == S_OK && isConnected == VARIANT_TRUE) { + GUID guid; + hr = connection->GetAdapterId(&guid); + if (hr == S_OK) { + adapterIds.push_back(std::move(guid)); + } + } + connection->Release(); } - } - connection->Release(); + connections->Release(); } - connections->Release(); - } - return adapterIds; + return adapterIds; } -std::set NetworkManager::GetConnectivityTypes() const { - ULONG bufferSize = 15 * 1024; - ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | - GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | - GAA_FLAG_SKIP_FRIENDLY_NAME; - std::vector buffer(bufferSize); - PIP_ADAPTER_ADDRESSES addresses = - reinterpret_cast(&buffer.front()); - DWORD rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); - if (rc == ERROR_BUFFER_OVERFLOW) { - buffer.resize(bufferSize); - addresses = reinterpret_cast(&buffer.front()); - rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); - } - - if (rc != NO_ERROR) { - return {ConnectivityType::None}; - } - - std::vector adapterIds = GetConnectedAdapterIds(); - if (adapterIds.empty()) { - return {ConnectivityType::None}; - } - - std::set connectivities; - for (; addresses != NULL; addresses = addresses->Next) { - NET_LUID luid; - rc = ConvertInterfaceIndexToLuid(addresses->IfIndex, &luid); - if (rc != NO_ERROR) { - continue; +std::set NetworkManager::GetConnectivityTypes() const { + ULONG bufferSize = 15 * 1024; + ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME; + std::vector buffer(bufferSize); + PIP_ADAPTER_ADDRESSES addresses = + reinterpret_cast(&buffer.front()); + DWORD rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); + if (rc == ERROR_BUFFER_OVERFLOW) { + buffer.resize(bufferSize); + addresses = reinterpret_cast(&buffer.front()); + rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); } - GUID guid; - rc = ConvertInterfaceLuidToGuid(&luid, &guid); if (rc != NO_ERROR) { - continue; - } - - if (std::find(adapterIds.begin(), adapterIds.end(), guid) != - adapterIds.end()) { - // Read more at - // https://learn.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-ip_adapter_addresses_lh - switch (addresses->IfType) { - case IF_TYPE_ETHERNET_CSMACD: - case IF_TYPE_IEEE1394: - connectivities.insert(ConnectivityType::Ethernet); - break; - case IF_TYPE_IEEE80211: - connectivities.insert(ConnectivityType::WiFi); - break; - case IF_TYPE_TUNNEL: - case IF_TYPE_PPP: - connectivities.insert(ConnectivityType::VPN); - break; - default: - connectivities.insert(ConnectivityType::Other); - break; - } - } - } - - if (connectivities.empty()) { - // If no specific connectivity types were found, return a set containing - // only None - return {ConnectivityType::None}; - } - - // Return the set of detected connectivity types - return connectivities; + return {ConnectivityType::None}; + } + + std::vector adapterIds = GetConnectedAdapterIds(); + if (adapterIds.empty()) { + return {ConnectivityType::None}; + } + + std::set connectivities; + for (; addresses != NULL; addresses = addresses->Next) { + NET_LUID luid; + rc = ConvertInterfaceIndexToLuid(addresses->IfIndex, &luid); + if (rc != NO_ERROR) { + continue; + } + + GUID guid; + rc = ConvertInterfaceLuidToGuid(&luid, &guid); + if (rc != NO_ERROR) { + continue; + } + + if (std::find(adapterIds.begin(), adapterIds.end(), guid) != + adapterIds.end()) { + // Read more at + // https://learn.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-ip_adapter_addresses_lh + switch (addresses->IfType) { + case IF_TYPE_ETHERNET_CSMACD: + case IF_TYPE_IEEE1394: + connectivities.insert(ConnectivityType::Ethernet); + break; + case IF_TYPE_IEEE80211: + connectivities.insert(ConnectivityType::WiFi); + break; + case IF_TYPE_TUNNEL: + case IF_TYPE_PPP: + connectivities.insert(ConnectivityType::VPN); + break; + default: + connectivities.insert(ConnectivityType::Other); + break; + } + } + } + + if (connectivities.empty()) { + // If no specific connectivity types were found, return a set containing + // only None + return {ConnectivityType::None}; + } + + // Return the set of detected connectivity types + return connectivities; } bool NetworkManager::StartListen(NetworkCallback pCallback) { - if (!pCallback || pListener) { - return false; - } + if (!pCallback || pListener) { + return false; + } - HRESULT hr = pNetworkListManager->QueryInterface( - IID_IConnectionPointContainer, (void **)&pCPContainer); - if (SUCCEEDED(hr)) { - hr = pCPContainer->FindConnectionPoint(IID_INetworkEvents, &pConnectPoint); + HRESULT hr = pNetworkListManager->QueryInterface( + IID_IConnectionPointContainer, (void **) &pCPContainer); if (SUCCEEDED(hr)) { - pListener = new NetworkListener(pCallback); - hr = pConnectPoint->Advise((IUnknown *)pListener, &dwCookie); - if (SUCCEEDED(hr)) { - return true; - } - } - } - return false; + hr = pCPContainer->FindConnectionPoint(IID_INetworkEvents, &pConnectPoint); + if (SUCCEEDED(hr)) { + pListener = new NetworkListener(pCallback); + hr = pConnectPoint->Advise((IUnknown *) pListener, &dwCookie); + if (SUCCEEDED(hr)) { + return true; + } + } + } + return false; } void NetworkManager::StopListen() { - if (pConnectPoint) { - pConnectPoint->Unadvise(dwCookie); - pConnectPoint->Release(); - pConnectPoint = NULL; - dwCookie = 0; - } - - if (pCPContainer) { - pCPContainer->Release(); - pCPContainer = NULL; - } - - if (pListener) { - pListener->Release(); - pListener = NULL; - } + if (pConnectPoint) { + pConnectPoint->Unadvise(dwCookie); + pConnectPoint->Release(); + pConnectPoint = NULL; + dwCookie = 0; + } + + if (pCPContainer) { + pCPContainer->Release(); + pCPContainer = NULL; + } + + if (pListener) { + pListener->Release(); + pListener = NULL; + } } bool NetworkManager::HasError() const { return GetLastError() != 0; } diff --git a/packages/connectivity_plus/connectivity_plus_platform_interface/CHANGELOG.md b/packages/connectivity_plus/connectivity_plus_platform_interface/CHANGELOG.md index 50d7973efe..6c4c587a32 100644 --- a/packages/connectivity_plus/connectivity_plus_platform_interface/CHANGELOG.md +++ b/packages/connectivity_plus/connectivity_plus_platform_interface/CHANGELOG.md @@ -1,22 +1,26 @@ ## 2.0.1 - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 2.0.0 > Note: This release has breaking changes. - - **FIX**(connectivity_plus): Fix connectivity state update on Android when network is lost ([#2673](https://github.com/fluttercommunity/plus_plugins/issues/2673)). ([21191682](https://github.com/fluttercommunity/plus_plugins/commit/2119168267e436e5900ea09cf68dd110e51b01e0)) - - **FIX**(connectivity_plus): Return valid connection type when only one available ([#2668](https://github.com/fluttercommunity/plus_plugins/issues/2668)). ([81026a4c](https://github.com/fluttercommunity/plus_plugins/commit/81026a4c6c07cb610299a8f17db69c518475a675)) - - **BREAKING** **FEAT**(connectivity_plus): support multiple connectivity types at the same time ([#2599](https://github.com/fluttercommunity/plus_plugins/issues/2599)). ([5b477468](https://github.com/fluttercommunity/plus_plugins/commit/5b4774683d6e186fbd69cf4208302221f52aa54d)) +- **FIX**(connectivity_plus): Fix connectivity state update on Android when network is + lost ([#2673](https://github.com/fluttercommunity/plus_plugins/issues/2673)). ([21191682](https://github.com/fluttercommunity/plus_plugins/commit/2119168267e436e5900ea09cf68dd110e51b01e0)) +- **FIX**(connectivity_plus): Return valid connection type when only one + available ([#2668](https://github.com/fluttercommunity/plus_plugins/issues/2668)). ([81026a4c](https://github.com/fluttercommunity/plus_plugins/commit/81026a4c6c07cb610299a8f17db69c518475a675)) +- **BREAKING** **FEAT**(connectivity_plus): support multiple connectivity types at the same + time ([#2599](https://github.com/fluttercommunity/plus_plugins/issues/2599)). ([5b477468](https://github.com/fluttercommunity/plus_plugins/commit/5b4774683d6e186fbd69cf4208302221f52aa54d)) ## 1.2.4 - - **FIX**: Do not return ConnectivityResult.none on iOS and MacOS with VPN (#1335). +- **FIX**: Do not return ConnectivityResult.none on iOS and MacOS with VPN (#1335). ## 1.2.3 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 1.2.2 @@ -94,7 +98,8 @@ - Bring ConnectivityResult and LocationAuthorizationStatus enums from the core package. - Use the above Enums as return values for ConnectivityPlatformInterface methods. - Modify the MethodChannel implementation so it returns the right types. -- Bring all utility methods, asserts and other logic that is only needed on the MethodChannel implementation from the core package. +- Bring all utility methods, asserts and other logic that is only needed on the MethodChannel + implementation from the core package. - Bring MethodChannel unit tests from core package. ## 0.1.1 diff --git a/packages/connectivity_plus/connectivity_plus_platform_interface/lib/connectivity_plus_platform_interface.dart b/packages/connectivity_plus/connectivity_plus_platform_interface/lib/connectivity_plus_platform_interface.dart index ef086a44e3..ccb155b1d3 100644 --- a/packages/connectivity_plus/connectivity_plus_platform_interface/lib/connectivity_plus_platform_interface.dart +++ b/packages/connectivity_plus/connectivity_plus_platform_interface/lib/connectivity_plus_platform_interface.dart @@ -46,6 +46,7 @@ abstract class ConnectivityPlatform extends PlatformInterface { /// Returns a Stream of ConnectivityResults changes. Stream> get onConnectivityChanged { throw UnimplementedError( - 'get onConnectivityChanged has not been implemented.'); + 'get onConnectivityChanged has not been implemented.', + ); } } diff --git a/packages/connectivity_plus/connectivity_plus_platform_interface/lib/method_channel_connectivity.dart b/packages/connectivity_plus/connectivity_plus_platform_interface/lib/method_channel_connectivity.dart index 95dcea4e50..6132627df9 100644 --- a/packages/connectivity_plus/connectivity_plus_platform_interface/lib/method_channel_connectivity.dart +++ b/packages/connectivity_plus/connectivity_plus_platform_interface/lib/method_channel_connectivity.dart @@ -14,13 +14,15 @@ import 'src/utils.dart'; class MethodChannelConnectivity extends ConnectivityPlatform { /// The method channel used to interact with the native platform. @visibleForTesting - MethodChannel methodChannel = - const MethodChannel('dev.fluttercommunity.plus/connectivity'); + MethodChannel methodChannel = const MethodChannel( + 'dev.fluttercommunity.plus/connectivity', + ); /// The event channel used to receive ConnectivityResult changes from the native platform. @visibleForTesting - EventChannel eventChannel = - const EventChannel('dev.fluttercommunity.plus/connectivity_status'); + EventChannel eventChannel = const EventChannel( + 'dev.fluttercommunity.plus/connectivity_status', + ); Stream>? _onConnectivityChanged; diff --git a/packages/connectivity_plus/connectivity_plus_platform_interface/lib/src/enums.dart b/packages/connectivity_plus/connectivity_plus_platform_interface/lib/src/enums.dart index 7f586995ab..2cd0821653 100644 --- a/packages/connectivity_plus/connectivity_plus_platform_interface/lib/src/enums.dart +++ b/packages/connectivity_plus/connectivity_plus_platform_interface/lib/src/enums.dart @@ -23,5 +23,5 @@ enum ConnectivityResult { vpn, /// Other: Device is connected to an unknown network - other + other, } diff --git a/packages/connectivity_plus/connectivity_plus_platform_interface/test/method_channel_connectivity_test.dart b/packages/connectivity_plus/connectivity_plus_platform_interface/test/method_channel_connectivity_test.dart index 244ffd9852..42d2a63c7b 100644 --- a/packages/connectivity_plus/connectivity_plus_platform_interface/test/method_channel_connectivity_test.dart +++ b/packages/connectivity_plus/connectivity_plus_platform_interface/test/method_channel_connectivity_test.dart @@ -18,68 +18,64 @@ void main() { methodChannelConnectivity = MethodChannelConnectivity(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - methodChannelConnectivity.methodChannel, - (MethodCall methodCall) async { - log.add(methodCall); - switch (methodCall.method) { - case 'check': - // Simulate returning a list of string of connectivity statuses - return ['wifi', 'mobile']; - default: - return null; - } - }, - ); + .setMockMethodCallHandler(methodChannelConnectivity.methodChannel, ( + MethodCall methodCall, + ) async { + log.add(methodCall); + switch (methodCall.method) { + case 'check': + // Simulate returning a list of string of connectivity statuses + return ['wifi', 'mobile']; + default: + return null; + } + }); log.clear(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler( - MethodChannel(methodChannelConnectivity.eventChannel.name), - (MethodCall methodCall) async { - switch (methodCall.method) { - case 'listen': - // Simulate returning a comma-separated string of connectivity statuses - await TestDefaultBinaryMessengerBinding - .instance.defaultBinaryMessenger - .handlePlatformMessage( - methodChannelConnectivity.eventChannel.name, - methodChannelConnectivity.eventChannel.codec - .encodeSuccessEnvelope(['wifi', 'mobile']), - (_) {}, - ); - break; - case 'cancel': - default: + MethodChannel(methodChannelConnectivity.eventChannel.name), + (MethodCall methodCall) async { + switch (methodCall.method) { + case 'listen': + // Simulate returning a comma-separated string of connectivity statuses + await TestDefaultBinaryMessengerBinding + .instance + .defaultBinaryMessenger + .handlePlatformMessage( + methodChannelConnectivity.eventChannel.name, + methodChannelConnectivity.eventChannel.codec + .encodeSuccessEnvelope(['wifi', 'mobile']), + (_) {}, + ); + break; + case 'cancel': + default: + return null; + } return null; - } - return null; - }, - ); + }, + ); }); // Test adjusted to handle multiple connectivity types test('onConnectivityChanged', () async { final result = await methodChannelConnectivity.onConnectivityChanged.first; - expect(result, - containsAll([ConnectivityResult.wifi, ConnectivityResult.mobile])); + expect( + result, + containsAll([ConnectivityResult.wifi, ConnectivityResult.mobile]), + ); }); // Test adjusted to handle multiple connectivity types test('checkConnectivity', () async { final result = await methodChannelConnectivity.checkConnectivity(); - expect(result, - containsAll([ConnectivityResult.wifi, ConnectivityResult.mobile])); expect( - log, - [ - isMethodCall( - 'check', - arguments: null, - ), - ], + result, + containsAll([ConnectivityResult.wifi, ConnectivityResult.mobile]), ); + expect(log, [isMethodCall('check', arguments: null)]); }); }); } diff --git a/packages/device_info_plus/device_info_plus/CHANGELOG.md b/packages/device_info_plus/device_info_plus/CHANGELOG.md index fe6e262735..a477d08044 100644 --- a/packages/device_info_plus/device_info_plus/CHANGELOG.md +++ b/packages/device_info_plus/device_info_plus/CHANGELOG.md @@ -1,13 +1,17 @@ ## 11.3.3 - - **FIX**(device_info_plus): handle nullability on getString(DEVICE_NAME) ([#3507](https://github.com/fluttercommunity/plus_plugins/issues/3507)). ([3201e056](https://github.com/fluttercommunity/plus_plugins/commit/3201e056b2a44ce74a3a9218fba59d71d9795379)) +- **FIX**(device_info_plus): handle nullability on getString( + DEVICE_NAME) ([#3507](https://github.com/fluttercommunity/plus_plugins/issues/3507)). ([3201e056](https://github.com/fluttercommunity/plus_plugins/commit/3201e056b2a44ce74a3a9218fba59d71d9795379)) ## 11.3.2 -**Note:** This release bumps dependency `win32_registry` from `1.1.5` to `2.0.1`. It will not compile if you have Dependency Overrides for that package. +**Note:** This release bumps dependency `win32_registry` from `1.1.5` to `2.0.1`. It will not +compile if you have Dependency Overrides for that package. - - **FIX**(device_info_plus): tighten dependency constraints ([#3497](https://github.com/fluttercommunity/plus_plugins/issues/3497)). ([c7e2428a](https://github.com/fluttercommunity/plus_plugins/commit/c7e2428a6075df4e37da9ef4934861c7cb0c3bee)) - - **FIX**(device_info_plus): fix memory leak when calling DeviceInfoPlugin().macOsInfo ([#3474](https://github.com/fluttercommunity/plus_plugins/issues/3474)). ([1cbf2b56](https://github.com/fluttercommunity/plus_plugins/commit/1cbf2b5621465456221b50ade7ac6c2f3266788d)) +- **FIX**(device_info_plus): tighten dependency + constraints ([#3497](https://github.com/fluttercommunity/plus_plugins/issues/3497)). ([c7e2428a](https://github.com/fluttercommunity/plus_plugins/commit/c7e2428a6075df4e37da9ef4934861c7cb0c3bee)) +- **FIX**(device_info_plus): fix memory leak when calling DeviceInfoPlugin() + .macOsInfo ([#3474](https://github.com/fluttercommunity/plus_plugins/issues/3474)). ([1cbf2b56](https://github.com/fluttercommunity/plus_plugins/commit/1cbf2b5621465456221b50ade7ac6c2f3266788d)) ## 11.3.1 @@ -15,62 +19,88 @@ ## 11.3.0 - - **FEAT**(device_info_plus): Add User Device Name in Android (PR [#3437](https://github.com/fluttercommunity/plus_plugins/issues/3437)) ([#3456](https://github.com/fluttercommunity/plus_plugins/issues/3456)). ([8c38a31d](https://github.com/fluttercommunity/plus_plugins/commit/8c38a31d7c1073d7011ec3e3193f6b99b3851ef1)) +- **FEAT**(device_info_plus): Add User Device Name in Android ( + PR [#3437](https://github.com/fluttercommunity/plus_plugins/issues/3437)) ([#3456](https://github.com/fluttercommunity/plus_plugins/issues/3456)). ([8c38a31d](https://github.com/fluttercommunity/plus_plugins/commit/8c38a31d7c1073d7011ec3e3193f6b99b3851ef1)) ## 11.2.2 - - **FIX**(device_info_plus): Replace throwing exception with returning default values on Windows ([#3445](https://github.com/fluttercommunity/plus_plugins/issues/3445)). ([084730f8](https://github.com/fluttercommunity/plus_plugins/commit/084730f82436b474b31b16f6dc2d7b90585e899f)) - - **DOCS**(device_info_plus): Update the documentation URL for property descriptions. ([#3441](https://github.com/fluttercommunity/plus_plugins/issues/3441)). ([743bec62](https://github.com/fluttercommunity/plus_plugins/commit/743bec626c909fdc8ba6d087006568cca60563d8)) +- **FIX**(device_info_plus): Replace throwing exception with returning default values on + Windows ([#3445](https://github.com/fluttercommunity/plus_plugins/issues/3445)). ([084730f8](https://github.com/fluttercommunity/plus_plugins/commit/084730f82436b474b31b16f6dc2d7b90585e899f)) +- **DOCS**(device_info_plus): Update the documentation URL for property + descriptions. ([#3441](https://github.com/fluttercommunity/plus_plugins/issues/3441)). ([743bec62](https://github.com/fluttercommunity/plus_plugins/commit/743bec626c909fdc8ba6d087006568cca60563d8)) ## 11.2.1 - - **FIX**(device_info_plus): Resolve compilation issues with SPM enabled ([#3405](https://github.com/fluttercommunity/plus_plugins/issues/3405)). ([3f098c30](https://github.com/fluttercommunity/plus_plugins/commit/3f098c30320e1595c06b093e8eb9827a44435c5d)) - - **FIX**(device_info_plus): device memory null error on Safari and Firefox ([#3401](https://github.com/fluttercommunity/plus_plugins/issues/3401)). ([2b7cb088](https://github.com/fluttercommunity/plus_plugins/commit/2b7cb0888cd725dc69e409590861fe8118058c4d)) - - **FIX**(device_info_plus): add @Suppress(deprecate) to Build.SERIAL ([#3402](https://github.com/fluttercommunity/plus_plugins/issues/3402)). ([8e70d3f3](https://github.com/fluttercommunity/plus_plugins/commit/8e70d3f33d5f1c005dbb1aef733a8a8578989bac)) +- **FIX**(device_info_plus): Resolve compilation issues with SPM + enabled ([#3405](https://github.com/fluttercommunity/plus_plugins/issues/3405)). ([3f098c30](https://github.com/fluttercommunity/plus_plugins/commit/3f098c30320e1595c06b093e8eb9827a44435c5d)) +- **FIX**(device_info_plus): device memory null error on Safari and + Firefox ([#3401](https://github.com/fluttercommunity/plus_plugins/issues/3401)). ([2b7cb088](https://github.com/fluttercommunity/plus_plugins/commit/2b7cb0888cd725dc69e409590861fe8118058c4d)) +- **FIX**(device_info_plus): add @Suppress(deprecate) to + Build.SERIAL ([#3402](https://github.com/fluttercommunity/plus_plugins/issues/3402)). ([8e70d3f3](https://github.com/fluttercommunity/plus_plugins/commit/8e70d3f33d5f1c005dbb1aef733a8a8578989bac)) ## 11.2.0 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) - - **FIX**(device_info_plus): fix the error in the e2e test. ([#3382](https://github.com/fluttercommunity/plus_plugins/issues/3382)). ([3d06bf0e](https://github.com/fluttercommunity/plus_plugins/commit/3d06bf0ed8f1029df1230e4be6e75537abfcb19f)) - - **FIX**(device_info_plus): Set correct Flutter and Dart versions requirements ([#3362](https://github.com/fluttercommunity/plus_plugins/issues/3362)). ([77861523](https://github.com/fluttercommunity/plus_plugins/commit/778615231c376c829d6241e7988f15a77bcaeb55)) - - **FEAT**(device_info_plus): Return model name for iOS and MacOS devices ([#3358](https://github.com/fluttercommunity/plus_plugins/issues/3358)). ([63ca4cd8](https://github.com/fluttercommunity/plus_plugins/commit/63ca4cd8127e010650468a79532dd3a6047d2b31)) - - **FEAT**(device_info_plus): Add the isiOSAppOnMac property for the iOS platform. ([#3383](https://github.com/fluttercommunity/plus_plugins/issues/3383)). ([e9077845](https://github.com/fluttercommunity/plus_plugins/commit/e9077845342023d325280985234b6a09d245ac02)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **FIX**(device_info_plus): fix the error in the e2e + test. ([#3382](https://github.com/fluttercommunity/plus_plugins/issues/3382)). ([3d06bf0e](https://github.com/fluttercommunity/plus_plugins/commit/3d06bf0ed8f1029df1230e4be6e75537abfcb19f)) +- **FIX**(device_info_plus): Set correct Flutter and Dart versions + requirements ([#3362](https://github.com/fluttercommunity/plus_plugins/issues/3362)). ([77861523](https://github.com/fluttercommunity/plus_plugins/commit/778615231c376c829d6241e7988f15a77bcaeb55)) +- **FEAT**(device_info_plus): Return model name for iOS and MacOS + devices ([#3358](https://github.com/fluttercommunity/plus_plugins/issues/3358)). ([63ca4cd8](https://github.com/fluttercommunity/plus_plugins/commit/63ca4cd8127e010650468a79532dd3a6047d2b31)) +- **FEAT**(device_info_plus): Add the isiOSAppOnMac property for the iOS + platform. ([#3383](https://github.com/fluttercommunity/plus_plugins/issues/3383)). ([e9077845](https://github.com/fluttercommunity/plus_plugins/commit/e9077845342023d325280985234b6a09d245ac02)) ## 11.1.1 - - **FIX**(device_info_plus): Update privacy manifest paths ([#3347](https://github.com/fluttercommunity/plus_plugins/issues/3347)). ([46df2302](https://github.com/fluttercommunity/plus_plugins/commit/46df23023a5ba6c98edd31d5fd06bec5df40bd3b)) +- **FIX**(device_info_plus): Update privacy manifest + paths ([#3347](https://github.com/fluttercommunity/plus_plugins/issues/3347)). ([46df2302](https://github.com/fluttercommunity/plus_plugins/commit/46df23023a5ba6c98edd31d5fd06bec5df40bd3b)) ## 11.1.0 - - **FIX**(device_info_plus): Ignore `MissingPermission` lint error on Android ([#3317](https://github.com/fluttercommunity/plus_plugins/issues/3317)). ([6469523f](https://github.com/fluttercommunity/plus_plugins/commit/6469523fb14f32f7aa23892183693a8f502992d3)) - - **FEAT**(device_info_plus): Add Swift Package Manager support ([#3167](https://github.com/fluttercommunity/plus_plugins/issues/3167)). ([6a347cb1](https://github.com/fluttercommunity/plus_plugins/commit/6a347cb106182d68329cd32827938e26bc7e7b00)) +- **FIX**(device_info_plus): Ignore `MissingPermission` lint error on + Android ([#3317](https://github.com/fluttercommunity/plus_plugins/issues/3317)). ([6469523f](https://github.com/fluttercommunity/plus_plugins/commit/6469523fb14f32f7aa23892183693a8f502992d3)) +- **FEAT**(device_info_plus): Add Swift Package Manager + support ([#3167](https://github.com/fluttercommunity/plus_plugins/issues/3167)). ([6a347cb1](https://github.com/fluttercommunity/plus_plugins/commit/6a347cb106182d68329cd32827938e26bc7e7b00)) ## 11.0.0 > Note: This release has breaking changes. - - **FIX**(all): Clean up macOS Privacy Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) - - **FIX**(all): Add macOS Privacy Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) - - **FIX**(device_info_plus): Fix type cast of digitalProductId on windows ([#3188](https://github.com/fluttercommunity/plus_plugins/issues/3188)). ([91f48a6b](https://github.com/fluttercommunity/plus_plugins/commit/91f48a6bc7d11c4238c9539ca06e6fa768995580)) - - **BREAKING** **FIX**(device_info_plus): fixed webasm compliance ([#3254](https://github.com/fluttercommunity/plus_plugins/issues/3254)). ([e35e2123](https://github.com/fluttercommunity/plus_plugins/commit/e35e2123451fc103bbb6f6d94f71ebced2ae8af5)) +- **FIX**(all): Clean up macOS Privacy + Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) +- **FIX**(all): Add macOS Privacy + Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) +- **FIX**(device_info_plus): Fix type cast of digitalProductId on + windows ([#3188](https://github.com/fluttercommunity/plus_plugins/issues/3188)). ([91f48a6b](https://github.com/fluttercommunity/plus_plugins/commit/91f48a6bc7d11c4238c9539ca06e6fa768995580)) +- **BREAKING** **FIX**(device_info_plus): fixed webasm + compliance ([#3254](https://github.com/fluttercommunity/plus_plugins/issues/3254)). ([e35e2123](https://github.com/fluttercommunity/plus_plugins/commit/e35e2123451fc103bbb6f6d94f71ebced2ae8af5)) ## 10.1.2 - - **DOCS**(device_info_plus): Update plugin requirements in README ([#3162](https://github.com/fluttercommunity/plus_plugins/issues/3162)). ([6cfa950f](https://github.com/fluttercommunity/plus_plugins/commit/6cfa950f66fec649093b6c44755dc06a3a23319e)) +- **DOCS**(device_info_plus): Update plugin requirements in + README ([#3162](https://github.com/fluttercommunity/plus_plugins/issues/3162)). ([6cfa950f](https://github.com/fluttercommunity/plus_plugins/commit/6cfa950f66fec649093b6c44755dc06a3a23319e)) ## 10.1.1 - - **CHORE**(device_info_plus): Use `>=0.5.0 < 2.0.0` version range for package:web. - - **FIX**(device_info_plus): fix integration_test iOS ([#2958](https://github.com/fluttercommunity/plus_plugins/issues/2958)). ([93ab854e](https://github.com/fluttercommunity/plus_plugins/commit/93ab854ee76a3de48387b6c54ddaeccb01cf49a9)) - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **CHORE**(device_info_plus): Use `>=0.5.0 < 2.0.0` version range for package:web. +- **FIX**(device_info_plus): fix integration_test + iOS ([#2958](https://github.com/fluttercommunity/plus_plugins/issues/2958)). ([93ab854e](https://github.com/fluttercommunity/plus_plugins/commit/93ab854ee76a3de48387b6c54ddaeccb01cf49a9)) +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 10.1.0 - - **REFACTOR**(device_info_plus): Migrate Android example to use the new plugins declaration ([#2769](https://github.com/fluttercommunity/plus_plugins/issues/2769)). ([6103b155](https://github.com/fluttercommunity/plus_plugins/commit/6103b1559d6f9383bd66460bf7717afeeeb51d86)) - - **FIX**(device_info_plus): WASM-compatible conditional imports ([#2826](https://github.com/fluttercommunity/plus_plugins/issues/2826)). ([11200cf4](https://github.com/fluttercommunity/plus_plugins/commit/11200cf4eb38bfa6bc83e955a3ceff7b8fc72493)) - - **FEAT**(device_info_plus): Add isLowRamDevice property to AndroidDeviceInfo ([#2765](https://github.com/fluttercommunity/plus_plugins/issues/2765)). ([1376b035](https://github.com/fluttercommunity/plus_plugins/commit/1376b0359fd39172cfb54595178313c73f5d1942)) - - **DOCS**(device_info_plus): Add iOS name property entitlements info ([#2756](https://github.com/fluttercommunity/plus_plugins/issues/2756)). ([d21f285a](https://github.com/fluttercommunity/plus_plugins/commit/d21f285a1d26e7a512c4a9aea579de9680a6ca48)) +- **REFACTOR**(device_info_plus): Migrate Android example to use the new plugins + declaration ([#2769](https://github.com/fluttercommunity/plus_plugins/issues/2769)). ([6103b155](https://github.com/fluttercommunity/plus_plugins/commit/6103b1559d6f9383bd66460bf7717afeeeb51d86)) +- **FIX**(device_info_plus): WASM-compatible conditional + imports ([#2826](https://github.com/fluttercommunity/plus_plugins/issues/2826)). ([11200cf4](https://github.com/fluttercommunity/plus_plugins/commit/11200cf4eb38bfa6bc83e955a3ceff7b8fc72493)) +- **FEAT**(device_info_plus): Add isLowRamDevice property to + AndroidDeviceInfo ([#2765](https://github.com/fluttercommunity/plus_plugins/issues/2765)). ([1376b035](https://github.com/fluttercommunity/plus_plugins/commit/1376b0359fd39172cfb54595178313c73f5d1942)) +- **DOCS**(device_info_plus): Add iOS name property entitlements + info ([#2756](https://github.com/fluttercommunity/plus_plugins/issues/2756)). ([d21f285a](https://github.com/fluttercommunity/plus_plugins/commit/d21f285a1d26e7a512c4a9aea579de9680a6ca48)) ## 10.0.1 @@ -79,134 +109,167 @@ In this release plugin migrated to package:web, meaning that it now supports WASM! Plugin now requires the following: + - Flutter >=3.19.0 - Dart >=3.3.0 - compileSDK 34 for Android part - Java 17 for Android part - Gradle 8.4 for Android part - - - **BREAKING** **REFACTOR**(device_info_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2589](https://github.com/fluttercommunity/plus_plugins/issues/2589)). ([1c586abf](https://github.com/fluttercommunity/plus_plugins/commit/1c586abf7ee351927242a70cb88e2e36140cec9e)) - - **BREAKING** **FIX**(device_info_plus): Remove Display Metrics from Android Device Info ([#2731](https://github.com/fluttercommunity/plus_plugins/issues/2731)). ([c5af3322](https://github.com/fluttercommunity/plus_plugins/commit/c5af332207e44902ac92765da72d2acb213fae91)) - - **BREAKING** **FEAT**(device_info_plus): migrate to package:web ([#2624](https://github.com/fluttercommunity/plus_plugins/issues/2624)). ([154e76ca](https://github.com/fluttercommunity/plus_plugins/commit/154e76ca2f9e8c1ccdaa6e2076426002c9d372a3)) - - **BREAKING** **BUILD**(device_info_plus): Target Java 17 on Android ([#2725](https://github.com/fluttercommunity/plus_plugins/issues/2725)). ([aa826dea](https://github.com/fluttercommunity/plus_plugins/commit/aa826deac5ef8136ce922f5823be2e7f90f828e9)) - - **BREAKING** **BUILD**(device_info_plus): Update to target and compile SDK 34 ([#2704](https://github.com/fluttercommunity/plus_plugins/pull/2704)). ([a3cd72f](https://github.com/fluttercommunity/plus_plugins/commit/a3cd72f86ba47f43c507f8b83f89aac7519404de)) - - **FIX**(device_info_plus): remove unnecessary print ([#2607](https://github.com/fluttercommunity/plus_plugins/issues/2607)). ([5d515816](https://github.com/fluttercommunity/plus_plugins/commit/5d5158169f75c50f15588c10e07af2e25f950c23)) - - **FIX**(device_info_plus): return type of isPhysicalDevice as boolean for ios ([#2508](https://github.com/fluttercommunity/plus_plugins/issues/2508)). ([e3a983bb](https://github.com/fluttercommunity/plus_plugins/commit/e3a983bbf0b0bb70c7c50835ddb7f3c4a46b7122)) - - **FIX**(device_info_plus): Add iOS Privacy Info ([#2582](https://github.com/fluttercommunity/plus_plugins/issues/2582)). ([34fe31eb](https://github.com/fluttercommunity/plus_plugins/commit/34fe31eb29e21fa9ea336e61d8df6858eb441a00)) - - **FEAT**(device_info_plus): Update min iOS target to 12 ([#2658](https://github.com/fluttercommunity/plus_plugins/issues/2658)). ([a3436100](https://github.com/fluttercommunity/plus_plugins/commit/a3436100fabd04a4d4db7ac09128b5b5962579d3)) - - **FEAT**(device_info_plus): LinuxDeviceInfo toString method ([#2652](https://github.com/fluttercommunity/plus_plugins/issues/2652)). ([f2fbcdb8](https://github.com/fluttercommunity/plus_plugins/commit/f2fbcdb813b62dcb76c18b00e51383e6643a93ed)) +- **BREAKING** **REFACTOR**(device_info_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to + 10.14 ([#2589](https://github.com/fluttercommunity/plus_plugins/issues/2589)). ([1c586abf](https://github.com/fluttercommunity/plus_plugins/commit/1c586abf7ee351927242a70cb88e2e36140cec9e)) +- **BREAKING** **FIX**(device_info_plus): Remove Display Metrics from Android Device + Info ([#2731](https://github.com/fluttercommunity/plus_plugins/issues/2731)). ([c5af3322](https://github.com/fluttercommunity/plus_plugins/commit/c5af332207e44902ac92765da72d2acb213fae91)) +- **BREAKING** **FEAT**(device_info_plus): migrate to package: + web ([#2624](https://github.com/fluttercommunity/plus_plugins/issues/2624)). ([154e76ca](https://github.com/fluttercommunity/plus_plugins/commit/154e76ca2f9e8c1ccdaa6e2076426002c9d372a3)) +- **BREAKING** **BUILD**(device_info_plus): Target Java 17 on + Android ([#2725](https://github.com/fluttercommunity/plus_plugins/issues/2725)). ([aa826dea](https://github.com/fluttercommunity/plus_plugins/commit/aa826deac5ef8136ce922f5823be2e7f90f828e9)) +- **BREAKING** **BUILD**(device_info_plus): Update to target and compile SDK + 34 ([#2704](https://github.com/fluttercommunity/plus_plugins/pull/2704)). ([a3cd72f](https://github.com/fluttercommunity/plus_plugins/commit/a3cd72f86ba47f43c507f8b83f89aac7519404de)) +- **FIX**(device_info_plus): remove unnecessary + print ([#2607](https://github.com/fluttercommunity/plus_plugins/issues/2607)). ([5d515816](https://github.com/fluttercommunity/plus_plugins/commit/5d5158169f75c50f15588c10e07af2e25f950c23)) +- **FIX**(device_info_plus): return type of isPhysicalDevice as boolean for + ios ([#2508](https://github.com/fluttercommunity/plus_plugins/issues/2508)). ([e3a983bb](https://github.com/fluttercommunity/plus_plugins/commit/e3a983bbf0b0bb70c7c50835ddb7f3c4a46b7122)) +- **FIX**(device_info_plus): Add iOS Privacy + Info ([#2582](https://github.com/fluttercommunity/plus_plugins/issues/2582)). ([34fe31eb](https://github.com/fluttercommunity/plus_plugins/commit/34fe31eb29e21fa9ea336e61d8df6858eb441a00)) +- **FEAT**(device_info_plus): Update min iOS target to + 12 ([#2658](https://github.com/fluttercommunity/plus_plugins/issues/2658)). ([a3436100](https://github.com/fluttercommunity/plus_plugins/commit/a3436100fabd04a4d4db7ac09128b5b5962579d3)) +- **FEAT**(device_info_plus): LinuxDeviceInfo toString + method ([#2652](https://github.com/fluttercommunity/plus_plugins/issues/2652)). ([f2fbcdb8](https://github.com/fluttercommunity/plus_plugins/commit/f2fbcdb813b62dcb76c18b00e51383e6643a93ed)) ## 10.0.0 -> Note: This release was retracted due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). +> Note: This release was retracted due +> to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). ## 9.1.2 - - **FIX**(device_info_plus): fix crash on non-standard Digital Product IDs ([#2537](https://github.com/fluttercommunity/plus_plugins/issues/2537)). ([7b318b5c](https://github.com/fluttercommunity/plus_plugins/commit/7b318b5cd8496cf7d31c62314eb9bae17f9ef8d6)) +- **FIX**(device_info_plus): fix crash on non-standard Digital Product + IDs ([#2537](https://github.com/fluttercommunity/plus_plugins/issues/2537)). ([7b318b5c](https://github.com/fluttercommunity/plus_plugins/commit/7b318b5cd8496cf7d31c62314eb9bae17f9ef8d6)) ## 9.1.1 - - **FIX**(device_info_plus): Fix deprecation warning on MacOS ([#2377](https://github.com/fluttercommunity/plus_plugins/issues/2377)). ([56a6d0ff](https://github.com/fluttercommunity/plus_plugins/commit/56a6d0ff3752570de89f00876eb7181d662a0465)) +- **FIX**(device_info_plus): Fix deprecation warning on + MacOS ([#2377](https://github.com/fluttercommunity/plus_plugins/issues/2377)). ([56a6d0ff](https://github.com/fluttercommunity/plus_plugins/commit/56a6d0ff3752570de89f00876eb7181d662a0465)) ## 9.1.0 -> Info: This release is a replacement for release 10.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. - - - **FIX**(device_info_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2256](https://github.com/fluttercommunity/plus_plugins/issues/2256)). ([313ec2c3](https://github.com/fluttercommunity/plus_plugins/commit/313ec2c328f34b278f197ee1f2d896f8820ac789)) - - **FIX**(device_info_plus): Revert bump compileSDK to 34 ([#2230](https://github.com/fluttercommunity/plus_plugins/issues/2230)). ([2ba5b054](https://github.com/fluttercommunity/plus_plugins/commit/2ba5b054948f48a9aae72c8a63b39f6536ab678d)) - - **FIX**(device_info_plus): Update exports to avoid web compatibility issues ([#2028](https://github.com/fluttercommunity/plus_plugins/issues/2028)). ([6c216053](https://github.com/fluttercommunity/plus_plugins/commit/6c2160537dc51493adc5bf22cd480a52582845b0)) - - **FIX**(device_info_plus): Regenerate iOS and MacOS example apps ([#1868](https://github.com/fluttercommunity/plus_plugins/issues/1868)). ([6e1111ac](https://github.com/fluttercommunity/plus_plugins/commit/6e1111acff40fef6f77fe2561810d679bafe938c)) - - **FEAT**(device_info_plus): Remove deprecated VALID_ARCHS iOS property ([#2022](https://github.com/fluttercommunity/plus_plugins/issues/2022)). ([13053295](https://github.com/fluttercommunity/plus_plugins/commit/13053295137201b34a6bf52e494ccf77e0321b18)) - - **DOCS**(device_info_plus): Add note about arch returned value on MacOS ([#2220](https://github.com/fluttercommunity/plus_plugins/issues/2220)). ([80409e2a](https://github.com/fluttercommunity/plus_plugins/commit/80409e2ab13a6379b9101034ad453517151a719a)) - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +> Info: This release is a replacement for release 10.0.0, which was retracted due to +> issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change +> was reverted the major release was also reverted in favor of this one. + +- **FIX**(device_info_plus): Change Kotlin version from 1.9.10 to + 1.7.22 ([#2256](https://github.com/fluttercommunity/plus_plugins/issues/2256)). ([313ec2c3](https://github.com/fluttercommunity/plus_plugins/commit/313ec2c328f34b278f197ee1f2d896f8820ac789)) +- **FIX**(device_info_plus): Revert bump compileSDK to + 34 ([#2230](https://github.com/fluttercommunity/plus_plugins/issues/2230)). ([2ba5b054](https://github.com/fluttercommunity/plus_plugins/commit/2ba5b054948f48a9aae72c8a63b39f6536ab678d)) +- **FIX**(device_info_plus): Update exports to avoid web compatibility + issues ([#2028](https://github.com/fluttercommunity/plus_plugins/issues/2028)). ([6c216053](https://github.com/fluttercommunity/plus_plugins/commit/6c2160537dc51493adc5bf22cd480a52582845b0)) +- **FIX**(device_info_plus): Regenerate iOS and MacOS example + apps ([#1868](https://github.com/fluttercommunity/plus_plugins/issues/1868)). ([6e1111ac](https://github.com/fluttercommunity/plus_plugins/commit/6e1111acff40fef6f77fe2561810d679bafe938c)) +- **FEAT**(device_info_plus): Remove deprecated VALID_ARCHS iOS + property ([#2022](https://github.com/fluttercommunity/plus_plugins/issues/2022)). ([13053295](https://github.com/fluttercommunity/plus_plugins/commit/13053295137201b34a6bf52e494ccf77e0321b18)) +- **DOCS**(device_info_plus): Add note about arch returned value on + MacOS ([#2220](https://github.com/fluttercommunity/plus_plugins/issues/2220)). ([80409e2a](https://github.com/fluttercommunity/plus_plugins/commit/80409e2ab13a6379b9101034ad453517151a719a)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 9.0.3 - - **FIX**(device_info_plus): Regenerate iOS and MacOS example apps ([#1868](https://github.com/fluttercommunity/plus_plugins/issues/1868)). ([6e1111ac](https://github.com/fluttercommunity/plus_plugins/commit/6e1111acff40fef6f77fe2561810d679bafe938c)) - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **FIX**(device_info_plus): Regenerate iOS and MacOS example + apps ([#1868](https://github.com/fluttercommunity/plus_plugins/issues/1868)). ([6e1111ac](https://github.com/fluttercommunity/plus_plugins/commit/6e1111acff40fef6f77fe2561810d679bafe938c)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 9.0.2 - - **DOCS**(device_info_plus): Add links to Android and iOS docs to every field ([#1857](https://github.com/fluttercommunity/plus_plugins/issues/1857)). ([89eb5217](https://github.com/fluttercommunity/plus_plugins/commit/89eb52177c90d5453ba512e73472536fc8a03c9a)) +- **DOCS**(device_info_plus): Add links to Android and iOS docs to every + field ([#1857](https://github.com/fluttercommunity/plus_plugins/issues/1857)). ([89eb5217](https://github.com/fluttercommunity/plus_plugins/commit/89eb52177c90d5453ba512e73472536fc8a03c9a)) ## 9.0.1 - - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) - - **CHORE**(device_info_plus): Win32 dependency upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) +- **FIX**: Add jvm target compatibility to Kotlin + plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **CHORE**(device_info_plus): Win32 dependency + upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) ## 9.0.0 > Note: This release has breaking changes. - - **CHORE**(device_info_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(device_info_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1781). - - **REFACTOR**(device_info_plus): Refactor Windows implementation (#1772). - - **REFACTOR**(device_info_plus): Remove redundant checks for PRODUCT strings with sdk (#1745). - - **REFACTOR**(device_info_plus): Declare proper nullability for iOS properties (#1728). +- **CHORE**(device_info_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to > + =2.18.0 <4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(device_info_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update + podspec file (#1781). +- **REFACTOR**(device_info_plus): Refactor Windows implementation (#1772). +- **REFACTOR**(device_info_plus): Remove redundant checks for PRODUCT strings with sdk (#1745). +- **REFACTOR**(device_info_plus): Declare proper nullability for iOS properties (#1728). ## 8.2.2 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 8.2.1 - - **FIX**(device_info_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1702). +- **FIX**(device_info_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1702). ## 8.2.0 - - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). - - **FEAT**(device_info_plus): add major, minor and patch versions to macos (#1649). +- **REFACTOR**(all): Remove all manual dependency_overrides (#1628). +- **FEAT**(device_info_plus): add major, minor and patch versions to macos (#1649). ## 8.1.0 - - **FEAT**: Add serialNumber property to AndroidDeviceInfo (#1349). - - **DOCS**: Updates for READMEs and website pages (#1389). - - **DOCS**: Explain how to get serial number on Android (#1390). - - **DOCS**: Add info about iOS 16 changes to device name (#1356). +- **FEAT**: Add serialNumber property to AndroidDeviceInfo (#1349). +- **DOCS**: Updates for READMEs and website pages (#1389). +- **DOCS**: Explain how to get serial number on Android (#1390). +- **DOCS**: Add info about iOS 16 changes to device name (#1356). ## 8.0.0 > Note: This release has breaking changes. - - **DOCS**: Document toMap deprecation (#1292). - - **BREAKING** **FEAT**: refactor of device_info_plus platform implementation (#1293). +- **DOCS**: Document toMap deprecation (#1292). +- **BREAKING** **FEAT**: refactor of device_info_plus platform implementation (#1293). ## 7.0.1 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 7.0.0 > Note: This release has breaking changes. - - **REFACTOR**: Migrate Android part to Kotlin, update Android dependencies (#1245). - - **FIX**: add `@Deprecated` annotation to `toMap` method (#1142). - - **DOCS**: Add info about Android properties availability, update API docs links (#1243). - - **BREAKING** **REFACTOR**: two-package federated architecture (#1228). +- **REFACTOR**: Migrate Android part to Kotlin, update Android dependencies (#1245). +- **FIX**: add `@Deprecated` annotation to `toMap` method (#1142). +- **DOCS**: Add info about Android properties availability, update API docs links (#1243). +- **BREAKING** **REFACTOR**: two-package federated architecture (#1228). ## 6.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**: Add support of Android display metrics (#829). +- **BREAKING** **FEAT**: Add support of Android display metrics (#829). ## 5.0.5 - - Update a dependency to the latest release. +- Update a dependency to the latest release. ## 5.0.4 - - **FIX**: fixed wrong dependency version #1175. +- **FIX**: fixed wrong dependency version #1175. ## 5.0.3 - - **FIX**: fix version dependency. +- **FIX**: fix version dependency. ## 5.0.2 - - **CHORE**: Version tagging using melos. +- **CHORE**: Version tagging using melos. ## 5.0.1 @@ -232,8 +295,10 @@ Plugin now requires the following: ## 4.1.0 -- Remove `androidId` (that already got removed from the method channel in 4.0.0, thus always returned null) -- There is a **new, separate [pub.dev package](https://pub.dev/packages/android_id) for getting the correct `androidId`** +- Remove `androidId` (that already got removed from the method channel in 4.0.0, thus always + returned null) +- There is a **new, separate [pub.dev package](https://pub.dev/packages/android_id) for getting the + correct `androidId`** ## 4.0.3 @@ -361,7 +426,8 @@ Update lower bound of dart dependency to 2.1.0. ## 0.4.2+3 -- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). +- Declare API stability and compatibility with `1.0.0` (more details + at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). ## 0.4.2+2 diff --git a/packages/device_info_plus/device_info_plus/README.md b/packages/device_info_plus/device_info_plus/README.md index fdfd7da563..17acecc0a4 100644 --- a/packages/device_info_plus/device_info_plus/README.md +++ b/packages/device_info_plus/device_info_plus/README.md @@ -11,8 +11,8 @@ Get current device information from within the Flutter application. ## Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :-----: | -| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ## Requirements @@ -63,13 +63,17 @@ final allInfo = deviceInfo.data; ### Android -To get serial number on Android your app needs to meet one of official [requirements](https://developer.android.com/reference/android/os/Build#getSerial()). +To get serial number on Android your app needs to meet one of +official [requirements](https://developer.android.com/reference/android/os/Build#getSerial()). In case the app doesn't meet any of requirements plugin will return `unknown`. ### iOS -The `name` property exposes the assigned device name by the owner. This value is obtained from the property `UIDevice.current.name`. -This property requires special entitlement [com.apple.developer.device-information.user-assigned-device-name](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_device-information_user-assigned-device-name) in iOS 16 and later, otherwise, the property `name` will always be `iPad` or `iPhone`. +The `name` property exposes the assigned device name by the owner. This value is obtained from the +property `UIDevice.current.name`. +This property requires special +entitlement [com.apple.developer.device-information.user-assigned-device-name](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_device-information_user-assigned-device-name) +in iOS 16 and later, otherwise, the property `name` will always be `iPad` or `iPhone`. ## Learn more diff --git a/packages/device_info_plus/device_info_plus/android/build.gradle b/packages/device_info_plus/device_info_plus/android/build.gradle index 5213cd0a10..d3eaa2139f 100644 --- a/packages/device_info_plus/device_info_plus/android/build.gradle +++ b/packages/device_info_plus/device_info_plus/android/build.gradle @@ -2,7 +2,7 @@ group 'dev.fluttercommunity.plus.device_info' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.7.22' + ext.kotlin_version = '2.1.10' repositories { google() mavenCentral() @@ -25,7 +25,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.device_info' diff --git a/packages/device_info_plus/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/device_info_plus/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties index e411586a54..2733ed5dc3 100644 --- a/packages/device_info_plus/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/device_info_plus/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/device_info_plus/device_info_plus/android/src/main/AndroidManifest.xml b/packages/device_info_plus/device_info_plus/android/src/main/AndroidManifest.xml index 412ea27f53..b2ec217505 100644 --- a/packages/device_info_plus/device_info_plus/android/src/main/AndroidManifest.xml +++ b/packages/device_info_plus/device_info_plus/android/src/main/AndroidManifest.xml @@ -1,2 +1 @@ - - + diff --git a/packages/device_info_plus/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt b/packages/device_info_plus/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt index 47f6614ef5..0d72ef6873 100644 --- a/packages/device_info_plus/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt +++ b/packages/device_info_plus/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt @@ -39,7 +39,8 @@ internal class MethodCallHandlerImpl( build["product"] = Build.PRODUCT if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - build["name"] = Settings.Global.getString(contentResolver, Settings.Global.DEVICE_NAME) ?: "" + build["name"] = + Settings.Global.getString(contentResolver, Settings.Global.DEVICE_NAME) ?: "" } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/packages/device_info_plus/device_info_plus/example/android/app/build.gradle b/packages/device_info_plus/device_info_plus/example/android/app/build.gradle index 1e70360c4e..93940d4795 100644 --- a/packages/device_info_plus/device_info_plus/example/android/app/build.gradle +++ b/packages/device_info_plus/device_info_plus/example/android/app/build.gradle @@ -23,7 +23,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'io.flutter.plugins.deviceinfoexample.example' @@ -47,7 +47,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.deviceinfoexample.example" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/packages/device_info_plus/device_info_plus/example/android/app/src/debug/AndroidManifest.xml b/packages/device_info_plus/device_info_plus/example/android/app/src/debug/AndroidManifest.xml index 175e81dcaf..3b661ee42b 100644 --- a/packages/device_info_plus/device_info_plus/example/android/app/src/debug/AndroidManifest.xml +++ b/packages/device_info_plus/device_info_plus/example/android/app/src/debug/AndroidManifest.xml @@ -3,5 +3,5 @@ - + diff --git a/packages/device_info_plus/device_info_plus/example/android/app/src/main/AndroidManifest.xml b/packages/device_info_plus/device_info_plus/example/android/app/src/main/AndroidManifest.xml index d75557c587..44ca18a607 100644 --- a/packages/device_info_plus/device_info_plus/example/android/app/src/main/AndroidManifest.xml +++ b/packages/device_info_plus/device_info_plus/example/android/app/src/main/AndroidManifest.xml @@ -7,32 +7,31 @@ FlutterApplication and put your custom class here. --> + android:icon="@mipmap/ic_launcher" + android:label="example"> + android:launchMode="singleTop" + android:theme="@style/LaunchTheme" + android:windowSoftInputMode="adjustResize"> + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" /> - - + + + diff --git a/packages/device_info_plus/device_info_plus/example/android/app/src/profile/AndroidManifest.xml b/packages/device_info_plus/device_info_plus/example/android/app/src/profile/AndroidManifest.xml index 175e81dcaf..3b661ee42b 100644 --- a/packages/device_info_plus/device_info_plus/example/android/app/src/profile/AndroidManifest.xml +++ b/packages/device_info_plus/device_info_plus/example/android/app/src/profile/AndroidManifest.xml @@ -3,5 +3,5 @@ - + diff --git a/packages/device_info_plus/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/device_info_plus/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties index 448814c79e..f3dd2fa1bd 100644 --- a/packages/device_info_plus/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/device_info_plus/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Oct 05 15:15:38 CEST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/device_info_plus/device_info_plus/example/android/settings.gradle b/packages/device_info_plus/device_info_plus/example/android/settings.gradle index fa3b4d0878..18a751a498 100644 --- a/packages/device_info_plus/device_info_plus/example/android/settings.gradle +++ b/packages/device_info_plus/device_info_plus/example/android/settings.gradle @@ -18,8 +18,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false - id "org.jetbrains.kotlin.android" version "1.9.23" apply false + id "com.android.application" version "8.9.0" apply false + id "org.jetbrains.kotlin.android" version "2.1.10" apply false } include ":app" diff --git a/packages/device_info_plus/device_info_plus/example/integration_test/device_info_plus_test.dart b/packages/device_info_plus/device_info_plus/example/integration_test/device_info_plus_test.dart index 2cb0a98006..2ce1dc17eb 100644 --- a/packages/device_info_plus/device_info_plus/example/integration_test/device_info_plus_test.dart +++ b/packages/device_info_plus/device_info_plus/example/integration_test/device_info_plus_test.dart @@ -65,8 +65,9 @@ void main() { } }); - testWidgets('Can get non-null iOS utsname fields', - (WidgetTester tester) async { + testWidgets('Can get non-null iOS utsname fields', ( + WidgetTester tester, + ) async { expect(iosInfo.utsname.machine, isNotNull); expect(iosInfo.utsname.nodename, isNotNull); expect(iosInfo.utsname.release, isNotNull); @@ -74,8 +75,9 @@ void main() { expect(iosInfo.utsname.version, isNotNull); }, skip: !Platform.isIOS); - testWidgets('Check all android info values are available', - (WidgetTester tester) async { + testWidgets('Check all android info values are available', ( + WidgetTester tester, + ) async { if (androidInfo.version.sdkInt >= 23) { expect(androidInfo.version.baseOS, isNotNull); expect(androidInfo.version.previewSdkInt, isNotNull); @@ -112,8 +114,9 @@ void main() { expect(androidInfo.serialNumber, isNotNull); }, skip: !Platform.isAndroid); - testWidgets('Check all macos info values are available', - ((WidgetTester tester) async { + testWidgets('Check all macos info values are available', (( + WidgetTester tester, + ) async { expect(macosInfo.computerName, isNotNull); expect(macosInfo.hostName, isNotNull); expect(macosInfo.arch, isNotNull); @@ -127,8 +130,9 @@ void main() { expect(macosInfo.systemGUID, isNotNull); }), skip: !Platform.isMacOS); - testWidgets('Check all Linux info values are available', - ((WidgetTester tester) async { + testWidgets('Check all Linux info values are available', (( + WidgetTester tester, + ) async { expect(linuxInfo.name, isNotNull); expect(linuxInfo.version, isNotNull); expect(linuxInfo.id, isNotNull); @@ -141,96 +145,43 @@ void main() { expect(linuxInfo.variantId, isNull); }), skip: !Platform.isLinux); - testWidgets('Check all Windows info values are available', - ((WidgetTester tester) async { - expect( - windowsInfo.numberOfCores, - isPositive, - ); - expect( - windowsInfo.computerName, - isNotEmpty, - ); - expect( - windowsInfo.systemMemoryInMegabytes, - isPositive, - ); - expect( - windowsInfo.userName, - isNotEmpty, - ); - expect( - windowsInfo.majorVersion, - equals(10), - ); - expect( - windowsInfo.minorVersion, - equals(0), - ); - expect( - windowsInfo.buildNumber, - greaterThan(10240), - ); - expect( - windowsInfo.platformId, - equals(2), - ); - expect( - windowsInfo.reserved, - isZero, - ); - expect( - windowsInfo.buildLab, - isNotEmpty, - ); + testWidgets('Check all Windows info values are available', (( + WidgetTester tester, + ) async { + expect(windowsInfo.numberOfCores, isPositive); + expect(windowsInfo.computerName, isNotEmpty); + expect(windowsInfo.systemMemoryInMegabytes, isPositive); + expect(windowsInfo.userName, isNotEmpty); + expect(windowsInfo.majorVersion, equals(10)); + expect(windowsInfo.minorVersion, equals(0)); + expect(windowsInfo.buildNumber, greaterThan(10240)); + expect(windowsInfo.platformId, equals(2)); + expect(windowsInfo.reserved, isZero); + expect(windowsInfo.buildLab, isNotEmpty); expect( windowsInfo.buildLab, - startsWith( - windowsInfo.buildNumber.toString(), - ), - ); - expect( - windowsInfo.buildLabEx, - isNotEmpty, + startsWith(windowsInfo.buildNumber.toString()), ); + expect(windowsInfo.buildLabEx, isNotEmpty); expect( windowsInfo.buildLab, startsWith(windowsInfo.buildNumber.toString()), ); + expect(windowsInfo.digitalProductId, isNotEmpty); + expect(windowsInfo.editionId, isNotEmpty); + expect(windowsInfo.productId, isNotEmpty); expect( - windowsInfo.digitalProductId, - isNotEmpty, - ); - expect( - windowsInfo.editionId, - isNotEmpty, - ); - expect( - windowsInfo.productId, - isNotEmpty, - ); - expect( - RegExp(r'^([A-Z0-9]{5}-){4}[A-Z0-9]{5}$') - .hasMatch(windowsInfo.productId) || - RegExp(r'^([A-Z0-9]{5}-){3}[A-Z0-9]{5}$') - .hasMatch(windowsInfo.productId), + RegExp( + r'^([A-Z0-9]{5}-){4}[A-Z0-9]{5}$', + ).hasMatch(windowsInfo.productId) || + RegExp( + r'^([A-Z0-9]{5}-){3}[A-Z0-9]{5}$', + ).hasMatch(windowsInfo.productId), isTrue, ); - expect( - windowsInfo.productName, - isNotEmpty, - ); - expect( - windowsInfo.productName, - startsWith('Windows'), - ); - expect( - windowsInfo.releaseId, - isNotEmpty, - ); - expect( - windowsInfo.deviceId, - isNotEmpty, - ); + expect(windowsInfo.productName, isNotEmpty); + expect(windowsInfo.productName, startsWith('Windows')); + expect(windowsInfo.releaseId, isNotEmpty); + expect(windowsInfo.deviceId, isNotEmpty); }), skip: !Platform.isWindows); } diff --git a/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2d..e882ab9889 100644 --- a/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon-App-1024x1024@1x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2fd4..781d7cdcac 100644 --- a/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" + "idiom": "universal", + "filename": "LaunchImage.png", + "scale": "1x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" + "idiom": "universal", + "filename": "LaunchImage@2x.png", + "scale": "2x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" + "idiom": "universal", + "filename": "LaunchImage@3x.png", + "scale": "3x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725b70..d880e1f556 100644 --- a/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/packages/device_info_plus/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,8 @@ # Launch Screen Assets -You can customize the launch screen with your own desired assets by replacing the image files in this directory. +You can customize the launch screen with your own desired assets by replacing the image files in +this directory. -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file +You can also do it by opening your Flutter project's Xcode project with +`open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and +dropping in the desired images. diff --git a/packages/device_info_plus/device_info_plus/example/lib/main.dart b/packages/device_info_plus/device_info_plus/example/lib/main.dart index 24afdc091d..2be5aeffec 100644 --- a/packages/device_info_plus/device_info_plus/example/lib/main.dart +++ b/packages/device_info_plus/device_info_plus/example/lib/main.dart @@ -13,11 +13,14 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { - runZonedGuarded(() { - runApp(const MyApp()); - }, (dynamic error, dynamic stack) { - developer.log("Something went wrong!", error: error, stackTrace: stack); - }); + runZonedGuarded( + () { + runApp(const MyApp()); + }, + (dynamic error, dynamic stack) { + developer.log("Something went wrong!", error: error, stackTrace: stack); + }, + ); } class MyApp extends StatefulWidget { @@ -45,24 +48,29 @@ class _MyAppState extends State { deviceData = _readWebBrowserInfo(await deviceInfoPlugin.webBrowserInfo); } else { deviceData = switch (defaultTargetPlatform) { - TargetPlatform.android => - _readAndroidBuildData(await deviceInfoPlugin.androidInfo), - TargetPlatform.iOS => - _readIosDeviceInfo(await deviceInfoPlugin.iosInfo), - TargetPlatform.linux => - _readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo), - TargetPlatform.windows => - _readWindowsDeviceInfo(await deviceInfoPlugin.windowsInfo), - TargetPlatform.macOS => - _readMacOsDeviceInfo(await deviceInfoPlugin.macOsInfo), + TargetPlatform.android => _readAndroidBuildData( + await deviceInfoPlugin.androidInfo, + ), + TargetPlatform.iOS => _readIosDeviceInfo( + await deviceInfoPlugin.iosInfo, + ), + TargetPlatform.linux => _readLinuxDeviceInfo( + await deviceInfoPlugin.linuxInfo, + ), + TargetPlatform.windows => _readWindowsDeviceInfo( + await deviceInfoPlugin.windowsInfo, + ), + TargetPlatform.macOS => _readMacOsDeviceInfo( + await deviceInfoPlugin.macOsInfo, + ), TargetPlatform.fuchsia => { - 'Error:': 'Fuchsia platform isn\'t supported' - }, + 'Error:': 'Fuchsia platform isn\'t supported', + }, }; } } on PlatformException { deviceData = { - 'Error:': 'Failed to get platform version.' + 'Error:': 'Failed to get platform version.', }; } @@ -219,51 +227,46 @@ class _MyAppState extends State { colorSchemeSeed: const Color(0x9f4376f8), ), home: Scaffold( - appBar: AppBar( - title: Text(_getAppBarTitle()), - elevation: 4, - ), + appBar: AppBar(title: Text(_getAppBarTitle()), elevation: 4), body: ListView( - children: _deviceData.keys.map( - (String property) { - return Row( - children: [ - Container( - padding: const EdgeInsets.all(10), - child: Text( - property, - style: const TextStyle( - fontWeight: FontWeight.bold, + children: + _deviceData.keys.map((String property) { + return Row( + children: [ + Container( + padding: const EdgeInsets.all(10), + child: Text( + property, + style: const TextStyle(fontWeight: FontWeight.bold), ), ), - ), - Expanded( - child: Container( - padding: const EdgeInsets.symmetric(vertical: 10), - child: Text( - '${_deviceData[property]}', - maxLines: 10, - overflow: TextOverflow.ellipsis, + Expanded( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Text( + '${_deviceData[property]}', + maxLines: 10, + overflow: TextOverflow.ellipsis, + ), ), ), - ), - ], - ); - }, - ).toList(), + ], + ); + }).toList(), ), ), ); } - String _getAppBarTitle() => kIsWeb - ? 'Web Browser info' - : switch (defaultTargetPlatform) { - TargetPlatform.android => 'Android Device Info', - TargetPlatform.iOS => 'iOS Device Info', - TargetPlatform.linux => 'Linux Device Info', - TargetPlatform.windows => 'Windows Device Info', - TargetPlatform.macOS => 'MacOS Device Info', - TargetPlatform.fuchsia => 'Fuchsia Device Info', - }; + String _getAppBarTitle() => + kIsWeb + ? 'Web Browser info' + : switch (defaultTargetPlatform) { + TargetPlatform.android => 'Android Device Info', + TargetPlatform.iOS => 'iOS Device Info', + TargetPlatform.linux => 'Linux Device Info', + TargetPlatform.windows => 'Windows Device Info', + TargetPlatform.macOS => 'MacOS Device Info', + TargetPlatform.fuchsia => 'Fuchsia Device Info', + }; } diff --git a/packages/device_info_plus/device_info_plus/example/linux/CMakeLists.txt b/packages/device_info_plus/device_info_plus/example/linux/CMakeLists.txt index fe30a3e6d3..1fe33d4474 100644 --- a/packages/device_info_plus/device_info_plus/example/linux/CMakeLists.txt +++ b/packages/device_info_plus/device_info_plus/example/linux/CMakeLists.txt @@ -9,19 +9,19 @@ cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif () # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -37,9 +37,9 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") # Application build add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) target_link_libraries(${BINARY_NAME} PRIVATE flutter) @@ -50,8 +50,8 @@ add_dependencies(${BINARY_NAME} flutter_assemble) # people trying to run the unbundled copy, put it in a subdirectory instead of # the default top-level location. set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) # Generated plugin build rules, which manage building the plugins and adding @@ -63,9 +63,9 @@ include(flutter/generated_plugins.cmake) # By default, "installing" just makes a relocatable bundle in the build # directory. set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () # Start with a clean build bundle directory every time. install(CODE " @@ -76,19 +76,19 @@ set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -97,10 +97,10 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () diff --git a/packages/device_info_plus/device_info_plus/example/linux/flutter/CMakeLists.txt b/packages/device_info_plus/device_info_plus/example/linux/flutter/CMakeLists.txt index 5b465c7ecf..03e4a7fe4a 100644 --- a/packages/device_info_plus/device_info_plus/example/linux/flutter/CMakeLists.txt +++ b/packages/device_info_plus/device_info_plus/example/linux/flutter/CMakeLists.txt @@ -12,9 +12,9 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # which isn't available in 3.10. function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) + foreach (element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) + endforeach (element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() @@ -35,38 +35,38 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO - PkgConfig::BLKID + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID ) add_dependencies(flutter flutter_assemble) @@ -75,15 +75,15 @@ add_dependencies(flutter flutter_assemble) # since currently there's no way to get a full input/output list from the # flutter tool. add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} ) diff --git a/packages/device_info_plus/device_info_plus/example/linux/main.cc b/packages/device_info_plus/device_info_plus/example/linux/main.cc index 8bc1561588..dbe6db8472 100644 --- a/packages/device_info_plus/device_info_plus/example/linux/main.cc +++ b/packages/device_info_plus/device_info_plus/example/linux/main.cc @@ -1,11 +1,12 @@ #include "my_application.h" int main(int argc, char **argv) { - // Only X11 is currently supported. - // Wayland support is being developed: - // https://github.com/flutter/flutter/issues/57932. - gdk_set_allowed_backends("x11"); + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); + g_autoptr(MyApplication) + app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); } diff --git a/packages/device_info_plus/device_info_plus/example/linux/my_application.cc b/packages/device_info_plus/device_info_plus/example/linux/my_application.cc index cef2f77145..20cf1fa128 100644 --- a/packages/device_info_plus/device_info_plus/example/linux/my_application.cc +++ b/packages/device_info_plus/device_info_plus/example/linux/my_application.cc @@ -5,41 +5,43 @@ #include "flutter/generated_plugin_registrant.h" struct _MyApplication { - GtkApplication parent_instance; + GtkApplication parent_instance; }; -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION +) // Implements GApplication::activate. static void my_application_activate(GApplication *application) { - GtkWindow *window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - - FlView *view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) + project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); } static void my_application_class_init(MyApplicationClass *klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->activate = my_application_activate; } -static void my_application_init(MyApplication *self) {} +static void my_application_init(MyApplication * self) {} MyApplication *my_application_new() { - return MY_APPLICATION(g_object_new( - my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); } diff --git a/packages/device_info_plus/device_info_plus/example/linux/my_application.h b/packages/device_info_plus/device_info_plus/example/linux/my_application.h index 3258a73cf4..5b081e77c6 100644 --- a/packages/device_info_plus/device_info_plus/example/linux/my_application.h +++ b/packages/device_info_plus/device_info_plus/example/linux/my_application.h @@ -4,7 +4,8 @@ #include G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) + GtkApplication +) /** * my_application_new: diff --git a/packages/device_info_plus/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/device_info_plus/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f19f..60e60c947e 100644 --- a/packages/device_info_plus/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/device_info_plus/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ + "images": [ { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" }, { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/device_info_plus/device_info_plus/example/web/index.html b/packages/device_info_plus/device_info_plus/example/web/index.html index 99eacb2839..87a594f74c 100644 --- a/packages/device_info_plus/device_info_plus/example/web/index.html +++ b/packages/device_info_plus/device_info_plus/example/web/index.html @@ -1,23 +1,23 @@ - - - + + + - - - - - + + + + + - - + + - example - + example + - + diff --git a/packages/device_info_plus/device_info_plus/example/web/manifest.json b/packages/device_info_plus/device_info_plus/example/web/manifest.json index 8c012917da..037463cc72 100644 --- a/packages/device_info_plus/device_info_plus/example/web/manifest.json +++ b/packages/device_info_plus/device_info_plus/example/web/manifest.json @@ -1,23 +1,23 @@ { - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] } diff --git a/packages/device_info_plus/device_info_plus/example/windows/CMakeLists.txt b/packages/device_info_plus/device_info_plus/example/windows/CMakeLists.txt index abf90408ef..5d3a4fe2dc 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/CMakeLists.txt +++ b/packages/device_info_plus/device_info_plus/example/windows/CMakeLists.txt @@ -9,17 +9,17 @@ set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() +if (IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else () + if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif () +endif () set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") @@ -31,11 +31,11 @@ add_definitions(-DUNICODE -D_UNICODE) # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -58,27 +58,27 @@ include(flutter/generated_plugins.cmake) set(BUILD_BUNDLE_DIR "$") # Make the "install" step default, as it's required to run. set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -87,9 +87,9 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/device_info_plus/device_info_plus/example/windows/flutter/CMakeLists.txt b/packages/device_info_plus/device_info_plus/example/windows/flutter/CMakeLists.txt index b02c5485c9..33bff4bf3c 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/flutter/CMakeLists.txt +++ b/packages/device_info_plus/device_info_plus/example/windows/flutter/CMakeLists.txt @@ -19,61 +19,61 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") add_dependencies(flutter flutter_assemble) # === Wrapper === list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" + "core_implementations.cc" + "standard_codec.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" + "plugin_registrar.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" + "flutter_engine.cc" + "flutter_view_controller.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") # Wrapper sources needed for a plugin. add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} ) apply_standard_settings(flutter_wrapper_plugin) set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_plugin flutter_assemble) # Wrapper sources needed for the runner. add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} ) apply_standard_settings(flutter_wrapper_app) target_link_libraries(flutter_wrapper_app PUBLIC flutter) target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_app flutter_assemble) @@ -84,20 +84,20 @@ add_dependencies(flutter_wrapper_app flutter_assemble) set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} ) diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/CMakeLists.txt b/packages/device_info_plus/device_info_plus/example/windows/runner/CMakeLists.txt index 977e38b5d1..3fdcb0dd27 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/CMakeLists.txt +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/CMakeLists.txt @@ -2,14 +2,14 @@ cmake_minimum_required(VERSION 3.15) project(runner LANGUAGES CXX) add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "run_loop.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" ) apply_standard_settings(${BINARY_NAME}) target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/Runner.rc b/packages/device_info_plus/device_info_plus/example/windows/runner/Runner.rc index 13f98c0aef..75f4fd1d8e 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/Runner.rc +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/Runner.rc @@ -1,6 +1,7 @@ // Microsoft Visual C++ generated resource script. // #pragma code_page(65001) + #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS @@ -20,27 +21,27 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// + ///////////////////////////////////////////////////////////////////////////// + // + // TEXTINCLUDE + // -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END + 1 TEXTINCLUDE + BEGIN + "resource.h\0" + END -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END + 2 TEXTINCLUDE + BEGIN + "#include ""winres.h""\r\n" + "\0" + END -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END + 3 TEXTINCLUDE + BEGIN + "\r\n" + "\0" + END #endif // APSTUDIO_INVOKED @@ -73,37 +74,41 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEVERSION VERSION_AS_NUMBER +PRODUCTVERSION VERSION_AS_NUMBER +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG +FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L +FILEFLAGS 0x0L #endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0x0L BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "io.flutter.plugins.deviceinfoexample" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2021 io.flutter.plugins.deviceinfoexample. All rights reserved." "\0" - VALUE "OriginalFilename", "example.exe" "\0" - VALUE "ProductName", "example" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" + BLOCK +"StringFileInfo" +BEGIN + BLOCK +"040904e4" +BEGIN + VALUE +"CompanyName", "io.flutter.plugins.deviceinfoexample" "\0" +VALUE "FileDescription", "A new Flutter project." "\0" +VALUE "FileVersion", VERSION_AS_STRING "\0" +VALUE "InternalName", "example" "\0" +VALUE "LegalCopyright", "Copyright (C) 2021 io.flutter.plugins.deviceinfoexample. All rights reserved." "\0" +VALUE "OriginalFilename", "example.exe" "\0" +VALUE "ProductName", "example" "\0" +VALUE "ProductVersion", VERSION_AS_STRING "\0" +END END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END +BLOCK "VarFileInfo" +BEGIN + VALUE +"Translation", 0x409, 1252 END + END #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/flutter_window.cpp b/packages/device_info_plus/device_info_plus/example/windows/runner/flutter_window.cpp index 0f0105d995..c0ae50a354 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/flutter_window.cpp +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/flutter_window.cpp @@ -6,59 +6,64 @@ FlutterWindow::FlutterWindow(RunLoop *run_loop, const flutter::DartProject &project) - : run_loop_(run_loop), project_(project) {} + : run_loop_(run_loop), project_(project) {} FlutterWindow::~FlutterWindow() {} bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } + if (!Win32Window::OnCreate()) { + return false; + } - RECT frame = GetClientArea(); + RECT frame = GetClientArea(); - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - return true; + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; } void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); - flutter_controller_ = nullptr; - } + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } - Win32Window::OnDestroy(); + Win32Window::OnDestroy(); } LRESULT FlutterWindow::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opporutunity to handle window messages. - if (flutter_controller_) { - std::optional result = + LPARAM const lparam) + +noexcept { +// Give Flutter, including plugins, an opporutunity to handle window messages. +if (flutter_controller_) { +std::optional result = flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, lparam); - if (result) { - return *result; - } - } +if (result) { +return * +result; +} +} - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } +switch (message) { +case WM_FONTCHANGE: +flutter_controller_->engine()->ReloadSystemFonts(); +break; +} - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +return +Win32Window::MessageHandler(hwnd, message, wparam, lparam +); } diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/flutter_window.h b/packages/device_info_plus/device_info_plus/example/windows/runner/flutter_window.h index 69234d4f5e..da91a8f3f2 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/flutter_window.h +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/flutter_window.h @@ -12,28 +12,33 @@ // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: - // Creates a new FlutterWindow driven by the |run_loop|, hosting a - // Flutter view running |project|. - explicit FlutterWindow(RunLoop *run_loop, - const flutter::DartProject &project); - virtual ~FlutterWindow(); + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + + virtual ~FlutterWindow(); protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; + // Win32Window: + bool OnCreate() override; + + void OnDestroy() override; + + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) + + noexcept override; private: - // The run loop driving events for this window. - RunLoop *run_loop_; + // The run loop driving events for this window. + RunLoop *run_loop_; - // The project to run. - flutter::DartProject project_; + // The project to run. + flutter::DartProject project_; - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; }; #endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/main.cpp b/packages/device_info_plus/device_info_plus/example/windows/runner/main.cpp index 098956860e..c92ebc79c9 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/main.cpp +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/main.cpp @@ -6,36 +6,52 @@ #include "run_loop.h" #include "utils.h" -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } +int APIENTRY +wWinMain(_In_ +HINSTANCE instance, _In_opt_ +HINSTANCE prev, + _In_ +wchar_t *command_line, _In_ +int show_command +) { +// Attach to console when present (e.g., 'flutter run') or create a +// new console when running with a debugger. +if (! +::AttachConsole(ATTACH_PARENT_PROCESS) +&& ::IsDebuggerPresent()) { +CreateAndAttachConsole(); - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); +} + +// Initialize COM, so that it is available for use in the library and/or +// plugins. +::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED +); - RunLoop run_loop; +RunLoop run_loop; - flutter::DartProject project(L"data"); +flutter::DartProject project(L"data"); - std::vector command_line_arguments = GetCommandLineArguments(); +std::vector command_line_arguments = GetCommandLineArguments(); - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); +project. +set_dart_entrypoint_arguments(std::move(command_line_arguments) +); + +FlutterWindow window(&run_loop, project); +Win32Window::Point origin(10, 10); +Win32Window::Size size(1280, 720); +if (!window.CreateAndShow(L"example", origin, size)) { +return +EXIT_FAILURE; +} +window.SetQuitOnClose(true); - FlutterWindow window(&run_loop, project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"example", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); +run_loop. - run_loop.Run(); +Run(); - ::CoUninitialize(); - return EXIT_SUCCESS; +::CoUninitialize(); +return +EXIT_SUCCESS; } diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/run_loop.cpp b/packages/device_info_plus/device_info_plus/example/windows/runner/run_loop.cpp index 31b89f6229..6ee4580c2e 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/run_loop.cpp +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/run_loop.cpp @@ -9,58 +9,58 @@ RunLoop::RunLoop() {} RunLoop::~RunLoop() {} void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - } } void RunLoop::RegisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.insert(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); } void RunLoop::UnregisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.erase(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); } RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { - TimePoint next_event_time = TimePoint::max(); - for (auto instance : flutter_instances_) { - std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); - if (wait_duration != std::chrono::nanoseconds::max()) { - next_event_time = - std::min(next_event_time, TimePoint::clock::now() + wait_duration); + TimePoint next_event_time = TimePoint::max(); + for (auto instance: flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } } - } - return next_event_time; + return next_event_time; } diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/run_loop.h b/packages/device_info_plus/device_info_plus/example/windows/runner/run_loop.h index 7fe1aaccc2..5105e29d76 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/run_loop.h +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/run_loop.h @@ -10,29 +10,31 @@ // as native messages. class RunLoop { public: - RunLoop(); - ~RunLoop(); + RunLoop(); - // Prevent copying - RunLoop(RunLoop const &) = delete; - RunLoop &operator=(RunLoop const &) = delete; + ~RunLoop(); - // Runs the run loop until the application quits. - void Run(); + // Prevent copying + RunLoop(RunLoop const &) = delete; - // Registers the given Flutter instance for event servicing. - void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + RunLoop &operator=(RunLoop const &) = delete; - // Unregisters the given Flutter instance from event servicing. - void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); private: - using TimePoint = std::chrono::steady_clock::time_point; + using TimePoint = std::chrono::steady_clock::time_point; - // Processes all currently pending messages for registered Flutter instances. - TimePoint ProcessFlutterMessages(); + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); - std::set flutter_instances_; + std::set flutter_instances_; }; #endif // RUNNER_RUN_LOOP_H_ diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/utils.cpp b/packages/device_info_plus/device_info_plus/example/windows/runner/utils.cpp index 7758aabf38..7113aa377e 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/utils.cpp +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/utils.cpp @@ -8,56 +8,56 @@ #include void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } } -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } - std::vector command_line_arguments; + std::vector command_line_arguments; - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } - ::LocalFree(argv); + ::LocalFree(argv); - return command_line_arguments; + return command_line_arguments; } std::string Utf8FromUtf16(const wchar_t *utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - int target_length = - ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, - nullptr, 0, nullptr, nullptr); - if (target_length == 0) { - return std::string(); - } - std::string utf8_string; - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), - target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; } diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/utils.h b/packages/device_info_plus/device_info_plus/example/windows/runner/utils.h index ff43ce2ce5..2deec25811 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/utils.h +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/utils.h @@ -14,6 +14,6 @@ std::string Utf8FromUtf16(const wchar_t *utf16_string); // Gets the command line arguments passed in as a std::vector, // encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); +std::vector GetCommandLineArguments(); #endif // RUNNER_UTILS_H_ diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/win32_window.cpp b/packages/device_info_plus/device_info_plus/example/windows/runner/win32_window.cpp index 90ff01e592..b87e3eb19d 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/win32_window.cpp +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/win32_window.cpp @@ -6,33 +6,36 @@ namespace { -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; // The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; + static int g_active_window_count = 0; -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + using EnableNonClientDpiScaling = + BOOL __stdcall(HWND + hwnd); // Scale helper to convert logical scaler values to physical using passed in // scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} + int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); + } // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. // This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { + void EnableFullDpiSupportIfAvailable(HWND + hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); - } +} +auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); +if (enable_non_client_dpi_scaling != nullptr) { +enable_non_client_dpi_scaling(hwnd); +FreeLibrary(user32_module); +} } } // namespace @@ -40,198 +43,228 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { // Manages the Win32Window's window class registration. class WindowClassRegistrar { public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registar instance. - static WindowClassRegistrar *GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; } - return instance_; - } - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t *GetWindowClass(); + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); private: - WindowClassRegistrar() = default; + WindowClassRegistrar() = default; - static WindowClassRegistrar *instance_; + static WindowClassRegistrar *instance_; - bool class_registered_ = false; + bool class_registered_ = false; }; WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; const wchar_t *WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; } void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; } Win32Window::Win32Window() { ++g_active_window_count; } Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); + --g_active_window_count; + Destroy(); } bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, const Size &size) { - Destroy(); + Destroy(); - const wchar_t *window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); - if (!window) { - return false; - } + if (!window) { + return false; + } - return OnCreate(); + return OnCreate(); } // static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window *that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } +LRESULT CALLBACK +Win32Window::WndProc(HWND +const window, +UINT const message, + WPARAM +const wparam, +LPARAM const lparam +) noexcept { +if (message == WM_NCCREATE) { +auto window_struct = reinterpret_cast(lparam); +SetWindowLongPtr(window, GWLP_USERDATA, +reinterpret_cast +(window_struct +->lpCreateParams)); + +auto that = static_cast(window_struct->lpCreateParams); +EnableFullDpiSupportIfAvailable(window); +that-> +window_handle_ = window; +} else if ( +Win32Window *that = GetThisFromHandle(window) +) { +return that-> +MessageHandler(window, message, wparam, lparam +); +} - return DefWindowProc(window, message, wparam, lparam); +return +DefWindowProc(window, message, wparam, lparam +); } LRESULT -Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } + Win32Window::MessageHandler(HWND +hwnd, +UINT const message, WPARAM +const wparam, +LPARAM const lparam +) noexcept { +switch (message) { +case WM_DESTROY: +window_handle_ = nullptr; + +Destroy(); + +if (quit_on_close_) { +PostQuitMessage(0); +} +return 0; - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - } +case WM_DPICHANGED: { +auto newRectSize = reinterpret_cast(lparam); +LONG newWidth = newRectSize->right - newRectSize->left; +LONG newHeight = newRectSize->bottom - newRectSize->top; - return DefWindowProc(window_handle_, message, wparam, lparam); +SetWindowPos(hwnd, nullptr, newRectSize +->left, newRectSize->top, newWidth, +newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + +return 0; +} +case WM_SIZE: { +RECT rect = GetClientArea(); +if (child_content_ != nullptr) { +// Size and position the child window. +MoveWindow(child_content_, rect +.left, rect.top, rect.right - rect.left, +rect.bottom - rect.top, TRUE); +} +return 0; +} + +case WM_ACTIVATE: +if (child_content_ != nullptr) { +SetFocus(child_content_); +} +return 0; +} + +return +DefWindowProc(window_handle_, message, wparam, lparam +); } void Win32Window::Destroy() { - OnDestroy(); + OnDestroy(); - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } } -Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); +Win32Window *Win32Window::GetThisFromHandle(HWND const window) + +noexcept { +return reinterpret_cast( +GetWindowLongPtr(window, GWLP_USERDATA +)); } -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); +void Win32Window::SetChildContent(HWND +content) { +child_content_ = content; +SetParent(content, window_handle_ +); +RECT frame = GetClientArea(); - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); +MoveWindow(content, frame +.left, frame.top, frame.right - frame.left, +frame.bottom - frame.top, true); - SetFocus(child_content_); +SetFocus(child_content_); } RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; } HWND Win32Window::GetHandle() { return window_handle_; } void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; + quit_on_close_ = quit_on_close; } bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; + // No-op; provided for subclasses. + return true; } void Win32Window::OnDestroy() { - // No-op; provided for subclasses. + // No-op; provided for subclasses. } diff --git a/packages/device_info_plus/device_info_plus/example/windows/runner/win32_window.h b/packages/device_info_plus/device_info_plus/example/windows/runner/win32_window.h index 7b518125bb..f8b5225436 100644 --- a/packages/device_info_plus/device_info_plus/example/windows/runner/win32_window.h +++ b/packages/device_info_plus/device_info_plus/example/windows/runner/win32_window.h @@ -12,84 +12,97 @@ // rendering and input handling class Win32Window { public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates and shows a win32 window with |title| and position and size using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring &title, const Point &origin, - const Size &size); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); + struct Point { + unsigned int x; + unsigned int y; -protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); + struct Size { + unsigned int width; + unsigned int height; - // Called when Destroy is called. - virtual void OnDestroy(); + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; -private: - friend class WindowClassRegistrar; + Win32Window(); + + virtual ~Win32Window(); - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); - // Retrieves a class instance pointer for |window| - static Win32Window *GetThisFromHandle(HWND const window) noexcept; + // Release OS resources associated with window. + void Destroy(); - bool quit_on_close_ = false; + // Inserts |content| into the window tree. + void SetChildContent(HWND content); - // window handle for top level window. - HWND window_handle_ = nullptr; + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); - // window handle for hosted content. - HWND child_content_ = nullptr; + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) + + noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK + WndProc(HWND + const window, + UINT const message, + WPARAM + const wparam, + LPARAM const lparam + ) + noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) + + noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; }; #endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m index cda41d953f..49f454dc29 100644 --- a/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m +++ b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m @@ -9,200 +9,200 @@ @implementation DeviceIdentifiers + (NSString *)userKnownDeviceModel:(NSString *)identifier { - if ([identifier isEqualToString:@"iPhone6,1"]) { - return @"iPhone 5s"; - } else if ([identifier isEqualToString:@"iPhone6,2"]) { - return @"iPhone 5s"; - } else if ([identifier isEqualToString:@"iPhone7,2"]) { - return @"iPhone 6"; - } else if ([identifier isEqualToString:@"iPhone7,1"]) { - return @"iPhone 6 Plus"; - } else if ([identifier isEqualToString:@"iPhone8,1"]) { - return @"iPhone 6s"; - } else if ([identifier isEqualToString:@"iPhone8,2"]) { - return @"iPhone 6s Plus"; - } else if ([identifier isEqualToString:@"iPhone9,1"] || - [identifier isEqualToString:@"iPhone9,3"]) { - return @"iPhone 7"; - } else if ([identifier isEqualToString:@"iPhone9,2"] || - [identifier isEqualToString:@"iPhone9,4"]) { - return @"iPhone 7 Plus"; - } else if ([identifier isEqualToString:@"iPhone8,4"]) { - return @"iPhone SE"; - } else if ([identifier isEqualToString:@"iPhone10,1"] || - [identifier isEqualToString:@"iPhone10,4"]) { - return @"iPhone 8"; - } else if ([identifier isEqualToString:@"iPhone10,2"] || - [identifier isEqualToString:@"iPhone10,5"]) { - return @"iPhone 8 Plus"; - } else if ([identifier isEqualToString:@"iPhone10,3"] || - [identifier isEqualToString:@"iPhone10,6"]) { - return @"iPhone X"; - } else if ([identifier isEqualToString:@"iPhone11,2"]) { - return @"iPhone XS"; - } else if ([identifier isEqualToString:@"iPhone11,4"] || - [identifier isEqualToString:@"iPhone11,6"]) { - return @"iPhone XS Max"; - } else if ([identifier isEqualToString:@"iPhone11,8"]) { - return @"iPhone XR"; - } else if ([identifier isEqualToString:@"iPhone12,1"]) { - return @"iPhone 11"; - } else if ([identifier isEqualToString:@"iPhone12,3"]) { - return @"iPhone 11 Pro"; - } else if ([identifier isEqualToString:@"iPhone12,5"]) { - return @"iPhone 11 Pro Max"; - } else if ([identifier isEqualToString:@"iPhone12,8"]) { - return @"iPhone SE 2"; - } else if ([identifier isEqualToString:@"iPhone13,2"]) { - return @"iPhone 12"; - } else if ([identifier isEqualToString:@"iPhone13,1"]) { - return @"iPhone 12 Mini"; - } else if ([identifier isEqualToString:@"iPhone13,3"]) { - return @"iPhone 12 Pro"; - } else if ([identifier isEqualToString:@"iPhone13,4"]) { - return @"iPhone 12 Pro Max"; - } else if ([identifier isEqualToString:@"iPhone14,5"]) { - return @"iPhone 13"; - } else if ([identifier isEqualToString:@"iPhone14,4"]) { - return @"iPhone 13 Mini"; - } else if ([identifier isEqualToString:@"iPhone14,2"]) { - return @"iPhone 13 Pro"; - } else if ([identifier isEqualToString:@"iPhone14,3"]) { - return @"iPhone 13 Pro Max"; - } else if ([identifier isEqualToString:@"iPhone14,6"]) { - return @"iPhone SE 3"; - } else if ([identifier isEqualToString:@"iPhone14,7"]) { - return @"iPhone 14"; - } else if ([identifier isEqualToString:@"iPhone14,8"]) { - return @"iPhone 14 Plus"; - } else if ([identifier isEqualToString:@"iPhone15,2"]) { - return @"iPhone 14 Pro"; - } else if ([identifier isEqualToString:@"iPhone15,3"]) { - return @"iPhone 14 Pro Max"; - } else if ([identifier isEqualToString:@"iPhone15,4"]) { - return @"iPhone 15"; - } else if ([identifier isEqualToString:@"iPhone15,5"]) { - return @"iPhone 15 Plus"; - } else if ([identifier isEqualToString:@"iPhone16,1"]) { - return @"iPhone 15 Pro"; - } else if ([identifier isEqualToString:@"iPhone16,2"]) { - return @"iPhone 15 Pro Max"; - } else if ([identifier isEqualToString:@"iPhone17,3"]) { - return @"iPhone 16"; - } else if ([identifier isEqualToString:@"iPhone17,4"]) { - return @"iPhone 16 Plus"; - } else if ([identifier isEqualToString:@"iPhone17,1"]) { - return @"iPhone 16 Pro"; - } else if ([identifier isEqualToString:@"iPhone17,2"]) { - return @"iPhone 16 Pro Max"; - // iPads - } else if ([identifier isEqualToString:@"iPad4,1"] || - [identifier isEqualToString:@"iPad4,2"] || - [identifier isEqualToString:@"iPad4,3"]) { - return @"iPad Air"; - } else if ([identifier isEqualToString:@"iPad5,3"] || - [identifier isEqualToString:@"iPad5,4"]) { - return @"iPad Air 2"; - } else if ([identifier isEqualToString:@"iPad6,11"] || - [identifier isEqualToString:@"iPad6,12"]) { - return @"iPad 5"; - } else if ([identifier isEqualToString:@"iPad7,5"] || - [identifier isEqualToString:@"iPad7,6"]) { - return @"iPad 6"; - } else if ([identifier isEqualToString:@"iPad11,3"] || - [identifier isEqualToString:@"iPad11,4"]) { - return @"iPad Air 3"; - } else if ([identifier isEqualToString:@"iPad7,11"] || - [identifier isEqualToString:@"iPad7,12"]) { - return @"iPad 7"; - } else if ([identifier isEqualToString:@"iPad11,6"] || - [identifier isEqualToString:@"iPad11,7"]) { - return @"iPad 8"; - } else if ([identifier isEqualToString:@"iPad12,1"] || - [identifier isEqualToString:@"iPad12,2"]) { - return @"iPad 9"; - } else if ([identifier isEqualToString:@"iPad13,18"] || - [identifier isEqualToString:@"iPad13,19"]) { - return @"iPad 10"; - } else if ([identifier isEqualToString:@"iPad13,1"] || - [identifier isEqualToString:@"iPad13,2"]) { - return @"iPad Air 4"; - } else if ([identifier isEqualToString:@"iPad13,16"] || - [identifier isEqualToString:@"iPad13,17"]) { - return @"iPad Air 5"; - } else if ([identifier isEqualToString:@"iPad14,8"] || - [identifier isEqualToString:@"iPad14,9"]) { - return @"iPad Air 11-Inch M2"; - } else if ([identifier isEqualToString:@"iPad14,10"] || - [identifier isEqualToString:@"iPad14,11"]) { - return @"iPad Air 13-Inch M2"; - } else if ([identifier isEqualToString:@"iPad2,5"] || - [identifier isEqualToString:@"iPad2,6"] || - [identifier isEqualToString:@"iPad2,7"]) { - return @"iPad Mini"; - } else if ([identifier isEqualToString:@"iPad4,4"] || - [identifier isEqualToString:@"iPad4,5"] || - [identifier isEqualToString:@"iPad4,6"]) { - return @"iPad Mini 2"; - } else if ([identifier isEqualToString:@"iPad4,7"] || - [identifier isEqualToString:@"iPad4,8"] || - [identifier isEqualToString:@"iPad4,9"]) { - return @"iPad Mini 3"; - } else if ([identifier isEqualToString:@"iPad5,1"] || - [identifier isEqualToString:@"iPad5,2"]) { - return @"iPad Mini 4"; - } else if ([identifier isEqualToString:@"iPad11,1"] || - [identifier isEqualToString:@"iPad11,2"]) { - return @"iPad Mini 5"; - } else if ([identifier isEqualToString:@"iPad14,1"] || - [identifier isEqualToString:@"iPad14,2"]) { - return @"iPad Mini 6"; - } else if ([identifier isEqualToString:@"iPad6,3"] || - [identifier isEqualToString:@"iPad6,4"]) { - return @"iPad Pro 9-Inch"; - } else if ([identifier isEqualToString:@"iPad6,7"] || - [identifier isEqualToString:@"iPad6,8"]) { - return @"iPad Pro 12-Inch"; - } else if ([identifier isEqualToString:@"iPad7,1"] || [identifier isEqualToString:@"iPad7,2"]) { - return @"iPad Pro 12-Inch 2"; - } else if ([identifier isEqualToString:@"iPad7,3"] || [identifier isEqualToString:@"iPad7,4"]) { - return @"iPad Pro 10-Inch"; - } else if ([identifier isEqualToString:@"iPad8,1"] || [identifier isEqualToString:@"iPad8,2"] || - [identifier isEqualToString:@"iPad8,3"] || [identifier isEqualToString:@"iPad8,4"]) { - return @"iPad Pro 11-Inch"; - } else if ([identifier isEqualToString:@"iPad8,5"] || [identifier isEqualToString:@"iPad8,6"] || - [identifier isEqualToString:@"iPad8,7"] || [identifier isEqualToString:@"iPad8,8"]) { - return @"iPad Pro 12-Inch 3"; - } else if ([identifier isEqualToString:@"iPad8,9"] || - [identifier isEqualToString:@"iPad8,10"]) { - return @"iPad Pro 11-Inch 2"; - } else if ([identifier isEqualToString:@"iPad8,11"] || - [identifier isEqualToString:@"iPad8,12"]) { - return @"iPad Pro 12-Inch 4"; - } else if ([identifier isEqualToString:@"iPad13,4"] || - [identifier isEqualToString:@"iPad13,5"] || - [identifier isEqualToString:@"iPad13,6"] || - [identifier isEqualToString:@"iPad13,7"]) { - return @"iPad Pro 11-Inch 3"; - } else if ([identifier isEqualToString:@"iPad13,8"] || - [identifier isEqualToString:@"iPad13,9"] || - [identifier isEqualToString:@"iPad13,10"] || - [identifier isEqualToString:@"iPad13,11"]) { - return @"iPad Pro 12-Inch 5"; - } else if ([identifier isEqualToString:@"iPad14,3"] || - [identifier isEqualToString:@"iPad14,4"]) { - return @"iPad Pro 11-Inch 4"; - } else if ([identifier isEqualToString:@"iPad14,5"] || - [identifier isEqualToString:@"iPad14,6"]) { - return @"iPad Pro 12-Inch 6"; - } else if ([identifier isEqualToString:@"iPad16,3"] || - [identifier isEqualToString:@"iPad16,4"]) { - return @"iPad Pro 11-Inch (M4)"; - } else if ([identifier isEqualToString:@"iPad16,5"] || - [identifier isEqualToString:@"iPad16,6"]) { - return @"iPad Pro 13-Inch (M4)"; - } else { - return @"Unknown device"; - } + if ([identifier isEqualToString:@"iPhone6,1"]) { + return @"iPhone 5s"; + } else if ([identifier isEqualToString:@"iPhone6,2"]) { + return @"iPhone 5s"; + } else if ([identifier isEqualToString:@"iPhone7,2"]) { + return @"iPhone 6"; + } else if ([identifier isEqualToString:@"iPhone7,1"]) { + return @"iPhone 6 Plus"; + } else if ([identifier isEqualToString:@"iPhone8,1"]) { + return @"iPhone 6s"; + } else if ([identifier isEqualToString:@"iPhone8,2"]) { + return @"iPhone 6s Plus"; + } else if ([identifier isEqualToString:@"iPhone9,1"] || + [identifier isEqualToString:@"iPhone9,3"]) { + return @"iPhone 7"; + } else if ([identifier isEqualToString:@"iPhone9,2"] || + [identifier isEqualToString:@"iPhone9,4"]) { + return @"iPhone 7 Plus"; + } else if ([identifier isEqualToString:@"iPhone8,4"]) { + return @"iPhone SE"; + } else if ([identifier isEqualToString:@"iPhone10,1"] || + [identifier isEqualToString:@"iPhone10,4"]) { + return @"iPhone 8"; + } else if ([identifier isEqualToString:@"iPhone10,2"] || + [identifier isEqualToString:@"iPhone10,5"]) { + return @"iPhone 8 Plus"; + } else if ([identifier isEqualToString:@"iPhone10,3"] || + [identifier isEqualToString:@"iPhone10,6"]) { + return @"iPhone X"; + } else if ([identifier isEqualToString:@"iPhone11,2"]) { + return @"iPhone XS"; + } else if ([identifier isEqualToString:@"iPhone11,4"] || + [identifier isEqualToString:@"iPhone11,6"]) { + return @"iPhone XS Max"; + } else if ([identifier isEqualToString:@"iPhone11,8"]) { + return @"iPhone XR"; + } else if ([identifier isEqualToString:@"iPhone12,1"]) { + return @"iPhone 11"; + } else if ([identifier isEqualToString:@"iPhone12,3"]) { + return @"iPhone 11 Pro"; + } else if ([identifier isEqualToString:@"iPhone12,5"]) { + return @"iPhone 11 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone12,8"]) { + return @"iPhone SE 2"; + } else if ([identifier isEqualToString:@"iPhone13,2"]) { + return @"iPhone 12"; + } else if ([identifier isEqualToString:@"iPhone13,1"]) { + return @"iPhone 12 Mini"; + } else if ([identifier isEqualToString:@"iPhone13,3"]) { + return @"iPhone 12 Pro"; + } else if ([identifier isEqualToString:@"iPhone13,4"]) { + return @"iPhone 12 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone14,5"]) { + return @"iPhone 13"; + } else if ([identifier isEqualToString:@"iPhone14,4"]) { + return @"iPhone 13 Mini"; + } else if ([identifier isEqualToString:@"iPhone14,2"]) { + return @"iPhone 13 Pro"; + } else if ([identifier isEqualToString:@"iPhone14,3"]) { + return @"iPhone 13 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone14,6"]) { + return @"iPhone SE 3"; + } else if ([identifier isEqualToString:@"iPhone14,7"]) { + return @"iPhone 14"; + } else if ([identifier isEqualToString:@"iPhone14,8"]) { + return @"iPhone 14 Plus"; + } else if ([identifier isEqualToString:@"iPhone15,2"]) { + return @"iPhone 14 Pro"; + } else if ([identifier isEqualToString:@"iPhone15,3"]) { + return @"iPhone 14 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone15,4"]) { + return @"iPhone 15"; + } else if ([identifier isEqualToString:@"iPhone15,5"]) { + return @"iPhone 15 Plus"; + } else if ([identifier isEqualToString:@"iPhone16,1"]) { + return @"iPhone 15 Pro"; + } else if ([identifier isEqualToString:@"iPhone16,2"]) { + return @"iPhone 15 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone17,3"]) { + return @"iPhone 16"; + } else if ([identifier isEqualToString:@"iPhone17,4"]) { + return @"iPhone 16 Plus"; + } else if ([identifier isEqualToString:@"iPhone17,1"]) { + return @"iPhone 16 Pro"; + } else if ([identifier isEqualToString:@"iPhone17,2"]) { + return @"iPhone 16 Pro Max"; + // iPads + } else if ([identifier isEqualToString:@"iPad4,1"] || + [identifier isEqualToString:@"iPad4,2"] || + [identifier isEqualToString:@"iPad4,3"]) { + return @"iPad Air"; + } else if ([identifier isEqualToString:@"iPad5,3"] || + [identifier isEqualToString:@"iPad5,4"]) { + return @"iPad Air 2"; + } else if ([identifier isEqualToString:@"iPad6,11"] || + [identifier isEqualToString:@"iPad6,12"]) { + return @"iPad 5"; + } else if ([identifier isEqualToString:@"iPad7,5"] || + [identifier isEqualToString:@"iPad7,6"]) { + return @"iPad 6"; + } else if ([identifier isEqualToString:@"iPad11,3"] || + [identifier isEqualToString:@"iPad11,4"]) { + return @"iPad Air 3"; + } else if ([identifier isEqualToString:@"iPad7,11"] || + [identifier isEqualToString:@"iPad7,12"]) { + return @"iPad 7"; + } else if ([identifier isEqualToString:@"iPad11,6"] || + [identifier isEqualToString:@"iPad11,7"]) { + return @"iPad 8"; + } else if ([identifier isEqualToString:@"iPad12,1"] || + [identifier isEqualToString:@"iPad12,2"]) { + return @"iPad 9"; + } else if ([identifier isEqualToString:@"iPad13,18"] || + [identifier isEqualToString:@"iPad13,19"]) { + return @"iPad 10"; + } else if ([identifier isEqualToString:@"iPad13,1"] || + [identifier isEqualToString:@"iPad13,2"]) { + return @"iPad Air 4"; + } else if ([identifier isEqualToString:@"iPad13,16"] || + [identifier isEqualToString:@"iPad13,17"]) { + return @"iPad Air 5"; + } else if ([identifier isEqualToString:@"iPad14,8"] || + [identifier isEqualToString:@"iPad14,9"]) { + return @"iPad Air 11-Inch M2"; + } else if ([identifier isEqualToString:@"iPad14,10"] || + [identifier isEqualToString:@"iPad14,11"]) { + return @"iPad Air 13-Inch M2"; + } else if ([identifier isEqualToString:@"iPad2,5"] || + [identifier isEqualToString:@"iPad2,6"] || + [identifier isEqualToString:@"iPad2,7"]) { + return @"iPad Mini"; + } else if ([identifier isEqualToString:@"iPad4,4"] || + [identifier isEqualToString:@"iPad4,5"] || + [identifier isEqualToString:@"iPad4,6"]) { + return @"iPad Mini 2"; + } else if ([identifier isEqualToString:@"iPad4,7"] || + [identifier isEqualToString:@"iPad4,8"] || + [identifier isEqualToString:@"iPad4,9"]) { + return @"iPad Mini 3"; + } else if ([identifier isEqualToString:@"iPad5,1"] || + [identifier isEqualToString:@"iPad5,2"]) { + return @"iPad Mini 4"; + } else if ([identifier isEqualToString:@"iPad11,1"] || + [identifier isEqualToString:@"iPad11,2"]) { + return @"iPad Mini 5"; + } else if ([identifier isEqualToString:@"iPad14,1"] || + [identifier isEqualToString:@"iPad14,2"]) { + return @"iPad Mini 6"; + } else if ([identifier isEqualToString:@"iPad6,3"] || + [identifier isEqualToString:@"iPad6,4"]) { + return @"iPad Pro 9-Inch"; + } else if ([identifier isEqualToString:@"iPad6,7"] || + [identifier isEqualToString:@"iPad6,8"]) { + return @"iPad Pro 12-Inch"; + } else if ([identifier isEqualToString:@"iPad7,1"] || [identifier isEqualToString:@"iPad7,2"]) { + return @"iPad Pro 12-Inch 2"; + } else if ([identifier isEqualToString:@"iPad7,3"] || [identifier isEqualToString:@"iPad7,4"]) { + return @"iPad Pro 10-Inch"; + } else if ([identifier isEqualToString:@"iPad8,1"] || [identifier isEqualToString:@"iPad8,2"] || + [identifier isEqualToString:@"iPad8,3"] || [identifier isEqualToString:@"iPad8,4"]) { + return @"iPad Pro 11-Inch"; + } else if ([identifier isEqualToString:@"iPad8,5"] || [identifier isEqualToString:@"iPad8,6"] || + [identifier isEqualToString:@"iPad8,7"] || [identifier isEqualToString:@"iPad8,8"]) { + return @"iPad Pro 12-Inch 3"; + } else if ([identifier isEqualToString:@"iPad8,9"] || + [identifier isEqualToString:@"iPad8,10"]) { + return @"iPad Pro 11-Inch 2"; + } else if ([identifier isEqualToString:@"iPad8,11"] || + [identifier isEqualToString:@"iPad8,12"]) { + return @"iPad Pro 12-Inch 4"; + } else if ([identifier isEqualToString:@"iPad13,4"] || + [identifier isEqualToString:@"iPad13,5"] || + [identifier isEqualToString:@"iPad13,6"] || + [identifier isEqualToString:@"iPad13,7"]) { + return @"iPad Pro 11-Inch 3"; + } else if ([identifier isEqualToString:@"iPad13,8"] || + [identifier isEqualToString:@"iPad13,9"] || + [identifier isEqualToString:@"iPad13,10"] || + [identifier isEqualToString:@"iPad13,11"]) { + return @"iPad Pro 12-Inch 5"; + } else if ([identifier isEqualToString:@"iPad14,3"] || + [identifier isEqualToString:@"iPad14,4"]) { + return @"iPad Pro 11-Inch 4"; + } else if ([identifier isEqualToString:@"iPad14,5"] || + [identifier isEqualToString:@"iPad14,6"]) { + return @"iPad Pro 12-Inch 6"; + } else if ([identifier isEqualToString:@"iPad16,3"] || + [identifier isEqualToString:@"iPad16,4"]) { + return @"iPad Pro 11-Inch (M4)"; + } else if ([identifier isEqualToString:@"iPad16,5"] || + [identifier isEqualToString:@"iPad16,6"]) { + return @"iPad Pro 13-Inch (M4)"; + } else { + return @"Unknown device"; + } } @end diff --git a/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m index 2b495c7c17..25b29642a1 100644 --- a/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m +++ b/packages/device_info_plus/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m @@ -7,71 +7,73 @@ #import @implementation FPPDeviceInfoPlusPlugin -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *channel = [FlutterMethodChannel - methodChannelWithName:@"dev.fluttercommunity.plus/device_info" - binaryMessenger:[registrar messenger]]; - FPPDeviceInfoPlusPlugin *instance = [[FPPDeviceInfoPlusPlugin alloc] init]; - [registrar addMethodCallDelegate:instance channel:channel]; ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/device_info" + binaryMessenger:[registrar messenger]]; + FPPDeviceInfoPlusPlugin *instance = [[FPPDeviceInfoPlusPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - if ([@"getDeviceInfo" isEqualToString:call.method]) { - UIDevice *device = [UIDevice currentDevice]; - struct utsname un; - uname(&un); + if ([@"getDeviceInfo" isEqualToString:call.method]) { + UIDevice *device = [UIDevice currentDevice]; + struct utsname un; + uname(&un); - NSNumber *isPhysicalNumber = - [NSNumber numberWithBool:[self isDevicePhysical]]; - NSProcessInfo *info = [NSProcessInfo processInfo]; - NSNumber *isiOSAppOnMac = [NSNumber numberWithBool:NO]; - if (@available(iOS 14.0, *)) { - isiOSAppOnMac = [NSNumber numberWithBool:[info isiOSAppOnMac]]; - } - NSString *machine; - NSString *deviceName; - if ([self isDevicePhysical]) { - machine = @(un.machine); + NSNumber *isPhysicalNumber = + [NSNumber numberWithBool:[self isDevicePhysical]]; + NSProcessInfo *info = [NSProcessInfo processInfo]; + NSNumber *isiOSAppOnMac = [NSNumber numberWithBool:NO]; + if (@available + (iOS + 14.0, *)) { + isiOSAppOnMac = [NSNumber numberWithBool:[info isiOSAppOnMac]]; + } + NSString *machine; + NSString *deviceName; + if ([self isDevicePhysical]) { + machine = @(un.machine); + } else { + machine = [info environment][@"SIMULATOR_MODEL_IDENTIFIER"]; + } + deviceName = [DeviceIdentifiers userKnownDeviceModel:machine]; + + result(@{ + @"name": [device name], + @"systemName": [device systemName], + @"systemVersion": [device systemVersion], + @"model": [device model], + @"localizedModel": [device localizedModel], + @"modelName": deviceName, + @"identifierForVendor": [[device identifierForVendor] UUIDString] + ?: [NSNull null], + @"isPhysicalDevice": isPhysicalNumber, + @"isiOSAppOnMac": isiOSAppOnMac, + @"utsname": @{ + @"sysname": @(un.sysname), + @"nodename": @(un.nodename), + @"release": @(un.release), + @"version": @(un.version), + @"machine": machine, + } + }); } else { - machine = [info environment][@"SIMULATOR_MODEL_IDENTIFIER"]; + result(FlutterMethodNotImplemented); } - deviceName = [DeviceIdentifiers userKnownDeviceModel:machine]; - - result(@{ - @"name" : [device name], - @"systemName" : [device systemName], - @"systemVersion" : [device systemVersion], - @"model" : [device model], - @"localizedModel" : [device localizedModel], - @"modelName" : deviceName, - @"identifierForVendor" : [[device identifierForVendor] UUIDString] - ?: [NSNull null], - @"isPhysicalDevice" : isPhysicalNumber, - @"isiOSAppOnMac" : isiOSAppOnMac, - @"utsname" : @{ - @"sysname" : @(un.sysname), - @"nodename" : @(un.nodename), - @"release" : @(un.release), - @"version" : @(un.version), - @"machine" : machine, - } - }); - } else { - result(FlutterMethodNotImplemented); - } } // return value is false if code is run on a simulator - (BOOL)isDevicePhysical { - BOOL isPhysicalDevice = NO; + BOOL isPhysicalDevice = NO; #if TARGET_OS_SIMULATOR - isPhysicalDevice = NO; + isPhysicalDevice = NO; #else - isPhysicalDevice = YES; + isPhysicalDevice = YES; #endif - return isPhysicalDevice; + return isPhysicalDevice; } @end diff --git a/packages/device_info_plus/device_info_plus/lib/device_info_plus.dart b/packages/device_info_plus/device_info_plus/lib/device_info_plus.dart index 38c8376299..27db3532f1 100644 --- a/packages/device_info_plus/device_info_plus/lib/device_info_plus.dart +++ b/packages/device_info_plus/device_info_plus/lib/device_info_plus.dart @@ -50,8 +50,9 @@ class DeviceInfoPlugin { /// /// See: https://developer.android.com/reference/android/os/Build.html Future get androidInfo async => - _cachedAndroidDeviceInfo ??= - AndroidDeviceInfo.fromMap((await _platform.deviceInfo()).data); + _cachedAndroidDeviceInfo ??= AndroidDeviceInfo.fromMap( + (await _platform.deviceInfo()).data, + ); /// This information does not change from call to call. Cache it. IosDeviceInfo? _cachedIosDeviceInfo; @@ -59,8 +60,10 @@ class DeviceInfoPlugin { /// Information derived from `UIDevice`. /// /// See: https://developer.apple.com/documentation/uikit/uidevice - Future get iosInfo async => _cachedIosDeviceInfo ??= - IosDeviceInfo.fromMap((await _platform.deviceInfo()).data); + Future get iosInfo async => + _cachedIosDeviceInfo ??= IosDeviceInfo.fromMap( + (await _platform.deviceInfo()).data, + ); /// This information does not change from call to call. Cache it. LinuxDeviceInfo? _cachedLinuxDeviceInfo; @@ -68,8 +71,9 @@ class DeviceInfoPlugin { /// Information derived from `/etc/os-release`. /// /// See: https://www.freedesktop.org/software/systemd/man/os-release.html - Future get linuxInfo async => _cachedLinuxDeviceInfo ??= - await _platform.deviceInfo() as LinuxDeviceInfo; + Future get linuxInfo async => + _cachedLinuxDeviceInfo ??= + await _platform.deviceInfo() as LinuxDeviceInfo; /// This information does not change from call to call. Cache it. WebBrowserInfo? _cachedWebBrowserInfo; @@ -82,8 +86,10 @@ class DeviceInfoPlugin { MacOsDeviceInfo? _cachedMacosDeviceInfo; /// Returns device information for macos. Information sourced from Sysctl. - Future get macOsInfo async => _cachedMacosDeviceInfo ??= - MacOsDeviceInfo.fromMap((await _platform.deviceInfo()).data); + Future get macOsInfo async => + _cachedMacosDeviceInfo ??= MacOsDeviceInfo.fromMap( + (await _platform.deviceInfo()).data, + ); WindowsDeviceInfo? _cachedWindowsDeviceInfo; diff --git a/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_linux.dart b/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_linux.dart index 95ab8eaca7..bc4b42d3d8 100644 --- a/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_linux.dart +++ b/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_linux.dart @@ -18,7 +18,7 @@ class DeviceInfoPlusLinuxPlugin extends DeviceInfoPlatform { /// DeviceInfoPlusLinuxPlugin({@visibleForTesting FileSystem? fileSystem}) - : _fileSystem = fileSystem ?? const LocalFileSystem(); + : _fileSystem = fileSystem ?? const LocalFileSystem(); @override Future deviceInfo() async { @@ -50,8 +50,9 @@ class DeviceInfoPlusLinuxPlugin extends DeviceInfoPlatform { } Future?> _getOsRelease() { - return _tryReadKeyValues('/etc/os-release').then((value) async => - value ?? await _tryReadKeyValues('/usr/lib/os-release')); + return _tryReadKeyValues('/etc/os-release').then( + (value) async => value ?? await _tryReadKeyValues('/usr/lib/os-release'), + ); } Future?> _getLsbRelease() { @@ -95,10 +96,12 @@ extension _Unquote on String { extension _KeyValues on List { Map toKeyValues() { - return Map.fromEntries(map((line) { - final parts = line.split('='); - if (parts.length != 2) return MapEntry(line, null); - return MapEntry(parts.first, parts.last.unquote()); - })); + return Map.fromEntries( + map((line) { + final parts = line.split('='); + if (parts.length != 2) return MapEntry(line, null); + return MapEntry(parts.first, parts.last.unquote()); + }), + ); } } diff --git a/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_web.dart b/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_web.dart index 30f5727ca3..c9f153a1c9 100644 --- a/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_web.dart +++ b/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_web.dart @@ -17,31 +17,30 @@ class DeviceInfoPlusWebPlugin extends DeviceInfoPlatform { /// Factory method that initializes the DeviceInfoPlus plugin platform /// with an instance of the plugin for the web. static void registerWith(Registrar registrar) { - DeviceInfoPlatform.instance = - DeviceInfoPlusWebPlugin(html.window.navigator); + DeviceInfoPlatform.instance = DeviceInfoPlusWebPlugin( + html.window.navigator, + ); } @override Future deviceInfo() { return Future.value( - WebBrowserInfo.fromMap( - { - 'appCodeName': _navigator.appCodeName, - 'appName': _navigator.appName, - 'appVersion': _navigator.appVersion, - 'deviceMemory': _navigator.safeDeviceMemory, - 'language': _navigator.language, - 'languages': _navigator.languages.toDart, - 'platform': _navigator.platform, - 'product': _navigator.product, - 'productSub': _navigator.productSub, - 'userAgent': _navigator.userAgent, - 'vendor': _navigator.vendor, - 'vendorSub': _navigator.vendorSub, - 'hardwareConcurrency': _navigator.hardwareConcurrency, - 'maxTouchPoints': _navigator.maxTouchPoints, - }, - ), + WebBrowserInfo.fromMap({ + 'appCodeName': _navigator.appCodeName, + 'appName': _navigator.appName, + 'appVersion': _navigator.appVersion, + 'deviceMemory': _navigator.safeDeviceMemory, + 'language': _navigator.language, + 'languages': _navigator.languages.toDart, + 'platform': _navigator.platform, + 'product': _navigator.product, + 'productSub': _navigator.productSub, + 'userAgent': _navigator.userAgent, + 'vendor': _navigator.vendor, + 'vendorSub': _navigator.vendorSub, + 'hardwareConcurrency': _navigator.hardwareConcurrency, + 'maxTouchPoints': _navigator.maxTouchPoints, + }), ); } } diff --git a/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_windows.dart b/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_windows.dart index 7287e180f4..e0395fd152 100644 --- a/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_windows.dart +++ b/packages/device_info_plus/device_info_plus/lib/src/device_info_plus_windows.dart @@ -30,10 +30,12 @@ class DeviceInfoPlusWindowsPlugin extends DeviceInfoPlatform { // package:win32, so we have to manually define it here. // // ignore: non_constant_identifier_names - void Function(Pointer) RtlGetVersion = - DynamicLibrary.open('ntdll.dll').lookupFunction< - Void Function(Pointer), - void Function(Pointer)>('RtlGetVersion'); + void Function(Pointer) RtlGetVersion = DynamicLibrary.open( + 'ntdll.dll', + ).lookupFunction< + Void Function(Pointer), + void Function(Pointer) + >('RtlGetVersion'); /// Returns a [WindowsDeviceInfo] with information about the device. @override @@ -44,30 +46,36 @@ class DeviceInfoPlusWindowsPlugin extends DeviceInfoPlatform { @visibleForTesting WindowsDeviceInfo getInfo() { final systemInfo = calloc(); - final osVersionInfo = calloc() - ..ref.dwOSVersionInfoSize = sizeOf(); + final osVersionInfo = + calloc() + ..ref.dwOSVersionInfoSize = sizeOf(); try { - final currentVersionKey = Registry.openPath(RegistryHive.localMachine, - path: r'SOFTWARE\Microsoft\Windows NT\CurrentVersion'); + final currentVersionKey = Registry.openPath( + RegistryHive.localMachine, + path: r'SOFTWARE\Microsoft\Windows NT\CurrentVersion', + ); final buildLab = currentVersionKey.getStringValue('BuildLab') ?? ''; final buildLabEx = currentVersionKey.getStringValue('BuildLabEx') ?? ''; final digitalProductId = currentVersionKey.getBinaryValue('DigitalProductId') ?? - Uint8List.fromList([]); + Uint8List.fromList([]); final displayVersion = currentVersionKey.getStringValue('DisplayVersion') ?? ''; final editionId = currentVersionKey.getStringValue('EditionID') ?? ''; final installDate = DateTime.fromMillisecondsSinceEpoch( - 1000 * (currentVersionKey.getIntValue('InstallDate') ?? 0)); + 1000 * (currentVersionKey.getIntValue('InstallDate') ?? 0), + ); final productId = currentVersionKey.getStringValue('ProductID') ?? ''; var productName = currentVersionKey.getStringValue('ProductName') ?? ''; final registeredOwner = currentVersionKey.getStringValue('RegisteredOwner') ?? ''; final releaseId = currentVersionKey.getStringValue('ReleaseId') ?? ''; - final sqmClientKey = Registry.openPath(RegistryHive.localMachine, - path: r'SOFTWARE\Microsoft\SQMClient'); + final sqmClientKey = Registry.openPath( + RegistryHive.localMachine, + path: r'SOFTWARE\Microsoft\SQMClient', + ); final machineId = sqmClientKey.getStringValue('MachineId') ?? ''; GetSystemInfo(systemInfo); @@ -140,8 +148,11 @@ class DeviceInfoPlusWindowsPlugin extends DeviceInfoPlatform { // Now allocate memory for a native string and call this a second time. final lpBuffer = wsalloc(nSize.value); try { - final result = - GetComputerNameEx(ComputerNameDnsFullyQualified, lpBuffer, nSize); + final result = GetComputerNameEx( + ComputerNameDnsFullyQualified, + lpBuffer, + nSize, + ); if (result != 0) { return lpBuffer.toDartString(); diff --git a/packages/device_info_plus/device_info_plus/lib/src/model/android_device_info.dart b/packages/device_info_plus/device_info_plus/lib/src/model/android_device_info.dart index d14c8c5908..92684d323b 100644 --- a/packages/device_info_plus/device_info_plus/lib/src/model/android_device_info.dart +++ b/packages/device_info_plus/device_info_plus/lib/src/model/android_device_info.dart @@ -33,11 +33,11 @@ class AndroidDeviceInfo extends BaseDeviceInfo { required List systemFeatures, required this.serialNumber, required this.isLowRamDevice, - }) : supported32BitAbis = List.unmodifiable(supported32BitAbis), - supported64BitAbis = List.unmodifiable(supported64BitAbis), - supportedAbis = List.unmodifiable(supportedAbis), - systemFeatures = List.unmodifiable(systemFeatures), - super(data); + }) : supported32BitAbis = List.unmodifiable(supported32BitAbis), + supported64BitAbis = List.unmodifiable(supported64BitAbis), + supportedAbis = List.unmodifiable(supportedAbis), + systemFeatures = List.unmodifiable(systemFeatures), + super(data); /// Android operating system version values derived from `android.os.Build.VERSION`. final AndroidBuildVersion version; @@ -150,7 +150,8 @@ class AndroidDeviceInfo extends BaseDeviceInfo { return AndroidDeviceInfo._( data: map, version: AndroidBuildVersion._fromMap( - map['version']?.cast() ?? {}), + map['version']?.cast() ?? {}, + ), board: map['board'], bootloader: map['bootloader'], brand: map['brand'], diff --git a/packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart b/packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart index aaf654a776..74b7678377 100644 --- a/packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart +++ b/packages/device_info_plus/device_info_plus/lib/src/model/ios_device_info.dart @@ -78,8 +78,9 @@ class IosDeviceInfo extends BaseDeviceInfo { identifierForVendor: map['identifierForVendor'], isPhysicalDevice: map['isPhysicalDevice'], isiOSAppOnMac: map['isiOSAppOnMac'], - utsname: - IosUtsname._fromMap(map['utsname']?.cast() ?? {}), + utsname: IosUtsname._fromMap( + map['utsname']?.cast() ?? {}, + ), ); } } diff --git a/packages/device_info_plus/device_info_plus/test/device_info_plus_web_test.dart b/packages/device_info_plus/device_info_plus/test/device_info_plus_web_test.dart index b4ed2a4f10..ce5056a2b4 100644 --- a/packages/device_info_plus/device_info_plus/test/device_info_plus_web_test.dart +++ b/packages/device_info_plus/device_info_plus/test/device_info_plus_web_test.dart @@ -6,25 +6,23 @@ import 'package:flutter_test/flutter_test.dart'; void main() { test('WebBrowserInfo from Map with values', () { - final info = WebBrowserInfo.fromMap( - { - 'appCodeName': 'CODENAME', - 'appName': 'NAME', - 'appVersion': 'VERSION', - 'deviceMemory': 64, - 'language': 'en', - 'languages': ['en', 'es'], - 'platform': 'PLATFORM', - 'product': 'PRODUCT', - 'productSub': 'PRODUCTSUB', - 'userAgent': - 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0', - 'vendor': 'VENDOR', - 'vendorSub': 'VENDORSUB', - 'hardwareConcurrency': 1, - 'maxTouchPoints': 2, - }, - ); + final info = WebBrowserInfo.fromMap({ + 'appCodeName': 'CODENAME', + 'appName': 'NAME', + 'appVersion': 'VERSION', + 'deviceMemory': 64, + 'language': 'en', + 'languages': ['en', 'es'], + 'platform': 'PLATFORM', + 'product': 'PRODUCT', + 'productSub': 'PRODUCTSUB', + 'userAgent': + 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0', + 'vendor': 'VENDOR', + 'vendorSub': 'VENDORSUB', + 'hardwareConcurrency': 1, + 'maxTouchPoints': 2, + }); expect(info.appName, 'NAME'); expect(info.browserName, BrowserName.firefox); diff --git a/packages/device_info_plus/device_info_plus/test/model/android_device_info_test.dart b/packages/device_info_plus/device_info_plus/test/model/android_device_info_test.dart index a5ab4e1ece..16d94a4e3f 100644 --- a/packages/device_info_plus/device_info_plus/test/model/android_device_info_test.dart +++ b/packages/device_info_plus/device_info_plus/test/model/android_device_info_test.dart @@ -8,8 +8,9 @@ part '../model/android_device_info_fake.dart'; void main() { group('$AndroidDeviceInfo fromMap | toMap', () { test('fromMap should return $AndroidDeviceInfo with correct values', () { - final androidDeviceInfo = - AndroidDeviceInfo.fromMap(_fakeAndroidDeviceInfo); + final androidDeviceInfo = AndroidDeviceInfo.fromMap( + _fakeAndroidDeviceInfo, + ); expect(androidDeviceInfo.id, 'id'); expect(androidDeviceInfo.host, 'host'); @@ -43,8 +44,9 @@ void main() { }); test('toMap should return map with correct key and map', () { - final androidDeviceInfo = - AndroidDeviceInfo.fromMap(_fakeAndroidDeviceInfo); + final androidDeviceInfo = AndroidDeviceInfo.fromMap( + _fakeAndroidDeviceInfo, + ); expect(androidDeviceInfo.data, _fakeAndroidDeviceInfo); }); diff --git a/packages/device_info_plus/device_info_plus_platform_interface/CHANGELOG.md b/packages/device_info_plus/device_info_plus_platform_interface/CHANGELOG.md index 541a79c7e9..cdcf91164e 100644 --- a/packages/device_info_plus/device_info_plus_platform_interface/CHANGELOG.md +++ b/packages/device_info_plus/device_info_plus_platform_interface/CHANGELOG.md @@ -1,43 +1,48 @@ ## 7.0.2 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 7.0.1 - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 7.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**: refactor of device_info_plus platform implementation (#1293). +- **BREAKING** **FEAT**: refactor of device_info_plus platform implementation (#1293). ## 6.0.1 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 6.0.0 > Note: This release has breaking changes. - - **FIX**: add `@Deprecated` annotation to `toMap` method (#1142). - - **DOCS**: Add info about Android properties availability, update API docs links (#1243). - - **BREAKING** **REFACTOR**: Change nullability for AndroidDeviceInfo properties (#1246). - - **BREAKING** **REFACTOR**: two-package federated architecture (#1228). +- **FIX**: add `@Deprecated` annotation to `toMap` method (#1142). +- **DOCS**: Add info about Android properties availability, update API docs links (#1243). +- **BREAKING** **REFACTOR**: Change nullability for AndroidDeviceInfo properties (#1246). +- **BREAKING** **REFACTOR**: two-package federated architecture (#1228). ## 5.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**: Add support of Android display metrics (#829). +- **BREAKING** **FEAT**: Add support of Android display metrics (#829). ## 4.0.1 - - **CHORE**: Version tagging using melos. +- **CHORE**: Version tagging using melos. ## 4.0.0 -- Re-introduce Windows: Add userName, majorVersion, minorVersion, buildNumber, platformId, csdVersion, servicePackMajor, servicePackMinor, suitMask, productType, reserved, buildLab, buildLabEx, digitalProductId, displayVersion, editionId, installDate, productId, productName, registeredOwner, releaseId, deviceId to WindowsDeviceInfo. +- Re-introduce Windows: Add userName, majorVersion, minorVersion, buildNumber, platformId, + csdVersion, servicePackMajor, servicePackMinor, suitMask, productType, reserved, buildLab, + buildLabEx, digitalProductId, displayVersion, editionId, installDate, productId, productName, + registeredOwner, releaseId, deviceId to WindowsDeviceInfo. ## 3.0.0 @@ -58,7 +63,10 @@ ## 2.4.0 -- Windows: Add userName, majorVersion, minorVersion, buildNumber, platformId, csdVersion, servicePackMajor, servicePackMinor, suitMask, productType, reserved, buildLab, buildLabEx, digitalProductId, displayVersion, editionId, installDate, productId, productName, registeredOwner, releaseId, deviceId to WindowsDeviceInfo. +- Windows: Add userName, majorVersion, minorVersion, buildNumber, platformId, csdVersion, + servicePackMajor, servicePackMinor, suitMask, productType, reserved, buildLab, buildLabEx, + digitalProductId, displayVersion, editionId, installDate, productId, productName, registeredOwner, + releaseId, deviceId to WindowsDeviceInfo. ## 2.3.0+1 diff --git a/packages/device_info_plus/device_info_plus_platform_interface/lib/method_channel/method_channel_device_info.dart b/packages/device_info_plus/device_info_plus_platform_interface/lib/method_channel/method_channel_device_info.dart index e6cc114ed2..aac1dcf2ff 100644 --- a/packages/device_info_plus/device_info_plus_platform_interface/lib/method_channel/method_channel_device_info.dart +++ b/packages/device_info_plus/device_info_plus_platform_interface/lib/method_channel/method_channel_device_info.dart @@ -9,13 +9,15 @@ import 'package:device_info_plus_platform_interface/device_info_plus_platform_in class MethodChannelDeviceInfo extends DeviceInfoPlatform { /// The method channel used to interact with the native platform. @visibleForTesting - MethodChannel channel = - const MethodChannel('dev.fluttercommunity.plus/device_info'); + MethodChannel channel = const MethodChannel( + 'dev.fluttercommunity.plus/device_info', + ); // Generic method channel for all devices @override Future deviceInfo() async { return BaseDeviceInfo( - (await channel.invokeMethod('getDeviceInfo')).cast()); + (await channel.invokeMethod('getDeviceInfo')).cast(), + ); } } diff --git a/packages/device_info_plus/device_info_plus_platform_interface/test/method_channel_device_info_test.dart b/packages/device_info_plus/device_info_plus_platform_interface/test/method_channel_device_info_test.dart index 5fc47a5e3a..b4a10cb136 100644 --- a/packages/device_info_plus/device_info_plus_platform_interface/test/method_channel_device_info_test.dart +++ b/packages/device_info_plus/device_info_plus_platform_interface/test/method_channel_device_info_test.dart @@ -16,17 +16,16 @@ void main() { methodChannelDeviceInfo = MethodChannelDeviceInfo(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - methodChannelDeviceInfo.channel, - (MethodCall methodCall) async { - switch (methodCall.method) { - case 'getDeviceInfo': - return {'device_info': 'is_fake'}; - default: - return null; - } - }, - ); + .setMockMethodCallHandler(methodChannelDeviceInfo.channel, ( + MethodCall methodCall, + ) async { + switch (methodCall.method) { + case 'getDeviceInfo': + return {'device_info': 'is_fake'}; + default: + return null; + } + }); }); test('deviceInfo', () async { diff --git a/packages/network_info_plus/network_info_plus/CHANGELOG.md b/packages/network_info_plus/network_info_plus/CHANGELOG.md index 6b777817a1..754c103627 100644 --- a/packages/network_info_plus/network_info_plus/CHANGELOG.md +++ b/packages/network_info_plus/network_info_plus/CHANGELOG.md @@ -1,40 +1,52 @@ ## 6.1.3 - - **FIX**(network_info_plus): Improve Wi-Fi IP address retrieval on iOS to avoid null ([#3408](https://github.com/fluttercommunity/plus_plugins/issues/3408)). ([7c8894b9](https://github.com/fluttercommunity/plus_plugins/commit/7c8894b99878ccbcc33845f9d19e0921470d5935)) +- **FIX**(network_info_plus): Improve Wi-Fi IP address retrieval on iOS to avoid + null ([#3408](https://github.com/fluttercommunity/plus_plugins/issues/3408)). ([7c8894b9](https://github.com/fluttercommunity/plus_plugins/commit/7c8894b99878ccbcc33845f9d19e0921470d5935)) ## 6.1.2 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 6.1.1 - - **FIX**(network_info_plus): Update privacy manifest path on MacOS ([#3350](https://github.com/fluttercommunity/plus_plugins/issues/3350)). ([18c81efd](https://github.com/fluttercommunity/plus_plugins/commit/18c81efd0b9f510023c481965b5868184d435961)) +- **FIX**(network_info_plus): Update privacy manifest path on + MacOS ([#3350](https://github.com/fluttercommunity/plus_plugins/issues/3350)). ([18c81efd](https://github.com/fluttercommunity/plus_plugins/commit/18c81efd0b9f510023c481965b5868184d435961)) ## 6.1.0 - - **FEAT**(network_info_plus): Add Swift Package Manager support ([#3172](https://github.com/fluttercommunity/plus_plugins/issues/3172)). ([bcf7a5bb](https://github.com/fluttercommunity/plus_plugins/commit/bcf7a5bbd06d667cc6a4390c7cb79c349bdce6c7)) +- **FEAT**(network_info_plus): Add Swift Package Manager + support ([#3172](https://github.com/fluttercommunity/plus_plugins/issues/3172)). ([bcf7a5bb](https://github.com/fluttercommunity/plus_plugins/commit/bcf7a5bbd06d667cc6a4390c7cb79c349bdce6c7)) ## 6.0.2 - - **FIX**(all): Clean up macOS Privacy Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) - - **FIX**(all): Add macOS Privacy Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) +- **FIX**(all): Clean up macOS Privacy + Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) +- **FIX**(all): Add macOS Privacy + Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) ## 6.0.1 - - **FIX**(network_info_plus): Avoid usage of unsupported package:win32 versions ([#3179](https://github.com/fluttercommunity/plus_plugins/issues/3179)). ([79f61add](https://github.com/fluttercommunity/plus_plugins/commit/79f61add195693f33330103dd5f31f6433dfc1f2)) +- **FIX**(network_info_plus): Avoid usage of unsupported package:win32 + versions ([#3179](https://github.com/fluttercommunity/plus_plugins/issues/3179)). ([79f61add](https://github.com/fluttercommunity/plus_plugins/commit/79f61add195693f33330103dd5f31f6433dfc1f2)) ## 6.0.0 > Note: This release has breaking changes. - - **BREAKING** **FIX**(network_info_plus): Do not ignore errors on Android ([#3080](https://github.com/fluttercommunity/plus_plugins/issues/3080)). ([5b0cdf4f](https://github.com/fluttercommunity/plus_plugins/commit/5b0cdf4f71a8cc21b245c7defe355ec7b5796cc2)) - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **BREAKING** **FIX**(network_info_plus): Do not ignore errors on + Android ([#3080](https://github.com/fluttercommunity/plus_plugins/issues/3080)). ([5b0cdf4f](https://github.com/fluttercommunity/plus_plugins/commit/5b0cdf4f71a8cc21b245c7defe355ec7b5796cc2)) +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 5.0.3 - - **REFACTOR**(network_info_plus): Migrate Android example to use the new plugins declaration ([#2768](https://github.com/fluttercommunity/plus_plugins/issues/2768)). ([d7206929](https://github.com/fluttercommunity/plus_plugins/commit/d72069292995355fbe0fe62ec6d74f34005008f6)) - - **DOCS**(network_info_plus): Add explanation on Wi-Fi name in quotes to README ([#2815](https://github.com/fluttercommunity/plus_plugins/issues/2815)). ([e94c9b4b](https://github.com/fluttercommunity/plus_plugins/commit/e94c9b4be566f99dba34718fc2b4868165d31026)) +- **REFACTOR**(network_info_plus): Migrate Android example to use the new plugins + declaration ([#2768](https://github.com/fluttercommunity/plus_plugins/issues/2768)). ([d7206929](https://github.com/fluttercommunity/plus_plugins/commit/d72069292995355fbe0fe62ec6d74f34005008f6)) +- **DOCS**(network_info_plus): Add explanation on Wi-Fi name in quotes to + README ([#2815](https://github.com/fluttercommunity/plus_plugins/issues/2815)). ([e94c9b4b](https://github.com/fluttercommunity/plus_plugins/commit/e94c9b4be566f99dba34718fc2b4868165d31026)) ## 5.0.2 @@ -43,14 +55,24 @@ > - Java 17 for Android part > - Gradle 8.4 for Android part -- **BREAKING** **REFACTOR**(network_info_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2590](https://github.com/fluttercommunity/plus_plugins/issues/2590)). ([4033e162](https://github.com/fluttercommunity/plus_plugins/commit/4033e1623de7836893a672098936c218ee9f7aca)) -- **BREAKING** **FEAT**(network_info_plus): Remove deprecated permission handling methods, update example and docs ([#2686](https://github.com/fluttercommunity/plus_plugins/issues/2686)). ([a71a27c5](https://github.com/fluttercommunity/plus_plugins/commit/a71a27c5fbdbbfc56a30359a1aff0a3d3da8dc73)) -- **BREAKING** **BUILD**(network_info_plus): Target Java 17 on Android ([#2726](https://github.com/fluttercommunity/plus_plugins/issues/2726)). ([5eaa3a7d](https://github.com/fluttercommunity/plus_plugins/commit/5eaa3a7d3ed47ced0a452f7604066d030490d379)) -- **BREAKING** **BUILD**(network_info_plus): Update to target and compile SDK 34 ([#2706](https://github.com/fluttercommunity/plus_plugins/pull/2706)). ([efb3bac](https://github.com/fluttercommunity/plus_plugins/commit/efb3bace46a1e71f4d4fef1d0de67c4195183bf3)) -- **FIX**(network_info_plus): Added getWifiIPv6, getWifiSubmask, getWifiBroadcast and getWifiGatewayIP functions for Windows and fixed getWifiName and getWifiBSSID. ([#2666](https://github.com/fluttercommunity/plus_plugins/issues/2666)). ([915a4431](https://github.com/fluttercommunity/plus_plugins/commit/915a44312b796b10ad65995e0297d7cd23b37cd0)) -- **FIX**(network_info_plus): Add iOS Privacy Info ([#2583](https://github.com/fluttercommunity/plus_plugins/issues/2583)). ([3b0cd6c3](https://github.com/fluttercommunity/plus_plugins/commit/3b0cd6c38e0b736a903c69cf6e3df8e40a37815f)) -- **FEAT**(network_info_plus): Update min iOS target to 12 ([#2659](https://github.com/fluttercommunity/plus_plugins/issues/2659)). ([c01d6012](https://github.com/fluttercommunity/plus_plugins/commit/c01d60120556449c4df5ce74d0f0941f4f8bc061)) -- **DOCS**(network_info_plus): Add note about ios simulators ([#2524](https://github.com/fluttercommunity/plus_plugins/issues/2524)). ([20a7515e](https://github.com/fluttercommunity/plus_plugins/commit/20a7515ead6ffbae02be0b1a5cba91c93bf5c84f)) +- **BREAKING** **REFACTOR**(network_info_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to + 10.14 ([#2590](https://github.com/fluttercommunity/plus_plugins/issues/2590)). ([4033e162](https://github.com/fluttercommunity/plus_plugins/commit/4033e1623de7836893a672098936c218ee9f7aca)) +- **BREAKING** **FEAT**(network_info_plus): Remove deprecated permission handling methods, update + example and + docs ([#2686](https://github.com/fluttercommunity/plus_plugins/issues/2686)). ([a71a27c5](https://github.com/fluttercommunity/plus_plugins/commit/a71a27c5fbdbbfc56a30359a1aff0a3d3da8dc73)) +- **BREAKING** **BUILD**(network_info_plus): Target Java 17 on + Android ([#2726](https://github.com/fluttercommunity/plus_plugins/issues/2726)). ([5eaa3a7d](https://github.com/fluttercommunity/plus_plugins/commit/5eaa3a7d3ed47ced0a452f7604066d030490d379)) +- **BREAKING** **BUILD**(network_info_plus): Update to target and compile SDK + 34 ([#2706](https://github.com/fluttercommunity/plus_plugins/pull/2706)). ([efb3bac](https://github.com/fluttercommunity/plus_plugins/commit/efb3bace46a1e71f4d4fef1d0de67c4195183bf3)) +- **FIX**(network_info_plus): Added getWifiIPv6, getWifiSubmask, getWifiBroadcast and + getWifiGatewayIP functions for Windows and fixed getWifiName and + getWifiBSSID. ([#2666](https://github.com/fluttercommunity/plus_plugins/issues/2666)). ([915a4431](https://github.com/fluttercommunity/plus_plugins/commit/915a44312b796b10ad65995e0297d7cd23b37cd0)) +- **FIX**(network_info_plus): Add iOS Privacy + Info ([#2583](https://github.com/fluttercommunity/plus_plugins/issues/2583)). ([3b0cd6c3](https://github.com/fluttercommunity/plus_plugins/commit/3b0cd6c38e0b736a903c69cf6e3df8e40a37815f)) +- **FEAT**(network_info_plus): Update min iOS target to + 12 ([#2659](https://github.com/fluttercommunity/plus_plugins/issues/2659)). ([c01d6012](https://github.com/fluttercommunity/plus_plugins/commit/c01d60120556449c4df5ce74d0f0941f4f8bc061)) +- **DOCS**(network_info_plus): Add note about ios + simulators ([#2524](https://github.com/fluttercommunity/plus_plugins/issues/2524)). ([20a7515e](https://github.com/fluttercommunity/plus_plugins/commit/20a7515ead6ffbae02be0b1a5cba91c93bf5c84f)) ## 5.0.1 @@ -58,79 +80,96 @@ ## 5.0.0 -> Note: This release was retracted due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). +> Note: This release was retracted due +> to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). ## 4.1.0+1 - - **DOCS**(network_info_plus): Add note about ios simulators ([#2524](https://github.com/fluttercommunity/plus_plugins/issues/2524)). ([20a7515e](https://github.com/fluttercommunity/plus_plugins/commit/20a7515ead6ffbae02be0b1a5cba91c93bf5c84f)) +- **DOCS**(network_info_plus): Add note about ios + simulators ([#2524](https://github.com/fluttercommunity/plus_plugins/issues/2524)). ([20a7515e](https://github.com/fluttercommunity/plus_plugins/commit/20a7515ead6ffbae02be0b1a5cba91c93bf5c84f)) ## 4.1.0 -> Info: This release is a replacement for release 5.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. +> Info: This release is a replacement for release 5.0.0, which was retracted due to +> issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change +> was reverted the major release was also reverted in favor of this one. - - **FIX**(network_info_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2255](https://github.com/fluttercommunity/plus_plugins/issues/2255)). ([2454eac1](https://github.com/fluttercommunity/plus_plugins/commit/2454eac19e08a7e03d7890ce56a97ce8707a5fbb)) - - **FIX**(network_info_plus): Revert bump compileSDK to 34 ([#2231](https://github.com/fluttercommunity/plus_plugins/issues/2231)). ([0c600ee5](https://github.com/fluttercommunity/plus_plugins/commit/0c600ee5fa0a0075ccd7446ad81857ed0855143d)) - - **FIX**(network_info_plus): Return nullable values on windows again ([#2101](https://github.com/fluttercommunity/plus_plugins/issues/2101)). ([ab6e6b52](https://github.com/fluttercommunity/plus_plugins/commit/ab6e6b52ff456fa4b6f8c5a8e2cf7df5a1dd1f4e)) - - **FEAT**(network_info_arm): Remove deprecated VALID_ARCHS iOS property ([#2026](https://github.com/fluttercommunity/plus_plugins/issues/2026)). ([5a20b5a7](https://github.com/fluttercommunity/plus_plugins/commit/5a20b5a7127670e37630d255b6f716777807ebe6)) +- **FIX**(network_info_plus): Change Kotlin version from 1.9.10 to + 1.7.22 ([#2255](https://github.com/fluttercommunity/plus_plugins/issues/2255)). ([2454eac1](https://github.com/fluttercommunity/plus_plugins/commit/2454eac19e08a7e03d7890ce56a97ce8707a5fbb)) +- **FIX**(network_info_plus): Revert bump compileSDK to + 34 ([#2231](https://github.com/fluttercommunity/plus_plugins/issues/2231)). ([0c600ee5](https://github.com/fluttercommunity/plus_plugins/commit/0c600ee5fa0a0075ccd7446ad81857ed0855143d)) +- **FIX**(network_info_plus): Return nullable values on windows + again ([#2101](https://github.com/fluttercommunity/plus_plugins/issues/2101)). ([ab6e6b52](https://github.com/fluttercommunity/plus_plugins/commit/ab6e6b52ff456fa4b6f8c5a8e2cf7df5a1dd1f4e)) +- **FEAT**(network_info_arm): Remove deprecated VALID_ARCHS iOS + property ([#2026](https://github.com/fluttercommunity/plus_plugins/issues/2026)). ([5a20b5a7](https://github.com/fluttercommunity/plus_plugins/commit/5a20b5a7127670e37630d255b6f716777807ebe6)) ## 4.0.2 - - **FIX**(network_info_plus): Regenerate iOS and MacOS example apps ([#1872](https://github.com/fluttercommunity/plus_plugins/issues/1872)). ([c9da2612](https://github.com/fluttercommunity/plus_plugins/commit/c9da2612801f26b943b2822be2baef0e695fdb02)) - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **FIX**(network_info_plus): Regenerate iOS and MacOS example + apps ([#1872](https://github.com/fluttercommunity/plus_plugins/issues/1872)). ([c9da2612](https://github.com/fluttercommunity/plus_plugins/commit/c9da2612801f26b943b2822be2baef0e695fdb02)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 4.0.1 - - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) - - **CHORE**(network_info_plus): Win32 dependency upgrade ([#1823](https://github.com/fluttercommunity/plus_plugins/pull/1823)). ([11b5c24](https://github.com/fluttercommunity/plus_plugins/commit/11b5c24e958adae089c285d585159844ef4d34dc)) +- **FIX**: Add jvm target compatibility to Kotlin + plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **CHORE**(network_info_plus): Win32 dependency + upgrade ([#1823](https://github.com/fluttercommunity/plus_plugins/pull/1823)). ([11b5c24](https://github.com/fluttercommunity/plus_plugins/commit/11b5c24e958adae089c285d585159844ef4d34dc)) ## 4.0.0 > Note: This release has breaking changes. - - **CHORE**(network_info_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(network_info_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1777). - - **REFACTOR**(network_info_plus): Rewrite Windows implementation in Dart (#1780). +- **CHORE**(network_info_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to > + =2.18.0 <4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(network_info_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update + podspec file (#1777). +- **REFACTOR**(network_info_plus): Rewrite Windows implementation in Dart (#1780). ## 3.0.5 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 3.0.4 - - **FIX**(network_info_plus): Type cast for Linux when calling getWifiIP() (#1717). - - **FIX**(network_info_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1703). +- **FIX**(network_info_plus): Type cast for Linux when calling getWifiIP() (#1717). +- **FIX**(network_info_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1703). ## 3.0.3 - - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). - - **FIX**(network_info_plus): import original `getgateway.*` from libnatpmp (#1592). - - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). +- **REFACTOR**(all): Remove all manual dependency_overrides (#1628). +- **FIX**(network_info_plus): import original `getgateway.*` from libnatpmp (#1592). +- **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). ## 3.0.2 - - **DOCS**: Updates for READMEs and website pages (#1389). +- **DOCS**: Updates for READMEs and website pages (#1389). ## 3.0.1 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 3.0.0 > Note: This release has breaking changes. - - **FIX**: lint warnings - add missing dependency for tests (#1233). - - **FIX**: Get SSID on Android 12 and newer (#1231). - - **BREAKING** **REFACTOR**: two-package federated architecture (#1235). +- **FIX**: lint warnings - add missing dependency for tests (#1233). +- **FIX**: Get SSID on Android 12 and newer (#1231). +- **BREAKING** **REFACTOR**: two-package federated architecture (#1235). ## 2.3.2 - - **FIX**: Mark iOS-specific permission methods as deprecated and update docs (#1155). +- **FIX**: Mark iOS-specific permission methods as deprecated and update docs (#1155). ## 2.3.1 - - **CHORE**: Version tagging using melos. +- **CHORE**: Version tagging using melos. ## 2.3.0 diff --git a/packages/network_info_plus/network_info_plus/README.md b/packages/network_info_plus/network_info_plus/README.md index 944d5b7a42..c73babf969 100644 --- a/packages/network_info_plus/network_info_plus/README.md +++ b/packages/network_info_plus/network_info_plus/README.md @@ -12,8 +12,8 @@ themselves accordingly. ## Platform Support | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-: | :---: | :-: | :---: | :----: | -| ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | The functionality is not supported on Web. @@ -48,33 +48,44 @@ final wifiGateway = await info.getWifiGatewayIP(); // 192.168.1.1 ### Device permissions -To access protected WiFi methods related to location, you must request additional permissions on Android and iOS. Users of this plugin should use the [permission_handler](https://pub.dev/packages/permission_handler) Flutter plugin to handle these cases. +To access protected WiFi methods related to location, you must request additional permissions on +Android and iOS. Users of this plugin should use +the [permission_handler](https://pub.dev/packages/permission_handler) Flutter plugin to handle these +cases. -See below for platform-specific information on which permissions need to be requested for protected methods. +See below for platform-specific information on which permissions need to be requested for protected +methods. ### Android **Wi-Fi Name in quotes** -The Android OS will return the Wi-Fi name surrounded in quotes. e.g. `"WiFi Name"` instead of `Wifi Name`. -These double quotes are added by the operating system, but only when the original Wi-Fi name doesn't contain +The Android OS will return the Wi-Fi name surrounded in quotes. e.g. `"WiFi Name"` instead of +`Wifi Name`. +These double quotes are added by the operating system, but only when the original Wi-Fi name doesn't +contain quotes already. The plugin will always return the Wi-Fi name as provided by the OS. This is a known limitation, do not create bug reports about this. #### Permissions on Android -To successfully get WiFi Name or Wi-Fi BSSID starting with Android 1O, ensure all of the following conditions are met: +To successfully get WiFi Name or Wi-Fi BSSID starting with Android 1O, ensure all of the following +conditions are met: -- If your app is targeting Android 10 (API level 29) SDK or higher, your app needs to have the ACCESS_FINE_LOCATION permission. +- If your app is targeting Android 10 (API level 29) SDK or higher, your app needs to have the + ACCESS_FINE_LOCATION permission. -- If your app is targeting SDK lower than Android 10 (API level 29), your app needs to have the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission. +- If your app is targeting SDK lower than Android 10 (API level 29), your app needs to have the + ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission. - Location services are enabled on the device (under Settings > Location). -- If you use device with Android 12 (API level 31) and newer be sure that your app has ACCESS_NETWORK_STATE permission. +- If you use device with Android 12 (API level 31) and newer be sure that your app has + ACCESS_NETWORK_STATE permission. -**This package does not provide the ACCESS_FINE_LOCATION nor the ACCESS_COARSE_LOCATION permission by default.** +**This package does not provide the ACCESS_FINE_LOCATION nor the ACCESS_COARSE_LOCATION permission +by default.** ### iOS @@ -84,11 +95,14 @@ On iOS simulators wifi info will always return `null`. #### iOS 12 -To use `.getWifiBSSID()` and `.getWifiName()` on iOS >= 12, the `Access WiFi information capability` in XCode must be enabled. Otherwise, both methods will return null. +To use `.getWifiBSSID()` and `.getWifiName()` on iOS >= 12, the `Access WiFi information capability` +in XCode must be enabled. Otherwise, both methods will return null. #### iOS 13 -The methods `.getWifiBSSID()` and `.getWifiName()` utilize the [`CNCopyCurrentNetworkInfo`](https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo) function on iOS. +The methods `.getWifiBSSID()` and `.getWifiName()` utilize the [ +`CNCopyCurrentNetworkInfo`](https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo) +function on iOS. As of iOS 13, Apple announced that these APIs will no longer return valid information. An app linked against iOS 12 or earlier receives pseudo-values such as: @@ -107,17 +121,25 @@ The `CNCopyCurrentNetworkInfo` will work for Apps that: - The app has active VPN configurations installed. -If your app falls into the last two categories, it will work as it is. If your app doesn't fall into the last two categories, -and you still need to access the wifi information, you should request user's authorization to use location information. +If your app falls into the last two categories, it will work as it is. If your app doesn't fall into +the last two categories, +and you still need to access the wifi information, you should request user's authorization to use +location information. -Make sure to add the following keys to your _Info.plist_ file, located in `/ios/Runner/Info.plist`: +Make sure to add the following keys to your _Info.plist_ file, located in +`/ios/Runner/Info.plist`: -- `NSLocationAlwaysAndWhenInUseUsageDescription` - describe why the app needs access to the user’s location information all the time (foreground and background). This is called _Privacy - Location Always and When In Use Usage Description_ in the visual editor. -- `NSLocationWhenInUseUsageDescription` - describe why the app needs access to the user’s location information when the app is running in the foreground. This is called _Privacy - Location When In Use Usage Description_ in the visual editor. +- `NSLocationAlwaysAndWhenInUseUsageDescription` - describe why the app needs access to the user’s + location information all the time (foreground and background). This is called _Privacy - Location + Always and When In Use Usage Description_ in the visual editor. +- `NSLocationWhenInUseUsageDescription` - describe why the app needs access to the user’s location + information when the app is running in the foreground. This is called _Privacy - Location When In + Use Usage Description_ in the visual editor. #### iOS 14 -Starting on iOS 14, the plugin uses the method `NEHotspotNetwork.fetchCurrentWithCompletionHandler` to obtain the WIFI SSID (name) and BSSID. +Starting on iOS 14, the plugin uses the method `NEHotspotNetwork.fetchCurrentWithCompletionHandler` +to obtain the WIFI SSID (name) and BSSID. According to this method documentation: @@ -134,14 +156,18 @@ According to this method documentation: **You will have to comply with ONE of the 4 conditions listed.** -The example application for this project, implements number 1 using the [permission_handler](https://pub.dev/packages/permission_handler) plugin. +The example application for this project, implements number 1 using +the [permission_handler](https://pub.dev/packages/permission_handler) plugin. Also, **your application needs the "com.apple.developer.networking.wifi-info" entitlement.** -This entitlement can be configured in xcode with the name "Access Wi-Fi information", and it is also found in the file `Runner.entitlements` in the example project. However, -**this entitlement is only possible when using a professional development team** and not a "Personal development team". +This entitlement can be configured in xcode with the name "Access Wi-Fi information", and it is also +found in the file `Runner.entitlements` in the example project. However, +**this entitlement is only possible when using a professional development team** and not a "Personal +development team". -Without complying with these conditions, the calls to `.getWifiBSSID()` and `.getWifiName()` will return null. +Without complying with these conditions, the calls to `.getWifiBSSID()` and `.getWifiName()` will +return null. ## Learn more diff --git a/packages/network_info_plus/network_info_plus/android/build.gradle b/packages/network_info_plus/network_info_plus/android/build.gradle index b653c42794..0d95edbef7 100644 --- a/packages/network_info_plus/network_info_plus/android/build.gradle +++ b/packages/network_info_plus/network_info_plus/android/build.gradle @@ -2,7 +2,7 @@ group 'dev.fluttercommunity.plus.network_info' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.7.22' + ext.kotlin_version = '2.1.10' repositories { google() mavenCentral() @@ -25,7 +25,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.network_info' diff --git a/packages/network_info_plus/network_info_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/network_info_plus/network_info_plus/android/gradle/wrapper/gradle-wrapper.properties index 774fae8767..2733ed5dc3 100644 --- a/packages/network_info_plus/network_info_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/network_info_plus/network_info_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/network_info_plus/network_info_plus/android/src/main/AndroidManifest.xml b/packages/network_info_plus/network_info_plus/android/src/main/AndroidManifest.xml index dd7b047f5f..457f09e905 100644 --- a/packages/network_info_plus/network_info_plus/android/src/main/AndroidManifest.xml +++ b/packages/network_info_plus/network_info_plus/android/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - - + package="dev.fluttercommunity.plus.network_info"> + + + diff --git a/packages/network_info_plus/network_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/network_info/NetworkInfoPlusPlugin.kt b/packages/network_info_plus/network_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/network_info/NetworkInfoPlusPlugin.kt index a1f7b06bc2..1ab62ad388 100644 --- a/packages/network_info_plus/network_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/network_info/NetworkInfoPlusPlugin.kt +++ b/packages/network_info_plus/network_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/network_info/NetworkInfoPlusPlugin.kt @@ -29,7 +29,8 @@ class NetworkInfoPlusPlugin : FlutterPlugin { var connectivityManager: ConnectivityManager? = null if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - connectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + connectivityManager = + context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager } val networkInfo = NetworkInfo(wifiManager, connectivityManager) diff --git a/packages/network_info_plus/network_info_plus/example/android/app/build.gradle b/packages/network_info_plus/network_info_plus/example/android/app/build.gradle index 6e56eead76..d48d814ffc 100644 --- a/packages/network_info_plus/network_info_plus/example/android/app/build.gradle +++ b/packages/network_info_plus/network_info_plus/example/android/app/build.gradle @@ -22,7 +22,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.network_info_plus_example' @@ -42,7 +42,7 @@ android { defaultConfig { applicationId "dev.fluttercommunity.plus.network_info_plus_example" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/packages/network_info_plus/network_info_plus/example/android/app/src/main/java/dev/fluttercommunity/plus/network_info_plus_example/FlutterActivityTest.java b/packages/network_info_plus/network_info_plus/example/android/app/src/main/java/dev/fluttercommunity/plus/network_info_plus_example/FlutterActivityTest.java index 251b10e998..655cd4bcde 100644 --- a/packages/network_info_plus/network_info_plus/example/android/app/src/main/java/dev/fluttercommunity/plus/network_info_plus_example/FlutterActivityTest.java +++ b/packages/network_info_plus/network_info_plus/example/android/app/src/main/java/dev/fluttercommunity/plus/network_info_plus_example/FlutterActivityTest.java @@ -5,13 +5,15 @@ package dev.fluttercommunity.plus.network_info_plus_example; import androidx.test.rule.ActivityTestRule; + import dev.flutter.plugins.integration_test.FlutterTestRunner; import io.flutter.embedding.android.FlutterActivity; + import org.junit.Rule; import org.junit.runner.RunWith; @RunWith(FlutterTestRunner.class) public class FlutterActivityTest { - @Rule - public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); } diff --git a/packages/network_info_plus/network_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/network_info_plus/network_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties index 10c8c0167e..8476a50e88 100644 --- a/packages/network_info_plus/network_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/network_info_plus/network_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Oct 05 15:29:21 CEST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/network_info_plus/network_info_plus/example/android/settings.gradle b/packages/network_info_plus/network_info_plus/example/android/settings.gradle index 5fad357a02..c45c7624c3 100644 --- a/packages/network_info_plus/network_info_plus/example/android/settings.gradle +++ b/packages/network_info_plus/network_info_plus/example/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false + id "com.android.application" version "8.9.0" apply false } include ":app" diff --git a/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2d..e882ab9889 100644 --- a/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon-App-1024x1024@1x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2fd4..781d7cdcac 100644 --- a/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" + "idiom": "universal", + "filename": "LaunchImage.png", + "scale": "1x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" + "idiom": "universal", + "filename": "LaunchImage@2x.png", + "scale": "2x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" + "idiom": "universal", + "filename": "LaunchImage@3x.png", + "scale": "3x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725b70..d880e1f556 100644 --- a/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/packages/network_info_plus/network_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,8 @@ # Launch Screen Assets -You can customize the launch screen with your own desired assets by replacing the image files in this directory. +You can customize the launch screen with your own desired assets by replacing the image files in +this directory. -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file +You can also do it by opening your Flutter project's Xcode project with +`open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and +dropping in the desired images. diff --git a/packages/network_info_plus/network_info_plus/example/lib/main.dart b/packages/network_info_plus/network_info_plus/example/lib/main.dart index c6b548ea31..437852aa1e 100644 --- a/packages/network_info_plus/network_info_plus/example/lib/main.dart +++ b/packages/network_info_plus/network_info_plus/example/lib/main.dart @@ -71,20 +71,18 @@ class _MyHomePageState extends State { elevation: 4, ), body: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Text( - 'Network info', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + 'Network info', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), - ), - const SizedBox(height: 16), - Text(_connectionStatus), - ], - )), + const SizedBox(height: 16), + Text(_connectionStatus), + ], + ), + ), ); } @@ -167,7 +165,8 @@ class _MyHomePageState extends State { } setState(() { - _connectionStatus = 'Wifi Name: $wifiName\n' + _connectionStatus = + 'Wifi Name: $wifiName\n' 'Wifi BSSID: $wifiBSSID\n' 'Wifi IPv4: $wifiIPv4\n' 'Wifi IPv6: $wifiIPv6\n' diff --git a/packages/network_info_plus/network_info_plus/example/linux/CMakeLists.txt b/packages/network_info_plus/network_info_plus/example/linux/CMakeLists.txt index 279007eb35..c460a20abe 100644 --- a/packages/network_info_plus/network_info_plus/example/linux/CMakeLists.txt +++ b/packages/network_info_plus/network_info_plus/example/linux/CMakeLists.txt @@ -9,19 +9,19 @@ cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif () # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -37,9 +37,9 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") # Application build add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) target_link_libraries(${BINARY_NAME} PRIVATE flutter) @@ -50,8 +50,8 @@ add_dependencies(${BINARY_NAME} flutter_assemble) # people trying to run the unbundled copy, put it in a subdirectory instead of # the default top-level location. set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) # Generated plugin build rules, which manage building the plugins and adding @@ -63,9 +63,9 @@ include(flutter/generated_plugins.cmake) # By default, "installing" just makes a relocatable bundle in the build # directory. set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () # Start with a clean build bundle directory every time. install(CODE " @@ -76,19 +76,19 @@ set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -97,10 +97,10 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () diff --git a/packages/network_info_plus/network_info_plus/example/linux/flutter/CMakeLists.txt b/packages/network_info_plus/network_info_plus/example/linux/flutter/CMakeLists.txt index 5b465c7ecf..03e4a7fe4a 100644 --- a/packages/network_info_plus/network_info_plus/example/linux/flutter/CMakeLists.txt +++ b/packages/network_info_plus/network_info_plus/example/linux/flutter/CMakeLists.txt @@ -12,9 +12,9 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # which isn't available in 3.10. function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) + foreach (element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) + endforeach (element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() @@ -35,38 +35,38 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO - PkgConfig::BLKID + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID ) add_dependencies(flutter flutter_assemble) @@ -75,15 +75,15 @@ add_dependencies(flutter flutter_assemble) # since currently there's no way to get a full input/output list from the # flutter tool. add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} ) diff --git a/packages/network_info_plus/network_info_plus/example/linux/main.cc b/packages/network_info_plus/network_info_plus/example/linux/main.cc index 8bc1561588..dbe6db8472 100644 --- a/packages/network_info_plus/network_info_plus/example/linux/main.cc +++ b/packages/network_info_plus/network_info_plus/example/linux/main.cc @@ -1,11 +1,12 @@ #include "my_application.h" int main(int argc, char **argv) { - // Only X11 is currently supported. - // Wayland support is being developed: - // https://github.com/flutter/flutter/issues/57932. - gdk_set_allowed_backends("x11"); + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); + g_autoptr(MyApplication) + app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); } diff --git a/packages/network_info_plus/network_info_plus/example/linux/my_application.cc b/packages/network_info_plus/network_info_plus/example/linux/my_application.cc index cef2f77145..20cf1fa128 100644 --- a/packages/network_info_plus/network_info_plus/example/linux/my_application.cc +++ b/packages/network_info_plus/network_info_plus/example/linux/my_application.cc @@ -5,41 +5,43 @@ #include "flutter/generated_plugin_registrant.h" struct _MyApplication { - GtkApplication parent_instance; + GtkApplication parent_instance; }; -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION +) // Implements GApplication::activate. static void my_application_activate(GApplication *application) { - GtkWindow *window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - - FlView *view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) + project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); } static void my_application_class_init(MyApplicationClass *klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->activate = my_application_activate; } -static void my_application_init(MyApplication *self) {} +static void my_application_init(MyApplication * self) {} MyApplication *my_application_new() { - return MY_APPLICATION(g_object_new( - my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); } diff --git a/packages/network_info_plus/network_info_plus/example/linux/my_application.h b/packages/network_info_plus/network_info_plus/example/linux/my_application.h index 3258a73cf4..5b081e77c6 100644 --- a/packages/network_info_plus/network_info_plus/example/linux/my_application.h +++ b/packages/network_info_plus/network_info_plus/example/linux/my_application.h @@ -4,7 +4,8 @@ #include G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) + GtkApplication +) /** * my_application_new: diff --git a/packages/network_info_plus/network_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/network_info_plus/network_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f19f..60e60c947e 100644 --- a/packages/network_info_plus/network_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/network_info_plus/network_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ + "images": [ { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" }, { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/network_info_plus/network_info_plus/example/web/index.html b/packages/network_info_plus/network_info_plus/example/web/index.html index 1460b5e9ba..f82ae7ce73 100644 --- a/packages/network_info_plus/network_info_plus/example/web/index.html +++ b/packages/network_info_plus/network_info_plus/example/web/index.html @@ -1,45 +1,45 @@ - - + Fore more details: + * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base + --> + - - - + + + - - - - - + + + + + - - + + - example - + example + - - - + + diff --git a/packages/network_info_plus/network_info_plus/example/web/manifest.json b/packages/network_info_plus/network_info_plus/example/web/manifest.json index 8c012917da..037463cc72 100644 --- a/packages/network_info_plus/network_info_plus/example/web/manifest.json +++ b/packages/network_info_plus/network_info_plus/example/web/manifest.json @@ -1,23 +1,23 @@ { - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] } diff --git a/packages/network_info_plus/network_info_plus/example/windows/CMakeLists.txt b/packages/network_info_plus/network_info_plus/example/windows/CMakeLists.txt index abf90408ef..5d3a4fe2dc 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/CMakeLists.txt +++ b/packages/network_info_plus/network_info_plus/example/windows/CMakeLists.txt @@ -9,17 +9,17 @@ set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() +if (IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else () + if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif () +endif () set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") @@ -31,11 +31,11 @@ add_definitions(-DUNICODE -D_UNICODE) # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -58,27 +58,27 @@ include(flutter/generated_plugins.cmake) set(BUILD_BUNDLE_DIR "$") # Make the "install" step default, as it's required to run. set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -87,9 +87,9 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/network_info_plus/network_info_plus/example/windows/flutter/CMakeLists.txt b/packages/network_info_plus/network_info_plus/example/windows/flutter/CMakeLists.txt index 744f08a938..bc1c2f9f44 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/flutter/CMakeLists.txt +++ b/packages/network_info_plus/network_info_plus/example/windows/flutter/CMakeLists.txt @@ -19,60 +19,60 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") add_dependencies(flutter flutter_assemble) # === Wrapper === list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" + "core_implementations.cc" + "standard_codec.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" + "plugin_registrar.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" + "flutter_engine.cc" + "flutter_view_controller.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") # Wrapper sources needed for a plugin. add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} ) apply_standard_settings(flutter_wrapper_plugin) set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_plugin flutter_assemble) # Wrapper sources needed for the runner. add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} ) apply_standard_settings(flutter_wrapper_app) target_link_libraries(flutter_wrapper_app PUBLIC flutter) target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_app flutter_assemble) @@ -83,20 +83,20 @@ add_dependencies(flutter_wrapper_app flutter_assemble) set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} ) diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/CMakeLists.txt b/packages/network_info_plus/network_info_plus/example/windows/runner/CMakeLists.txt index 977e38b5d1..3fdcb0dd27 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/CMakeLists.txt +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/CMakeLists.txt @@ -2,14 +2,14 @@ cmake_minimum_required(VERSION 3.15) project(runner LANGUAGES CXX) add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "run_loop.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" ) apply_standard_settings(${BINARY_NAME}) target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/Runner.rc b/packages/network_info_plus/network_info_plus/example/windows/runner/Runner.rc index 58e39f4962..994ec61ea4 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/Runner.rc +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/Runner.rc @@ -1,6 +1,7 @@ // Microsoft Visual C++ generated resource script. // #pragma code_page(65001) + #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS @@ -20,27 +21,27 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// + ///////////////////////////////////////////////////////////////////////////// + // + // TEXTINCLUDE + // -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END + 1 TEXTINCLUDE + BEGIN + "resource.h\0" + END -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END + 2 TEXTINCLUDE + BEGIN + "#include ""winres.h""\r\n" + "\0" + END -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END + 3 TEXTINCLUDE + BEGIN + "\r\n" + "\0" + END #endif // APSTUDIO_INVOKED @@ -73,37 +74,41 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEVERSION VERSION_AS_NUMBER +PRODUCTVERSION VERSION_AS_NUMBER +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG +FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L +FILEFLAGS 0x0L #endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0x0L BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "dev.fluttercommunity.plus" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2020 dev.fluttercommunity.plus. All rights reserved." "\0" - VALUE "OriginalFilename", "example.exe" "\0" - VALUE "ProductName", "example" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" + BLOCK +"StringFileInfo" +BEGIN + BLOCK +"040904e4" +BEGIN + VALUE +"CompanyName", "dev.fluttercommunity.plus" "\0" +VALUE "FileDescription", "A new Flutter project." "\0" +VALUE "FileVersion", VERSION_AS_STRING "\0" +VALUE "InternalName", "example" "\0" +VALUE "LegalCopyright", "Copyright (C) 2020 dev.fluttercommunity.plus. All rights reserved." "\0" +VALUE "OriginalFilename", "example.exe" "\0" +VALUE "ProductName", "example" "\0" +VALUE "ProductVersion", VERSION_AS_STRING "\0" +END END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END +BLOCK "VarFileInfo" +BEGIN + VALUE +"Translation", 0x409, 1252 END + END #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/flutter_window.cpp b/packages/network_info_plus/network_info_plus/example/windows/runner/flutter_window.cpp index 0f0105d995..c0ae50a354 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/flutter_window.cpp +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/flutter_window.cpp @@ -6,59 +6,64 @@ FlutterWindow::FlutterWindow(RunLoop *run_loop, const flutter::DartProject &project) - : run_loop_(run_loop), project_(project) {} + : run_loop_(run_loop), project_(project) {} FlutterWindow::~FlutterWindow() {} bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } + if (!Win32Window::OnCreate()) { + return false; + } - RECT frame = GetClientArea(); + RECT frame = GetClientArea(); - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - return true; + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; } void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); - flutter_controller_ = nullptr; - } + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } - Win32Window::OnDestroy(); + Win32Window::OnDestroy(); } LRESULT FlutterWindow::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opporutunity to handle window messages. - if (flutter_controller_) { - std::optional result = + LPARAM const lparam) + +noexcept { +// Give Flutter, including plugins, an opporutunity to handle window messages. +if (flutter_controller_) { +std::optional result = flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, lparam); - if (result) { - return *result; - } - } +if (result) { +return * +result; +} +} - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } +switch (message) { +case WM_FONTCHANGE: +flutter_controller_->engine()->ReloadSystemFonts(); +break; +} - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +return +Win32Window::MessageHandler(hwnd, message, wparam, lparam +); } diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/flutter_window.h b/packages/network_info_plus/network_info_plus/example/windows/runner/flutter_window.h index 69234d4f5e..da91a8f3f2 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/flutter_window.h +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/flutter_window.h @@ -12,28 +12,33 @@ // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: - // Creates a new FlutterWindow driven by the |run_loop|, hosting a - // Flutter view running |project|. - explicit FlutterWindow(RunLoop *run_loop, - const flutter::DartProject &project); - virtual ~FlutterWindow(); + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + + virtual ~FlutterWindow(); protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; + // Win32Window: + bool OnCreate() override; + + void OnDestroy() override; + + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) + + noexcept override; private: - // The run loop driving events for this window. - RunLoop *run_loop_; + // The run loop driving events for this window. + RunLoop *run_loop_; - // The project to run. - flutter::DartProject project_; + // The project to run. + flutter::DartProject project_; - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; }; #endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/main.cpp b/packages/network_info_plus/network_info_plus/example/windows/runner/main.cpp index 098956860e..c92ebc79c9 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/main.cpp +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/main.cpp @@ -6,36 +6,52 @@ #include "run_loop.h" #include "utils.h" -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } +int APIENTRY +wWinMain(_In_ +HINSTANCE instance, _In_opt_ +HINSTANCE prev, + _In_ +wchar_t *command_line, _In_ +int show_command +) { +// Attach to console when present (e.g., 'flutter run') or create a +// new console when running with a debugger. +if (! +::AttachConsole(ATTACH_PARENT_PROCESS) +&& ::IsDebuggerPresent()) { +CreateAndAttachConsole(); - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); +} + +// Initialize COM, so that it is available for use in the library and/or +// plugins. +::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED +); - RunLoop run_loop; +RunLoop run_loop; - flutter::DartProject project(L"data"); +flutter::DartProject project(L"data"); - std::vector command_line_arguments = GetCommandLineArguments(); +std::vector command_line_arguments = GetCommandLineArguments(); - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); +project. +set_dart_entrypoint_arguments(std::move(command_line_arguments) +); + +FlutterWindow window(&run_loop, project); +Win32Window::Point origin(10, 10); +Win32Window::Size size(1280, 720); +if (!window.CreateAndShow(L"example", origin, size)) { +return +EXIT_FAILURE; +} +window.SetQuitOnClose(true); - FlutterWindow window(&run_loop, project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"example", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); +run_loop. - run_loop.Run(); +Run(); - ::CoUninitialize(); - return EXIT_SUCCESS; +::CoUninitialize(); +return +EXIT_SUCCESS; } diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/run_loop.cpp b/packages/network_info_plus/network_info_plus/example/windows/runner/run_loop.cpp index 31b89f6229..6ee4580c2e 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/run_loop.cpp +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/run_loop.cpp @@ -9,58 +9,58 @@ RunLoop::RunLoop() {} RunLoop::~RunLoop() {} void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - } } void RunLoop::RegisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.insert(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); } void RunLoop::UnregisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.erase(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); } RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { - TimePoint next_event_time = TimePoint::max(); - for (auto instance : flutter_instances_) { - std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); - if (wait_duration != std::chrono::nanoseconds::max()) { - next_event_time = - std::min(next_event_time, TimePoint::clock::now() + wait_duration); + TimePoint next_event_time = TimePoint::max(); + for (auto instance: flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } } - } - return next_event_time; + return next_event_time; } diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/run_loop.h b/packages/network_info_plus/network_info_plus/example/windows/runner/run_loop.h index 7fe1aaccc2..5105e29d76 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/run_loop.h +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/run_loop.h @@ -10,29 +10,31 @@ // as native messages. class RunLoop { public: - RunLoop(); - ~RunLoop(); + RunLoop(); - // Prevent copying - RunLoop(RunLoop const &) = delete; - RunLoop &operator=(RunLoop const &) = delete; + ~RunLoop(); - // Runs the run loop until the application quits. - void Run(); + // Prevent copying + RunLoop(RunLoop const &) = delete; - // Registers the given Flutter instance for event servicing. - void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + RunLoop &operator=(RunLoop const &) = delete; - // Unregisters the given Flutter instance from event servicing. - void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); private: - using TimePoint = std::chrono::steady_clock::time_point; + using TimePoint = std::chrono::steady_clock::time_point; - // Processes all currently pending messages for registered Flutter instances. - TimePoint ProcessFlutterMessages(); + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); - std::set flutter_instances_; + std::set flutter_instances_; }; #endif // RUNNER_RUN_LOOP_H_ diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/utils.cpp b/packages/network_info_plus/network_info_plus/example/windows/runner/utils.cpp index 7758aabf38..7113aa377e 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/utils.cpp +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/utils.cpp @@ -8,56 +8,56 @@ #include void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } } -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } - std::vector command_line_arguments; + std::vector command_line_arguments; - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } - ::LocalFree(argv); + ::LocalFree(argv); - return command_line_arguments; + return command_line_arguments; } std::string Utf8FromUtf16(const wchar_t *utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - int target_length = - ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, - nullptr, 0, nullptr, nullptr); - if (target_length == 0) { - return std::string(); - } - std::string utf8_string; - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), - target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; } diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/utils.h b/packages/network_info_plus/network_info_plus/example/windows/runner/utils.h index ff43ce2ce5..2deec25811 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/utils.h +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/utils.h @@ -14,6 +14,6 @@ std::string Utf8FromUtf16(const wchar_t *utf16_string); // Gets the command line arguments passed in as a std::vector, // encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); +std::vector GetCommandLineArguments(); #endif // RUNNER_UTILS_H_ diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/win32_window.cpp b/packages/network_info_plus/network_info_plus/example/windows/runner/win32_window.cpp index 90ff01e592..b87e3eb19d 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/win32_window.cpp +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/win32_window.cpp @@ -6,33 +6,36 @@ namespace { -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; // The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; + static int g_active_window_count = 0; -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + using EnableNonClientDpiScaling = + BOOL __stdcall(HWND + hwnd); // Scale helper to convert logical scaler values to physical using passed in // scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} + int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); + } // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. // This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { + void EnableFullDpiSupportIfAvailable(HWND + hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); - } +} +auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); +if (enable_non_client_dpi_scaling != nullptr) { +enable_non_client_dpi_scaling(hwnd); +FreeLibrary(user32_module); +} } } // namespace @@ -40,198 +43,228 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { // Manages the Win32Window's window class registration. class WindowClassRegistrar { public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registar instance. - static WindowClassRegistrar *GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; } - return instance_; - } - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t *GetWindowClass(); + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); private: - WindowClassRegistrar() = default; + WindowClassRegistrar() = default; - static WindowClassRegistrar *instance_; + static WindowClassRegistrar *instance_; - bool class_registered_ = false; + bool class_registered_ = false; }; WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; const wchar_t *WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; } void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; } Win32Window::Win32Window() { ++g_active_window_count; } Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); + --g_active_window_count; + Destroy(); } bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, const Size &size) { - Destroy(); + Destroy(); - const wchar_t *window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); - if (!window) { - return false; - } + if (!window) { + return false; + } - return OnCreate(); + return OnCreate(); } // static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window *that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } +LRESULT CALLBACK +Win32Window::WndProc(HWND +const window, +UINT const message, + WPARAM +const wparam, +LPARAM const lparam +) noexcept { +if (message == WM_NCCREATE) { +auto window_struct = reinterpret_cast(lparam); +SetWindowLongPtr(window, GWLP_USERDATA, +reinterpret_cast +(window_struct +->lpCreateParams)); + +auto that = static_cast(window_struct->lpCreateParams); +EnableFullDpiSupportIfAvailable(window); +that-> +window_handle_ = window; +} else if ( +Win32Window *that = GetThisFromHandle(window) +) { +return that-> +MessageHandler(window, message, wparam, lparam +); +} - return DefWindowProc(window, message, wparam, lparam); +return +DefWindowProc(window, message, wparam, lparam +); } LRESULT -Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } + Win32Window::MessageHandler(HWND +hwnd, +UINT const message, WPARAM +const wparam, +LPARAM const lparam +) noexcept { +switch (message) { +case WM_DESTROY: +window_handle_ = nullptr; + +Destroy(); + +if (quit_on_close_) { +PostQuitMessage(0); +} +return 0; - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - } +case WM_DPICHANGED: { +auto newRectSize = reinterpret_cast(lparam); +LONG newWidth = newRectSize->right - newRectSize->left; +LONG newHeight = newRectSize->bottom - newRectSize->top; - return DefWindowProc(window_handle_, message, wparam, lparam); +SetWindowPos(hwnd, nullptr, newRectSize +->left, newRectSize->top, newWidth, +newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + +return 0; +} +case WM_SIZE: { +RECT rect = GetClientArea(); +if (child_content_ != nullptr) { +// Size and position the child window. +MoveWindow(child_content_, rect +.left, rect.top, rect.right - rect.left, +rect.bottom - rect.top, TRUE); +} +return 0; +} + +case WM_ACTIVATE: +if (child_content_ != nullptr) { +SetFocus(child_content_); +} +return 0; +} + +return +DefWindowProc(window_handle_, message, wparam, lparam +); } void Win32Window::Destroy() { - OnDestroy(); + OnDestroy(); - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } } -Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); +Win32Window *Win32Window::GetThisFromHandle(HWND const window) + +noexcept { +return reinterpret_cast( +GetWindowLongPtr(window, GWLP_USERDATA +)); } -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); +void Win32Window::SetChildContent(HWND +content) { +child_content_ = content; +SetParent(content, window_handle_ +); +RECT frame = GetClientArea(); - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); +MoveWindow(content, frame +.left, frame.top, frame.right - frame.left, +frame.bottom - frame.top, true); - SetFocus(child_content_); +SetFocus(child_content_); } RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; } HWND Win32Window::GetHandle() { return window_handle_; } void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; + quit_on_close_ = quit_on_close; } bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; + // No-op; provided for subclasses. + return true; } void Win32Window::OnDestroy() { - // No-op; provided for subclasses. + // No-op; provided for subclasses. } diff --git a/packages/network_info_plus/network_info_plus/example/windows/runner/win32_window.h b/packages/network_info_plus/network_info_plus/example/windows/runner/win32_window.h index 7b518125bb..f8b5225436 100644 --- a/packages/network_info_plus/network_info_plus/example/windows/runner/win32_window.h +++ b/packages/network_info_plus/network_info_plus/example/windows/runner/win32_window.h @@ -12,84 +12,97 @@ // rendering and input handling class Win32Window { public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates and shows a win32 window with |title| and position and size using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring &title, const Point &origin, - const Size &size); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); + struct Point { + unsigned int x; + unsigned int y; -protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); + struct Size { + unsigned int width; + unsigned int height; - // Called when Destroy is called. - virtual void OnDestroy(); + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; -private: - friend class WindowClassRegistrar; + Win32Window(); + + virtual ~Win32Window(); - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); - // Retrieves a class instance pointer for |window| - static Win32Window *GetThisFromHandle(HWND const window) noexcept; + // Release OS resources associated with window. + void Destroy(); - bool quit_on_close_ = false; + // Inserts |content| into the window tree. + void SetChildContent(HWND content); - // window handle for top level window. - HWND window_handle_ = nullptr; + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); - // window handle for hosted content. - HWND child_content_ = nullptr; + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) + + noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK + WndProc(HWND + const window, + UINT const message, + WPARAM + const wparam, + LPARAM const lparam + ) + noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) + + noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; }; #endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPCaptiveNetworkInfoProvider.m b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPCaptiveNetworkInfoProvider.m index c97f6b38db..544fa2eeff 100644 --- a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPCaptiveNetworkInfoProvider.m +++ b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPCaptiveNetworkInfoProvider.m @@ -4,23 +4,23 @@ @implementation FPPCaptiveNetworkInfoProvider - (void)fetchNetworkInfoWithCompletionHandler: - (void (^)(FPPNetworkInfo *network))completionHandler { - dispatch_async(dispatch_get_main_queue(), ^{ - NSArray *interfaceNames = (__bridge_transfer id)CNCopySupportedInterfaces(); - for (NSString *interfaceName in interfaceNames) { - NSDictionary *networkInfo = - (__bridge_transfer id)CNCopyCurrentNetworkInfo( - (__bridge CFStringRef)interfaceName); - if (networkInfo) { - NSString *ssid = networkInfo[(NSString *)kCNNetworkInfoKeySSID]; - NSString *bssid = networkInfo[(NSString *)kCNNetworkInfoKeyBSSID]; - completionHandler([[FPPNetworkInfo alloc] initWithSSID:ssid - BSSID:bssid]); - return; - } - } - completionHandler(nil); - }); + (void (^)(FPPNetworkInfo *network))completionHandler { + dispatch_async(dispatch_get_main_queue(), ^{ + NSArray *interfaceNames = (__bridge_transfer id) CNCopySupportedInterfaces(); + for (NSString *interfaceName in interfaceNames) { + NSDictionary *networkInfo = + (__bridge_transfer id) CNCopyCurrentNetworkInfo( + (__bridge CFStringRef) interfaceName); + if (networkInfo) { + NSString *ssid = networkInfo[(NSString *) kCNNetworkInfoKeySSID]; + NSString *bssid = networkInfo[(NSString *) kCNNetworkInfoKeyBSSID]; + completionHandler([[FPPNetworkInfo alloc] initWithSSID:ssid + BSSID:bssid]); + return; + } + } + completionHandler(nil); + }); } @end diff --git a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPHotspotNetworkInfoProvider.m b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPHotspotNetworkInfoProvider.m index 5365f5a529..3bf6138f23 100644 --- a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPHotspotNetworkInfoProvider.m +++ b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPHotspotNetworkInfoProvider.m @@ -4,19 +4,21 @@ @implementation FPPHotspotNetworkInfoProvider - (void)fetchNetworkInfoWithCompletionHandler: - (void (^)(FPPNetworkInfo *network))completionHandler - API_AVAILABLE(ios(14)) { - [NEHotspotNetwork fetchCurrentWithCompletionHandler:^( - NEHotspotNetwork *network) { - dispatch_async(dispatch_get_main_queue(), ^{ - if (network) { - completionHandler([[FPPNetworkInfo alloc] initWithSSID:network.SSID - BSSID:network.BSSID]); - return; - } - completionHandler(nil); - }); - }]; + (void (^)(FPPNetworkInfo *network))completionHandler +API_AVAILABLE + +(ios(14)) { + [NEHotspotNetwork fetchCurrentWithCompletionHandler:^( + NEHotspotNetwork *network) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (network) { + completionHandler([[FPPNetworkInfo alloc] initWithSSID:network.SSID + BSSID:network.BSSID]); + return; + } + completionHandler(nil); + }); + }]; } @end diff --git a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPNetworkInfo.m b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPNetworkInfo.m index e8c881303d..3a195a9bcd 100644 --- a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPNetworkInfo.m +++ b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPNetworkInfo.m @@ -3,11 +3,11 @@ @implementation FPPNetworkInfo - (instancetype)initWithSSID:(NSString *)SSID BSSID:(NSString *)BSSID { - if ((self = [super init])) { - _SSID = [SSID copy]; - _BSSID = [BSSID copy]; - } - return self; + if ((self = [super init])) { + _SSID = [SSID copy]; + _BSSID = [BSSID copy]; + } + return self; } @end diff --git a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPNetworkInfoPlusPlugin.m b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPNetworkInfoPlusPlugin.m index 64161b9280..bba96079b5 100644 --- a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPNetworkInfoPlusPlugin.m +++ b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/FPPNetworkInfoPlusPlugin.m @@ -19,156 +19,158 @@ @interface FPPNetworkInfoPlusPlugin () -@property(strong, nonatomic) id networkInfoProvider; +@property(strong, nonatomic) id networkInfoProvider; - (instancetype)initWithNetworkInfoProvider: - (id)networkInfoProvider; + (id )networkInfoProvider; @end @implementation FPPNetworkInfoPlusPlugin { } -+ (void)registerWithRegistrar:(NSObject *)registrar { - id networkInfoProvider; - if (@available(iOS 14, *)) { - networkInfoProvider = [[FPPHotspotNetworkInfoProvider alloc] init]; - } else { - networkInfoProvider = [[FPPCaptiveNetworkInfoProvider alloc] init]; - } - FPPNetworkInfoPlusPlugin *instance = [[FPPNetworkInfoPlusPlugin alloc] - initWithNetworkInfoProvider:networkInfoProvider]; - - FlutterMethodChannel *channel = [FlutterMethodChannel - methodChannelWithName:@"dev.fluttercommunity.plus/network_info" - binaryMessenger:[registrar messenger]]; - [registrar addMethodCallDelegate:instance channel:channel]; ++ (void)registerWithRegistrar:(NSObject *)registrar { + id networkInfoProvider; + if (@available + (iOS + 14, *)) { + networkInfoProvider = [[FPPHotspotNetworkInfoProvider alloc] init]; + } else { + networkInfoProvider = [[FPPCaptiveNetworkInfoProvider alloc] init]; + } + FPPNetworkInfoPlusPlugin *instance = [[FPPNetworkInfoPlusPlugin alloc] + initWithNetworkInfoProvider:networkInfoProvider]; + + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/network_info" + binaryMessenger:[registrar messenger]]; + [registrar addMethodCallDelegate:instance channel:channel]; } - (instancetype)initWithNetworkInfoProvider: - (id)networkInfoProvider { - if ((self = [super init])) { - self.networkInfoProvider = networkInfoProvider; - } - return self; + (id )networkInfoProvider { + if ((self = [super init])) { + self.networkInfoProvider = networkInfoProvider; + } + return self; } #pragma mark - Callbacks - (NSString *)getGatewayIP { - struct in_addr gatewayAddr; - int gatewayAdressResult = getdefaultgateway(&(gatewayAddr.s_addr)); - if (gatewayAdressResult >= 0) { - return [NSString stringWithFormat:@"%s", inet_ntoa(gatewayAddr)]; - } else { - return nil; - } + struct in_addr gatewayAddr; + int gatewayAdressResult = getdefaultgateway(&(gatewayAddr.s_addr)); + if (gatewayAdressResult >= 0) { + return [NSString stringWithFormat:@"%s", inet_ntoa(gatewayAddr)]; + } else { + return nil; + } } - (NSString *)getWifiIP { - __block NSString *addr = nil; - [self enumerateWifiAddresses:AF_INET - usingBlock:^(struct ifaddrs *ifaddr) { - if (addr) return; - addr = [self descriptionForAddress:ifaddr->ifa_addr]; - }]; - return addr; + __block NSString *addr = nil; + [self enumerateWifiAddresses:AF_INET + usingBlock:^(struct ifaddrs *ifaddr) { + if (addr) return; + addr = [self descriptionForAddress:ifaddr->ifa_addr]; + }]; + return addr; } - (NSString *)getWifiIPv6 { - __block NSString *addr = nil; - [self enumerateWifiAddresses:AF_INET6 - usingBlock:^(struct ifaddrs *ifaddr) { - if (addr) return; - addr = [self descriptionForAddress:ifaddr->ifa_addr]; - }]; - return addr; + __block NSString *addr = nil; + [self enumerateWifiAddresses:AF_INET6 + usingBlock:^(struct ifaddrs *ifaddr) { + if (addr) return; + addr = [self descriptionForAddress:ifaddr->ifa_addr]; + }]; + return addr; } - (NSString *)getWifiSubmask { - __block NSString *addr = nil; - [self enumerateWifiAddresses:AF_INET - usingBlock:^(struct ifaddrs *ifaddr) { - if (addr) return; - addr = [self descriptionForAddress:ifaddr->ifa_netmask]; - }]; - return addr; + __block NSString *addr = nil; + [self enumerateWifiAddresses:AF_INET + usingBlock:^(struct ifaddrs *ifaddr) { + if (addr) return; + addr = [self descriptionForAddress:ifaddr->ifa_netmask]; + }]; + return addr; } - (NSString *)getWifiBroadcast { - __block NSString *addr = nil; - [self enumerateWifiAddresses:AF_INET - usingBlock:^(struct ifaddrs *ifaddr) { - if (addr) return; - addr = [self descriptionForAddress:ifaddr->ifa_dstaddr]; - }]; - return addr; + __block NSString *addr = nil; + [self enumerateWifiAddresses:AF_INET + usingBlock:^(struct ifaddrs *ifaddr) { + if (addr) return; + addr = [self descriptionForAddress:ifaddr->ifa_dstaddr]; + }]; + return addr; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - if ([call.method isEqualToString:@"wifiName"]) { - [self.networkInfoProvider - fetchNetworkInfoWithCompletionHandler:^(FPPNetworkInfo *networkInfo) { - result(networkInfo.SSID); - }]; - } else if ([call.method isEqualToString:@"wifiBSSID"]) { - [self.networkInfoProvider - fetchNetworkInfoWithCompletionHandler:^(FPPNetworkInfo *networkInfo) { - result(networkInfo.BSSID); - }]; - } else if ([call.method isEqualToString:@"wifiIPAddress"]) { - result([self getWifiIP]); - } else if ([call.method isEqualToString:@"wifiIPv6Address"]) { - result([self getWifiIPv6]); - } else if ([call.method isEqualToString:@"wifiSubmask"]) { - result([self getWifiSubmask]); - } else if ([call.method isEqualToString:@"wifiBroadcast"]) { - result([self getWifiBroadcast]); - } else if ([call.method isEqualToString:@"wifiGatewayAddress"]) { - result([self getGatewayIP]); - } else { - result(FlutterMethodNotImplemented); - } + if ([call.method isEqualToString:@"wifiName"]) { + [self.networkInfoProvider + fetchNetworkInfoWithCompletionHandler:^(FPPNetworkInfo *networkInfo) { + result(networkInfo.SSID); + }]; + } else if ([call.method isEqualToString:@"wifiBSSID"]) { + [self.networkInfoProvider + fetchNetworkInfoWithCompletionHandler:^(FPPNetworkInfo *networkInfo) { + result(networkInfo.BSSID); + }]; + } else if ([call.method isEqualToString:@"wifiIPAddress"]) { + result([self getWifiIP]); + } else if ([call.method isEqualToString:@"wifiIPv6Address"]) { + result([self getWifiIPv6]); + } else if ([call.method isEqualToString:@"wifiSubmask"]) { + result([self getWifiSubmask]); + } else if ([call.method isEqualToString:@"wifiBroadcast"]) { + result([self getWifiBroadcast]); + } else if ([call.method isEqualToString:@"wifiGatewayAddress"]) { + result([self getGatewayIP]); + } else { + result(FlutterMethodNotImplemented); + } } #pragma mark - Utils - (void)enumerateWifiAddresses:(NSInteger)family usingBlock:(void (^)(struct ifaddrs *))block { - struct ifaddrs *interfaces = NULL; - struct ifaddrs *temp_addr = NULL; - int success = 0; - - // retrieve the current interfaces - returns 0 on success - success = getifaddrs(&interfaces); - if (success != 0) { - NSLog(@"Error: getifaddrs() failed with error code: %d", success); - return; - } - - // Loop through linked list of interfaces - temp_addr = interfaces; - while (temp_addr != NULL) { - if (temp_addr->ifa_addr->sa_family == family) { - // One of `en` interfaces should be WiFi interface - if (strncmp(temp_addr->ifa_name, "en", 2) == 0) { - block(temp_addr); - } - } - - temp_addr = temp_addr->ifa_next; - } - - // Free memory - freeifaddrs(interfaces); + struct ifaddrs *interfaces = NULL; + struct ifaddrs *temp_addr = NULL; + int success = 0; + + // retrieve the current interfaces - returns 0 on success + success = getifaddrs(&interfaces); + if (success != 0) { + NSLog(@"Error: getifaddrs() failed with error code: %d", success); + return; + } + + // Loop through linked list of interfaces + temp_addr = interfaces; + while (temp_addr != NULL) { + if (temp_addr->ifa_addr->sa_family == family) { + // One of `en` interfaces should be WiFi interface + if (strncmp(temp_addr->ifa_name, "en", 2) == 0) { + block(temp_addr); + } + } + + temp_addr = temp_addr->ifa_next; + } + + // Free memory + freeifaddrs(interfaces); } - (NSString *)descriptionForAddress:(struct sockaddr *)addr { - char hostname[NI_MAXHOST]; - getnameinfo(addr, addr->sa_len, hostname, NI_MAXHOST, NULL, 0, - NI_NUMERICHOST); - return [NSString stringWithUTF8String:hostname]; + char hostname[NI_MAXHOST]; + getnameinfo(addr, addr->sa_len, hostname, NI_MAXHOST, NULL, 0, + NI_NUMERICHOST); + return [NSString stringWithUTF8String:hostname]; } @end diff --git a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/getgateway.c b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/getgateway.c index 35adb84e35..a3f821dfa0 100644 --- a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/getgateway.c +++ b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/getgateway.c @@ -29,11 +29,16 @@ POSSIBILITY OF SUCH DAMAGE. */ #include #include + #ifndef _WIN32 + #include + #endif #if !defined(_MSC_VER) + #include + #endif /* There is no portable method to get the default route gateway. * So below are four (or five ?) differents functions implementing this. @@ -145,96 +150,96 @@ eth0 00000000 00000000 0001 0 0 1000 00000000 */ int getdefaultgateway(in_addr_t * addr) { - unsigned long d, g; - char buf[256]; - int line = 0; - FILE * f; - char * p; - f = fopen("/proc/net/route", "r"); - if(!f) - return FAILED; - while(fgets(buf, sizeof(buf), f)) { - if(line > 0) { /* skip the first line */ - p = buf; - /* skip the interface name */ - while(*p && !isspace(*p)) - p++; - while(*p && isspace(*p)) - p++; - if(sscanf(p, "%lx%lx", &d, &g)==2) { - if(d == 0 && g != 0) { /* default */ - *addr = g; - fclose(f); - return SUCCESS; - } - } - } - line++; - } - /* default route not found ! */ - if(f) - fclose(f); - return FAILED; + unsigned long d, g; + char buf[256]; + int line = 0; + FILE * f; + char * p; + f = fopen("/proc/net/route", "r"); + if(!f) + return FAILED; + while(fgets(buf, sizeof(buf), f)) { + if(line > 0) { /* skip the first line */ + p = buf; + /* skip the interface name */ + while(*p && !isspace(*p)) + p++; + while(*p && isspace(*p)) + p++; + if(sscanf(p, "%lx%lx", &d, &g)==2) { + if(d == 0 && g != 0) { /* default */ + *addr = g; + fclose(f); + return SUCCESS; + } + } + } + line++; + } + /* default route not found ! */ + if(f) + fclose(f); + return FAILED; } #elif defined(USE_SYSCTL_NET_ROUTE) #define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) int getdefaultgateway(in_addr_t * addr) { #if 0 - /* net.route.0.inet.dump.0.0 ? */ - int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, - NET_RT_DUMP, 0, 0/*tableid*/}; + /* net.route.0.inet.dump.0.0 ? */ + int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, + NET_RT_DUMP, 0, 0/*tableid*/}; #endif - /* net.route.0.inet.flags.gateway */ - int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, - NET_RT_FLAGS, RTF_GATEWAY}; - size_t l; - char * buf, * p; - struct rt_msghdr * rt; - struct sockaddr * sa; - struct sockaddr * sa_tab[RTAX_MAX]; - int i; - int r = FAILED; - if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) { - return FAILED; - } - if(l>0) { - buf = malloc(l); - if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { - free(buf); - return FAILED; - } - for(p=buf; prtm_msglen) { - rt = (struct rt_msghdr *)p; - sa = (struct sockaddr *)(rt + 1); - for(i=0; irtm_addrs & (1 << i)) { - sa_tab[i] = sa; - sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); - } else { - sa_tab[i] = NULL; - } - } - if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) + /* net.route.0.inet.flags.gateway */ + int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, + NET_RT_FLAGS, RTF_GATEWAY}; + size_t l; + char * buf, * p; + struct rt_msghdr * rt; + struct sockaddr * sa; + struct sockaddr * sa_tab[RTAX_MAX]; + int i; + int r = FAILED; + if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) { + return FAILED; + } + if(l>0) { + buf = malloc(l); + if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { + free(buf); + return FAILED; + } + for(p=buf; prtm_msglen) { + rt = (struct rt_msghdr *)p; + sa = (struct sockaddr *)(rt + 1); + for(i=0; irtm_addrs & (1 << i)) { + sa_tab[i] = sa; + sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); + } else { + sa_tab[i] = NULL; + } + } + if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) && sa_tab[RTAX_DST]->sa_family == AF_INET && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) { - if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) { - char if_name[IF_NAMESIZE]; - if_indextoname(rt->rtm_index, if_name); - if(strcmp(if_name, "en0") == 0) { - *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr; - r = SUCCESS; - } - } - } - } - free(buf); - } - return r; + if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) { + char if_name[IF_NAMESIZE]; + if_indextoname(rt->rtm_index, if_name); + if(strcmp(if_name, "en0") == 0) { + *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr; + r = SUCCESS; + } + } + } + } + free(buf); + } + return r; } #elif defined(USE_SOCKET_ROUTE) @@ -327,195 +332,195 @@ int getdefaultgateway(in_addr_t *addr) int getdefaultgateway(in_addr_t * addr) { - HKEY networkCardsKey; - HKEY networkCardKey; - HKEY interfacesKey; - HKEY interfaceKey; - DWORD i = 0; - DWORD numSubKeys = 0; - TCHAR keyName[MAX_KEY_LENGTH]; - DWORD keyNameLength = MAX_KEY_LENGTH; - TCHAR keyValue[MAX_VALUE_LENGTH]; - DWORD keyValueLength = MAX_VALUE_LENGTH; - DWORD keyValueType = REG_SZ; - TCHAR gatewayValue[MAX_VALUE_LENGTH]; - DWORD gatewayValueLength = MAX_VALUE_LENGTH; - DWORD gatewayValueType = REG_MULTI_SZ; - int done = 0; - - //const char * networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; - //const char * interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; + HKEY networkCardsKey; + HKEY networkCardKey; + HKEY interfacesKey; + HKEY interfaceKey; + DWORD i = 0; + DWORD numSubKeys = 0; + TCHAR keyName[MAX_KEY_LENGTH]; + DWORD keyNameLength = MAX_KEY_LENGTH; + TCHAR keyValue[MAX_VALUE_LENGTH]; + DWORD keyValueLength = MAX_VALUE_LENGTH; + DWORD keyValueType = REG_SZ; + TCHAR gatewayValue[MAX_VALUE_LENGTH]; + DWORD gatewayValueLength = MAX_VALUE_LENGTH; + DWORD gatewayValueType = REG_MULTI_SZ; + int done = 0; + + //const char * networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; + //const char * interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; #ifdef UNICODE - LPCTSTR networkCardsPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; - LPCTSTR interfacesPath = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; + LPCTSTR networkCardsPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; + LPCTSTR interfacesPath = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; #define STR_SERVICENAME L"ServiceName" #define STR_DHCPDEFAULTGATEWAY L"DhcpDefaultGateway" #define STR_DEFAULTGATEWAY L"DefaultGateway" #else - LPCTSTR networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; - LPCTSTR interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; + LPCTSTR networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; + LPCTSTR interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; #define STR_SERVICENAME "ServiceName" #define STR_DHCPDEFAULTGATEWAY "DhcpDefaultGateway" #define STR_DEFAULTGATEWAY "DefaultGateway" #endif - // The windows registry lists its primary network devices in the following location: - // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards - // - // Each network device has its own subfolder, named with an index, with various properties: - // -NetworkCards - // -5 - // -Description = Broadcom 802.11n Network Adapter - // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D} - // -8 - // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller - // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD} - // - // The above service name is the name of a subfolder within: - // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces - // - // There may be more subfolders in this interfaces path than listed in the network cards path above: - // -Interfaces - // -{3a539854-6a70-11db-887c-806e6f6e6963} - // -DhcpIPAddress = 0.0.0.0 - // -[more] - // -{E35A72F8-5065-4097-8DFE-C7790774EE4D} - // -DhcpIPAddress = 10.0.1.4 - // -DhcpDefaultGateway = 10.0.1.1 - // -[more] - // -{86226414-5545-4335-A9D1-5BD7120119AD} - // -DhcpIpAddress = 10.0.1.5 - // -DhcpDefaultGateay = 10.0.1.1 - // -[more] - // - // In order to extract this information, we enumerate each network card, and extract the ServiceName value. - // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value. - // Once one is found, we're done. - // - // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value. - // However, the technique used is the technique most cited on the web, and we assume it to be more correct. - - if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key - networkCardsPath, // Name of registry subkey to open - 0, // Reserved - must be zero - KEY_READ, // Mask - desired access rights - &networkCardsKey)) // Pointer to output key - { - // Unable to open network cards keys - return -1; - } - - if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key - interfacesPath, // Name of registry subkey to open - 0, // Reserved - must be zero - KEY_READ, // Mask - desired access rights - &interfacesKey)) // Pointer to output key - { - // Unable to open interfaces key - RegCloseKey(networkCardsKey); - return -1; - } - - // Figure out how many subfolders are within the NetworkCards folder - RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys); - - // Enumrate through each subfolder within the NetworkCards folder - for(i = 0; i < numSubKeys && !done; i++) - { - keyNameLength = MAX_KEY_LENGTH; - if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key - i, // Index of subkey to retrieve - keyName, // Buffer that receives the name of the subkey - &keyNameLength, // Variable that receives the size of the above buffer - NULL, // Reserved - must be NULL - NULL, // Buffer that receives the class string - NULL, // Variable that receives the size of the above buffer - NULL)) // Variable that receives the last write time of subkey - { - if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS) - { - keyValueLength = MAX_VALUE_LENGTH; - if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key - STR_SERVICENAME, // Name of key to query - NULL, // Reserved - must be NULL - &keyValueType, // Receives value type - (LPBYTE)keyValue, // Receives value - &keyValueLength)) // Receives value length in bytes - { + // The windows registry lists its primary network devices in the following location: + // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards + // + // Each network device has its own subfolder, named with an index, with various properties: + // -NetworkCards + // -5 + // -Description = Broadcom 802.11n Network Adapter + // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D} + // -8 + // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller + // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD} + // + // The above service name is the name of a subfolder within: + // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces + // + // There may be more subfolders in this interfaces path than listed in the network cards path above: + // -Interfaces + // -{3a539854-6a70-11db-887c-806e6f6e6963} + // -DhcpIPAddress = 0.0.0.0 + // -[more] + // -{E35A72F8-5065-4097-8DFE-C7790774EE4D} + // -DhcpIPAddress = 10.0.1.4 + // -DhcpDefaultGateway = 10.0.1.1 + // -[more] + // -{86226414-5545-4335-A9D1-5BD7120119AD} + // -DhcpIpAddress = 10.0.1.5 + // -DhcpDefaultGateay = 10.0.1.1 + // -[more] + // + // In order to extract this information, we enumerate each network card, and extract the ServiceName value. + // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value. + // Once one is found, we're done. + // + // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value. + // However, the technique used is the technique most cited on the web, and we assume it to be more correct. + + if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key + networkCardsPath, // Name of registry subkey to open + 0, // Reserved - must be zero + KEY_READ, // Mask - desired access rights + &networkCardsKey)) // Pointer to output key + { + // Unable to open network cards keys + return -1; + } + + if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key + interfacesPath, // Name of registry subkey to open + 0, // Reserved - must be zero + KEY_READ, // Mask - desired access rights + &interfacesKey)) // Pointer to output key + { + // Unable to open interfaces key + RegCloseKey(networkCardsKey); + return -1; + } + + // Figure out how many subfolders are within the NetworkCards folder + RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys); + + // Enumrate through each subfolder within the NetworkCards folder + for(i = 0; i < numSubKeys && !done; i++) + { + keyNameLength = MAX_KEY_LENGTH; + if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key + i, // Index of subkey to retrieve + keyName, // Buffer that receives the name of the subkey + &keyNameLength, // Variable that receives the size of the above buffer + NULL, // Reserved - must be NULL + NULL, // Buffer that receives the class string + NULL, // Variable that receives the size of the above buffer + NULL)) // Variable that receives the last write time of subkey + { + if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS) + { + keyValueLength = MAX_VALUE_LENGTH; + if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key + STR_SERVICENAME, // Name of key to query + NULL, // Reserved - must be NULL + &keyValueType, // Receives value type + (LPBYTE)keyValue, // Receives value + &keyValueLength)) // Receives value length in bytes + { // printf("keyValue: %s\n", keyValue); - if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS) - { - gatewayValueLength = MAX_VALUE_LENGTH; - if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key - STR_DHCPDEFAULTGATEWAY, // Name of key to query - NULL, // Reserved - must be NULL - &gatewayValueType, // Receives value type - (LPBYTE)gatewayValue, // Receives value - &gatewayValueLength)) // Receives value length in bytes - { - // Check to make sure it's a string - if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) - { - //printf("gatewayValue: %s\n", gatewayValue); - done = 1; - } - } - else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key - STR_DEFAULTGATEWAY, // Name of key to query - NULL, // Reserved - must be NULL - &gatewayValueType, // Receives value type - (LPBYTE)gatewayValue,// Receives value - &gatewayValueLength)) // Receives value length in bytes - { - // Check to make sure it's a string - if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) - { - //printf("gatewayValue: %s\n", gatewayValue); - done = 1; - } - } - RegCloseKey(interfaceKey); - } - } - RegCloseKey(networkCardKey); - } - } - } - - RegCloseKey(interfacesKey); - RegCloseKey(networkCardsKey); - - if(done) - { + if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS) + { + gatewayValueLength = MAX_VALUE_LENGTH; + if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key + STR_DHCPDEFAULTGATEWAY, // Name of key to query + NULL, // Reserved - must be NULL + &gatewayValueType, // Receives value type + (LPBYTE)gatewayValue, // Receives value + &gatewayValueLength)) // Receives value length in bytes + { + // Check to make sure it's a string + if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) + { + //printf("gatewayValue: %s\n", gatewayValue); + done = 1; + } + } + else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key + STR_DEFAULTGATEWAY, // Name of key to query + NULL, // Reserved - must be NULL + &gatewayValueType, // Receives value type + (LPBYTE)gatewayValue,// Receives value + &gatewayValueLength)) // Receives value length in bytes + { + // Check to make sure it's a string + if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) + { + //printf("gatewayValue: %s\n", gatewayValue); + done = 1; + } + } + RegCloseKey(interfaceKey); + } + } + RegCloseKey(networkCardKey); + } + } + } + + RegCloseKey(interfacesKey); + RegCloseKey(networkCardsKey); + + if(done) + { #if UNICODE - char tmp[32]; - for(i = 0; i < 32; i++) { - tmp[i] = (char)gatewayValue[i]; - if(!tmp[i]) - break; - } - tmp[31] = '\0'; - *addr = inet_addr(tmp); + char tmp[32]; + for(i = 0; i < 32; i++) { + tmp[i] = (char)gatewayValue[i]; + if(!tmp[i]) + break; + } + tmp[31] = '\0'; + *addr = inet_addr(tmp); #else - *addr = inet_addr(gatewayValue); + *addr = inet_addr(gatewayValue); #endif - return 0; - } + return 0; + } - return -1; + return -1; } #elif defined(USE_WIN32_CODE_2) int getdefaultgateway(in_addr_t *addr) { - MIB_IPFORWARDROW ip_forward; - memset(&ip_forward, 0, sizeof(ip_forward)); - if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR) - return -1; - *addr = ip_forward.dwForwardNextHop; - return 0; + MIB_IPFORWARDROW ip_forward; + memset(&ip_forward, 0, sizeof(ip_forward)); + if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR) + return -1; + *addr = ip_forward.dwForwardNextHop; + return 0; } #elif defined(USE_HAIKU_CODE) @@ -573,9 +578,8 @@ int getdefaultgateway(in_addr_t *addr) #else /* fallback */ -int getdefaultgateway(in_addr_t * addr) -{ - (void)addr; +int getdefaultgateway(in_addr_t *addr) { + (void) addr; return -1; } diff --git a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/include/network_info_plus/FPPNetworkInfoProvider.h b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/include/network_info_plus/FPPNetworkInfoProvider.h index 572bbe1511..a48320d273 100644 --- a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/include/network_info_plus/FPPNetworkInfoProvider.h +++ b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/include/network_info_plus/FPPNetworkInfoProvider.h @@ -4,6 +4,6 @@ @protocol FPPNetworkInfoProvider - (void)fetchNetworkInfoWithCompletionHandler: - (void (^)(FPPNetworkInfo *networkInfo))completionHandler; + (void (^)(FPPNetworkInfo *networkInfo))completionHandler; @end diff --git a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/include/network_info_plus/route.h b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/include/network_info_plus/route.h index 55a555a377..f34426c1cc 100644 --- a/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/include/network_info_plus/route.h +++ b/packages/network_info_plus/network_info_plus/ios/network_info_plus/Sources/network_info_plus/include/network_info_plus/route.h @@ -63,6 +63,7 @@ #ifndef _NET_ROUTE_H_ #define _NET_ROUTE_H_ + #include #include #include @@ -104,17 +105,17 @@ struct route; * retransmission behavior and are included in the routing structure. */ struct rt_metrics { - u_int32_t rmx_locks; /* Kernel must leave these values alone */ - u_int32_t rmx_mtu; /* MTU for this path */ - u_int32_t rmx_hopcount; /* max hops expected */ - int32_t rmx_expire; /* lifetime for route, e.g. redirect */ - u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */ - u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */ - u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */ - u_int32_t rmx_rtt; /* estimated round trip time */ - u_int32_t rmx_rttvar; /* estimated rtt variance */ - u_int32_t rmx_pksent; /* packets sent using this route */ - u_int32_t rmx_filler[4]; /* will be used for T/TCP later */ + u_int32_t rmx_locks; /* Kernel must leave these values alone */ + u_int32_t rmx_mtu; /* MTU for this path */ + u_int32_t rmx_hopcount; /* max hops expected */ + int32_t rmx_expire; /* lifetime for route, e.g. redirect */ + u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */ + u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */ + u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */ + u_int32_t rmx_rtt; /* estimated round trip time */ + u_int32_t rmx_rttvar; /* estimated rtt variance */ + u_int32_t rmx_pksent; /* packets sent using this route */ + u_int32_t rmx_filler[4]; /* will be used for T/TCP later */ }; /* @@ -184,57 +185,57 @@ struct rtentry { #define RTF_PRCLONING 0x10000 /* protocol requires cloning */ #define RTF_WASCLONED 0x20000 /* route generated through cloning */ #define RTF_PROTO3 0x40000 /* protocol specific routing flag */ - /* 0x80000 unused */ +/* 0x80000 unused */ #define RTF_PINNED 0x100000 /* future use */ #define RTF_LOCAL 0x200000 /* route represents a local address */ #define RTF_BROADCAST 0x400000 /* route represents a bcast address */ #define RTF_MULTICAST 0x800000 /* route represents a mcast address */ #define RTF_IFSCOPE 0x1000000 /* has valid interface scope */ #define RTF_CONDEMNED 0x2000000 /* defunct; no longer modifiable */ - /* 0x4000000 and up unassigned */ +/* 0x4000000 and up unassigned */ /* * Routing statistics. */ struct rtstat { - short rts_badredirect; /* bogus redirect calls */ - short rts_dynamic; /* routes created by redirects */ - short rts_newgateway; /* routes modified by redirects */ - short rts_unreach; /* lookups which failed */ - short rts_wildcard; /* lookups satisfied by a wildcard */ + short rts_badredirect; /* bogus redirect calls */ + short rts_dynamic; /* routes created by redirects */ + short rts_newgateway; /* routes modified by redirects */ + short rts_unreach; /* lookups which failed */ + short rts_wildcard; /* lookups satisfied by a wildcard */ }; /* * Structures for routing messages. */ struct rt_msghdr { - u_short rtm_msglen; /* to skip over non-understood messages */ - u_char rtm_version; /* future binary compatibility */ - u_char rtm_type; /* message type */ - u_short rtm_index; /* index for associated ifp */ - int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ - int rtm_addrs; /* bitmask identifying sockaddrs in msg */ - pid_t rtm_pid; /* identify sender */ - int rtm_seq; /* for sender to identify action */ - int rtm_errno; /* why failed */ - int rtm_use; /* from rtentry */ - u_int32_t rtm_inits; /* which metrics we are initializing */ - struct rt_metrics rtm_rmx; /* metrics themselves */ + u_short rtm_msglen; /* to skip over non-understood messages */ + u_char rtm_version; /* future binary compatibility */ + u_char rtm_type; /* message type */ + u_short rtm_index; /* index for associated ifp */ + int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ + int rtm_addrs; /* bitmask identifying sockaddrs in msg */ + pid_t rtm_pid; /* identify sender */ + int rtm_seq; /* for sender to identify action */ + int rtm_errno; /* why failed */ + int rtm_use; /* from rtentry */ + u_int32_t rtm_inits; /* which metrics we are initializing */ + struct rt_metrics rtm_rmx; /* metrics themselves */ }; struct rt_msghdr2 { - u_short rtm_msglen; /* to skip over non-understood messages */ - u_char rtm_version; /* future binary compatibility */ - u_char rtm_type; /* message type */ - u_short rtm_index; /* index for associated ifp */ - int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ - int rtm_addrs; /* bitmask identifying sockaddrs in msg */ - int32_t rtm_refcnt; /* reference count */ - int rtm_parentflags; /* flags of the parent route */ - int rtm_reserved; /* reserved field set to 0 */ - int rtm_use; /* from rtentry */ - u_int32_t rtm_inits; /* which metrics we are initializing */ - struct rt_metrics rtm_rmx; /* metrics themselves */ + u_short rtm_msglen; /* to skip over non-understood messages */ + u_char rtm_version; /* future binary compatibility */ + u_char rtm_type; /* message type */ + u_short rtm_index; /* index for associated ifp */ + int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ + int rtm_addrs; /* bitmask identifying sockaddrs in msg */ + int32_t rtm_refcnt; /* reference count */ + int rtm_parentflags; /* flags of the parent route */ + int rtm_reserved; /* reserved field set to 0 */ + int rtm_use; /* from rtentry */ + u_int32_t rtm_inits; /* which metrics we are initializing */ + struct rt_metrics rtm_rmx; /* metrics themselves */ }; #define RTM_VERSION 5 /* Up the ante and ignore older versions */ @@ -303,17 +304,17 @@ struct rt_msghdr2 { #define RTAX_MAX 8 /* size of array to allocate */ struct rt_addrinfo { - int rti_addrs; - struct sockaddr *rti_info[RTAX_MAX]; + int rti_addrs; + struct sockaddr *rti_info[RTAX_MAX]; }; struct route_cb { - int ip_count; - int ip6_count; - int ipx_count; - int ns_count; - int iso_count; - int any_count; + int ip_count; + int ip6_count; + int ipx_count; + int ns_count; + int iso_count; + int any_count; }; #ifdef PRIVATE diff --git a/packages/network_info_plus/network_info_plus/lib/src/network_info_plus_linux.dart b/packages/network_info_plus/network_info_plus/lib/src/network_info_plus_linux.dart index b4bf1211c0..37a88ba4fe 100644 --- a/packages/network_info_plus/network_info_plus/lib/src/network_info_plus_linux.dart +++ b/packages/network_info_plus/network_info_plus/lib/src/network_info_plus_linux.dart @@ -9,8 +9,8 @@ import 'package:nm/nm.dart'; // ignore_for_file: public_member_api_docs typedef _DeviceGetter = Future Function(NetworkManagerDevice? device); -typedef _ConnectionGetter = Future Function( - NetworkManagerActiveConnection? connection); +typedef _ConnectionGetter = + Future Function(NetworkManagerActiveConnection? connection); @visibleForTesting typedef NetworkManagerClientFactory = NetworkManagerClient Function(); @@ -76,8 +76,9 @@ class NetworkInfoPlusLinuxPlugin extends NetworkInfoPlatform { Future _getDeviceValue(_DeviceGetter getter) { return _getConnectionValue((connection) { - final device = connection?.devices - .firstWhereOrNull((device) => device.wireless != null); + final device = connection?.devices.firstWhereOrNull( + (device) => device.wireless != null, + ); return getter(device); }); } @@ -113,6 +114,7 @@ class NetworkInfoPlusLinuxPlugin extends NetworkInfoPlatform { extension _IpInt on int { int byteAt(int i) => (this >> (i * 8)) & 0xff; + String toIpString() => '${byteAt(0)}.${byteAt(1)}.${byteAt(2)}.${byteAt(3)}'; } diff --git a/packages/network_info_plus/network_info_plus/lib/src/network_info_plus_windows.dart b/packages/network_info_plus/network_info_plus/lib/src/network_info_plus_windows.dart index ad0a4a6a33..ff626f1750 100644 --- a/packages/network_info_plus/network_info_plus/lib/src/network_info_plus_windows.dart +++ b/packages/network_info_plus/network_info_plus/lib/src/network_info_plus_windows.dart @@ -9,10 +9,11 @@ import 'package:win32/win32.dart'; import 'package:network_info_plus_platform_interface/network_info_plus_platform_interface.dart'; import 'package:win32/winsock2.dart'; -typedef WlanQuery = String? Function( - Pointer pGuid, - Pointer pAttributes, -); +typedef WlanQuery = + String? Function( + Pointer pGuid, + Pointer pAttributes, + ); class NetworkInfoPlusWindowsPlugin extends NetworkInfoPlatform { int clientHandle = NULL; @@ -63,9 +64,12 @@ class NetworkInfoPlusWindowsPlugin extends NetworkInfoPlatform { } for (var i = 0; i < ppInterfaceList.value.ref.dwNumberOfItems; i++) { - final pInterfaceGuid = calloc() - ..ref.setGUID(ppInterfaceList.value.ref.InterfaceInfo[i].InterfaceGuid - .toString()); + final pInterfaceGuid = + calloc() + ..ref.setGUID( + ppInterfaceList.value.ref.InterfaceInfo[i].InterfaceGuid + .toString(), + ); const opCode = 7; // wlan_intf_opcode_current_connection final pdwDataSize = calloc(); @@ -128,8 +132,10 @@ class NetworkInfoPlusWindowsPlugin extends NetworkInfoPlatform { } } - Pointer? getAdapterAddress(Pointer pGuid, - Pointer pIpAdapterAddresses) { + Pointer? getAdapterAddress( + Pointer pGuid, + Pointer pIpAdapterAddresses, + ) { final ifLuid = calloc(); try { if (ConvertInterfaceGuidToLuid(pGuid, ifLuid) != NO_ERROR) { @@ -151,51 +157,59 @@ class NetworkInfoPlusWindowsPlugin extends NetworkInfoPlatform { @override Future getWifiName() { - return Future.value(query((pGuid, pAttributes) { - final DOT11_SSID ssid = - pAttributes.ref.wlanAssociationAttributes.dot11Ssid; - final charCodes = []; - for (var i = 0; i < ssid.uSSIDLength; i++) { - if (ssid.ucSSID[i] == 0x00) break; - charCodes.add(ssid.ucSSID[i]); - } - return String.fromCharCodes(charCodes); - })); + return Future.value( + query((pGuid, pAttributes) { + final DOT11_SSID ssid = + pAttributes.ref.wlanAssociationAttributes.dot11Ssid; + final charCodes = []; + for (var i = 0; i < ssid.uSSIDLength; i++) { + if (ssid.ucSSID[i] == 0x00) break; + charCodes.add(ssid.ucSSID[i]); + } + return String.fromCharCodes(charCodes); + }), + ); } /// Obtains the wifi BSSID of the connected network. @override Future getWifiBSSID() { - return Future.value(query((pGuid, pAttributes) { - return formatBssid([ - pAttributes.ref.wlanAssociationAttributes.dot11Bssid[0], - pAttributes.ref.wlanAssociationAttributes.dot11Bssid[1], - pAttributes.ref.wlanAssociationAttributes.dot11Bssid[2], - pAttributes.ref.wlanAssociationAttributes.dot11Bssid[3], - pAttributes.ref.wlanAssociationAttributes.dot11Bssid[4], - pAttributes.ref.wlanAssociationAttributes.dot11Bssid[5], - ]); - })); + return Future.value( + query((pGuid, pAttributes) { + return formatBssid([ + pAttributes.ref.wlanAssociationAttributes.dot11Bssid[0], + pAttributes.ref.wlanAssociationAttributes.dot11Bssid[1], + pAttributes.ref.wlanAssociationAttributes.dot11Bssid[2], + pAttributes.ref.wlanAssociationAttributes.dot11Bssid[3], + pAttributes.ref.wlanAssociationAttributes.dot11Bssid[4], + pAttributes.ref.wlanAssociationAttributes.dot11Bssid[5], + ]); + }), + ); } Future getIPAddr(int family) { - return Future.value(query((pGuid, pAttributes) { - final ulSize = calloc(); - Pointer pIpAdapterAddress = nullptr; - try { - GetAdaptersAddresses(family, 0, nullptr, nullptr, ulSize); - pIpAdapterAddress = HeapAlloc(GetProcessHeap(), 0, ulSize.value).cast(); - GetAdaptersAddresses(family, 0, nullptr, pIpAdapterAddress, ulSize); - final pAddr = getAdapterAddress(pGuid, pIpAdapterAddress); - if (pAddr == null) return null; - if (pAddr.ref.FirstUnicastAddress == nullptr) return null; - return formatIPAddress( - pAddr.ref.FirstUnicastAddress.ref.Address.lpSockaddr); - } finally { - free(ulSize); - if (pIpAdapterAddress != nullptr) free(pIpAdapterAddress); - } - })); + return Future.value( + query((pGuid, pAttributes) { + final ulSize = calloc(); + Pointer pIpAdapterAddress = nullptr; + try { + GetAdaptersAddresses(family, 0, nullptr, nullptr, ulSize); + pIpAdapterAddress = + HeapAlloc(GetProcessHeap(), 0, ulSize.value).cast(); + GetAdaptersAddresses(family, 0, nullptr, pIpAdapterAddress, ulSize); + final pAddr = getAdapterAddress(pGuid, pIpAdapterAddress); + if (pAddr == null) return null; + if (pAddr.ref.FirstUnicastAddress == nullptr) return null; + return formatIPAddress( + pAddr.ref.FirstUnicastAddress.ref.Address.lpSockaddr, + ); + } finally { + free(ulSize); + if (pIpAdapterAddress != nullptr) free(pIpAdapterAddress); + } + }), + ); } /// Obtains the IP v4 address of the connected wifi network @@ -213,33 +227,36 @@ class NetworkInfoPlusWindowsPlugin extends NetworkInfoPlatform { /// Obtains the subnet mask of the connected wifi network @override Future getWifiSubmask() { - return Future.value(query((pGuid, pAttributes) { - final ulSize = calloc(); - Pointer pIpAdapterAddress = nullptr; - try { - GetAdaptersAddresses( - ADDRESS_FAMILY.AF_INET, - 0, - nullptr, - nullptr, - ulSize, - ); - pIpAdapterAddress = HeapAlloc(GetProcessHeap(), 0, ulSize.value).cast(); - GetAdaptersAddresses( - ADDRESS_FAMILY.AF_INET, - 0, - nullptr, - pIpAdapterAddress, - ulSize, - ); - final pAddr = getAdapterAddress(pGuid, pIpAdapterAddress); - if (pAddr == null) return null; - return extractSubnet(pAddr); - } finally { - free(ulSize); - if (pIpAdapterAddress != nullptr) free(pIpAdapterAddress); - } - })); + return Future.value( + query((pGuid, pAttributes) { + final ulSize = calloc(); + Pointer pIpAdapterAddress = nullptr; + try { + GetAdaptersAddresses( + ADDRESS_FAMILY.AF_INET, + 0, + nullptr, + nullptr, + ulSize, + ); + pIpAdapterAddress = + HeapAlloc(GetProcessHeap(), 0, ulSize.value).cast(); + GetAdaptersAddresses( + ADDRESS_FAMILY.AF_INET, + 0, + nullptr, + pIpAdapterAddress, + ulSize, + ); + final pAddr = getAdapterAddress(pGuid, pIpAdapterAddress); + if (pAddr == null) return null; + return extractSubnet(pAddr); + } finally { + free(ulSize); + if (pIpAdapterAddress != nullptr) free(pIpAdapterAddress); + } + }), + ); } String extractSubnet(Pointer pIpAdapterAddress) { @@ -274,8 +291,9 @@ class NetworkInfoPlusWindowsPlugin extends NetworkInfoPlatform { final List subnetParts = subnet.split('.'); String broadcast = ''; for (int i = 0; i < 4; i++) { - broadcast += (int.parse(ipParts[i]) | (~int.parse(subnetParts[i]) & 0xff)) - .toString(); + broadcast += + (int.parse(ipParts[i]) | (~int.parse(subnetParts[i]) & 0xff)) + .toString(); if (i < 3) broadcast += '.'; } return broadcast; @@ -285,34 +303,38 @@ class NetworkInfoPlusWindowsPlugin extends NetworkInfoPlatform { /// This is the IP address of the router @override Future getWifiGatewayIP() { - return Future.value(query((pGuid, pAttributes) { - final ulSize = calloc(); - Pointer pIpAdapterAddress = nullptr; - try { - GetAdaptersAddresses( - ADDRESS_FAMILY.AF_INET, - 0x80, - nullptr, - nullptr, - ulSize, - ); - pIpAdapterAddress = HeapAlloc(GetProcessHeap(), 0, ulSize.value).cast(); - GetAdaptersAddresses( - ADDRESS_FAMILY.AF_INET, - 0x80, - nullptr, - pIpAdapterAddress, - ulSize, - ); - final pAddr = getAdapterAddress(pGuid, pIpAdapterAddress); - if (pAddr == null) return null; - if (pAddr.ref.FirstGatewayAddress == nullptr) return null; - return formatIPAddress( - pAddr.ref.FirstGatewayAddress.ref.Address.lpSockaddr); - } finally { - free(ulSize); - if (pIpAdapterAddress != nullptr) free(pIpAdapterAddress); - } - })); + return Future.value( + query((pGuid, pAttributes) { + final ulSize = calloc(); + Pointer pIpAdapterAddress = nullptr; + try { + GetAdaptersAddresses( + ADDRESS_FAMILY.AF_INET, + 0x80, + nullptr, + nullptr, + ulSize, + ); + pIpAdapterAddress = + HeapAlloc(GetProcessHeap(), 0, ulSize.value).cast(); + GetAdaptersAddresses( + ADDRESS_FAMILY.AF_INET, + 0x80, + nullptr, + pIpAdapterAddress, + ulSize, + ); + final pAddr = getAdapterAddress(pGuid, pIpAdapterAddress); + if (pAddr == null) return null; + if (pAddr.ref.FirstGatewayAddress == nullptr) return null; + return formatIPAddress( + pAddr.ref.FirstGatewayAddress.ref.Address.lpSockaddr, + ); + } finally { + free(ulSize); + if (pIpAdapterAddress != nullptr) free(pIpAdapterAddress); + } + }), + ); } } diff --git a/packages/network_info_plus/network_info_plus/test/network_info_plus_windows_test.dart b/packages/network_info_plus/network_info_plus/test/network_info_plus_windows_test.dart index d8032a5531..31059db28d 100644 --- a/packages/network_info_plus/network_info_plus/test/network_info_plus_windows_test.dart +++ b/packages/network_info_plus/network_info_plus/test/network_info_plus_windows_test.dart @@ -27,8 +27,10 @@ void main() { final plugin = NetworkInfoPlusWindowsPlugin(); final ipAddress = await plugin.getWifiIP(); expect( - ipAddress, - matches( - r'^(?=\d+\.\d+\.\d+\.\d+$)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.?){4}$')); + ipAddress, + matches( + r'^(?=\d+\.\d+\.\d+\.\d+$)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.?){4}$', + ), + ); }); } diff --git a/packages/network_info_plus/network_info_plus_platform_interface/CHANGELOG.md b/packages/network_info_plus/network_info_plus_platform_interface/CHANGELOG.md index 1f2c3b0c64..63b96fc970 100644 --- a/packages/network_info_plus/network_info_plus_platform_interface/CHANGELOG.md +++ b/packages/network_info_plus/network_info_plus_platform_interface/CHANGELOG.md @@ -1,20 +1,24 @@ ## 2.0.2 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 2.0.1 - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 2.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**(network_info_plus): Remove deprecated permission handling methods, update example and docs ([#2686](https://github.com/fluttercommunity/plus_plugins/issues/2686)). ([a71a27c5](https://github.com/fluttercommunity/plus_plugins/commit/a71a27c5fbdbbfc56a30359a1aff0a3d3da8dc73)) +- **BREAKING** **FEAT**(network_info_plus): Remove deprecated permission handling methods, update + example and + docs ([#2686](https://github.com/fluttercommunity/plus_plugins/issues/2686)). ([a71a27c5](https://github.com/fluttercommunity/plus_plugins/commit/a71a27c5fbdbbfc56a30359a1aff0a3d3da8dc73)) ## 1.1.3 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 1.1.2 diff --git a/packages/network_info_plus/network_info_plus_platform_interface/lib/method_channel_network_info.dart b/packages/network_info_plus/network_info_plus_platform_interface/lib/method_channel_network_info.dart index 8c5c6b5253..58ca7a8d36 100644 --- a/packages/network_info_plus/network_info_plus_platform_interface/lib/method_channel_network_info.dart +++ b/packages/network_info_plus/network_info_plus_platform_interface/lib/method_channel_network_info.dart @@ -12,8 +12,9 @@ import 'package:meta/meta.dart'; class MethodChannelNetworkInfo extends NetworkInfoPlatform { /// The method channel used to interact with the native platform. @visibleForTesting - MethodChannel methodChannel = - const MethodChannel('dev.fluttercommunity.plus/network_info'); + MethodChannel methodChannel = const MethodChannel( + 'dev.fluttercommunity.plus/network_info', + ); @override Future getWifiName() async { diff --git a/packages/network_info_plus/network_info_plus_platform_interface/lib/src/enums.dart b/packages/network_info_plus/network_info_plus_platform_interface/lib/src/enums.dart index 8cd7abaf25..9b2323444c 100644 --- a/packages/network_info_plus/network_info_plus_platform_interface/lib/src/enums.dart +++ b/packages/network_info_plus/network_info_plus_platform_interface/lib/src/enums.dart @@ -16,5 +16,5 @@ enum LocationAuthorizationStatus { authorizedWhenInUse, /// Status unknown. - unknown + unknown, } diff --git a/packages/network_info_plus/network_info_plus_platform_interface/test/method_channel_network_info_test.dart b/packages/network_info_plus/network_info_plus_platform_interface/test/method_channel_network_info_test.dart index 4cd4d12525..13c188537c 100644 --- a/packages/network_info_plus/network_info_plus_platform_interface/test/method_channel_network_info_test.dart +++ b/packages/network_info_plus/network_info_plus_platform_interface/test/method_channel_network_info_test.dart @@ -17,133 +17,78 @@ void main() { methodChannelNetworkInfo = MethodChannelNetworkInfo(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - methodChannelNetworkInfo.methodChannel, - (MethodCall methodCall) async { - log.add(methodCall); - switch (methodCall.method) { - case 'wifiName': - return '1337wifi'; - case 'wifiBSSID': - return 'c0:ff:33:c0:d3:55'; - case 'wifiIPAddress': - return '127.0.0.1'; - case 'wifiIPv6Address': - return '2002:7f00:0001:0:0:0:0:0'; - case 'wifiBroadcast': - return '127.0.0.255'; - case 'wifiGatewayAddress': - return '127.0.0.0'; - case 'wifiSubmask': - return '255.255.255.0'; - case 'requestLocationServiceAuthorization': - return 'authorizedAlways'; - case 'getLocationServiceAuthorization': - return 'authorizedAlways'; - default: - return null; - } - }, - ); + .setMockMethodCallHandler(methodChannelNetworkInfo.methodChannel, ( + MethodCall methodCall, + ) async { + log.add(methodCall); + switch (methodCall.method) { + case 'wifiName': + return '1337wifi'; + case 'wifiBSSID': + return 'c0:ff:33:c0:d3:55'; + case 'wifiIPAddress': + return '127.0.0.1'; + case 'wifiIPv6Address': + return '2002:7f00:0001:0:0:0:0:0'; + case 'wifiBroadcast': + return '127.0.0.255'; + case 'wifiGatewayAddress': + return '127.0.0.0'; + case 'wifiSubmask': + return '255.255.255.0'; + case 'requestLocationServiceAuthorization': + return 'authorizedAlways'; + case 'getLocationServiceAuthorization': + return 'authorizedAlways'; + default: + return null; + } + }); log.clear(); }); test('getWifiName', () async { final result = await methodChannelNetworkInfo.getWifiName(); expect(result, '1337wifi'); - expect( - log, - [ - isMethodCall( - 'wifiName', - arguments: null, - ), - ], - ); + expect(log, [isMethodCall('wifiName', arguments: null)]); }); test('getWifiBSSID', () async { final result = await methodChannelNetworkInfo.getWifiBSSID(); expect(result, 'c0:ff:33:c0:d3:55'); - expect( - log, - [ - isMethodCall( - 'wifiBSSID', - arguments: null, - ), - ], - ); + expect(log, [isMethodCall('wifiBSSID', arguments: null)]); }); test('getWifiIP', () async { final result = await methodChannelNetworkInfo.getWifiIP(); expect(result, '127.0.0.1'); - expect( - log, - [ - isMethodCall( - 'wifiIPAddress', - arguments: null, - ), - ], - ); + expect(log, [isMethodCall('wifiIPAddress', arguments: null)]); }); test('getWifiIPv6', () async { final result = await methodChannelNetworkInfo.getWifiIPv6(); expect(result, '2002:7f00:0001:0:0:0:0:0'); - expect( - log, - [ - isMethodCall( - 'wifiIPv6Address', - arguments: null, - ), - ], - ); + expect(log, [isMethodCall('wifiIPv6Address', arguments: null)]); }); test('getWifiBroadcast', () async { final result = await methodChannelNetworkInfo.getWifiBroadcast(); expect(result, '127.0.0.255'); - expect( - log, - [ - isMethodCall( - 'wifiBroadcast', - arguments: null, - ), - ], - ); + expect(log, [isMethodCall('wifiBroadcast', arguments: null)]); }); test('getWifiGatewayIP', () async { final result = await methodChannelNetworkInfo.getWifiGatewayIP(); expect(result, '127.0.0.0'); - expect( - log, - [ - isMethodCall( - 'wifiGatewayAddress', - arguments: null, - ), - ], - ); + expect(log, [ + isMethodCall('wifiGatewayAddress', arguments: null), + ]); }); test('getWifiSubmask', () async { final result = await methodChannelNetworkInfo.getWifiSubmask(); expect(result, '255.255.255.0'); - expect( - log, - [ - isMethodCall( - 'wifiSubmask', - arguments: null, - ), - ], - ); + expect(log, [isMethodCall('wifiSubmask', arguments: null)]); }); }); } diff --git a/packages/package_info_plus/package_info_plus/CHANGELOG.md b/packages/package_info_plus/package_info_plus/CHANGELOG.md index c30f28653a..6110a18a76 100644 --- a/packages/package_info_plus/package_info_plus/CHANGELOG.md +++ b/packages/package_info_plus/package_info_plus/CHANGELOG.md @@ -1,67 +1,90 @@ ## 8.3.0 - - **FEAT**(package_info_plus): add update time ([#3466](https://github.com/fluttercommunity/plus_plugins/issues/3466)). ([c0ab9214](https://github.com/fluttercommunity/plus_plugins/commit/c0ab9214479653ce976e427dc0fa5e58b71e7f66)) +- **FEAT**(package_info_plus): add update + time ([#3466](https://github.com/fluttercommunity/plus_plugins/issues/3466)). ([c0ab9214](https://github.com/fluttercommunity/plus_plugins/commit/c0ab9214479653ce976e427dc0fa5e58b71e7f66)) ## 8.2.1 - - **FIX**(package_info_plus): convert installTime to String instead of DateTime to avoid serialization issues ([#3464](https://github.com/fluttercommunity/plus_plugins/issues/3464)). ([aa10ce75](https://github.com/fluttercommunity/plus_plugins/commit/aa10ce758b6ee6895c7b4a05f16ffa08a434fa20)) - - **FIX**(package_info_plus): fix macOS compilation warning ([#3460](https://github.com/fluttercommunity/plus_plugins/issues/3460)). ([6eec56c4](https://github.com/fluttercommunity/plus_plugins/commit/6eec56c4a2a5f49894e60c3b9ea263c3096c01d5)) +- **FIX**(package_info_plus): convert installTime to String instead of DateTime to avoid + serialization + issues ([#3464](https://github.com/fluttercommunity/plus_plugins/issues/3464)). ([aa10ce75](https://github.com/fluttercommunity/plus_plugins/commit/aa10ce758b6ee6895c7b4a05f16ffa08a434fa20)) +- **FIX**(package_info_plus): fix macOS compilation + warning ([#3460](https://github.com/fluttercommunity/plus_plugins/issues/3460)). ([6eec56c4](https://github.com/fluttercommunity/plus_plugins/commit/6eec56c4a2a5f49894e60c3b9ea263c3096c01d5)) ## 8.2.0 - - **FEAT**(package_info_plus): add install time ([#3434](https://github.com/fluttercommunity/plus_plugins/issues/3434)). ([0ea0402f](https://github.com/fluttercommunity/plus_plugins/commit/0ea0402f824104c36a806f32e88727801b40ba4c)) +- **FEAT**(package_info_plus): add install + time ([#3434](https://github.com/fluttercommunity/plus_plugins/issues/3434)). ([0ea0402f](https://github.com/fluttercommunity/plus_plugins/commit/0ea0402f824104c36a806f32e88727801b40ba4c)) ## 8.1.4 - - **DOCS**(package_info_plus): doc ref links and unnecessary library names ([#3433](https://github.com/fluttercommunity/plus_plugins/issues/3433)). ([9275f622](https://github.com/fluttercommunity/plus_plugins/commit/9275f622191cee76bfcd90f3f96e6bbea1923f24)) +- **DOCS**(package_info_plus): doc ref links and unnecessary library + names ([#3433](https://github.com/fluttercommunity/plus_plugins/issues/3433)). ([9275f622](https://github.com/fluttercommunity/plus_plugins/commit/9275f622191cee76bfcd90f3f96e6bbea1923f24)) ## 8.1.3 - - **FIX**(package_info_plus): Resolve compilation issues with SPM enabled ([#3406](https://github.com/fluttercommunity/plus_plugins/issues/3406)). ([d421ec0e](https://github.com/fluttercommunity/plus_plugins/commit/d421ec0e75df5af3394e567e45ba63dbfc1839da)) +- **FIX**(package_info_plus): Resolve compilation issues with SPM + enabled ([#3406](https://github.com/fluttercommunity/plus_plugins/issues/3406)). ([d421ec0e](https://github.com/fluttercommunity/plus_plugins/commit/d421ec0e75df5af3394e567e45ba63dbfc1839da)) ## 8.1.2 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) - - **FIX**(package_info_plus): add support for file scheme on web ([#3345](https://github.com/fluttercommunity/plus_plugins/issues/3345)). ([2d69758d](https://github.com/fluttercommunity/plus_plugins/commit/2d69758d86346203a37dabf876a7bb9862c1e553)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **FIX**(package_info_plus): add support for file scheme on + web ([#3345](https://github.com/fluttercommunity/plus_plugins/issues/3345)). ([2d69758d](https://github.com/fluttercommunity/plus_plugins/commit/2d69758d86346203a37dabf876a7bb9862c1e553)) ## 8.1.1 - - **FIX**(package_info_plus): Update privacy manifest path ([#3348](https://github.com/fluttercommunity/plus_plugins/issues/3348)). ([f47fcc97](https://github.com/fluttercommunity/plus_plugins/commit/f47fcc9774a860d7cffe306ba6ecca4ccae2896f)) +- **FIX**(package_info_plus): Update privacy manifest + path ([#3348](https://github.com/fluttercommunity/plus_plugins/issues/3348)). ([f47fcc97](https://github.com/fluttercommunity/plus_plugins/commit/f47fcc9774a860d7cffe306ba6ecca4ccae2896f)) ## 8.1.0 - - **FEAT**(package_info_plus): Add Swift Package Manager support ([#3171](https://github.com/fluttercommunity/plus_plugins/issues/3171)). ([a14d4727](https://github.com/fluttercommunity/plus_plugins/commit/a14d472749b28826b8402cc612e29f0860cc44bc)) +- **FEAT**(package_info_plus): Add Swift Package Manager + support ([#3171](https://github.com/fluttercommunity/plus_plugins/issues/3171)). ([a14d4727](https://github.com/fluttercommunity/plus_plugins/commit/a14d472749b28826b8402cc612e29f0860cc44bc)) ## 8.0.3 - - **FIX**(all): Clean up macOS Privacy Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) - - **FIX**(all): Add macOS Privacy Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) +- **FIX**(all): Clean up macOS Privacy + Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) +- **FIX**(all): Add macOS Privacy + Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) ## 8.0.2 - - **CHORE**(package_info_plus): Update to package:web to ">=0.5.0 <2.0.0" ([#3102](https://github.com/fluttercommunity/plus_plugins/pull/3102)). ([05f8afb8](https://github.com/fluttercommunity/plus_plugins/commit/05f8afb8fc43bc702ab5e3e14e3cba9d79983446)) - - **DOCS**(package_info_plus): Update plugin requirements in README ([#3163](https://github.com/fluttercommunity/plus_plugins/issues/3163)). ([6f09bb7e](https://github.com/fluttercommunity/plus_plugins/commit/6f09bb7ec4c0f88fea557a87dc0cd3aaa64ac9ee)) +- **CHORE**(package_info_plus): Update to package:web to ">=0.5.0 < + 2.0.0" ([#3102](https://github.com/fluttercommunity/plus_plugins/pull/3102)). ([05f8afb8](https://github.com/fluttercommunity/plus_plugins/commit/05f8afb8fc43bc702ab5e3e14e3cba9d79983446)) +- **DOCS**(package_info_plus): Update plugin requirements in + README ([#3163](https://github.com/fluttercommunity/plus_plugins/issues/3163)). ([6f09bb7e](https://github.com/fluttercommunity/plus_plugins/commit/6f09bb7ec4c0f88fea557a87dc0cd3aaa64ac9ee)) ## 8.0.1 - - **FIX**(package_info_plus): Address changed fields nullability on Android 15 (API 35) ([#2975](https://github.com/fluttercommunity/plus_plugins/issues/2975)). ([dfa3bc2d](https://github.com/fluttercommunity/plus_plugins/commit/dfa3bc2de7d2a010bc81b0a7f19395b373e31cf1)) - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **FIX**(package_info_plus): Address changed fields nullability on Android 15 (API + 35) ([#2975](https://github.com/fluttercommunity/plus_plugins/issues/2975)). ([dfa3bc2d](https://github.com/fluttercommunity/plus_plugins/commit/dfa3bc2de7d2a010bc81b0a7f19395b373e31cf1)) +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 8.0.0 > Note: This release has breaking changes. - - **DOCS**(package_info_plus): Add platform specific documentation ([#2845](https://github.com/fluttercommunity/plus_plugins/issues/2845)). ([ad06a236](https://github.com/fluttercommunity/plus_plugins/commit/ad06a236d7647e958f4b25cd9ee8fe68f4c4faf3)) - - **DOCS**(package_info_plus): Improve web documentation re. CORS ([#2841](https://github.com/fluttercommunity/plus_plugins/issues/2841)). ([7d712ef8](https://github.com/fluttercommunity/plus_plugins/commit/7d712ef816808d533b2fd0b4f8c9f11ebb23ab53)) - - **BREAKING** **FEAT**(package_info_plus): Switch to SHA-256 for `buildSignature` on Android ([#2835](https://github.com/fluttercommunity/plus_plugins/issues/2835)). ([7259af20](https://github.com/fluttercommunity/plus_plugins/commit/7259af200810bd717d95688fbcdca67a028f9cd0)) +- **DOCS**(package_info_plus): Add platform specific + documentation ([#2845](https://github.com/fluttercommunity/plus_plugins/issues/2845)). ([ad06a236](https://github.com/fluttercommunity/plus_plugins/commit/ad06a236d7647e958f4b25cd9ee8fe68f4c4faf3)) +- **DOCS**(package_info_plus): Improve web documentation re. + CORS ([#2841](https://github.com/fluttercommunity/plus_plugins/issues/2841)). ([7d712ef8](https://github.com/fluttercommunity/plus_plugins/commit/7d712ef816808d533b2fd0b4f8c9f11ebb23ab53)) +- **BREAKING** **FEAT**(package_info_plus): Switch to SHA-256 for `buildSignature` on + Android ([#2835](https://github.com/fluttercommunity/plus_plugins/issues/2835)). ([7259af20](https://github.com/fluttercommunity/plus_plugins/commit/7259af200810bd717d95688fbcdca67a028f9cd0)) ## 7.0.0 > Note: This release has breaking changes. - - **REFACTOR**(package_info_plus): Migrate Android example to use the new plugins declaration ([#2715](https://github.com/fluttercommunity/plus_plugins/issues/2715)). ([33681cd9](https://github.com/fluttercommunity/plus_plugins/commit/33681cd91982d4db8e6d3d0e1ccf7c604091e48f)) - - **BREAKING** **FEAT**(package_info_plus): Support multiple version.json locations in web ([#2733](https://github.com/fluttercommunity/plus_plugins/issues/2733)). ([26047f30](https://github.com/fluttercommunity/plus_plugins/commit/26047f3062ea23f8e124f1c64e03dd8a566e9bac)) +- **REFACTOR**(package_info_plus): Migrate Android example to use the new plugins + declaration ([#2715](https://github.com/fluttercommunity/plus_plugins/issues/2715)). ([33681cd9](https://github.com/fluttercommunity/plus_plugins/commit/33681cd91982d4db8e6d3d0e1ccf7c604091e48f)) +- **BREAKING** **FEAT**(package_info_plus): Support multiple version.json locations in + web ([#2733](https://github.com/fluttercommunity/plus_plugins/issues/2733)). ([26047f30](https://github.com/fluttercommunity/plus_plugins/commit/26047f3062ea23f8e124f1c64e03dd8a566e9bac)) ## 6.0.0 @@ -70,112 +93,144 @@ In this release plugin migrated from dart:html to js_interop, meaning that it now supports WASM! Plugin now requires the following: + - Flutter >=3.19.0 - Dart >=3.3.0 - compileSDK 34 for Android part - Java 17 for Android part - Gradle 8.4 for Android part - - **BREAKING** **REFACTOR**(package_info_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2593](https://github.com/fluttercommunity/plus_plugins/issues/2593)). ([99c832ea](https://github.com/fluttercommunity/plus_plugins/commit/99c832ea646ae525e8af93be64fb94e09f1059f2)) - - **BREAKING** **BUILD**(package_info_plus): Target Java 17 on Android ([#2728](https://github.com/fluttercommunity/plus_plugins/issues/2728)). ([23f2a7c2](https://github.com/fluttercommunity/plus_plugins/commit/23f2a7c2bb649e84763f0ba6489acf5d9487e185)) - - **BREAKING** **BUILD**(package_info_plus): Update to target and compile SDK 34 ([#2707](https://github.com/fluttercommunity/plus_plugins/pull/2707)). ([df33fbd](https://github.com/fluttercommunity/plus_plugins/commit/df33fbdb4b6f03949b317c0019bc3f9098195340)) - - **FIX**(package_info_plus): Add iOS Privacy Info ([#2584](https://github.com/fluttercommunity/plus_plugins/issues/2584)). ([895fe1a2](https://github.com/fluttercommunity/plus_plugins/commit/895fe1a2658f7f1d61b830d769e0b251e82991b4)) - - **FEAT**(package_info_plus): Update min iOS target to 12, bump min Dart SDK to 3.3 ([#2660](https://github.com/fluttercommunity/plus_plugins/issues/2660)). ([6c0766dd](https://github.com/fluttercommunity/plus_plugins/commit/6c0766dd4f2a04f6dd3731584d6d8463db60a6d9)) - - **FEAT**(package_info_plus): Use js_interop instead of html to support compilation to WASM ([#2625](https://github.com/fluttercommunity/plus_plugins/issues/2625)). ([c9435836](https://github.com/fluttercommunity/plus_plugins/commit/c9435836e8c7b354d5ca5383029e0172efe301d1)) +- **BREAKING** **REFACTOR**(package_info_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to + 10.14 ([#2593](https://github.com/fluttercommunity/plus_plugins/issues/2593)). ([99c832ea](https://github.com/fluttercommunity/plus_plugins/commit/99c832ea646ae525e8af93be64fb94e09f1059f2)) +- **BREAKING** **BUILD**(package_info_plus): Target Java 17 on + Android ([#2728](https://github.com/fluttercommunity/plus_plugins/issues/2728)). ([23f2a7c2](https://github.com/fluttercommunity/plus_plugins/commit/23f2a7c2bb649e84763f0ba6489acf5d9487e185)) +- **BREAKING** **BUILD**(package_info_plus): Update to target and compile SDK + 34 ([#2707](https://github.com/fluttercommunity/plus_plugins/pull/2707)). ([df33fbd](https://github.com/fluttercommunity/plus_plugins/commit/df33fbdb4b6f03949b317c0019bc3f9098195340)) +- **FIX**(package_info_plus): Add iOS Privacy + Info ([#2584](https://github.com/fluttercommunity/plus_plugins/issues/2584)). ([895fe1a2](https://github.com/fluttercommunity/plus_plugins/commit/895fe1a2658f7f1d61b830d769e0b251e82991b4)) +- **FEAT**(package_info_plus): Update min iOS target to 12, bump min Dart SDK to + 3.3 ([#2660](https://github.com/fluttercommunity/plus_plugins/issues/2660)). ([6c0766dd](https://github.com/fluttercommunity/plus_plugins/commit/6c0766dd4f2a04f6dd3731584d6d8463db60a6d9)) +- **FEAT**(package_info_plus): Use js_interop instead of html to support compilation to + WASM ([#2625](https://github.com/fluttercommunity/plus_plugins/issues/2625)). ([c9435836](https://github.com/fluttercommunity/plus_plugins/commit/c9435836e8c7b354d5ca5383029e0172efe301d1)) ## 5.0.1 > Note: This release has breaking changes. - - **BREAKING** **FIX**(package_info_plus): Allow no page extension in versionJsonUrl on web ([#2381](https://github.com/fluttercommunity/plus_plugins/issues/2381)). ([32652b87](https://github.com/fluttercommunity/plus_plugins/commit/32652b8750245207240e383690e3b434149b87d0)) - - **BREAKING**(package_info_plus): Bump min Dart to 3.2.0 and min Flutter to 3.6.0 to support pkg:web ([#2316](https://github.com/fluttercommunity/plus_plugins/issues/2316)). ([450aeb57](https://github.com/fluttercommunity/plus_plugins/commit/450aeb578db80a9c7fb473cea133dbc87a68e530)) - - **FEAT**(package_info_plus): Migrate to pkg:web from dart:html. ([#2316](https://github.com/fluttercommunity/plus_plugins/issues/2316)). ([450aeb57](https://github.com/fluttercommunity/plus_plugins/commit/450aeb578db80a9c7fb473cea133dbc87a68e530)) +- **BREAKING** **FIX**(package_info_plus): Allow no page extension in versionJsonUrl on + web ([#2381](https://github.com/fluttercommunity/plus_plugins/issues/2381)). ([32652b87](https://github.com/fluttercommunity/plus_plugins/commit/32652b8750245207240e383690e3b434149b87d0)) +- **BREAKING**(package_info_plus): Bump min Dart to 3.2.0 and min Flutter to 3.6.0 to support pkg: + web ([#2316](https://github.com/fluttercommunity/plus_plugins/issues/2316)). ([450aeb57](https://github.com/fluttercommunity/plus_plugins/commit/450aeb578db80a9c7fb473cea133dbc87a68e530)) +- **FEAT**(package_info_plus): Migrate to pkg:web from dart: + html. ([#2316](https://github.com/fluttercommunity/plus_plugins/issues/2316)). ([450aeb57](https://github.com/fluttercommunity/plus_plugins/commit/450aeb578db80a9c7fb473cea133dbc87a68e530)) ## 5.0.0 -> Note: This release was retracted due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). +> Note: This release was retracted due +> to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). ## 4.2.0 -> Info: This release is a replacement for release 5.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. +> Info: This release is a replacement for release 5.0.0, which was retracted due to +> issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change +> was reverted the major release was also reverted in favor of this one. - - **FIX**(package_info_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2254](https://github.com/fluttercommunity/plus_plugins/issues/2254)). ([885a2a1f](https://github.com/fluttercommunity/plus_plugins/commit/885a2a1fa086f19ca8d9effaaea22272d1a8260a)) - - **FIX**(package_info_plus): Revert bump compileSDK to 34 ([#2232](https://github.com/fluttercommunity/plus_plugins/issues/2232)). ([e25e3902](https://github.com/fluttercommunity/plus_plugins/commit/e25e3902a0353baa929a269e4440e4ff0ef7efac)) - - **FEAT**(package_info_plus): Remove deprecated VALID_ARCHS iOS property ([#2023](https://github.com/fluttercommunity/plus_plugins/issues/2023)). ([4e172576](https://github.com/fluttercommunity/plus_plugins/commit/4e1725762b98070ef6d8b90aea55ca35580ac349)) - - **DOCS**(package_info_plus): Add explanation for known issue on Windows ([#2029](https://github.com/fluttercommunity/plus_plugins/issues/2029)). ([87457bf4](https://github.com/fluttercommunity/plus_plugins/commit/87457bf437465e32f8bb5a340b3c4f33fbc0a5b4)) +- **FIX**(package_info_plus): Change Kotlin version from 1.9.10 to + 1.7.22 ([#2254](https://github.com/fluttercommunity/plus_plugins/issues/2254)). ([885a2a1f](https://github.com/fluttercommunity/plus_plugins/commit/885a2a1fa086f19ca8d9effaaea22272d1a8260a)) +- **FIX**(package_info_plus): Revert bump compileSDK to + 34 ([#2232](https://github.com/fluttercommunity/plus_plugins/issues/2232)). ([e25e3902](https://github.com/fluttercommunity/plus_plugins/commit/e25e3902a0353baa929a269e4440e4ff0ef7efac)) +- **FEAT**(package_info_plus): Remove deprecated VALID_ARCHS iOS + property ([#2023](https://github.com/fluttercommunity/plus_plugins/issues/2023)). ([4e172576](https://github.com/fluttercommunity/plus_plugins/commit/4e1725762b98070ef6d8b90aea55ca35580ac349)) +- **DOCS**(package_info_plus): Add explanation for known issue on + Windows ([#2029](https://github.com/fluttercommunity/plus_plugins/issues/2029)). ([87457bf4](https://github.com/fluttercommunity/plus_plugins/commit/87457bf437465e32f8bb5a340b3c4f33fbc0a5b4)) ## 4.1.0 - - **FIX**(package_info_plus): proper version.json url for files with special characters ([#2015](https://github.com/fluttercommunity/plus_plugins/issues/2015)). ([235ee391](https://github.com/fluttercommunity/plus_plugins/commit/235ee391b87e9fa06ffc6c12a8fcdb1f6b446ca5)) - - **FIX**(package_info_plus): not working in Windows release mode from network location ([#1931](https://github.com/fluttercommunity/plus_plugins/issues/1931)). ([784caca5](https://github.com/fluttercommunity/plus_plugins/commit/784caca5b373b2ed95a76a256499bd2ae0b6fe41)) - - **FIX**(package_info_plus): Regenerate iOS and MacOS example apps ([#1871](https://github.com/fluttercommunity/plus_plugins/issues/1871)). ([0102fbbd](https://github.com/fluttercommunity/plus_plugins/commit/0102fbbdd096b23c802c31de69ec0bb08141645e)) - - **FEAT**(package_info_plus): Added toMap method ([#1926](https://github.com/fluttercommunity/plus_plugins/issues/1926)). ([4696ff45](https://github.com/fluttercommunity/plus_plugins/commit/4696ff450c4c1a84b43ba5ef3453265bdd569ada)) - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **FIX**(package_info_plus): proper version.json url for files with special + characters ([#2015](https://github.com/fluttercommunity/plus_plugins/issues/2015)). ([235ee391](https://github.com/fluttercommunity/plus_plugins/commit/235ee391b87e9fa06ffc6c12a8fcdb1f6b446ca5)) +- **FIX**(package_info_plus): not working in Windows release mode from network + location ([#1931](https://github.com/fluttercommunity/plus_plugins/issues/1931)). ([784caca5](https://github.com/fluttercommunity/plus_plugins/commit/784caca5b373b2ed95a76a256499bd2ae0b6fe41)) +- **FIX**(package_info_plus): Regenerate iOS and MacOS example + apps ([#1871](https://github.com/fluttercommunity/plus_plugins/issues/1871)). ([0102fbbd](https://github.com/fluttercommunity/plus_plugins/commit/0102fbbdd096b23c802c31de69ec0bb08141645e)) +- **FEAT**(package_info_plus): Added toMap + method ([#1926](https://github.com/fluttercommunity/plus_plugins/issues/1926)). ([4696ff45](https://github.com/fluttercommunity/plus_plugins/commit/4696ff450c4c1a84b43ba5ef3453265bdd569ada)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 4.0.2 -- **CHORE**(package_info_plus): Update http dependency constraints (#1851)([#1851](https://github.com/fluttercommunity/plus_plugins/pull/1851)). ([1463bea](https://github.com/fluttercommunity/plus_plugins/commit/1463bea77b79ee1460798b9f65d2a467023b2e38)) +- **CHORE**(package_info_plus): Update http dependency constraints ( + #1851)([#1851](https://github.com/fluttercommunity/plus_plugins/pull/1851)). ([1463bea](https://github.com/fluttercommunity/plus_plugins/commit/1463bea77b79ee1460798b9f65d2a467023b2e38)) ## 4.0.1 - - **FIX**(package_info_plus): Get Windows package info when app is on a network drive ([#1697](https://github.com/fluttercommunity/plus_plugins/issues/1697)). ([d7f9c28b](https://github.com/fluttercommunity/plus_plugins/commit/d7f9c28b20842b882b5e196bc3d1ce7963067db6)) - - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) - - **CHORE**(package_info_plus): Win32 dependency upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) +- **FIX**(package_info_plus): Get Windows package info when app is on a network + drive ([#1697](https://github.com/fluttercommunity/plus_plugins/issues/1697)). ([d7f9c28b](https://github.com/fluttercommunity/plus_plugins/commit/d7f9c28b20842b882b5e196bc3d1ce7963067db6)) +- **FIX**: Add jvm target compatibility to Kotlin + plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **CHORE**(package_info_plus): Win32 dependency + upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) ## 4.0.0 > Note: This release has breaking changes. - - **CHORE**(package_info_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(package_info_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1776). - - **REFACTOR**(package_info_plus): Tidy up Windows implementation (#1768). - - **DOCS**(package_info_plus): Explain why buildNumber returns version when no build number defined (#1729). +- **CHORE**(package_info_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to > + =2.18.0 <4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(package_info_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update + podspec file (#1776). +- **REFACTOR**(package_info_plus): Tidy up Windows implementation (#1768). +- **DOCS**(package_info_plus): Explain why buildNumber returns version when no build number + defined (#1729). ## 3.1.2 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 3.1.1 - - **FIX**(package_info_plus): remove html file parts from version url (#1330). - - **FIX**(package_info_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1704). +- **FIX**(package_info_plus): remove html file parts from version url (#1330). +- **FIX**(package_info_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1704). ## 3.1.0 - - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). - - **FIX**(package_info_plus): Make example app content scrollable (#1614). - - **FIX**(package_info_plus): Make installerStore an optional argument in mocks (#1547). - - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). - - **FEAT**(package_info_plus): Use new API to get install source on Android >= 11 (#1616). +- **REFACTOR**(all): Remove all manual dependency_overrides (#1628). +- **FIX**(package_info_plus): Make example app content scrollable (#1614). +- **FIX**(package_info_plus): Make installerStore an optional argument in mocks (#1547). +- **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). +- **FEAT**(package_info_plus): Use new API to get install source on Android >= 11 (#1616). ## 3.0.3 - - **REFACTOR**: Remove nullable struct fields (#1526). - - **DOCS**: Fixed markdown table formatting in README (#1477). - - **DOCS**: Updates for READMEs and website pages (#1389). +- **REFACTOR**: Remove nullable struct fields (#1526). +- **DOCS**: Fixed markdown table formatting in README (#1477). +- **DOCS**: Updates for READMEs and website pages (#1389). ## 3.0.2 - - **FIX**: adds value equality for PackageInfo (#1328). +- **FIX**: adds value equality for PackageInfo (#1328). ## 3.0.1 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 3.0.0 > Note: This release has breaking changes. - - **BREAKING** **REFACTOR**: two-package federated architecture (#1236). - - **BREAKING** **REFACTOR**: two-package federated architecture (#1228). +- **BREAKING** **REFACTOR**: two-package federated architecture (#1236). +- **BREAKING** **REFACTOR**: two-package federated architecture (#1228). ## 2.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**: Add information about the installer store (#1135). +- **BREAKING** **FEAT**: Add information about the installer store (#1135). ## 1.4.3+1 @@ -231,7 +286,8 @@ Plugin now requires the following: ## 1.0.5 -- Remove the `required` keyword of `buildSignature` in `PackageInfo`'s constructor to restore backward compatibility +- Remove the `required` keyword of `buildSignature` in `PackageInfo`'s constructor to restore + backward compatibility ## 1.0.4 @@ -315,7 +371,8 @@ Plugin now requires the following: ## 0.4.0+16 -- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). +- Declare API stability and compatibility with `1.0.0` (more details + at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). ## 0.4.0+15 @@ -348,7 +405,8 @@ Plugin now requires the following: ## 0.4.0+9 -- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to + support apps that has not been migrated to AndroidX. ## 0.4.0+8 diff --git a/packages/package_info_plus/package_info_plus/README.md b/packages/package_info_plus/package_info_plus/README.md index 638d1ab20d..e0aac45699 100644 --- a/packages/package_info_plus/package_info_plus/README.md +++ b/packages/package_info_plus/package_info_plus/README.md @@ -10,9 +10,9 @@ This Flutter plugin provides an API for querying information about an applicatio ## Platform Support -| Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :---: | :---: | :---: | :---: | :-----: | -|✅|✅|✅|✅|✅|✅| +| Android | iOS | MacOS | Web | Linux | Windows | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ## Requirements @@ -57,7 +57,8 @@ String buildNumber = packageInfo.buildNumber; Flutter build tools allow only digits and `.` (dot) symbols to be used in `version` of `pubspec.yaml` on iOS/MacOS to comply with official version format from Apple. -More info available in [this comment](https://github.com/fluttercommunity/plus_plugins/issues/389#issuecomment-1106764429) +More info available +in [this comment](https://github.com/fluttercommunity/plus_plugins/issues/389#issuecomment-1106764429) #### I have changed version in pubspec.yaml and plugin returns wrong info @@ -75,12 +76,16 @@ See https://github.com/fluttercommunity/plus_plugins/issues/309 #### I see wrong version on Windows platform -There was an [issue](https://github.com/flutter/flutter/issues/73652) in Flutter, which is already resolved since Flutter 3.3. -If your project was created before Flutter 3.3 you need to migrate the project according to [this guide](https://docs.flutter.dev/release/breaking-changes/windows-version-information) first to get correct version with `package_info_plus` +There was an [issue](https://github.com/flutter/flutter/issues/73652) in Flutter, which is already +resolved since Flutter 3.3. +If your project was created before Flutter 3.3 you need to migrate the project according +to [this guide](https://docs.flutter.dev/release/breaking-changes/windows-version-information) first +to get correct version with `package_info_plus` ### Web -In a web environment, the package uses the `version.json` file that it is generated in the build process. +In a web environment, the package uses the `version.json` file that it is generated in the build +process. #### Accessing the `version.json` @@ -94,8 +99,10 @@ See the documentation at the method `fromPlatform()` to learn more. #### CORS `version.json` access -It could be possible that the plugin cannot access the `version.json` file because the server is preventing it. -This can be due a CORS issue, and it is known to happen when hosting the Flutter code on Firebase Hosting. +It could be possible that the plugin cannot access the `version.json` file because the server is +preventing it. +This can be due a CORS issue, and it is known to happen when hosting the Flutter code on Firebase +Hosting. Ensure that your CORS Firebase configuration allows it. ## Learn more diff --git a/packages/package_info_plus/package_info_plus/android/build.gradle b/packages/package_info_plus/package_info_plus/android/build.gradle index 56b6a2beb1..03b5596319 100644 --- a/packages/package_info_plus/package_info_plus/android/build.gradle +++ b/packages/package_info_plus/package_info_plus/android/build.gradle @@ -2,7 +2,7 @@ group 'dev.fluttercommunity.plus.packageinfo' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.7.22' + ext.kotlin_version = '2.1.10' repositories { google() @@ -26,7 +26,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.packageinfo' diff --git a/packages/package_info_plus/package_info_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/package_info_plus/package_info_plus/android/gradle/wrapper/gradle-wrapper.properties index e411586a54..2733ed5dc3 100644 --- a/packages/package_info_plus/package_info_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/package_info_plus/package_info_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/package_info_plus/package_info_plus/android/src/main/AndroidManifest.xml b/packages/package_info_plus/package_info_plus/android/src/main/AndroidManifest.xml index 8b327e5486..9b965db539 100644 --- a/packages/package_info_plus/package_info_plus/android/src/main/AndroidManifest.xml +++ b/packages/package_info_plus/package_info_plus/android/src/main/AndroidManifest.xml @@ -1,2 +1 @@ - - + diff --git a/packages/package_info_plus/package_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.kt b/packages/package_info_plus/package_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.kt index ff96497a48..b837a68408 100644 --- a/packages/package_info_plus/package_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.kt +++ b/packages/package_info_plus/package_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.kt @@ -45,7 +45,10 @@ class PackageInfoPlugin : MethodCallHandler, FlutterPlugin { val infoMap = HashMap() infoMap.apply { - put("appName", info.applicationInfo?.loadLabel(packageManager)?.toString() ?: "") + put( + "appName", + info.applicationInfo?.loadLabel(packageManager)?.toString() ?: "" + ) put("packageName", applicationContext!!.packageName) put("version", info.versionName ?: "") put("buildNumber", getLongVersionCode(info).toString()) diff --git a/packages/package_info_plus/package_info_plus/example/android/app/build.gradle b/packages/package_info_plus/package_info_plus/example/android/app/build.gradle index a03abe94af..65f5f695c0 100644 --- a/packages/package_info_plus/package_info_plus/example/android/app/build.gradle +++ b/packages/package_info_plus/package_info_plus/example/android/app/build.gradle @@ -23,7 +23,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'io.flutter.plugins.packageinfoexample' @@ -47,7 +47,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.packageinfoexample" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/packages/package_info_plus/package_info_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties b/packages/package_info_plus/package_info_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties index fce403e45e..2733ed5dc3 100644 --- a/packages/package_info_plus/package_info_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties +++ b/packages/package_info_plus/package_info_plus/example/android/app/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/package_info_plus/package_info_plus/example/android/app/src/androidTest/java/io/flutter/plugins/packageinfoexample/EmbedderV1ActivityTest.java b/packages/package_info_plus/package_info_plus/example/android/app/src/androidTest/java/io/flutter/plugins/packageinfoexample/EmbedderV1ActivityTest.java index ab1d2d2963..5e16660760 100644 --- a/packages/package_info_plus/package_info_plus/example/android/app/src/androidTest/java/io/flutter/plugins/packageinfoexample/EmbedderV1ActivityTest.java +++ b/packages/package_info_plus/package_info_plus/example/android/app/src/androidTest/java/io/flutter/plugins/packageinfoexample/EmbedderV1ActivityTest.java @@ -5,13 +5,15 @@ package io.flutter.plugins.packageinfoexample; import androidx.test.rule.ActivityTestRule; + import dev.flutter.plugins.integration_test.FlutterTestRunner; + import org.junit.Rule; import org.junit.runner.RunWith; @RunWith(FlutterTestRunner.class) public class EmbedderV1ActivityTest { - @Rule - public ActivityTestRule rule = - new ActivityTestRule<>(EmbedderV1Activity.class); + @Rule + public ActivityTestRule rule = + new ActivityTestRule<>(EmbedderV1Activity.class); } diff --git a/packages/package_info_plus/package_info_plus/example/android/app/src/androidTest/java/io/flutter/plugins/packageinfoexample/MainActivityTest.java b/packages/package_info_plus/package_info_plus/example/android/app/src/androidTest/java/io/flutter/plugins/packageinfoexample/MainActivityTest.java index 91aad52d42..8f22e90da1 100644 --- a/packages/package_info_plus/package_info_plus/example/android/app/src/androidTest/java/io/flutter/plugins/packageinfoexample/MainActivityTest.java +++ b/packages/package_info_plus/package_info_plus/example/android/app/src/androidTest/java/io/flutter/plugins/packageinfoexample/MainActivityTest.java @@ -5,13 +5,15 @@ package io.flutter.plugins.packageinfoexample; import androidx.test.rule.ActivityTestRule; + import dev.flutter.plugins.integration_test.FlutterTestRunner; import io.flutter.embedding.android.FlutterActivity; + import org.junit.Rule; import org.junit.runner.RunWith; @RunWith(FlutterTestRunner.class) public class MainActivityTest { - @Rule - public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); } diff --git a/packages/package_info_plus/package_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/package_info_plus/package_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties index 4d6272d996..e6045a9835 100644 --- a/packages/package_info_plus/package_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/package_info_plus/package_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip diff --git a/packages/package_info_plus/package_info_plus/example/android/settings.gradle b/packages/package_info_plus/package_info_plus/example/android/settings.gradle index fa3b4d0878..18a751a498 100644 --- a/packages/package_info_plus/package_info_plus/example/android/settings.gradle +++ b/packages/package_info_plus/package_info_plus/example/android/settings.gradle @@ -18,8 +18,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false - id "org.jetbrains.kotlin.android" version "1.9.23" apply false + id "com.android.application" version "8.9.0" apply false + id "org.jetbrains.kotlin.android" version "2.1.10" apply false } include ":app" diff --git a/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_test.dart b/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_test.dart index 8ea41c3de7..92042d575a 100644 --- a/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_test.dart +++ b/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_test.dart @@ -172,10 +172,7 @@ void main() { } else { final expectedInstallTimeIso = testStartTime.toIso8601String(); final installTimeRegex = RegExp( - expectedInstallTimeIso.replaceAll( - RegExp(r'\d:\d\d\..+$'), - r'.+$', - ), + expectedInstallTimeIso.replaceAll(RegExp(r'\d:\d\d\..+$'), r'.+$'), ); if (Platform.isAndroid) { @@ -200,7 +197,9 @@ void main() { expect(find.text('Package Info Plus Example'), findsOneWidget); expect(find.text('4'), findsOneWidget); expect( - find.text('io.flutter.plugins.packageInfoExample'), findsOneWidget); + find.text('io.flutter.plugins.packageInfoExample'), + findsOneWidget, + ); expect(find.text('1.2.3'), findsOneWidget); expect(find.text('Not set'), findsOneWidget); expect(find.text('com.apple.simulator'), findsOneWidget); @@ -209,7 +208,9 @@ void main() { expect(find.text('Package Info Plus Example'), findsOneWidget); expect(find.text('4'), findsOneWidget); expect( - find.text('io.flutter.plugins.packageInfoExample'), findsOneWidget); + find.text('io.flutter.plugins.packageInfoExample'), + findsOneWidget, + ); expect(find.text('1.2.3'), findsOneWidget); expect(find.text('Not set'), findsOneWidget); expect(find.text('not available'), findsOneWidget); diff --git a/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_web_test.dart b/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_web_test.dart index b9bf613d10..b0b74a58c0 100644 --- a/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_web_test.dart +++ b/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_web_test.dart @@ -45,199 +45,196 @@ void main() { late MockClient client; late MockAssetManager assetManagerMock; - group( - 'Package Info Web', - () { - setUp(() { - client = MockClient(); - plugin = PackageInfoPlusWebPlugin(client); - }); + group('Package Info Web', () { + setUp(() { + client = MockClient(); + plugin = PackageInfoPlusWebPlugin(client); + }); - testWidgets( - 'Get correct values when response status is 200', - (tester) async { - when(client.get(any)).thenAnswer( - (_) => Future.value( - http.Response(jsonEncode(VERSION_JSON), 200), - ), - ); + testWidgets('Get correct values when response status is 200', ( + tester, + ) async { + when(client.get(any)).thenAnswer( + (_) => Future.value(http.Response(jsonEncode(VERSION_JSON), 200)), + ); - final versionMap = await plugin.getAll(); + final versionMap = await plugin.getAll(); - expect(versionMap.appName, VERSION_JSON['app_name']); - expect(versionMap.version, VERSION_JSON['version']); - expect(versionMap.buildNumber, VERSION_JSON['build_number']); - expect(versionMap.packageName, VERSION_JSON['package_name']); - expect(versionMap.buildSignature, VERSION_JSON['build_signature']); - }, - ); + expect(versionMap.appName, VERSION_JSON['app_name']); + expect(versionMap.version, VERSION_JSON['version']); + expect(versionMap.buildNumber, VERSION_JSON['build_number']); + expect(versionMap.packageName, VERSION_JSON['package_name']); + expect(versionMap.buildSignature, VERSION_JSON['build_signature']); + }); - testWidgets( - 'Get empty values when response status is not 200', - (tester) async { - when(client.get(any)).thenAnswer( - (_) => Future.value( - http.Response('', 404), - ), - ); + testWidgets('Get empty values when response status is not 200', ( + tester, + ) async { + when( + client.get(any), + ).thenAnswer((_) => Future.value(http.Response('', 404))); - final versionMap = await plugin.getAll(); + final versionMap = await plugin.getAll(); - expect(versionMap.appName, isEmpty); - expect(versionMap.buildNumber, isEmpty); - expect(versionMap.packageName, isEmpty); - expect(versionMap.version, isEmpty); - expect(versionMap.buildSignature, isEmpty); - }, - ); + expect(versionMap.appName, isEmpty); + expect(versionMap.buildNumber, isEmpty); + expect(versionMap.packageName, isEmpty); + expect(versionMap.version, isEmpty); + expect(versionMap.buildSignature, isEmpty); + }); - testWidgets( - 'Get correct values when using a custom base URL', - (tester) async { - const String baseUrl = 'https://www.example.com/'; - final DateTime now = DateTime.now(); - final Clock fakeClock = Clock(() => now); - - await withClock(fakeClock, () async { - final int cache = now.millisecondsSinceEpoch; - - when(client.get( - Uri.parse('${baseUrl}version.json?cachebuster=$cache'), - )).thenAnswer( - (_) => Future.value( - http.Response(jsonEncode(VERSION_JSON), 200), - ), - ); - - final versionMap = await plugin.getAll(baseUrl: baseUrl); - - expect(versionMap.appName, VERSION_JSON['app_name']); - expect(versionMap.version, VERSION_JSON['version']); - expect(versionMap.buildNumber, VERSION_JSON['build_number']); - expect(versionMap.packageName, VERSION_JSON['package_name']); - expect(versionMap.buildSignature, VERSION_JSON['build_signature']); - }); - }, - ); + testWidgets('Get correct values when using a custom base URL', ( + tester, + ) async { + const String baseUrl = 'https://www.example.com/'; + final DateTime now = DateTime.now(); + final Clock fakeClock = Clock(() => now); - testWidgets( - 'Get correct versionJsonUrl for http and https', - (tester) async { - expect( - plugin.versionJsonUrl('https://example.com/#/my-page', 1), - Uri.parse('https://example.com/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('https://example.com/a/b/c/#/my-page', 1), - Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('https://example.com/a/b/c/#/my-page', 1), - Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl( - 'https://example.com/?hello_world=true#/my-page', 1), - Uri.parse('https://example.com/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl( - 'https://example.com/a/b/c/?hello_world=true#/my-page', 1), - Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), - ); - expect( - // 'c' here is to be considered as a page, not a folder - plugin.versionJsonUrl( - 'https://example.com/a/b/c?hello_world=true#/my-page', 1), - Uri.parse('https://example.com/a/b/version.json?cachebuster=1'), - ); - }, + await withClock(fakeClock, () async { + final int cache = now.millisecondsSinceEpoch; + + when( + client.get(Uri.parse('${baseUrl}version.json?cachebuster=$cache')), + ).thenAnswer( + (_) => Future.value(http.Response(jsonEncode(VERSION_JSON), 200)), + ); + + final versionMap = await plugin.getAll(baseUrl: baseUrl); + + expect(versionMap.appName, VERSION_JSON['app_name']); + expect(versionMap.version, VERSION_JSON['version']); + expect(versionMap.buildNumber, VERSION_JSON['build_number']); + expect(versionMap.packageName, VERSION_JSON['package_name']); + expect(versionMap.buildSignature, VERSION_JSON['build_signature']); + }); + }); + + testWidgets('Get correct versionJsonUrl for http and https', ( + tester, + ) async { + expect( + plugin.versionJsonUrl('https://example.com/#/my-page', 1), + Uri.parse('https://example.com/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('https://example.com/a/b/c/#/my-page', 1), + Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('https://example.com/a/b/c/#/my-page', 1), + Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl( + 'https://example.com/?hello_world=true#/my-page', + 1, + ), + Uri.parse('https://example.com/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl( + 'https://example.com/a/b/c/?hello_world=true#/my-page', + 1, + ), + Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), ); + expect( + // 'c' here is to be considered as a page, not a folder + plugin.versionJsonUrl( + 'https://example.com/a/b/c?hello_world=true#/my-page', + 1, + ), + Uri.parse('https://example.com/a/b/version.json?cachebuster=1'), + ); + }); - testWidgets( - 'Get correct versionJsonUrl for urls to html files', - (tester) async { - expect( - plugin.versionJsonUrl('https://example.com', 1), - Uri.parse('https://example.com/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('https://example.com/', 1), - Uri.parse('https://example.com/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('https://example.com/index.html', 1), - Uri.parse('https://example.com/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('https://example.com/index.html#/my-page', 1), - Uri.parse('https://example.com/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl( - 'https://example.com/index.html?hello_world=true/#/my-page', 1), - Uri.parse('https://example.com/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('https://example.com/a/b/c/wrapper.html', 1), - Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl( - 'https://example.com/my-special-file.html', 1), - Uri.parse('https://example.com/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl( - 'https://example.com/a/b/c/my-special-file.html', 1), - Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), - ); - }, + testWidgets('Get correct versionJsonUrl for urls to html files', ( + tester, + ) async { + expect( + plugin.versionJsonUrl('https://example.com', 1), + Uri.parse('https://example.com/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('https://example.com/', 1), + Uri.parse('https://example.com/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('https://example.com/index.html', 1), + Uri.parse('https://example.com/version.json?cachebuster=1'), ); + expect( + plugin.versionJsonUrl('https://example.com/index.html#/my-page', 1), + Uri.parse('https://example.com/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl( + 'https://example.com/index.html?hello_world=true/#/my-page', + 1, + ), + Uri.parse('https://example.com/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('https://example.com/a/b/c/wrapper.html', 1), + Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('https://example.com/my-special-file.html', 1), + Uri.parse('https://example.com/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl( + 'https://example.com/a/b/c/my-special-file.html', + 1, + ), + Uri.parse('https://example.com/a/b/c/version.json?cachebuster=1'), + ); + }); - testWidgets('Get correct versionJsonUrl for chrome-extension', - (tester) async { - expect( - plugin.versionJsonUrl('chrome-extension://abcdefgh', 1), - Uri.parse('chrome-extension://abcdefgh/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('chrome-extension://abcdefgh/a/b/c', 1), - Uri.parse( - 'chrome-extension://abcdefgh/a/b/c/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('chrome-extension://abcdefgh/#my-page', 1), - Uri.parse('chrome-extension://abcdefgh/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl( - 'chrome-extension://abcdefgh/a/b/c/#my-page', 1), - Uri.parse( - 'chrome-extension://abcdefgh/a/b/c/version.json?cachebuster=1'), - ); - }); + testWidgets('Get correct versionJsonUrl for chrome-extension', ( + tester, + ) async { + expect( + plugin.versionJsonUrl('chrome-extension://abcdefgh', 1), + Uri.parse('chrome-extension://abcdefgh/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('chrome-extension://abcdefgh/a/b/c', 1), + Uri.parse( + 'chrome-extension://abcdefgh/a/b/c/version.json?cachebuster=1', + ), + ); + expect( + plugin.versionJsonUrl('chrome-extension://abcdefgh/#my-page', 1), + Uri.parse('chrome-extension://abcdefgh/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('chrome-extension://abcdefgh/a/b/c/#my-page', 1), + Uri.parse( + 'chrome-extension://abcdefgh/a/b/c/version.json?cachebuster=1', + ), + ); + }); - testWidgets('Get correct versionJsonUrl for file', (tester) async { - expect( - plugin.versionJsonUrl('file://abcdefgh', 1), - Uri.parse('file:///version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('file://abcdefgh/a/b/c', 1), - Uri.parse('file:///a/b/c/version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('file://abcdefgh/#my-page', 1), - Uri.parse('file:///version.json?cachebuster=1'), - ); - expect( - plugin.versionJsonUrl('file://abcdefgh/a/b/c/#my-page', 1), - Uri.parse('file:///a/b/c/version.json?cachebuster=1'), - ); - }); - }, - ); + testWidgets('Get correct versionJsonUrl for file', (tester) async { + expect( + plugin.versionJsonUrl('file://abcdefgh', 1), + Uri.parse('file:///version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('file://abcdefgh/a/b/c', 1), + Uri.parse('file:///a/b/c/version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('file://abcdefgh/#my-page', 1), + Uri.parse('file:///version.json?cachebuster=1'), + ); + expect( + plugin.versionJsonUrl('file://abcdefgh/a/b/c/#my-page', 1), + Uri.parse('file:///a/b/c/version.json?cachebuster=1'), + ); + }); + }); group('Package Info Web (using MockAssetManager)', () { setUp(() { @@ -246,39 +243,35 @@ void main() { plugin = PackageInfoPlusWebPlugin(client, assetManagerMock); }); - testWidgets( - 'Get correct values when using the AssetManager baseUrl', - (tester) async { - const String baseUrl = 'https://an.example.com/using-asset-manager/'; - const String assetsDir = 'assets'; - final DateTime now = DateTime.now(); - final Clock fakeClock = Clock(() => now); + testWidgets('Get correct values when using the AssetManager baseUrl', ( + tester, + ) async { + const String baseUrl = 'https://an.example.com/using-asset-manager/'; + const String assetsDir = 'assets'; + final DateTime now = DateTime.now(); + final Clock fakeClock = Clock(() => now); - when(assetManagerMock.assetsDir).thenReturn(assetsDir); - when(assetManagerMock.getAssetUrl('')) - .thenReturn('$baseUrl$assetsDir/'); + when(assetManagerMock.assetsDir).thenReturn(assetsDir); + when(assetManagerMock.getAssetUrl('')).thenReturn('$baseUrl$assetsDir/'); - await withClock(fakeClock, () async { - final int cache = now.millisecondsSinceEpoch; + await withClock(fakeClock, () async { + final int cache = now.millisecondsSinceEpoch; - when(client.get( - Uri.parse('${baseUrl}version.json?cachebuster=$cache'), - )).thenAnswer( - (_) => Future.value( - http.Response(jsonEncode(VERSION_JSON), 200), - ), - ); + when( + client.get(Uri.parse('${baseUrl}version.json?cachebuster=$cache')), + ).thenAnswer( + (_) => Future.value(http.Response(jsonEncode(VERSION_JSON), 200)), + ); - final versionMap = await plugin.getAll(); + final versionMap = await plugin.getAll(); - expect(versionMap.appName, VERSION_JSON['app_name']); - expect(versionMap.version, VERSION_JSON['version']); - expect(versionMap.buildNumber, VERSION_JSON['build_number']); - expect(versionMap.packageName, VERSION_JSON['package_name']); - expect(versionMap.buildSignature, VERSION_JSON['build_signature']); - }); - }, - ); + expect(versionMap.appName, VERSION_JSON['app_name']); + expect(versionMap.version, VERSION_JSON['version']); + expect(versionMap.buildNumber, VERSION_JSON['build_number']); + expect(versionMap.packageName, VERSION_JSON['package_name']); + expect(versionMap.buildSignature, VERSION_JSON['build_signature']); + }); + }); testWidgets( 'Has preference for the custom base URL over the other 2 locations', @@ -290,26 +283,27 @@ void main() { final Clock fakeClock = Clock(() => now); when(assetManagerMock.assetsDir).thenReturn(assetsDir); - when(assetManagerMock.getAssetUrl('')) - .thenReturn('$managerBaseUrl$assetsDir/'); + when( + assetManagerMock.getAssetUrl(''), + ).thenReturn('$managerBaseUrl$assetsDir/'); await withClock(fakeClock, () async { final int cache = now.millisecondsSinceEpoch; - when(client.get( - Uri.parse('${customBaseUrl}version.json?cachebuster=$cache'), - )).thenAnswer( - (_) => Future.value( - http.Response(jsonEncode(VERSION_JSON), 200), + when( + client.get( + Uri.parse('${customBaseUrl}version.json?cachebuster=$cache'), ), + ).thenAnswer( + (_) => Future.value(http.Response(jsonEncode(VERSION_JSON), 200)), ); - when(client.get( - Uri.parse('${managerBaseUrl}version.json?cachebuster=$cache'), - )).thenAnswer( - (_) => Future.value( - http.Response(jsonEncode(VERSION_2_JSON), 200), + when( + client.get( + Uri.parse('${managerBaseUrl}version.json?cachebuster=$cache'), ), + ).thenAnswer( + (_) => Future.value(http.Response(jsonEncode(VERSION_2_JSON), 200)), ); final versionMap = await plugin.getAll(baseUrl: customBaseUrl); diff --git a/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_web_test.mocks.dart b/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_web_test.mocks.dart index bd10e30c8e..439eb05c78 100644 --- a/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_web_test.mocks.dart +++ b/packages/package_info_plus/package_info_plus/example/integration_test/package_info_plus_web_test.mocks.dart @@ -26,34 +26,19 @@ import 'package:mockito/src/dummies.dart' as _i5; // ignore_for_file: subtype_of_sealed_class class _FakeResponse_0 extends _i1.SmartFake implements _i2.Response { - _FakeResponse_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeResponse_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeStreamedResponse_1 extends _i1.SmartFake implements _i2.StreamedResponse { - _FakeStreamedResponse_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeStreamedResponse_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeObject_2 extends _i1.SmartFake implements Object { - _FakeObject_2( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeObject_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } /// A class which mocks [Client]. @@ -65,46 +50,30 @@ class MockClient extends _i1.Mock implements _i2.Client { } @override - _i3.Future<_i2.Response> head( - Uri? url, { - Map? headers, - }) => + _i3.Future<_i2.Response> head(Uri? url, {Map? headers}) => (super.noSuchMethod( - Invocation.method( - #head, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #head, - [url], - {#headers: headers}, - ), - )), - ) as _i3.Future<_i2.Response>); + Invocation.method(#head, [url], {#headers: headers}), + returnValue: _i3.Future<_i2.Response>.value( + _FakeResponse_0( + this, + Invocation.method(#head, [url], {#headers: headers}), + ), + ), + ) + as _i3.Future<_i2.Response>); @override - _i3.Future<_i2.Response> get( - Uri? url, { - Map? headers, - }) => + _i3.Future<_i2.Response> get(Uri? url, {Map? headers}) => (super.noSuchMethod( - Invocation.method( - #get, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #get, - [url], - {#headers: headers}, - ), - )), - ) as _i3.Future<_i2.Response>); + Invocation.method(#get, [url], {#headers: headers}), + returnValue: _i3.Future<_i2.Response>.value( + _FakeResponse_0( + this, + Invocation.method(#get, [url], {#headers: headers}), + ), + ), + ) + as _i3.Future<_i2.Response>); @override _i3.Future<_i2.Response> post( @@ -114,28 +83,23 @@ class MockClient extends _i1.Mock implements _i2.Client { _i4.Encoding? encoding, }) => (super.noSuchMethod( - Invocation.method( - #post, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #post, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); + Invocation.method( + #post, + [url], + {#headers: headers, #body: body, #encoding: encoding}, + ), + returnValue: _i3.Future<_i2.Response>.value( + _FakeResponse_0( + this, + Invocation.method( + #post, + [url], + {#headers: headers, #body: body, #encoding: encoding}, + ), + ), + ), + ) + as _i3.Future<_i2.Response>); @override _i3.Future<_i2.Response> put( @@ -145,28 +109,23 @@ class MockClient extends _i1.Mock implements _i2.Client { _i4.Encoding? encoding, }) => (super.noSuchMethod( - Invocation.method( - #put, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #put, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); + Invocation.method( + #put, + [url], + {#headers: headers, #body: body, #encoding: encoding}, + ), + returnValue: _i3.Future<_i2.Response>.value( + _FakeResponse_0( + this, + Invocation.method( + #put, + [url], + {#headers: headers, #body: body, #encoding: encoding}, + ), + ), + ), + ) + as _i3.Future<_i2.Response>); @override _i3.Future<_i2.Response> patch( @@ -176,28 +135,23 @@ class MockClient extends _i1.Mock implements _i2.Client { _i4.Encoding? encoding, }) => (super.noSuchMethod( - Invocation.method( - #patch, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #patch, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); + Invocation.method( + #patch, + [url], + {#headers: headers, #body: body, #encoding: encoding}, + ), + returnValue: _i3.Future<_i2.Response>.value( + _FakeResponse_0( + this, + Invocation.method( + #patch, + [url], + {#headers: headers, #body: body, #encoding: encoding}, + ), + ), + ), + ) + as _i3.Future<_i2.Response>); @override _i3.Future<_i2.Response> delete( @@ -207,49 +161,36 @@ class MockClient extends _i1.Mock implements _i2.Client { _i4.Encoding? encoding, }) => (super.noSuchMethod( - Invocation.method( - #delete, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #delete, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); + Invocation.method( + #delete, + [url], + {#headers: headers, #body: body, #encoding: encoding}, + ), + returnValue: _i3.Future<_i2.Response>.value( + _FakeResponse_0( + this, + Invocation.method( + #delete, + [url], + {#headers: headers, #body: body, #encoding: encoding}, + ), + ), + ), + ) + as _i3.Future<_i2.Response>); @override - _i3.Future read( - Uri? url, { - Map? headers, - }) => + _i3.Future read(Uri? url, {Map? headers}) => (super.noSuchMethod( - Invocation.method( - #read, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future.value(_i5.dummyValue( - this, - Invocation.method( - #read, - [url], - {#headers: headers}, - ), - )), - ) as _i3.Future); + Invocation.method(#read, [url], {#headers: headers}), + returnValue: _i3.Future.value( + _i5.dummyValue( + this, + Invocation.method(#read, [url], {#headers: headers}), + ), + ), + ) + as _i3.Future); @override _i3.Future<_i6.Uint8List> readBytes( @@ -257,39 +198,29 @@ class MockClient extends _i1.Mock implements _i2.Client { Map? headers, }) => (super.noSuchMethod( - Invocation.method( - #readBytes, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future<_i6.Uint8List>.value(_i6.Uint8List(0)), - ) as _i3.Future<_i6.Uint8List>); + Invocation.method(#readBytes, [url], {#headers: headers}), + returnValue: _i3.Future<_i6.Uint8List>.value(_i6.Uint8List(0)), + ) + as _i3.Future<_i6.Uint8List>); @override _i3.Future<_i2.StreamedResponse> send(_i2.BaseRequest? request) => (super.noSuchMethod( - Invocation.method( - #send, - [request], - ), - returnValue: - _i3.Future<_i2.StreamedResponse>.value(_FakeStreamedResponse_1( - this, - Invocation.method( - #send, - [request], - ), - )), - ) as _i3.Future<_i2.StreamedResponse>); + Invocation.method(#send, [request]), + returnValue: _i3.Future<_i2.StreamedResponse>.value( + _FakeStreamedResponse_1( + this, + Invocation.method(#send, [request]), + ), + ), + ) + as _i3.Future<_i2.StreamedResponse>); @override void close() => super.noSuchMethod( - Invocation.method( - #close, - [], - ), - returnValueForMissingStub: null, - ); + Invocation.method(#close, []), + returnValueForMissingStub: null, + ); } /// A class which mocks [AssetManager]. @@ -301,50 +232,42 @@ class MockAssetManager extends _i1.Mock implements _i7.AssetManager { } @override - String get assetsDir => (super.noSuchMethod( - Invocation.getter(#assetsDir), - returnValue: _i5.dummyValue( - this, - Invocation.getter(#assetsDir), - ), - ) as String); + String get assetsDir => + (super.noSuchMethod( + Invocation.getter(#assetsDir), + returnValue: _i5.dummyValue( + this, + Invocation.getter(#assetsDir), + ), + ) + as String); @override - String getAssetUrl(String? asset) => (super.noSuchMethod( - Invocation.method( - #getAssetUrl, - [asset], - ), - returnValue: _i5.dummyValue( - this, - Invocation.method( - #getAssetUrl, - [asset], - ), - ), - ) as String); + String getAssetUrl(String? asset) => + (super.noSuchMethod( + Invocation.method(#getAssetUrl, [asset]), + returnValue: _i5.dummyValue( + this, + Invocation.method(#getAssetUrl, [asset]), + ), + ) + as String); @override - _i3.Future loadAsset(String? asset) => (super.noSuchMethod( - Invocation.method( - #loadAsset, - [asset], - ), - returnValue: _i3.Future.value(_FakeObject_2( - this, - Invocation.method( - #loadAsset, - [asset], - ), - )), - ) as _i3.Future); + _i3.Future loadAsset(String? asset) => + (super.noSuchMethod( + Invocation.method(#loadAsset, [asset]), + returnValue: _i3.Future.value( + _FakeObject_2(this, Invocation.method(#loadAsset, [asset])), + ), + ) + as _i3.Future); @override - _i3.Future<_i6.ByteData> load(String? asset) => (super.noSuchMethod( - Invocation.method( - #load, - [asset], - ), - returnValue: _i3.Future<_i6.ByteData>.value(_i6.ByteData(0)), - ) as _i3.Future<_i6.ByteData>); + _i3.Future<_i6.ByteData> load(String? asset) => + (super.noSuchMethod( + Invocation.method(#load, [asset]), + returnValue: _i3.Future<_i6.ByteData>.value(_i6.ByteData(0)), + ) + as _i3.Future<_i6.ByteData>); } diff --git a/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2d..e882ab9889 100644 --- a/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon-App-1024x1024@1x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2fd4..781d7cdcac 100644 --- a/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" + "idiom": "universal", + "filename": "LaunchImage.png", + "scale": "1x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" + "idiom": "universal", + "filename": "LaunchImage@2x.png", + "scale": "2x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" + "idiom": "universal", + "filename": "LaunchImage@3x.png", + "scale": "3x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725b70..d880e1f556 100644 --- a/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/packages/package_info_plus/package_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,8 @@ # Launch Screen Assets -You can customize the launch screen with your own desired assets by replacing the image files in this directory. +You can customize the launch screen with your own desired assets by replacing the image files in +this directory. -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file +You can also do it by opening your Flutter project's Xcode project with +`open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and +dropping in the desired images. diff --git a/packages/package_info_plus/package_info_plus/example/linux/CMakeLists.txt b/packages/package_info_plus/package_info_plus/example/linux/CMakeLists.txt index 279007eb35..c460a20abe 100644 --- a/packages/package_info_plus/package_info_plus/example/linux/CMakeLists.txt +++ b/packages/package_info_plus/package_info_plus/example/linux/CMakeLists.txt @@ -9,19 +9,19 @@ cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif () # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -37,9 +37,9 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") # Application build add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) target_link_libraries(${BINARY_NAME} PRIVATE flutter) @@ -50,8 +50,8 @@ add_dependencies(${BINARY_NAME} flutter_assemble) # people trying to run the unbundled copy, put it in a subdirectory instead of # the default top-level location. set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) # Generated plugin build rules, which manage building the plugins and adding @@ -63,9 +63,9 @@ include(flutter/generated_plugins.cmake) # By default, "installing" just makes a relocatable bundle in the build # directory. set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () # Start with a clean build bundle directory every time. install(CODE " @@ -76,19 +76,19 @@ set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -97,10 +97,10 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () diff --git a/packages/package_info_plus/package_info_plus/example/linux/flutter/CMakeLists.txt b/packages/package_info_plus/package_info_plus/example/linux/flutter/CMakeLists.txt index 5b465c7ecf..03e4a7fe4a 100644 --- a/packages/package_info_plus/package_info_plus/example/linux/flutter/CMakeLists.txt +++ b/packages/package_info_plus/package_info_plus/example/linux/flutter/CMakeLists.txt @@ -12,9 +12,9 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # which isn't available in 3.10. function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) + foreach (element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) + endforeach (element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() @@ -35,38 +35,38 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO - PkgConfig::BLKID + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID ) add_dependencies(flutter flutter_assemble) @@ -75,15 +75,15 @@ add_dependencies(flutter flutter_assemble) # since currently there's no way to get a full input/output list from the # flutter tool. add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} ) diff --git a/packages/package_info_plus/package_info_plus/example/linux/main.cc b/packages/package_info_plus/package_info_plus/example/linux/main.cc index 26cd225d93..317ce77dbf 100644 --- a/packages/package_info_plus/package_info_plus/example/linux/main.cc +++ b/packages/package_info_plus/package_info_plus/example/linux/main.cc @@ -1,6 +1,7 @@ #include "my_application.h" int main(int argc, char **argv) { - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); + g_autoptr(MyApplication) + app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); } diff --git a/packages/package_info_plus/package_info_plus/example/linux/my_application.cc b/packages/package_info_plus/package_info_plus/example/linux/my_application.cc index 8f6e1346a5..d5a61547d4 100644 --- a/packages/package_info_plus/package_info_plus/example/linux/my_application.cc +++ b/packages/package_info_plus/package_info_plus/example/linux/my_application.cc @@ -1,6 +1,7 @@ #include "my_application.h" #include + #ifdef GDK_WINDOWING_X11 #include #endif @@ -8,64 +9,66 @@ #include "flutter/generated_plugin_registrant.h" struct _MyApplication { - GtkApplication parent_instance; + GtkApplication parent_instance; }; -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION +) // Implements GApplication::activate. static void my_application_activate(GApplication *application) { - GtkWindow *window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - // Use a header bar when running in GNOME as this is the common style used - // by applications and is the setup most users will be using (e.g. Ubuntu - // desktop). - // If running on X and not using GNOME then just use a traditional title bar - // in case the window manager does more exotic layout, e.g. tiling. - // If running on Wayland assume the header bar will work (may need changing - // if future cases occur). - gboolean use_header_bar = TRUE; + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; #ifdef GDK_WINDOWING_X11 - GdkScreen *screen = gtk_window_get_screen(window); - if (GDK_IS_X11_SCREEN(screen)) { - const gchar *wm_name = gdk_x11_screen_get_window_manager_name(screen); - if (g_strcmp0(wm_name, "GNOME Shell") != 0) { - use_header_bar = FALSE; + GdkScreen *screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar *wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } } - } #endif - if (use_header_bar) { - GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - } else { - gtk_window_set_title(window, "example"); - } + if (use_header_bar) { + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "example"); + } - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); - g_autoptr(FlDartProject) project = fl_dart_project_new(); + g_autoptr(FlDartProject) + project = fl_dart_project_new(); - FlView *view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - gtk_widget_grab_focus(GTK_WIDGET(view)); + gtk_widget_grab_focus(GTK_WIDGET(view)); } static void my_application_class_init(MyApplicationClass *klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->activate = my_application_activate; } -static void my_application_init(MyApplication *self) {} +static void my_application_init(MyApplication * self) {} MyApplication *my_application_new() { - return MY_APPLICATION(g_object_new( - my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); } diff --git a/packages/package_info_plus/package_info_plus/example/linux/my_application.h b/packages/package_info_plus/package_info_plus/example/linux/my_application.h index 3258a73cf4..5b081e77c6 100644 --- a/packages/package_info_plus/package_info_plus/example/linux/my_application.h +++ b/packages/package_info_plus/package_info_plus/example/linux/my_application.h @@ -4,7 +4,8 @@ #include G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) + GtkApplication +) /** * my_application_new: diff --git a/packages/package_info_plus/package_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/package_info_plus/package_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f19f..60e60c947e 100644 --- a/packages/package_info_plus/package_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/package_info_plus/package_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ + "images": [ { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" }, { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/package_info_plus/package_info_plus/example/web/index.html b/packages/package_info_plus/package_info_plus/example/web/index.html index 45cf2ca304..00e94fd0c6 100644 --- a/packages/package_info_plus/package_info_plus/example/web/index.html +++ b/packages/package_info_plus/package_info_plus/example/web/index.html @@ -1,46 +1,46 @@ - - - - - - - - - - - - - - - - - example - - - - - + + + + + + + + + + + + + + + + + example + + + + + - + diff --git a/packages/package_info_plus/package_info_plus/example/web/manifest.json b/packages/package_info_plus/package_info_plus/example/web/manifest.json index 8c012917da..037463cc72 100644 --- a/packages/package_info_plus/package_info_plus/example/web/manifest.json +++ b/packages/package_info_plus/package_info_plus/example/web/manifest.json @@ -1,23 +1,23 @@ { - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] } diff --git a/packages/package_info_plus/package_info_plus/example/windows/CMakeLists.txt b/packages/package_info_plus/package_info_plus/example/windows/CMakeLists.txt index c0270746b1..2239f9e919 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/CMakeLists.txt +++ b/packages/package_info_plus/package_info_plus/example/windows/CMakeLists.txt @@ -12,17 +12,17 @@ cmake_policy(SET CMP0063 NEW) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() +if (IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else () + if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif () +endif () # Define settings for the Profile build mode. set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") @@ -38,11 +38,11 @@ add_definitions(-DUNICODE -D_UNICODE) # default. In most cases, you should add new options to specific targets instead # of modifying this function. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() # Flutter library and tool build rules. @@ -64,27 +64,27 @@ include(flutter/generated_plugins.cmake) set(BUILD_BUNDLE_DIR "$") # Make the "install" step default, as it's required to run. set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -93,9 +93,9 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/package_info_plus/package_info_plus/example/windows/flutter/CMakeLists.txt b/packages/package_info_plus/package_info_plus/example/windows/flutter/CMakeLists.txt index 930d2071a3..8b3e3cbd78 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/flutter/CMakeLists.txt +++ b/packages/package_info_plus/package_info_plus/example/windows/flutter/CMakeLists.txt @@ -20,61 +20,61 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") add_dependencies(flutter flutter_assemble) # === Wrapper === list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" + "core_implementations.cc" + "standard_codec.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" + "plugin_registrar.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" + "flutter_engine.cc" + "flutter_view_controller.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") # Wrapper sources needed for a plugin. add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} ) apply_standard_settings(flutter_wrapper_plugin) set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_plugin flutter_assemble) # Wrapper sources needed for the runner. add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} ) apply_standard_settings(flutter_wrapper_app) target_link_libraries(flutter_wrapper_app PUBLIC flutter) target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_app flutter_assemble) @@ -85,20 +85,20 @@ add_dependencies(flutter_wrapper_app flutter_assemble) set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} ) diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/CMakeLists.txt b/packages/package_info_plus/package_info_plus/example/windows/runner/CMakeLists.txt index 17411a8ab8..5f16fbe95f 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/CMakeLists.txt +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/CMakeLists.txt @@ -7,13 +7,13 @@ project(runner LANGUAGES CXX) # # Any new source files that you add to the application should be added here. add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" ) # Apply the standard set of build settings. This can be removed for applications diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/Runner.rc b/packages/package_info_plus/package_info_plus/example/windows/runner/Runner.rc index 7f035cd3f7..60b29949b3 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/Runner.rc +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/Runner.rc @@ -1,6 +1,7 @@ // Microsoft Visual C++ generated resource script. // #pragma code_page(65001) + #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS @@ -20,27 +21,27 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// + ///////////////////////////////////////////////////////////////////////////// + // + // TEXTINCLUDE + // -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END + 1 TEXTINCLUDE + BEGIN + "resource.h\0" + END -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END + 2 TEXTINCLUDE + BEGIN + "#include ""winres.h""\r\n" + "\0" + END -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END + 3 TEXTINCLUDE + BEGIN + "\r\n" + "\0" + END #endif // APSTUDIO_INVOKED @@ -73,37 +74,41 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEVERSION VERSION_AS_NUMBER +PRODUCTVERSION VERSION_AS_NUMBER +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG +FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L +FILEFLAGS 0x0L #endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0x0L BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "io.flutter.plugins" "\0" - VALUE "FileDescription", "example" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2022 io.flutter.plugins. All rights reserved." "\0" - VALUE "OriginalFilename", "example.exe" "\0" - VALUE "ProductName", "example" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" + BLOCK +"StringFileInfo" +BEGIN + BLOCK +"040904e4" +BEGIN + VALUE +"CompanyName", "io.flutter.plugins" "\0" +VALUE "FileDescription", "example" "\0" +VALUE "FileVersion", VERSION_AS_STRING "\0" +VALUE "InternalName", "example" "\0" +VALUE "LegalCopyright", "Copyright (C) 2022 io.flutter.plugins. All rights reserved." "\0" +VALUE "OriginalFilename", "example.exe" "\0" +VALUE "ProductName", "example" "\0" +VALUE "ProductVersion", VERSION_AS_STRING "\0" +END END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END +BLOCK "VarFileInfo" +BEGIN + VALUE +"Translation", 0x409, 1252 END + END #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/flutter_window.cpp b/packages/package_info_plus/package_info_plus/example/windows/runner/flutter_window.cpp index edfe54e14e..c0c0eafc2a 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/flutter_window.cpp +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/flutter_window.cpp @@ -5,57 +5,62 @@ #include "flutter/generated_plugin_registrant.h" FlutterWindow::FlutterWindow(const flutter::DartProject &project) - : project_(project) {} + : project_(project) {} FlutterWindow::~FlutterWindow() {} bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } - - RECT frame = GetClientArea(); - - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - return true; + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; } void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - flutter_controller_ = nullptr; - } + if (flutter_controller_) { + flutter_controller_ = nullptr; + } - Win32Window::OnDestroy(); + Win32Window::OnDestroy(); } LRESULT FlutterWindow::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opportunity to handle window messages. - if (flutter_controller_) { - std::optional result = + LPARAM const lparam) + +noexcept { +// Give Flutter, including plugins, an opportunity to handle window messages. +if (flutter_controller_) { +std::optional result = flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, lparam); - if (result) { - return *result; - } - } +if (result) { +return * +result; +} +} - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } +switch (message) { +case WM_FONTCHANGE: +flutter_controller_->engine()->ReloadSystemFonts(); +break; +} - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +return +Win32Window::MessageHandler(hwnd, message, wparam, lparam +); } diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/flutter_window.h b/packages/package_info_plus/package_info_plus/example/windows/runner/flutter_window.h index 7fa026bf24..aa8164f054 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/flutter_window.h +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/flutter_window.h @@ -11,23 +11,28 @@ // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: - // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject &project); - virtual ~FlutterWindow(); + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject &project); + + virtual ~FlutterWindow(); protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; + // Win32Window: + bool OnCreate() override; + + void OnDestroy() override; + + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) + + noexcept override; private: - // The project to run. - flutter::DartProject project_; + // The project to run. + flutter::DartProject project_; - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; }; #endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/main.cpp b/packages/package_info_plus/package_info_plus/example/windows/runner/main.cpp index 261f186935..02f805bfa5 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/main.cpp +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/main.cpp @@ -5,38 +5,54 @@ #include "flutter_window.h" #include "utils.h" -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - flutter::DartProject project(L"data"); - - std::vector command_line_arguments = GetCommandLineArguments(); - - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - - FlutterWindow window(project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"example", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - ::MSG msg; - while (::GetMessage(&msg, nullptr, 0, 0)) { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - ::CoUninitialize(); - return EXIT_SUCCESS; +int APIENTRY +wWinMain(_In_ +HINSTANCE instance, _In_opt_ +HINSTANCE prev, + _In_ +wchar_t *command_line, _In_ +int show_command +) { +// Attach to console when present (e.g., 'flutter run') or create a +// new console when running with a debugger. +if (! +::AttachConsole(ATTACH_PARENT_PROCESS) +&& ::IsDebuggerPresent()) { +CreateAndAttachConsole(); + +} + +// Initialize COM, so that it is available for use in the library and/or +// plugins. +::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED +); + +flutter::DartProject project(L"data"); + +std::vector command_line_arguments = GetCommandLineArguments(); + +project. +set_dart_entrypoint_arguments(std::move(command_line_arguments) +); + +FlutterWindow window(project); +Win32Window::Point origin(10, 10); +Win32Window::Size size(1280, 720); +if (!window.CreateAndShow(L"example", origin, size)) { +return +EXIT_FAILURE; +} +window.SetQuitOnClose(true); + +::MSG msg; +while ( +::GetMessage(&msg, nullptr, +0, 0)) { +::TranslateMessage(&msg); +::DispatchMessage(&msg); +} + +::CoUninitialize(); +return +EXIT_SUCCESS; } diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/utils.cpp b/packages/package_info_plus/package_info_plus/example/windows/runner/utils.cpp index 739b61f203..73fd1065bc 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/utils.cpp +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/utils.cpp @@ -8,56 +8,56 @@ #include void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } } -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } - std::vector command_line_arguments; + std::vector command_line_arguments; - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } - ::LocalFree(argv); + ::LocalFree(argv); - return command_line_arguments; + return command_line_arguments; } std::string Utf8FromUtf16(const wchar_t *utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - int target_length = - ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, - nullptr, 0, nullptr, nullptr); - std::string utf8_string; - if (target_length == 0 || target_length > utf8_string.max_size()) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } return utf8_string; - } - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), - target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; } diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/utils.h b/packages/package_info_plus/package_info_plus/example/windows/runner/utils.h index ff43ce2ce5..2deec25811 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/utils.h +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/utils.h @@ -14,6 +14,6 @@ std::string Utf8FromUtf16(const wchar_t *utf16_string); // Gets the command line arguments passed in as a std::vector, // encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); +std::vector GetCommandLineArguments(); #endif // RUNNER_UTILS_H_ diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/win32_window.cpp b/packages/package_info_plus/package_info_plus/example/windows/runner/win32_window.cpp index 90ff01e592..b87e3eb19d 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/win32_window.cpp +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/win32_window.cpp @@ -6,33 +6,36 @@ namespace { -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; // The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; + static int g_active_window_count = 0; -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + using EnableNonClientDpiScaling = + BOOL __stdcall(HWND + hwnd); // Scale helper to convert logical scaler values to physical using passed in // scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} + int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); + } // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. // This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { + void EnableFullDpiSupportIfAvailable(HWND + hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); - } +} +auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); +if (enable_non_client_dpi_scaling != nullptr) { +enable_non_client_dpi_scaling(hwnd); +FreeLibrary(user32_module); +} } } // namespace @@ -40,198 +43,228 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { // Manages the Win32Window's window class registration. class WindowClassRegistrar { public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registar instance. - static WindowClassRegistrar *GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; } - return instance_; - } - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t *GetWindowClass(); + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); private: - WindowClassRegistrar() = default; + WindowClassRegistrar() = default; - static WindowClassRegistrar *instance_; + static WindowClassRegistrar *instance_; - bool class_registered_ = false; + bool class_registered_ = false; }; WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; const wchar_t *WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; } void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; } Win32Window::Win32Window() { ++g_active_window_count; } Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); + --g_active_window_count; + Destroy(); } bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, const Size &size) { - Destroy(); + Destroy(); - const wchar_t *window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); - if (!window) { - return false; - } + if (!window) { + return false; + } - return OnCreate(); + return OnCreate(); } // static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window *that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } +LRESULT CALLBACK +Win32Window::WndProc(HWND +const window, +UINT const message, + WPARAM +const wparam, +LPARAM const lparam +) noexcept { +if (message == WM_NCCREATE) { +auto window_struct = reinterpret_cast(lparam); +SetWindowLongPtr(window, GWLP_USERDATA, +reinterpret_cast +(window_struct +->lpCreateParams)); + +auto that = static_cast(window_struct->lpCreateParams); +EnableFullDpiSupportIfAvailable(window); +that-> +window_handle_ = window; +} else if ( +Win32Window *that = GetThisFromHandle(window) +) { +return that-> +MessageHandler(window, message, wparam, lparam +); +} - return DefWindowProc(window, message, wparam, lparam); +return +DefWindowProc(window, message, wparam, lparam +); } LRESULT -Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } + Win32Window::MessageHandler(HWND +hwnd, +UINT const message, WPARAM +const wparam, +LPARAM const lparam +) noexcept { +switch (message) { +case WM_DESTROY: +window_handle_ = nullptr; + +Destroy(); + +if (quit_on_close_) { +PostQuitMessage(0); +} +return 0; - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - } +case WM_DPICHANGED: { +auto newRectSize = reinterpret_cast(lparam); +LONG newWidth = newRectSize->right - newRectSize->left; +LONG newHeight = newRectSize->bottom - newRectSize->top; - return DefWindowProc(window_handle_, message, wparam, lparam); +SetWindowPos(hwnd, nullptr, newRectSize +->left, newRectSize->top, newWidth, +newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + +return 0; +} +case WM_SIZE: { +RECT rect = GetClientArea(); +if (child_content_ != nullptr) { +// Size and position the child window. +MoveWindow(child_content_, rect +.left, rect.top, rect.right - rect.left, +rect.bottom - rect.top, TRUE); +} +return 0; +} + +case WM_ACTIVATE: +if (child_content_ != nullptr) { +SetFocus(child_content_); +} +return 0; +} + +return +DefWindowProc(window_handle_, message, wparam, lparam +); } void Win32Window::Destroy() { - OnDestroy(); + OnDestroy(); - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } } -Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); +Win32Window *Win32Window::GetThisFromHandle(HWND const window) + +noexcept { +return reinterpret_cast( +GetWindowLongPtr(window, GWLP_USERDATA +)); } -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); +void Win32Window::SetChildContent(HWND +content) { +child_content_ = content; +SetParent(content, window_handle_ +); +RECT frame = GetClientArea(); - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); +MoveWindow(content, frame +.left, frame.top, frame.right - frame.left, +frame.bottom - frame.top, true); - SetFocus(child_content_); +SetFocus(child_content_); } RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; } HWND Win32Window::GetHandle() { return window_handle_; } void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; + quit_on_close_ = quit_on_close; } bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; + // No-op; provided for subclasses. + return true; } void Win32Window::OnDestroy() { - // No-op; provided for subclasses. + // No-op; provided for subclasses. } diff --git a/packages/package_info_plus/package_info_plus/example/windows/runner/win32_window.h b/packages/package_info_plus/package_info_plus/example/windows/runner/win32_window.h index 7b518125bb..f8b5225436 100644 --- a/packages/package_info_plus/package_info_plus/example/windows/runner/win32_window.h +++ b/packages/package_info_plus/package_info_plus/example/windows/runner/win32_window.h @@ -12,84 +12,97 @@ // rendering and input handling class Win32Window { public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates and shows a win32 window with |title| and position and size using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring &title, const Point &origin, - const Size &size); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); + struct Point { + unsigned int x; + unsigned int y; -protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); + struct Size { + unsigned int width; + unsigned int height; - // Called when Destroy is called. - virtual void OnDestroy(); + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; -private: - friend class WindowClassRegistrar; + Win32Window(); + + virtual ~Win32Window(); - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); - // Retrieves a class instance pointer for |window| - static Win32Window *GetThisFromHandle(HWND const window) noexcept; + // Release OS resources associated with window. + void Destroy(); - bool quit_on_close_ = false; + // Inserts |content| into the window tree. + void SetChildContent(HWND content); - // window handle for top level window. - HWND window_handle_ = nullptr; + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); - // window handle for hosted content. - HWND child_content_ = nullptr; + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) + + noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK + WndProc(HWND + const window, + UINT const message, + WPARAM + const wparam, + LPARAM const lparam + ) + noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) + + noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; }; #endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/package_info_plus/package_info_plus/ios/package_info_plus/Sources/package_info_plus/FPPPackageInfoPlusPlugin.m b/packages/package_info_plus/package_info_plus/ios/package_info_plus/Sources/package_info_plus/FPPPackageInfoPlusPlugin.m index 8dd5dcf28b..ed3b1df523 100644 --- a/packages/package_info_plus/package_info_plus/ios/package_info_plus/Sources/package_info_plus/FPPPackageInfoPlusPlugin.m +++ b/packages/package_info_plus/package_info_plus/ios/package_info_plus/Sources/package_info_plus/FPPPackageInfoPlusPlugin.m @@ -5,55 +5,56 @@ #import "./include/package_info_plus/FPPPackageInfoPlusPlugin.h" @implementation FPPPackageInfoPlusPlugin -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *channel = [FlutterMethodChannel - methodChannelWithName:@"dev.fluttercommunity.plus/package_info" - binaryMessenger:[registrar messenger]]; - FPPPackageInfoPlusPlugin *instance = [[FPPPackageInfoPlusPlugin alloc] init]; - [registrar addMethodCallDelegate:instance channel:channel]; ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/package_info" + binaryMessenger:[registrar messenger]]; + FPPPackageInfoPlusPlugin *instance = [[FPPPackageInfoPlusPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - if ([call.method isEqualToString:@"getAll"]) { - NSString *appStoreReceipt = - [[[NSBundle mainBundle] appStoreReceiptURL] path]; - - NSString *installerStore = - [appStoreReceipt containsString:@"CoreSimulator"] - ? @"com.apple.simulator" - : [appStoreReceipt containsString:@"sandboxReceipt"] - ? @"com.apple.testflight" - : @"com.apple"; - - NSDate *installDate = [self getInstallDate]; - NSDate *updateDate = [self getUpdateDate]; - - result(@{ - @"appName" : [[NSBundle mainBundle] - objectForInfoDictionaryKey:@"CFBundleDisplayName"] - ?: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"] - ?: [NSNull null], - @"packageName" : [[NSBundle mainBundle] bundleIdentifier] - ?: [NSNull null], - @"version" : [[NSBundle mainBundle] - objectForInfoDictionaryKey:@"CFBundleShortVersionString"] - ?: [NSNull null], - @"buildNumber" : [[NSBundle mainBundle] - objectForInfoDictionaryKey:@"CFBundleVersion"] - ?: [NSNull null], - @"installerStore" : installerStore, - @"installTime" : [self getTimeMillisStringFromDate:installDate] ?: [NSNull null], - @"updateTime" : [self getTimeMillisStringFromDate:updateDate] ?: [NSNull null] - }); - - } else { - result(FlutterMethodNotImplemented); - } + if ([call.method isEqualToString:@"getAll"]) { + NSString *appStoreReceipt = + [[[NSBundle mainBundle] appStoreReceiptURL] path]; + + NSString *installerStore = + [appStoreReceipt containsString:@"CoreSimulator"] + ? @"com.apple.simulator" + : [appStoreReceipt containsString:@"sandboxReceipt"] + ? @"com.apple.testflight" + : @"com.apple"; + + NSDate *installDate = [self getInstallDate]; + NSDate *updateDate = [self getUpdateDate]; + + result(@{ + @"appName": [[NSBundle mainBundle] + objectForInfoDictionaryKey:@"CFBundleDisplayName"] + ?: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"] + ?: [NSNull null], + @"packageName": [[NSBundle mainBundle] bundleIdentifier] + ?: [NSNull null], + @"version": [[NSBundle mainBundle] + objectForInfoDictionaryKey:@"CFBundleShortVersionString"] + ?: [NSNull null], + @"buildNumber": [[NSBundle mainBundle] + objectForInfoDictionaryKey:@"CFBundleVersion"] + ?: [NSNull null], + @"installerStore": installerStore, + @"installTime": [self getTimeMillisStringFromDate:installDate] + ?: [NSNull null], + @"updateTime": [self getTimeMillisStringFromDate:updateDate] ?: [NSNull null] + }); + + } else { + result(FlutterMethodNotImplemented); + } } - (NSDate *)getInstallDate { - NSURL* urlToDocumentsFolder = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; + NSURL *urlToDocumentsFolder = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; __autoreleasing NSError *error; NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:urlToDocumentsFolder.path error:&error]; @@ -81,7 +82,7 @@ - (NSString *)getTimeMillisStringFromDate:(NSDate *)date { return nil; } - NSNumber *timeMillis = @((long long)([date timeIntervalSince1970] * 1000)); + NSNumber *timeMillis = @((long long) ([date timeIntervalSince1970] * 1000)); return [timeMillis stringValue]; } diff --git a/packages/package_info_plus/package_info_plus/lib/src/file_attribute.dart b/packages/package_info_plus/package_info_plus/lib/src/file_attribute.dart index d4ce98c49d..38212ca57d 100644 --- a/packages/package_info_plus/package_info_plus/lib/src/file_attribute.dart +++ b/packages/package_info_plus/package_info_plus/lib/src/file_attribute.dart @@ -28,17 +28,16 @@ class FileAttributes { late final DateTime? lastWriteTime; FileAttributes(this.filePath) { - final (:creationTime, :lastWriteTime) = - getFileCreationAndLastWriteTime(filePath); + final (:creationTime, :lastWriteTime) = getFileCreationAndLastWriteTime( + filePath, + ); this.creationTime = creationTime; this.lastWriteTime = lastWriteTime; } - static ({ - DateTime? creationTime, - DateTime? lastWriteTime, - }) getFileCreationAndLastWriteTime(String filePath) { + static ({DateTime? creationTime, DateTime? lastWriteTime}) + getFileCreationAndLastWriteTime(String filePath) { if (!File(filePath).existsSync()) { throw ArgumentError.value(filePath, 'filePath', 'File not present'); } @@ -54,12 +53,8 @@ class FileAttributes { final FILEATTRIBUTEDATA fileInformation = lpFileInformation.ref; return ( - creationTime: fileTimeToDartDateTime( - fileInformation.ftCreationTime, - ), - lastWriteTime: fileTimeToDartDateTime( - fileInformation.ftLastWriteTime, - ), + creationTime: fileTimeToDartDateTime(fileInformation.ftCreationTime), + lastWriteTime: fileTimeToDartDateTime(fileInformation.ftLastWriteTime), ); } finally { free(lptstrFilename); diff --git a/packages/package_info_plus/package_info_plus/lib/src/file_version_info.dart b/packages/package_info_plus/package_info_plus/lib/src/file_version_info.dart index 3e383a8da9..4253fbf53a 100644 --- a/packages/package_info_plus/package_info_plus/lib/src/file_version_info.dart +++ b/packages/package_info_plus/package_info_plus/lib/src/file_version_info.dart @@ -22,6 +22,7 @@ base class LANGANDCODEPAGE extends Struct { class FileVersionInfoData { const FileVersionInfoData({required this.lpBlock, required this.lpLang}); + final Pointer lpBlock; final Pointer lpLang; } @@ -35,14 +36,23 @@ class FileVersionInfo { void dispose() => free(_data.lpBlock); String get companyName => getValue('CompanyName'); + String get companyShortName => getValue('CompanyShortName'); + String get productName => getValue('ProductName'); + String get productShortName => getValue('ProductShortName'); + String get internalName => getValue('InternalName'); + String get productVersion => getValue('ProductVersion'); + String get specialBuild => getValue('SpecialBuild'); + String get originalFilename => getValue('OriginalFilename'); + String get fileDescription => getValue('FileDescription'); + String get fileVersion => getValue('FileVersion'); String getValue(String name) { @@ -66,8 +76,12 @@ class FileVersionInfo { final lang = toHex4(langCodepage[0]); final codepage = toHex4(langCodepage[1]); final lpSubBlock = TEXT('\\StringFileInfo\\$lang$codepage\\$name'); - final res = - VerQueryValue(_data.lpBlock, lpSubBlock, lplpBuffer.cast(), puLen); + final res = VerQueryValue( + _data.lpBlock, + lpSubBlock, + lplpBuffer.cast(), + puLen, + ); free(lpSubBlock); if (res != 0 && lplpBuffer.address != 0 && puLen.value > 0) { diff --git a/packages/package_info_plus/package_info_plus/lib/src/package_info_plus_linux.dart b/packages/package_info_plus/package_info_plus/lib/src/package_info_plus_linux.dart index 0a0764201d..b2f21b3060 100644 --- a/packages/package_info_plus/package_info_plus/lib/src/package_info_plus_linux.dart +++ b/packages/package_info_plus/package_info_plus/lib/src/package_info_plus_linux.dart @@ -45,7 +45,8 @@ class PackageInfoPlusLinuxPlugin extends PackageInfoPlatform { } Future<({DateTime? created, DateTime? modified})> _getExeAttributes( - String exePath) async { + String exePath, + ) async { try { final statResult = await Process.run( 'stat', @@ -74,24 +75,24 @@ class PackageInfoPlusLinuxPlugin extends PackageInfoPlatform { ); final modificationTime = _parseSecondsString(modificationMillis); - return ( - created: creationTime, - modified: modificationTime, - ); + return (created: creationTime, modified: modificationTime); } catch (_) { return (created: null, modified: null); } } Future<({DateTime created, DateTime modified})> _fallbackAttributes( - String exePath) async { + String exePath, + ) async { final modifiedTime = await File(exePath).lastModified(); return (created: modifiedTime, modified: modifiedTime); } - DateTime? _parseSecondsString(String? secondsString, - {bool allowZero = true}) { + DateTime? _parseSecondsString( + String? secondsString, { + bool allowZero = true, + }) { if (secondsString == null) { return null; } diff --git a/packages/package_info_plus/package_info_plus/lib/src/package_info_plus_web.dart b/packages/package_info_plus/package_info_plus/lib/src/package_info_plus_web.dart index abae97b8e4..3e884cae36 100644 --- a/packages/package_info_plus/package_info_plus/lib/src/package_info_plus_web.dart +++ b/packages/package_info_plus/package_info_plus/lib/src/package_info_plus_web.dart @@ -17,7 +17,7 @@ class PackageInfoPlusWebPlugin extends PackageInfoPlatform { /// Create plugin with http client and asset manager for testing purposes. PackageInfoPlusWebPlugin([this._client, AssetManager? assetManagerMock]) - : _assetManager = assetManagerMock ?? assetManager; + : _assetManager = assetManagerMock ?? assetManager; /// Registers this class as the default instance of [PackageInfoPlatform]. static void registerWith(Registrar registrar) { @@ -48,8 +48,9 @@ class PackageInfoPlusWebPlugin extends PackageInfoPlatform { // Add file and cachebuster query return uri.replace( - query: 'cachebuster=$cacheBuster', - pathSegments: [...segments, 'version.json']); + query: 'cachebuster=$cacheBuster', + pathSegments: [...segments, 'version.json'], + ); } @override @@ -57,9 +58,9 @@ class PackageInfoPlusWebPlugin extends PackageInfoPlatform { final int cacheBuster = clock.now().millisecondsSinceEpoch; final Map versionMap = await _getVersionMap(baseUrl, cacheBuster) ?? - await _getVersionMap(_assetManager.baseUrl, cacheBuster) ?? - await _getVersionMap(web.window.document.baseURI, cacheBuster) ?? - {}; + await _getVersionMap(_assetManager.baseUrl, cacheBuster) ?? + await _getVersionMap(web.window.document.baseURI, cacheBuster) ?? + {}; return PackageInfoData( appName: versionMap['app_name'] ?? '', diff --git a/packages/package_info_plus/package_info_plus/macos/package_info_plus/Sources/package_info_plus/FPPPackageInfoPlusPlugin.m b/packages/package_info_plus/package_info_plus/macos/package_info_plus/Sources/package_info_plus/FPPPackageInfoPlusPlugin.m index 08943a9e4e..ab65be0d2f 100644 --- a/packages/package_info_plus/package_info_plus/macos/package_info_plus/Sources/package_info_plus/FPPPackageInfoPlusPlugin.m +++ b/packages/package_info_plus/package_info_plus/macos/package_info_plus/Sources/package_info_plus/FPPPackageInfoPlusPlugin.m @@ -5,44 +5,45 @@ #import "./include/package_info_plus/FPPPackageInfoPlusPlugin.h" @implementation FPPPackageInfoPlusPlugin -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *channel = [FlutterMethodChannel - methodChannelWithName:@"dev.fluttercommunity.plus/package_info" - binaryMessenger:[registrar messenger]]; - FPPPackageInfoPlusPlugin *instance = [[FPPPackageInfoPlusPlugin alloc] init]; - [registrar addMethodCallDelegate:instance channel:channel]; ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/package_info" + binaryMessenger:[registrar messenger]]; + FPPPackageInfoPlusPlugin *instance = [[FPPPackageInfoPlusPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - if ([call.method isEqualToString:@"getAll"]) { - NSDate *installDate = [self getInstallDate]; - NSDate *updateDate = [self getUpdateDate]; - - result(@{ - @"appName" : [[NSBundle mainBundle] - objectForInfoDictionaryKey:@"CFBundleDisplayName"] - ?: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"] - ?: [NSNull null], - @"packageName" : [[NSBundle mainBundle] bundleIdentifier] - ?: [NSNull null], - @"version" : [[NSBundle mainBundle] - objectForInfoDictionaryKey:@"CFBundleShortVersionString"] - ?: [NSNull null], - @"buildNumber" : [[NSBundle mainBundle] - objectForInfoDictionaryKey:@"CFBundleVersion"] - ?: [NSNull null], - @"installerStore" : [NSNull null], - @"installTime" : [self getTimeMillisStringFromDate:installDate] ?: [NSNull null], - @"updateTime" : [self getTimeMillisStringFromDate:updateDate] ?: [NSNull null] - }); - } else { - result(FlutterMethodNotImplemented); - } + if ([call.method isEqualToString:@"getAll"]) { + NSDate *installDate = [self getInstallDate]; + NSDate *updateDate = [self getUpdateDate]; + + result(@{ + @"appName": [[NSBundle mainBundle] + objectForInfoDictionaryKey:@"CFBundleDisplayName"] + ?: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"] + ?: [NSNull null], + @"packageName": [[NSBundle mainBundle] bundleIdentifier] + ?: [NSNull null], + @"version": [[NSBundle mainBundle] + objectForInfoDictionaryKey:@"CFBundleShortVersionString"] + ?: [NSNull null], + @"buildNumber": [[NSBundle mainBundle] + objectForInfoDictionaryKey:@"CFBundleVersion"] + ?: [NSNull null], + @"installerStore": [NSNull null], + @"installTime": [self getTimeMillisStringFromDate:installDate] + ?: [NSNull null], + @"updateTime": [self getTimeMillisStringFromDate:updateDate] ?: [NSNull null] + }); + } else { + result(FlutterMethodNotImplemented); + } } - (NSDate *)getInstallDate { - NSURL* urlToDocumentsFolder = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; + NSURL *urlToDocumentsFolder = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; __autoreleasing NSError *error; NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:urlToDocumentsFolder.path error:&error]; @@ -70,7 +71,7 @@ - (NSString *)getTimeMillisStringFromDate:(NSDate *)date { return nil; } - NSNumber *timeMillis = @((long long)([date timeIntervalSince1970] * 1000)); + NSNumber *timeMillis = @((long long) ([date timeIntervalSince1970] * 1000)); return [timeMillis stringValue]; } diff --git a/packages/package_info_plus/package_info_plus/test/package_info_plus_windows_test.dart b/packages/package_info_plus/package_info_plus/test/package_info_plus_windows_test.dart index 4b76909c7a..9aa78a4879 100644 --- a/packages/package_info_plus/package_info_plus/test/package_info_plus_windows_test.dart +++ b/packages/package_info_plus/package_info_plus/test/package_info_plus_windows_test.dart @@ -62,11 +62,14 @@ void main() { const missingFile = 'C:\\macos\\system128\\colonel.dll'; expect( - () => FileVersionInfo(missingFile), - throwsA(isArgumentError.having( + () => FileVersionInfo(missingFile), + throwsA( + isArgumentError.having( (e) => e.message, 'message', startsWith('File not present'), - ))); + ), + ), + ); }); } diff --git a/packages/package_info_plus/package_info_plus/test/package_info_test.dart b/packages/package_info_plus/package_info_plus/test/package_info_test.dart index 583cf4c508..8cd7976f73 100644 --- a/packages/package_info_plus/package_info_plus/test/package_info_test.dart +++ b/packages/package_info_plus/package_info_plus/test/package_info_test.dart @@ -20,51 +20,48 @@ void main() { final mockUpdateTime = now; TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - channel, - (MethodCall methodCall) async { - log.add(methodCall); - switch (methodCall.method) { - case 'getAll': - return { - 'appName': 'package_info_example', - 'buildNumber': '1', - 'packageName': 'io.flutter.plugins.packageinfoexample', - 'version': '1.0', - 'installerStore': null, - 'installTime': mockInstallTime.millisecondsSinceEpoch.toString(), - 'updateTime': mockUpdateTime.millisecondsSinceEpoch.toString(), - }; - default: - assert(false); - return null; - } - }, - ); + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { + log.add(methodCall); + switch (methodCall.method) { + case 'getAll': + return { + 'appName': 'package_info_example', + 'buildNumber': '1', + 'packageName': 'io.flutter.plugins.packageinfoexample', + 'version': '1.0', + 'installerStore': null, + 'installTime': mockInstallTime.millisecondsSinceEpoch.toString(), + 'updateTime': mockUpdateTime.millisecondsSinceEpoch.toString(), + }; + default: + assert(false); + return null; + } + }); tearDown(() { log.clear(); }); - test('fromPlatform', () async { - final info = await PackageInfo.fromPlatform(); - expect(info.appName, 'package_info_example'); - expect(info.buildNumber, '1'); - expect(info.packageName, 'io.flutter.plugins.packageinfoexample'); - expect(info.version, '1.0'); - expect(info.installerStore, null); - expect(info.installTime, mockInstallTime); - expect(info.updateTime, mockUpdateTime); - expect( - log, - [ - isMethodCall('getAll', arguments: null), - ], - ); - }, onPlatform: { - 'linux': - const Skip('PackageInfoPlus on Linux does not use platform channels'), - }); + test( + 'fromPlatform', + () async { + final info = await PackageInfo.fromPlatform(); + expect(info.appName, 'package_info_example'); + expect(info.buildNumber, '1'); + expect(info.packageName, 'io.flutter.plugins.packageinfoexample'); + expect(info.version, '1.0'); + expect(info.installerStore, null); + expect(info.installTime, mockInstallTime); + expect(info.updateTime, mockUpdateTime); + expect(log, [isMethodCall('getAll', arguments: null)]); + }, + onPlatform: { + 'linux': const Skip( + 'PackageInfoPlus on Linux does not use platform channels', + ), + }, + ); test('Mock initial values', () async { PackageInfo.setMockInitialValues( diff --git a/packages/package_info_plus/package_info_plus_platform_interface/CHANGELOG.md b/packages/package_info_plus/package_info_plus_platform_interface/CHANGELOG.md index 4dbfce7dfb..d0b7c62804 100644 --- a/packages/package_info_plus/package_info_plus_platform_interface/CHANGELOG.md +++ b/packages/package_info_plus/package_info_plus_platform_interface/CHANGELOG.md @@ -1,34 +1,39 @@ ## 3.2.0 - - **FEAT**(package_info_plus): add update time ([#3466](https://github.com/fluttercommunity/plus_plugins/issues/3466)). ([c0ab9214](https://github.com/fluttercommunity/plus_plugins/commit/c0ab9214479653ce976e427dc0fa5e58b71e7f66)) +- **FEAT**(package_info_plus): add update + time ([#3466](https://github.com/fluttercommunity/plus_plugins/issues/3466)). ([c0ab9214](https://github.com/fluttercommunity/plus_plugins/commit/c0ab9214479653ce976e427dc0fa5e58b71e7f66)) ## 3.1.0 - - **FEAT**(package_info_plus): add install time ([#3434](https://github.com/fluttercommunity/plus_plugins/issues/3434)). ([0ea0402f](https://github.com/fluttercommunity/plus_plugins/commit/0ea0402f824104c36a806f32e88727801b40ba4c)) +- **FEAT**(package_info_plus): add install + time ([#3434](https://github.com/fluttercommunity/plus_plugins/issues/3434)). ([0ea0402f](https://github.com/fluttercommunity/plus_plugins/commit/0ea0402f824104c36a806f32e88727801b40ba4c)) ## 3.0.2 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 3.0.1 - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 3.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**(package_info_plus): Support multiple version.json locations in web ([#2733](https://github.com/fluttercommunity/plus_plugins/issues/2733)). ([26047f30](https://github.com/fluttercommunity/plus_plugins/commit/26047f3062ea23f8e124f1c64e03dd8a566e9bac)) +- **BREAKING** **FEAT**(package_info_plus): Support multiple version.json locations in + web ([#2733](https://github.com/fluttercommunity/plus_plugins/issues/2733)). ([26047f30](https://github.com/fluttercommunity/plus_plugins/commit/26047f3062ea23f8e124f1c64e03dd8a566e9bac)) ## 2.0.1 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 2.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**: Add information about the installer store (#1135). +- **BREAKING** **FEAT**: Add information about the installer store (#1135). ## 1.0.2 diff --git a/packages/package_info_plus/package_info_plus_platform_interface/lib/method_channel_package_info.dart b/packages/package_info_plus/package_info_plus_platform_interface/lib/method_channel_package_info.dart index 3bf014328a..6a4f9ef156 100644 --- a/packages/package_info_plus/package_info_plus_platform_interface/lib/method_channel_package_info.dart +++ b/packages/package_info_plus/package_info_plus_platform_interface/lib/method_channel_package_info.dart @@ -3,8 +3,9 @@ import 'package:package_info_plus_platform_interface/package_info_data.dart'; import 'package_info_platform_interface.dart'; -const MethodChannel _channel = - MethodChannel('dev.fluttercommunity.plus/package_info'); +const MethodChannel _channel = MethodChannel( + 'dev.fluttercommunity.plus/package_info', +); /// An implementation of [PackageInfoPlatform] that uses method channels. class MethodChannelPackageInfo extends PackageInfoPlatform { diff --git a/packages/package_info_plus/package_info_plus_platform_interface/test/method_channel_package_info_test.dart b/packages/package_info_plus/package_info_plus_platform_interface/test/method_channel_package_info_test.dart index 4affe9f121..12ef697318 100644 --- a/packages/package_info_plus/package_info_plus_platform_interface/test/method_channel_package_info_test.dart +++ b/packages/package_info_plus/package_info_plus_platform_interface/test/method_channel_package_info_test.dart @@ -14,8 +14,10 @@ void main() { group('$PackageInfoPlatform', () { test('$PackageInfoPlatform() is the default instance', () { - expect(PackageInfoPlatform.instance, - isInstanceOf()); + expect( + PackageInfoPlatform.instance, + isInstanceOf(), + ); }); test('Cannot be implemented with `implements`', () { @@ -38,25 +40,22 @@ void main() { const channel = MethodChannel('dev.fluttercommunity.plus/package_info'); final log = []; TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - channel, - (MethodCall methodCall) async { - log.add(methodCall); - switch (methodCall.method) { - case 'getAll': - return { - 'appName': 'package_info_example', - 'buildNumber': '1', - 'packageName': 'io.flutter.plugins.packageinfoexample', - 'version': '1.0', - 'installerStore': 'testflight', - }; - default: - assert(false); - return null; - } - }, - ); + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { + log.add(methodCall); + switch (methodCall.method) { + case 'getAll': + return { + 'appName': 'package_info_example', + 'buildNumber': '1', + 'packageName': 'io.flutter.plugins.packageinfoexample', + 'version': '1.0', + 'installerStore': 'testflight', + }; + default: + assert(false); + return null; + } + }); final packageInfo = MethodChannelPackageInfo(); @@ -66,10 +65,7 @@ void main() { test('getAll', () async { await packageInfo.getAll(); - expect( - log, - [isMethodCall('getAll', arguments: null)], - ); + expect(log, [isMethodCall('getAll', arguments: null)]); }); }); } diff --git a/packages/sensors_plus/sensors_plus/CHANGELOG.md b/packages/sensors_plus/sensors_plus/CHANGELOG.md index e49cb4c8f0..b8062ead6f 100644 --- a/packages/sensors_plus/sensors_plus/CHANGELOG.md +++ b/packages/sensors_plus/sensors_plus/CHANGELOG.md @@ -1,137 +1,181 @@ ## 6.1.1 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 6.1.0 - - **FEAT**(sensors_plus): Add Swift Package Manager support ([#3170](https://github.com/fluttercommunity/plus_plugins/issues/3170)). ([3a0798c4](https://github.com/fluttercommunity/plus_plugins/commit/3a0798c4ef747b7d66ab74af3d5bea6fa3a1aa26)) +- **FEAT**(sensors_plus): Add Swift Package Manager + support ([#3170](https://github.com/fluttercommunity/plus_plugins/issues/3170)). ([3a0798c4](https://github.com/fluttercommunity/plus_plugins/commit/3a0798c4ef747b7d66ab74af3d5bea6fa3a1aa26)) ## 6.0.1 - - **DOCS**(sensors_plus): Update plugin requirements in README ([#3164](https://github.com/fluttercommunity/plus_plugins/issues/3164)). ([82d95db4](https://github.com/fluttercommunity/plus_plugins/commit/82d95db42dbe9bad821fbcd033ea317cf6771691)) +- **DOCS**(sensors_plus): Update plugin requirements in + README ([#3164](https://github.com/fluttercommunity/plus_plugins/issues/3164)). ([82d95db4](https://github.com/fluttercommunity/plus_plugins/commit/82d95db42dbe9bad821fbcd033ea317cf6771691)) ## 6.0.0 -> Note: This release has breaking changes. Starting with this release on iOS it is required to add `NSMotionUsageDescription` entry in the Info.plist file. More info available in the README file. +> Note: This release has breaking changes. Starting with this release on iOS it is required to add +`NSMotionUsageDescription` entry in the Info.plist file. More info available in the README file. - - **BREAKING** **FEAT**(sensors_plus): Add support for platform timestamp in event ([#2506](https://github.com/fluttercommunity/plus_plugins/issues/2506)). ([8b3df176](https://github.com/fluttercommunity/plus_plugins/commit/8b3df17650769b913f64db48d2f56ab7a9a15616)) - - **BREAKING** **FEAT**(sensors_plus): Add barometer support for all platforms ([#3079](https://github.com/fluttercommunity/plus_plugins/issues/3079)). ([5fa797d0](https://github.com/fluttercommunity/plus_plugins/commit/5fa797d033606106a762828c38c59597fe0e9253)) - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **BREAKING** **FEAT**(sensors_plus): Add support for platform timestamp in + event ([#2506](https://github.com/fluttercommunity/plus_plugins/issues/2506)). ([8b3df176](https://github.com/fluttercommunity/plus_plugins/commit/8b3df17650769b913f64db48d2f56ab7a9a15616)) +- **BREAKING** **FEAT**(sensors_plus): Add barometer support for all + platforms ([#3079](https://github.com/fluttercommunity/plus_plugins/issues/3079)). ([5fa797d0](https://github.com/fluttercommunity/plus_plugins/commit/5fa797d033606106a762828c38c59597fe0e9253)) +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 5.0.1 - - **REFACTOR**(sensors_plus): Migrate Android example to use the new plugins declaration ([#2743](https://github.com/fluttercommunity/plus_plugins/issues/2743)). ([e884a9e9](https://github.com/fluttercommunity/plus_plugins/commit/e884a9e9979f8bda400fe063e73fc6f9a91dbfce)) - - **FIX**(sensors_plus): WASM-compatible conditional imports ([#2824](https://github.com/fluttercommunity/plus_plugins/issues/2824)). ([823a7d78](https://github.com/fluttercommunity/plus_plugins/commit/823a7d785c7bff4823e10d044291396e97ec4a3c)) +- **REFACTOR**(sensors_plus): Migrate Android example to use the new plugins + declaration ([#2743](https://github.com/fluttercommunity/plus_plugins/issues/2743)). ([e884a9e9](https://github.com/fluttercommunity/plus_plugins/commit/e884a9e9979f8bda400fe063e73fc6f9a91dbfce)) +- **FIX**(sensors_plus): WASM-compatible conditional + imports ([#2824](https://github.com/fluttercommunity/plus_plugins/issues/2824)). ([823a7d78](https://github.com/fluttercommunity/plus_plugins/commit/823a7d785c7bff4823e10d044291396e97ec4a3c)) ## 5.0.0 > Note: This release has breaking changes. -In this release plugin migrated migrated from dart:html to js_interop, meaning that it now supports WASM! +In this release plugin migrated migrated from dart:html to js_interop, meaning that it now supports +WASM! Plugin now requires the following: + - Flutter >=3.19.0 - Dart >=3.3.0 - compileSDK 34 for Android part - Java 17 for Android part - Gradle 8.4 for Android part - - **BREAKING** **FEAT**(sensors_plus): Migrate to dart:js_interop ([#2697](https://github.com/fluttercommunity/plus_plugins/issues/2697)). ([48edfa20](https://github.com/fluttercommunity/plus_plugins/commit/48edfa20558530cd08a55a880a42f3d080ccbe94)) - - **BREAKING** **BUILD**(sensors_plus): Target Java 17 on Android ([#2729](https://github.com/fluttercommunity/plus_plugins/issues/2729)). ([7a83e355](https://github.com/fluttercommunity/plus_plugins/commit/7a83e3558db7c8d4d217a485ef9a5b0c1ed7039a)) - - **BREAKING** **BUILD**(sensors_plus): Update to target and compile SDK 34 ([#2708](https://github.com/fluttercommunity/plus_plugins/pull/2708)). ([f110dfd](https://github.com/fluttercommunity/plus_plugins/commit/f110dfdd87f9de4346e8f9f765c0f05e0a02d1fa)) - - **FIX**(sensors_plus): Add try-catch for release builds ([#2718](https://github.com/fluttercommunity/plus_plugins/issues/2718)). ([c37acd67](https://github.com/fluttercommunity/plus_plugins/commit/c37acd671801e6ebb1249b2ce1939799ea27b6fb)) - - **FIX**(sensors_plus): Add iOS Privacy Info ([#2585](https://github.com/fluttercommunity/plus_plugins/issues/2585)). ([9b7198a9](https://github.com/fluttercommunity/plus_plugins/commit/9b7198a91ed2778a1399a9152441bea7fa75bf6e)) - - **FEAT**(sensors_plus): Update min iOS target to 12 ([#2661](https://github.com/fluttercommunity/plus_plugins/issues/2661)). ([ca5d660f](https://github.com/fluttercommunity/plus_plugins/commit/ca5d660f8cb7350f7c364b9c91a377c21f7dd0a1)) +- **BREAKING** **FEAT**(sensors_plus): Migrate to dart: + js_interop ([#2697](https://github.com/fluttercommunity/plus_plugins/issues/2697)). ([48edfa20](https://github.com/fluttercommunity/plus_plugins/commit/48edfa20558530cd08a55a880a42f3d080ccbe94)) +- **BREAKING** **BUILD**(sensors_plus): Target Java 17 on + Android ([#2729](https://github.com/fluttercommunity/plus_plugins/issues/2729)). ([7a83e355](https://github.com/fluttercommunity/plus_plugins/commit/7a83e3558db7c8d4d217a485ef9a5b0c1ed7039a)) +- **BREAKING** **BUILD**(sensors_plus): Update to target and compile SDK + 34 ([#2708](https://github.com/fluttercommunity/plus_plugins/pull/2708)). ([f110dfd](https://github.com/fluttercommunity/plus_plugins/commit/f110dfdd87f9de4346e8f9f765c0f05e0a02d1fa)) +- **FIX**(sensors_plus): Add try-catch for release + builds ([#2718](https://github.com/fluttercommunity/plus_plugins/issues/2718)). ([c37acd67](https://github.com/fluttercommunity/plus_plugins/commit/c37acd671801e6ebb1249b2ce1939799ea27b6fb)) +- **FIX**(sensors_plus): Add iOS Privacy + Info ([#2585](https://github.com/fluttercommunity/plus_plugins/issues/2585)). ([9b7198a9](https://github.com/fluttercommunity/plus_plugins/commit/9b7198a91ed2778a1399a9152441bea7fa75bf6e)) +- **FEAT**(sensors_plus): Update min iOS target to + 12 ([#2661](https://github.com/fluttercommunity/plus_plugins/issues/2661)). ([ca5d660f](https://github.com/fluttercommunity/plus_plugins/commit/ca5d660f8cb7350f7c364b9c91a377c21f7dd0a1)) ## 4.0.2 - - **FIX**(sensors_plus): Close magnetometerStreamController on web ([#2456](https://github.com/fluttercommunity/plus_plugins/issues/2456)). ([64200667](https://github.com/fluttercommunity/plus_plugins/commit/64200667e94ec6eedeb3f8224f355d113dee3ac8)) +- **FIX**(sensors_plus): Close magnetometerStreamController on + web ([#2456](https://github.com/fluttercommunity/plus_plugins/issues/2456)). ([64200667](https://github.com/fluttercommunity/plus_plugins/commit/64200667e94ec6eedeb3f8224f355d113dee3ac8)) ## 4.0.1+1 - - **DOCS**(sensors_plus): Update README to mention how sampling rate works on Android ([#2452](https://github.com/fluttercommunity/plus_plugins/issues/2452)). ([4d8ce2f8](https://github.com/fluttercommunity/plus_plugins/commit/4d8ce2f8e9eb09e8ae6e5616599a593ff182ea24)) +- **DOCS**(sensors_plus): Update README to mention how sampling rate works on + Android ([#2452](https://github.com/fluttercommunity/plus_plugins/issues/2452)). ([4d8ce2f8](https://github.com/fluttercommunity/plus_plugins/commit/4d8ce2f8e9eb09e8ae6e5616599a593ff182ea24)) ## 4.0.1 > Note: This release has breaking changes. - - **BREAKING** **FIX**(sensors_plus): Use magnetometer instead of deviceMotion on iOS ([#2250](https://github.com/fluttercommunity/plus_plugins/issues/2250)). ([d1751024](https://github.com/fluttercommunity/plus_plugins/commit/d175102404f5a614360dc52380e95aa0a6308481)) - - **FEAT**(sensors_plus): Configurable sample rate on Android and iOS ([#2248](https://github.com/fluttercommunity/plus_plugins/issues/2248)). ([82ffe46c](https://github.com/fluttercommunity/plus_plugins/commit/82ffe46c6ff02a7fcaad35c74c872e1ceb37621c)) - - **DOCS**(sensors_plus): Add info about sensors sampling rate configuration ([#2393](https://github.com/fluttercommunity/plus_plugins/issues/2393)). ([35900ead](https://github.com/fluttercommunity/plus_plugins/commit/35900eadd91e88d5eb2d28eeb32048edbb1057c9)) +- **BREAKING** **FIX**(sensors_plus): Use magnetometer instead of deviceMotion on + iOS ([#2250](https://github.com/fluttercommunity/plus_plugins/issues/2250)). ([d1751024](https://github.com/fluttercommunity/plus_plugins/commit/d175102404f5a614360dc52380e95aa0a6308481)) +- **FEAT**(sensors_plus): Configurable sample rate on Android and + iOS ([#2248](https://github.com/fluttercommunity/plus_plugins/issues/2248)). ([82ffe46c](https://github.com/fluttercommunity/plus_plugins/commit/82ffe46c6ff02a7fcaad35c74c872e1ceb37621c)) +- **DOCS**(sensors_plus): Add info about sensors sampling rate + configuration ([#2393](https://github.com/fluttercommunity/plus_plugins/issues/2393)). ([35900ead](https://github.com/fluttercommunity/plus_plugins/commit/35900eadd91e88d5eb2d28eeb32048edbb1057c9)) ## 4.0.0 -This release was retracted due to [#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251). +This release was retracted due +to [#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251). ## 3.1.0 -> Info: This release is a replacement for release 4.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. - - - **FIX**(sensors_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2253](https://github.com/fluttercommunity/plus_plugins/issues/2253)). ([10fade07](https://github.com/fluttercommunity/plus_plugins/commit/10fade073928e2676e6383e0697ba0d123ab4a87)) - - **FIX**(sensors_plus): Close stream controllers onCancel on web ([#2249](https://github.com/fluttercommunity/plus_plugins/issues/2249)). ([476e17bc](https://github.com/fluttercommunity/plus_plugins/commit/476e17bc7e404862dafc5eb57c57908181f3f52f)) - - **FIX**(sensors_plus): Revert bump compileSDK to 34 ([#2233](https://github.com/fluttercommunity/plus_plugins/issues/2233)). ([8574422a](https://github.com/fluttercommunity/plus_plugins/commit/8574422aad07955e6a2bad7863f557c7ae0a1d57)) - - **FIX**(sensors_plus): Error handling of native crashes (e.g. missing hardware) ([#1987](https://github.com/fluttercommunity/plus_plugins/issues/1987)). ([ee942290](https://github.com/fluttercommunity/plus_plugins/commit/ee9422901bc16a5e6e183f918646865336646955)) - - **FEAT**(sensors_plus): Remove deprecated VALID_ARCHS iOS property ([#2027](https://github.com/fluttercommunity/plus_plugins/issues/2027)). ([8ba4197e](https://github.com/fluttercommunity/plus_plugins/commit/8ba4197ee4258f56984e69d4c1196c234ed3dce0)) +> Info: This release is a replacement for release 4.0.0, which was retracted due to +> issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change +> was reverted the major release was also reverted in favor of this one. + +- **FIX**(sensors_plus): Change Kotlin version from 1.9.10 to + 1.7.22 ([#2253](https://github.com/fluttercommunity/plus_plugins/issues/2253)). ([10fade07](https://github.com/fluttercommunity/plus_plugins/commit/10fade073928e2676e6383e0697ba0d123ab4a87)) +- **FIX**(sensors_plus): Close stream controllers onCancel on + web ([#2249](https://github.com/fluttercommunity/plus_plugins/issues/2249)). ([476e17bc](https://github.com/fluttercommunity/plus_plugins/commit/476e17bc7e404862dafc5eb57c57908181f3f52f)) +- **FIX**(sensors_plus): Revert bump compileSDK to + 34 ([#2233](https://github.com/fluttercommunity/plus_plugins/issues/2233)). ([8574422a](https://github.com/fluttercommunity/plus_plugins/commit/8574422aad07955e6a2bad7863f557c7ae0a1d57)) +- **FIX**(sensors_plus): Error handling of native crashes (e.g. missing + hardware) ([#1987](https://github.com/fluttercommunity/plus_plugins/issues/1987)). ([ee942290](https://github.com/fluttercommunity/plus_plugins/commit/ee9422901bc16a5e6e183f918646865336646955)) +- **FEAT**(sensors_plus): Remove deprecated VALID_ARCHS iOS + property ([#2027](https://github.com/fluttercommunity/plus_plugins/issues/2027)). ([8ba4197e](https://github.com/fluttercommunity/plus_plugins/commit/8ba4197ee4258f56984e69d4c1196c234ed3dce0)) ## 3.0.3 - - **FIX**(sensors_plus): fixed the deprecated syntax ([#1904](https://github.com/fluttercommunity/plus_plugins/issues/1904)). ([57f06352](https://github.com/fluttercommunity/plus_plugins/commit/57f06352ccf0c6aec0f483cb595764826623e311)) - - **FIX**(sensors_plus): Regenerate iOS example app ([#1870](https://github.com/fluttercommunity/plus_plugins/issues/1870)). ([5046f542](https://github.com/fluttercommunity/plus_plugins/commit/5046f542433726534a2fb1c06c85f8bfc5f41398)) - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **FIX**(sensors_plus): fixed the deprecated + syntax ([#1904](https://github.com/fluttercommunity/plus_plugins/issues/1904)). ([57f06352](https://github.com/fluttercommunity/plus_plugins/commit/57f06352ccf0c6aec0f483cb595764826623e311)) +- **FIX**(sensors_plus): Regenerate iOS example + app ([#1870](https://github.com/fluttercommunity/plus_plugins/issues/1870)). ([5046f542](https://github.com/fluttercommunity/plus_plugins/commit/5046f542433726534a2fb1c06c85f8bfc5f41398)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 3.0.2 - - **FIX**(sensors_plus): Fix issues with emitting multiple sensors events on iOS ([#1859](https://github.com/fluttercommunity/plus_plugins/issues/1859)). ([d33b20fa](https://github.com/fluttercommunity/plus_plugins/commit/d33b20fa7c76368dbcc12064df8469c301658b53)) +- **FIX**(sensors_plus): Fix issues with emitting multiple sensors events on + iOS ([#1859](https://github.com/fluttercommunity/plus_plugins/issues/1859)). ([d33b20fa](https://github.com/fluttercommunity/plus_plugins/commit/d33b20fa7c76368dbcc12064df8469c301658b53)) ## 3.0.1 - - **FIX**(sensors_plus): Fix crash on Android if device has no requested sensor ([#1405](https://github.com/fluttercommunity/plus_plugins/issues/1405)). ([a078b4e8](https://github.com/fluttercommunity/plus_plugins/commit/a078b4e8464a3b8dce24ee5112394097d981a173)) - - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) - - **DOCS**(sensor_plus): Add info about possible error cases ([#1830](https://github.com/fluttercommunity/plus_plugins/issues/1830)). ([58d512de](https://github.com/fluttercommunity/plus_plugins/commit/58d512de24f9f4eeb154375958378868fd4bb1a7)) - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) - - **CHORE**(sensors_plus): Win32 dependency upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) +- **FIX**(sensors_plus): Fix crash on Android if device has no requested + sensor ([#1405](https://github.com/fluttercommunity/plus_plugins/issues/1405)). ([a078b4e8](https://github.com/fluttercommunity/plus_plugins/commit/a078b4e8464a3b8dce24ee5112394097d981a173)) +- **FIX**: Add jvm target compatibility to Kotlin + plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) +- **DOCS**(sensor_plus): Add info about possible error + cases ([#1830](https://github.com/fluttercommunity/plus_plugins/issues/1830)). ([58d512de](https://github.com/fluttercommunity/plus_plugins/commit/58d512de24f9f4eeb154375958378868fd4bb1a7)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **CHORE**(sensors_plus): Win32 dependency + upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) ## 3.0.0 > Note: This release has breaking changes. - - **CHORE**(sensors_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(sensors_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1774). - - **REFACTOR**(sensors_plus): Remove manual dependency_override in example app. +- **CHORE**(sensors_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 < + 4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(sensors_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update + podspec file (#1774). +- **REFACTOR**(sensors_plus): Remove manual dependency_override in example app. ## 2.0.5 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 2.0.4 - - **FIX**(sensors_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1705). +- **FIX**(sensors_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1705). ## 2.0.3 - - **DOCS**(sensor_plus): improve description of accelerometer (#1425). +- **DOCS**(sensor_plus): improve description of accelerometer (#1425). ## 2.0.2 - - **DOCS**: Updates for READMEs and website pages (#1389). +- **DOCS**: Updates for READMEs and website pages (#1389). ## 2.0.1 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 2.0.0 > Note: This release has breaking changes. - - **FIX**: lint warnings - add missing dependency for tests (#1233). - - **DOCS**: Update website docs and README (#1247). - - **BREAKING** **REFACTOR**: two-package federated architecture (#1237). +- **FIX**: lint warnings - add missing dependency for tests (#1233). +- **DOCS**: Update website docs and README (#1247). +- **BREAKING** **REFACTOR**: two-package federated architecture (#1237). ## 1.4.1 - - **CHORE**: Version tagging using melos. +- **CHORE**: Version tagging using melos. ## 1.4.0 @@ -158,7 +202,8 @@ This release was retracted due to [#2251](https://github.com/fluttercommunity/pl ## 1.3.1 -- Fix: unregister listeners on Android in `onDetachFromEngine` to not receive sensors events after app was killed +- Fix: unregister listeners on Android in `onDetachFromEngine` to not receive sensors events after + app was killed ## 1.3.0 @@ -231,7 +276,8 @@ This release was retracted due to [#2251](https://github.com/fluttercommunity/pl ## 0.4.1+10 -- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). +- Declare API stability and compatibility with `1.0.0` (more details + at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). ## 0.4.1+9 @@ -287,7 +333,8 @@ This release was retracted due to [#2251](https://github.com/fluttercommunity/pl ## 0.4.0+2 -- Suppress deprecation warning for BinaryMessages. See: https://github.com/flutter/flutter/issues/33446 +- Suppress deprecation warning for BinaryMessages. + See: https://github.com/flutter/flutter/issues/33446 ## 0.4.0+1 diff --git a/packages/sensors_plus/sensors_plus/README.md b/packages/sensors_plus/sensors_plus/README.md index 13b5066022..5d111dac18 100644 --- a/packages/sensors_plus/sensors_plus/README.md +++ b/packages/sensors_plus/sensors_plus/README.md @@ -6,14 +6,14 @@ [](https://flutter.dev/docs/development/packages-and-plugins/favorites) -A Flutter plugin to access the accelerometer, gyroscope, magnetometer and +A Flutter plugin to access the accelerometer, gyroscope, magnetometer and barometer sensors. ## Platform Support -| Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :---: | :---: | :---: | :---: | :-----: | -| ✅ | ✅ | ❌ | ✅* | ❌ | ❌ | +| Android | iOS | MacOS | Web | Linux | Windows | +|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| ✅ | ✅ | ❌ | ✅* | ❌ | ❌ | \* Currently it is not possible to set sensors sampling rate on web @@ -31,8 +31,12 @@ barometer sensors. ## Usage Add `sensors_plus` as a dependency in your pubspec.yaml file. - -On iOS you must also include a key called [`NSMotionUsageDescription`](https://developer.apple.com/documentation/bundleresources/information_property_list/nsmotionusagedescription) in your app's `Info.plist` file. This key provides a message that tells the user why the app is requesting access to the device’s motion data. The plugin itself needs access to motion data to get barometer data. + +On iOS you must also include a key called [ +`NSMotionUsageDescription`](https://developer.apple.com/documentation/bundleresources/information_property_list/nsmotionusagedescription) +in your app's `Info.plist` file. This key provides a message that tells the user why the app is +requesting access to the device’s motion data. The plugin itself needs access to motion data to get +barometer data. Example Info.plist entry: @@ -43,7 +47,9 @@ Example Info.plist entry: > [!CAUTION] > -> Adding [`NSMotionUsageDescription`](https://developer.apple.com/documentation/bundleresources/information_property_list/nsmotionusagedescription) is a requirement and not doing so will crash your app when it attempts to access motion data. +> Adding [ +`NSMotionUsageDescription`](https://developer.apple.com/documentation/bundleresources/information_property_list/nsmotionusagedescription) +> is a requirement and not doing so will crash your app when it attempts to access motion data. The plugin exposes such classes of sensor events through a set of streams: @@ -53,7 +59,8 @@ The plugin exposes such classes of sensor events through a set of streams: If the device is moving e.g. towards north and its speed is increasing, the reported acceleration is towards north; if it is slowing down, the reported acceleration is towards south; if it is turning right, the reported acceleration is towards east. - The data of this stream is obtained by filtering out the effect of gravity from `AccelerometerEvent`. + The data of this stream is obtained by filtering out the effect of gravity from + `AccelerometerEvent`. - `AccelerometerEvent` describes the acceleration of the device, in m/s2, including the effects of gravity. Unlike `UserAccelerometerEvent`, this stream reports raw data from the accelerometer (physical sensor embedded in the mobile device) without any post-processing. @@ -62,12 +69,13 @@ The plugin exposes such classes of sensor events through a set of streams: This means that, at the surface of Earth, even if the device is completely still, the reading of `AccelerometerEvent` is an acceleration of intensity 9.8 directed upwards (the opposite of the graviational acceleration). - This can be used to infer information about the position of the device (horizontal/vertical/tilted). + This can be used to infer information about the position of the device ( + horizontal/vertical/tilted). `AccelerometerEvent` reports zero acceleration if the device is free falling. - `GyroscopeEvent` describes the rotation of the device. - `MagnetometerEvent` describes the ambient magnetic field surrounding the device. A compass is an example usage of this data. -- `BarometerEvent` describes the atmospheric pressure surrounding the device, in hPa. +- `BarometerEvent` describes the atmospheric pressure surrounding the device, in hPa. An altimeter is an example usage of this data. Not supported on web browsers. These events are exposed through a `BroadcastStream`: `accelerometerEvents`, @@ -145,12 +153,16 @@ barometerEvents.listen( // [BarometerEvent (pressure: 1000.0)] ``` -Alternatively, every stream allows to specify the sampling rate for its sensor using one of predefined constants or using a custom value. +Alternatively, every stream allows to specify the sampling rate for its sensor using one of +predefined constants or using a custom value. > [!NOTE] > -> On Android it is not guaranteed that events from sensors will arrive with specified sampling rate as it is noted in [the official Android documentation](https://developer.android.com/reference/android/hardware/SensorManager.html#registerListener(android.hardware.SensorEventListener,%20android.hardware.Sensor,%20int)) (see the description for the `samplingPeriodUs` parameter). In reality delay varies depending on Android version, device hardware and vendor's OS customisations. - +> On Android it is not guaranteed that events from sensors will arrive with specified sampling rate +> as it is noted +> in [the official Android documentation](https://developer.android.com/reference/android/hardware/SensorManager.html#registerListener(android.hardware.SensorEventListener,%20android.hardware.Sensor,%20int)) ( +> see the description for the `samplingPeriodUs` parameter). In reality delay varies depending on +> Android version, device hardware and vendor's OS customisations. ```dart magnetometerEvents(samplingPeriod: SensorInterval.normalInterval).listen( @@ -171,27 +183,37 @@ sensor data. ### Platform Restrictions and Considerations -The following lists the restrictions for the sensors on certain platforms due to limitations of the platform. +The following lists the restrictions for the sensors on certain platforms due to limitations of the +platform. - **Magnetometer and Barometer missing for web** - The Magnetometer API is currently not supported by any modern web browsers. Check browser compatibility matrix on [MDN docs for Magnetormeter API](https://developer.mozilla.org/en-US/docs/Web/API/Magnetometer). + The Magnetometer API is currently not supported by any modern web browsers. Check browser + compatibility matrix + on [MDN docs for Magnetormeter API](https://developer.mozilla.org/en-US/docs/Web/API/Magnetometer). - The Barometer API does not exist for web platforms as can be seen at [MDN docs forn Sensors API](https://developer.mozilla.org/en-US/docs/Web/API/Sensor_APIs). + The Barometer API does not exist for web platforms as can be seen + at [MDN docs forn Sensors API](https://developer.mozilla.org/en-US/docs/Web/API/Sensor_APIs). - Developers should consider alternative methods or inform users about the limitation when their application runs on a web platform. + Developers should consider alternative methods or inform users about the limitation when their + application runs on a web platform. > [!NOTE] > -> Plugin won't crash the app in the case of usage on these platforms, but it is highly recommended to add onError() to handle such cases gracefully. +> Plugin won't crash the app in the case of usage on these platforms, but it is highly recommended +> to add onError() to handle such cases gracefully. - **Sampling periods for web** - Currently it is not possible to set sensors sampling rate on web. Calls to event streams at specied sampling periods will have the sampling period ignored. + Currently it is not possible to set sensors sampling rate on web. Calls to event streams at + specied sampling periods will have the sampling period ignored. - **Barometer sampling period limitation for iOS** - On iOS devices, barometer updates are [CMAltimeter](https://developer.apple.com/documentation/coremotion/cmaltimeter) which provides updates at regular intervals that cannot be controlled by the user. Calls to `barometerEventStream` at specied sampling periods will have the sampling period ignored. + On iOS devices, barometer updates + are [CMAltimeter](https://developer.apple.com/documentation/coremotion/cmaltimeter) which provides + updates at regular intervals that cannot be controlled by the user. Calls to + `barometerEventStream` at specied sampling periods will have the sampling period ignored. ## Learn more diff --git a/packages/sensors_plus/sensors_plus/android/build.gradle b/packages/sensors_plus/sensors_plus/android/build.gradle index 915ddac953..0a6f610a77 100644 --- a/packages/sensors_plus/sensors_plus/android/build.gradle +++ b/packages/sensors_plus/sensors_plus/android/build.gradle @@ -2,7 +2,7 @@ group 'dev.fluttercommunity.plus.sensors' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.7.22' + ext.kotlin_version = '2.1.10' repositories { google() mavenCentral() @@ -25,7 +25,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.sensors' @@ -47,6 +47,6 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" } } diff --git a/packages/sensors_plus/sensors_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/sensors_plus/sensors_plus/android/gradle/wrapper/gradle-wrapper.properties index e411586a54..2733ed5dc3 100644 --- a/packages/sensors_plus/sensors_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/sensors_plus/sensors_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/sensors_plus/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/StreamHandlerImpl.kt b/packages/sensors_plus/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/StreamHandlerImpl.kt index f74d14b18d..8eb2c98eeb 100644 --- a/packages/sensors_plus/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/StreamHandlerImpl.kt +++ b/packages/sensors_plus/sensors_plus/android/src/main/kotlin/dev/fluttercommunity/plus/sensors/StreamHandlerImpl.kt @@ -16,7 +16,8 @@ internal class StreamHandlerImpl( private var sensor: Sensor? = null - private var timestampMicroAtBoot: Long = System.currentTimeMillis() * 1000 - SystemClock.elapsedRealtimeNanos() / 1000 + private var timestampMicroAtBoot: Long = + System.currentTimeMillis() * 1000 - SystemClock.elapsedRealtimeNanos() / 1000 var samplingPeriod = 200000 set(value) { diff --git a/packages/sensors_plus/sensors_plus/example/android/app/build.gradle b/packages/sensors_plus/sensors_plus/example/android/app/build.gradle index 7ec46491a4..b0d8b8380b 100644 --- a/packages/sensors_plus/sensors_plus/example/android/app/build.gradle +++ b/packages/sensors_plus/sensors_plus/example/android/app/build.gradle @@ -22,7 +22,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'io.flutter.plugins.sensorsexample' @@ -42,7 +42,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.sensorsexample" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/packages/sensors_plus/sensors_plus/example/android/app/src/main/java/io/flutter/plugins/sensorsexample/FlutterActivityTest.java b/packages/sensors_plus/sensors_plus/example/android/app/src/main/java/io/flutter/plugins/sensorsexample/FlutterActivityTest.java index 0835b0f594..202cde04a5 100644 --- a/packages/sensors_plus/sensors_plus/example/android/app/src/main/java/io/flutter/plugins/sensorsexample/FlutterActivityTest.java +++ b/packages/sensors_plus/sensors_plus/example/android/app/src/main/java/io/flutter/plugins/sensorsexample/FlutterActivityTest.java @@ -5,13 +5,15 @@ package io.flutter.plugins.sensorsexample; import androidx.test.rule.ActivityTestRule; + import dev.flutter.plugins.integration_test.FlutterTestRunner; import io.flutter.embedding.android.FlutterActivity; + import org.junit.Rule; import org.junit.runner.RunWith; @RunWith(FlutterTestRunner.class) public class FlutterActivityTest { - @Rule - public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); } diff --git a/packages/sensors_plus/sensors_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/sensors_plus/sensors_plus/example/android/gradle/wrapper/gradle-wrapper.properties index cae4528dfb..c0bc428bc1 100644 --- a/packages/sensors_plus/sensors_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/sensors_plus/sensors_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/sensors_plus/sensors_plus/example/android/settings.gradle b/packages/sensors_plus/sensors_plus/example/android/settings.gradle index 5fad357a02..c45c7624c3 100644 --- a/packages/sensors_plus/sensors_plus/example/android/settings.gradle +++ b/packages/sensors_plus/sensors_plus/example/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false + id "com.android.application" version "8.9.0" apply false } include ":app" diff --git a/packages/sensors_plus/sensors_plus/example/integration_test/sensors_plus_test.dart b/packages/sensors_plus/sensors_plus/example/integration_test/sensors_plus_test.dart index 602a896218..cb4f429e65 100644 --- a/packages/sensors_plus/sensors_plus/example/integration_test/sensors_plus_test.dart +++ b/packages/sensors_plus/sensors_plus/example/integration_test/sensors_plus_test.dart @@ -11,15 +11,19 @@ void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); // NOTE: The accelerometer events are not returned on iOS simulators. - testWidgets('Can subscribe to accelerometerEvents and get non-null events', - (WidgetTester tester) async { - final completer = Completer(); - late StreamSubscription subscription; - subscription = - accelerometerEventStream().listen((AccelerometerEvent event) { - completer.complete(event); - subscription.cancel(); - }); - expect(await completer.future, isNotNull); - }, skip: !Platform.isAndroid); + testWidgets( + 'Can subscribe to accelerometerEvents and get non-null events', + (WidgetTester tester) async { + final completer = Completer(); + late StreamSubscription subscription; + subscription = accelerometerEventStream().listen(( + AccelerometerEvent event, + ) { + completer.complete(event); + subscription.cancel(); + }); + expect(await completer.future, isNotNull); + }, + skip: !Platform.isAndroid, + ); } diff --git a/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2d..e882ab9889 100644 --- a/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon-App-1024x1024@1x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2fd4..781d7cdcac 100644 --- a/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" + "idiom": "universal", + "filename": "LaunchImage.png", + "scale": "1x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" + "idiom": "universal", + "filename": "LaunchImage@2x.png", + "scale": "2x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" + "idiom": "universal", + "filename": "LaunchImage@3x.png", + "scale": "3x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725b70..d880e1f556 100644 --- a/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/packages/sensors_plus/sensors_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,8 @@ # Launch Screen Assets -You can customize the launch screen with your own desired assets by replacing the image files in this directory. +You can customize the launch screen with your own desired assets by replacing the image files in +this directory. -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file +You can also do it by opening your Flutter project's Xcode project with +`open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and +dropping in the desired images. diff --git a/packages/sensors_plus/sensors_plus/example/lib/main.dart b/packages/sensors_plus/sensors_plus/example/lib/main.dart index 93ec4ad684..cd3d6aa593 100644 --- a/packages/sensors_plus/sensors_plus/example/lib/main.dart +++ b/packages/sensors_plus/sensors_plus/example/lib/main.dart @@ -14,12 +14,10 @@ import 'snake.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); - SystemChrome.setPreferredOrientations( - [ - DeviceOrientation.portraitUp, - DeviceOrientation.portraitDown, - ], - ); + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); runApp(const MyApp()); } @@ -80,10 +78,7 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Sensors Plus Example'), - elevation: 4, - ), + appBar: AppBar(title: const Text('Sensors Plus Example'), elevation: 4), body: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ @@ -130,7 +125,8 @@ class _MyHomePageState extends State { Text(_userAccelerometerEvent?.y.toStringAsFixed(1) ?? '?'), Text(_userAccelerometerEvent?.z.toStringAsFixed(1) ?? '?'), Text( - '${_userAccelerometerLastInterval?.toString() ?? '?'} ms'), + '${_userAccelerometerLastInterval?.toString() ?? '?'} ms', + ), ], ), TableRow( @@ -195,7 +191,8 @@ class _MyHomePageState extends State { child: Text('Barometer'), ), Text( - '${_barometerEvent?.pressure.toStringAsFixed(1) ?? '?'} hPa'), + '${_barometerEvent?.pressure.toStringAsFixed(1) ?? '?'} hPa', + ), Text('${_barometerLastInterval?.toString() ?? '?'} ms'), ], ), @@ -210,18 +207,24 @@ class _MyHomePageState extends State { segments: [ ButtonSegment( value: SensorInterval.gameInterval, - label: Text('Game\n' - '(${SensorInterval.gameInterval.inMilliseconds}ms)'), + label: Text( + 'Game\n' + '(${SensorInterval.gameInterval.inMilliseconds}ms)', + ), ), ButtonSegment( value: SensorInterval.uiInterval, - label: Text('UI\n' - '(${SensorInterval.uiInterval.inMilliseconds}ms)'), + label: Text( + 'UI\n' + '(${SensorInterval.uiInterval.inMilliseconds}ms)', + ), ), ButtonSegment( value: SensorInterval.normalInterval, - label: Text('Normal\n' - '(${SensorInterval.normalInterval.inMilliseconds}ms)'), + label: Text( + 'Normal\n' + '(${SensorInterval.normalInterval.inMilliseconds}ms)', + ), ), const ButtonSegment( value: Duration(milliseconds: 500), @@ -238,7 +241,8 @@ class _MyHomePageState extends State { setState(() { sensorInterval = value.first; userAccelerometerEventStream( - samplingPeriod: sensorInterval); + samplingPeriod: sensorInterval, + ); accelerometerEventStream(samplingPeriod: sensorInterval); gyroscopeEventStream(samplingPeriod: sensorInterval); magnetometerEventStream(samplingPeriod: sensorInterval); @@ -281,14 +285,16 @@ class _MyHomePageState extends State { }, onError: (e) { showDialog( - context: context, - builder: (context) { - return const AlertDialog( - title: Text("Sensor Not Found"), - content: Text( - "It seems that your device doesn't support User Accelerometer Sensor"), - ); - }); + context: context, + builder: (context) { + return const AlertDialog( + title: Text("Sensor Not Found"), + content: Text( + "It seems that your device doesn't support User Accelerometer Sensor", + ), + ); + }, + ); }, cancelOnError: true, ), @@ -310,14 +316,16 @@ class _MyHomePageState extends State { }, onError: (e) { showDialog( - context: context, - builder: (context) { - return const AlertDialog( - title: Text("Sensor Not Found"), - content: Text( - "It seems that your device doesn't support Accelerometer Sensor"), - ); - }); + context: context, + builder: (context) { + return const AlertDialog( + title: Text("Sensor Not Found"), + content: Text( + "It seems that your device doesn't support Accelerometer Sensor", + ), + ); + }, + ); }, cancelOnError: true, ), @@ -339,14 +347,16 @@ class _MyHomePageState extends State { }, onError: (e) { showDialog( - context: context, - builder: (context) { - return const AlertDialog( - title: Text("Sensor Not Found"), - content: Text( - "It seems that your device doesn't support Gyroscope Sensor"), - ); - }); + context: context, + builder: (context) { + return const AlertDialog( + title: Text("Sensor Not Found"), + content: Text( + "It seems that your device doesn't support Gyroscope Sensor", + ), + ); + }, + ); }, cancelOnError: true, ), @@ -368,14 +378,16 @@ class _MyHomePageState extends State { }, onError: (e) { showDialog( - context: context, - builder: (context) { - return const AlertDialog( - title: Text("Sensor Not Found"), - content: Text( - "It seems that your device doesn't support Magnetometer Sensor"), - ); - }); + context: context, + builder: (context) { + return const AlertDialog( + title: Text("Sensor Not Found"), + content: Text( + "It seems that your device doesn't support Magnetometer Sensor", + ), + ); + }, + ); }, cancelOnError: true, ), @@ -397,14 +409,16 @@ class _MyHomePageState extends State { }, onError: (e) { showDialog( - context: context, - builder: (context) { - return const AlertDialog( - title: Text("Sensor Not Found"), - content: Text( - "It seems that your device doesn't support Barometer Sensor"), - ); - }); + context: context, + builder: (context) { + return const AlertDialog( + title: Text("Sensor Not Found"), + content: Text( + "It seems that your device doesn't support Barometer Sensor", + ), + ); + }, + ); }, cancelOnError: true, ), diff --git a/packages/sensors_plus/sensors_plus/example/lib/snake.dart b/packages/sensors_plus/sensors_plus/example/lib/snake.dart index 5aca1e4294..48ef0a9929 100644 --- a/packages/sensors_plus/sensors_plus/example/lib/snake.dart +++ b/packages/sensors_plus/sensors_plus/example/lib/snake.dart @@ -35,9 +35,10 @@ class SnakeBoardPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final blackLine = Paint()..color = Colors.black; - final blackFilled = Paint() - ..color = Colors.black - ..style = PaintingStyle.fill; + final blackFilled = + Paint() + ..color = Colors.black + ..style = PaintingStyle.fill; canvas.drawRect( Rect.fromPoints(Offset.zero, size.bottomLeft(Offset.zero)), blackLine, @@ -82,8 +83,9 @@ class SnakeState extends State { @override void initState() { super.initState(); - _streamSubscription = - accelerometerEventStream().listen((AccelerometerEvent event) { + _streamSubscription = accelerometerEventStream().listen(( + AccelerometerEvent event, + ) { setState(() { acceleration = event; }); @@ -97,13 +99,14 @@ class SnakeState extends State { } void _step() { - final newDirection = acceleration == null - ? null - : acceleration!.x.abs() < 1.0 && acceleration!.y.abs() < 1.0 + final newDirection = + acceleration == null + ? null + : acceleration!.x.abs() < 1.0 && acceleration!.y.abs() < 1.0 ? null : (acceleration!.x.abs() < acceleration!.y.abs()) - ? math.Point(0, acceleration!.y.sign.toInt()) - : math.Point(-acceleration!.x.sign.toInt(), 0); + ? math.Point(0, acceleration!.y.sign.toInt()) + : math.Point(-acceleration!.x.sign.toInt(), 0); state!.step(newDirection); } } diff --git a/packages/sensors_plus/sensors_plus/example/web/index.html b/packages/sensors_plus/sensors_plus/example/web/index.html index 2022dbf1d2..9e9c4c81ba 100644 --- a/packages/sensors_plus/sensors_plus/example/web/index.html +++ b/packages/sensors_plus/sensors_plus/example/web/index.html @@ -1,33 +1,33 @@ - - - - + + + + - - - - + + + + - + example - - - - - - - + + + + + + + diff --git a/packages/sensors_plus/sensors_plus/example/web/manifest.json b/packages/sensors_plus/sensors_plus/example/web/manifest.json index beeb46b0a3..719f3d1ae3 100644 --- a/packages/sensors_plus/sensors_plus/example/web/manifest.json +++ b/packages/sensors_plus/sensors_plus/example/web/manifest.json @@ -1,23 +1,23 @@ { - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "Flutter Sensors Plus example", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "Flutter Sensors Plus example", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] } diff --git a/packages/sensors_plus/sensors_plus/lib/src/sensors.dart b/packages/sensors_plus/sensors_plus/lib/src/sensors.dart index 2caf36b3da..d882c9f34e 100644 --- a/packages/sensors_plus/sensors_plus/lib/src/sensors.dart +++ b/packages/sensors_plus/sensors_plus/lib/src/sensors.dart @@ -50,7 +50,8 @@ class Sensors extends SensorsPlatform { Duration samplingPeriod = SensorInterval.normalInterval, }) { return _platform.userAccelerometerEventStream( - samplingPeriod: samplingPeriod); + samplingPeriod: samplingPeriod, + ); } /// Returns a broadcast stream of events from the device magnetometer at the diff --git a/packages/sensors_plus/sensors_plus/lib/src/web_sensors.dart b/packages/sensors_plus/sensors_plus/lib/src/web_sensors.dart index 00cbd56b4b..a6295d55ba 100644 --- a/packages/sensors_plus/sensors_plus/lib/src/web_sensors.dart +++ b/packages/sensors_plus/sensors_plus/lib/src/web_sensors.dart @@ -72,36 +72,37 @@ class WebSensorsPlugin extends SensorsPlatform { _featureDetected( () { final accelerometer = Accelerometer( - SensorOptions( - frequency: samplingPeriod.frequency, - ), + SensorOptions(frequency: samplingPeriod.frequency), ); accelerometer.start(); - accelerometer.onreading = (Event _) { - _accelerometerStreamController!.add( - AccelerometerEvent( - accelerometer.x, - accelerometer.y, - accelerometer.z, - DateTime.now(), - ), - ); - }.toJS; - - accelerometer.onerror = (SensorErrorEvent e) { - developer.log( - 'The accelerometer API is supported but something is wrong!', - error: e.error.message, - ); - }.toJS; + accelerometer.onreading = + (Event _) { + _accelerometerStreamController!.add( + AccelerometerEvent( + accelerometer.x, + accelerometer.y, + accelerometer.z, + DateTime.now(), + ), + ); + }.toJS; + + accelerometer.onerror = + (SensorErrorEvent e) { + developer.log( + 'The accelerometer API is supported but something is wrong!', + error: e.error.message, + ); + }.toJS; }, apiName: 'Accelerometer()', permissionName: 'accelerometer', onError: () { - _accelerometerStreamController! - .add(AccelerometerEvent(0, 0, 0, DateTime.now())); + _accelerometerStreamController!.add( + AccelerometerEvent(0, 0, 0, DateTime.now()), + ); }, ); _accelerometerResultStream = @@ -127,36 +128,37 @@ class WebSensorsPlugin extends SensorsPlatform { _featureDetected( () { final gyroscope = Gyroscope( - SensorOptions( - frequency: samplingPeriod.frequency, - ), + SensorOptions(frequency: samplingPeriod.frequency), ); gyroscope.start(); - gyroscope.onreading = (Event _) { - _gyroscopeEventStreamController!.add( - GyroscopeEvent( - gyroscope.x, - gyroscope.y, - gyroscope.z, - DateTime.now(), - ), - ); - }.toJS; - - gyroscope.onerror = (SensorErrorEvent e) { - developer.log( - 'The gyroscope API is supported but something is wrong!', - error: e.error.message, - ); - }.toJS; + gyroscope.onreading = + (Event _) { + _gyroscopeEventStreamController!.add( + GyroscopeEvent( + gyroscope.x, + gyroscope.y, + gyroscope.z, + DateTime.now(), + ), + ); + }.toJS; + + gyroscope.onerror = + (SensorErrorEvent e) { + developer.log( + 'The gyroscope API is supported but something is wrong!', + error: e.error.message, + ); + }.toJS; }, apiName: 'Gyroscope()', permissionName: 'gyroscope', onError: () { - _gyroscopeEventStreamController! - .add(GyroscopeEvent(0, 0, 0, DateTime.now())); + _gyroscopeEventStreamController!.add( + GyroscopeEvent(0, 0, 0, DateTime.now()), + ); }, ); _gyroscopeEventResultStream = @@ -183,36 +185,37 @@ class WebSensorsPlugin extends SensorsPlatform { _featureDetected( () { final linearAccelerationSensor = LinearAccelerationSensor( - SensorOptions( - frequency: samplingPeriod.frequency, - ), + SensorOptions(frequency: samplingPeriod.frequency), ); linearAccelerationSensor.start(); - linearAccelerationSensor.onreading = (Event _) { - _gyroscopeEventStreamController!.add( - GyroscopeEvent( - linearAccelerationSensor.x, - linearAccelerationSensor.y, - linearAccelerationSensor.z, - DateTime.now(), - ), - ); - }.toJS; - - linearAccelerationSensor.onerror = (SensorErrorEvent e) { - developer.log( - 'The linear acceleration API is supported but something is wrong!', - error: e.error.message, - ); - }.toJS; + linearAccelerationSensor.onreading = + (Event _) { + _gyroscopeEventStreamController!.add( + GyroscopeEvent( + linearAccelerationSensor.x, + linearAccelerationSensor.y, + linearAccelerationSensor.z, + DateTime.now(), + ), + ); + }.toJS; + + linearAccelerationSensor.onerror = + (SensorErrorEvent e) { + developer.log( + 'The linear acceleration API is supported but something is wrong!', + error: e.error.message, + ); + }.toJS; }, apiName: 'LinearAccelerationSensor()', permissionName: 'accelerometer', onError: () { - _userAccelerometerStreamController! - .add(UserAccelerometerEvent(0, 0, 0, DateTime.now())); + _userAccelerometerStreamController!.add( + UserAccelerometerEvent(0, 0, 0, DateTime.now()), + ); }, ); _userAccelerometerResultStream = @@ -239,36 +242,37 @@ class WebSensorsPlugin extends SensorsPlatform { _featureDetected( () { final magnetometerSensor = Magnetometer( - SensorOptions( - frequency: samplingPeriod.frequency, - ), + SensorOptions(frequency: samplingPeriod.frequency), ); magnetometerSensor.start(); - magnetometerSensor.onreading = (Event _) { - _gyroscopeEventStreamController!.add( - GyroscopeEvent( - magnetometerSensor.x, - magnetometerSensor.y, - magnetometerSensor.z, - DateTime.now(), - ), - ); - }.toJS; - - magnetometerSensor.onerror = (SensorErrorEvent e) { - developer.log( - 'The magnetometer API is supported but something is wrong!', - error: e, - ); - }.toJS; + magnetometerSensor.onreading = + (Event _) { + _gyroscopeEventStreamController!.add( + GyroscopeEvent( + magnetometerSensor.x, + magnetometerSensor.y, + magnetometerSensor.z, + DateTime.now(), + ), + ); + }.toJS; + + magnetometerSensor.onerror = + (SensorErrorEvent e) { + developer.log( + 'The magnetometer API is supported but something is wrong!', + error: e, + ); + }.toJS; }, apiName: 'Magnetometer()', permissionName: 'magnetometer', onError: () { - _magnetometerStreamController! - .add(MagnetometerEvent(0, 0, 0, DateTime.now())); + _magnetometerStreamController!.add( + MagnetometerEvent(0, 0, 0, DateTime.now()), + ); }, ); _magnetometerResultStream = diff --git a/packages/sensors_plus/sensors_plus/lib/src/web_sensors_interop.dart b/packages/sensors_plus/sensors_plus/lib/src/web_sensors_interop.dart index 73fad6d897..65a7c060f7 100644 --- a/packages/sensors_plus/sensors_plus/lib/src/web_sensors_interop.dart +++ b/packages/sensors_plus/sensors_plus/lib/src/web_sensors_interop.dart @@ -4,15 +4,16 @@ import 'dart:js_interop'; /// https://developer.mozilla.org/en-US/docs/Web/API/Accelerometer @JS('Accelerometer') extension type Accelerometer._(JSObject _) implements JSObject { - external factory Accelerometer([ - SensorOptions options, - ]); + external factory Accelerometer([SensorOptions options]); external double get x; + external double get y; + external double get z; external set onreading(JSFunction callback); + external set onerror(JSFunction callback); external void start(); @@ -22,15 +23,16 @@ extension type Accelerometer._(JSObject _) implements JSObject { /// https://developer.mozilla.org/en-US/docs/Web/API/Gyroscope @JS('Gyroscope') extension type Gyroscope._(JSObject _) implements JSObject { - external factory Gyroscope([ - SensorOptions options, - ]); + external factory Gyroscope([SensorOptions options]); external double get x; + external double get y; + external double get z; external set onreading(JSFunction callback); + external set onerror(JSFunction callback); external void start(); @@ -40,15 +42,16 @@ extension type Gyroscope._(JSObject _) implements JSObject { /// https://developer.mozilla.org/en-US/docs/Web/API/LinearAccelerationSensor @JS('LinearAccelerationSensor') extension type LinearAccelerationSensor._(JSObject _) implements JSObject { - external factory LinearAccelerationSensor([ - SensorOptions options, - ]); + external factory LinearAccelerationSensor([SensorOptions options]); external double get x; + external double get y; + external double get z; external set onreading(JSFunction callback); + external set onerror(JSFunction callback); external void start(); @@ -58,24 +61,23 @@ extension type LinearAccelerationSensor._(JSObject _) implements JSObject { /// https://developer.mozilla.org/en-US/docs/Web/API/Magnetometer @JS('Magnetometer') extension type Magnetometer._(JSObject _) implements JSObject { - external factory Magnetometer([ - SensorOptions options, - ]); + external factory Magnetometer([SensorOptions options]); external double get x; + external double get y; + external double get z; external set onreading(JSFunction callback); + external set onerror(JSFunction callback); external void start(); } extension type SensorOptions._(JSObject _) implements JSObject { - external factory SensorOptions({ - int frequency, - }); + external factory SensorOptions({int frequency}); } /// Event @@ -92,5 +94,6 @@ extension type SensorErrorEvent(JSObject _) implements JSObject { /// https://developer.mozilla.org/en-US/docs/Web/API/DOMException extension type DOMException(JSObject _) implements JSObject { external String? get name; + external String? get message; } diff --git a/packages/sensors_plus/sensors_plus/test/sensors_test.dart b/packages/sensors_plus/sensors_plus/test/sensors_test.dart index bacca67d95..da15a1deee 100644 --- a/packages/sensors_plus/sensors_plus/test/sensors_test.dart +++ b/packages/sensors_plus/sensors_plus/test/sensors_test.dart @@ -94,10 +94,7 @@ void main() { test('barometerEvents are streamed', () async { const channelName = 'dev.fluttercommunity.plus/sensors/barometer'; final date = DateTime.now(); - final sensorData = [ - 1000.0, - date.microsecondsSinceEpoch.toDouble(), - ]; + final sensorData = [1000.0, date.microsecondsSinceEpoch.toDouble()]; _initializeFakeMethodChannel('setBarometerSamplingPeriod'); _initializeFakeSensorChannel(channelName, sensorData); @@ -112,15 +109,16 @@ void _initializeFakeMethodChannel(String methodName) { const standardMethod = StandardMethodCodec(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMessageHandler('dev.fluttercommunity.plus/sensors/method', - (ByteData? message) async { - final methodCall = standardMethod.decodeMethodCall(message); - if (methodCall.method == methodName) { - return standardMethod.encodeSuccessEnvelope(null); - } else { - fail('Expected $methodName'); - } - }); + .setMockMessageHandler('dev.fluttercommunity.plus/sensors/method', ( + ByteData? message, + ) async { + final methodCall = standardMethod.decodeMethodCall(message); + if (methodCall.method == methodName) { + return standardMethod.encodeSuccessEnvelope(null); + } else { + fail('Expected $methodName'); + } + }); } void _initializeFakeSensorChannel(String channelName, List sensorData) { @@ -128,24 +126,20 @@ void _initializeFakeSensorChannel(String channelName, List sensorData) { void emitEvent(ByteData? event) { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .handlePlatformMessage( - channelName, - event, - (ByteData? reply) {}, - ); + .handlePlatformMessage(channelName, event, (ByteData? reply) {}); } TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMessageHandler(channelName, (ByteData? message) async { - final methodCall = standardMethod.decodeMethodCall(message); - if (methodCall.method == 'listen') { - emitEvent(standardMethod.encodeSuccessEnvelope(sensorData)); - emitEvent(null); - return standardMethod.encodeSuccessEnvelope(null); - } else if (methodCall.method == 'cancel') { - return standardMethod.encodeSuccessEnvelope(null); - } else { - fail('Expected listen or cancel'); - } - }); + final methodCall = standardMethod.decodeMethodCall(message); + if (methodCall.method == 'listen') { + emitEvent(standardMethod.encodeSuccessEnvelope(sensorData)); + emitEvent(null); + return standardMethod.encodeSuccessEnvelope(null); + } else if (methodCall.method == 'cancel') { + return standardMethod.encodeSuccessEnvelope(null); + } else { + fail('Expected listen or cancel'); + } + }); } diff --git a/packages/sensors_plus/sensors_plus_platform_interface/CHANGELOG.md b/packages/sensors_plus/sensors_plus_platform_interface/CHANGELOG.md index c7f7e34f97..4cd4ab6ca5 100644 --- a/packages/sensors_plus/sensors_plus_platform_interface/CHANGELOG.md +++ b/packages/sensors_plus/sensors_plus_platform_interface/CHANGELOG.md @@ -1,27 +1,33 @@ ## 2.0.1 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 2.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**(sensors_plus): Add support for platform timestamp in event ([#2506](https://github.com/fluttercommunity/plus_plugins/issues/2506)). ([8b3df176](https://github.com/fluttercommunity/plus_plugins/commit/8b3df17650769b913f64db48d2f56ab7a9a15616)) - - **BREAKING** **FEAT**(sensors_plus): add barometer support for all platforms ([#3079](https://github.com/fluttercommunity/plus_plugins/issues/3079)). ([5fa797d0](https://github.com/fluttercommunity/plus_plugins/commit/5fa797d033606106a762828c38c59597fe0e9253)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **BREAKING** **FEAT**(sensors_plus): Add support for platform timestamp in + event ([#2506](https://github.com/fluttercommunity/plus_plugins/issues/2506)). ([8b3df176](https://github.com/fluttercommunity/plus_plugins/commit/8b3df17650769b913f64db48d2f56ab7a9a15616)) +- **BREAKING** **FEAT**(sensors_plus): add barometer support for all + platforms ([#3079](https://github.com/fluttercommunity/plus_plugins/issues/3079)). ([5fa797d0](https://github.com/fluttercommunity/plus_plugins/commit/5fa797d033606106a762828c38c59597fe0e9253)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) ## 1.2.0 - - **FIX**(sensors_plus): Add protection of reserved samplingPeriod value ([#2390](https://github.com/fluttercommunity/plus_plugins/issues/2390)). ([559faa18](https://github.com/fluttercommunity/plus_plugins/commit/559faa180b20e825918f920c373e6646b7931760)) - - **FEAT**(sensors_plus): Configurable sample rate ([#2248](https://github.com/fluttercommunity/plus_plugins/issues/2248)). ([82ffe46c](https://github.com/fluttercommunity/plus_plugins/commit/82ffe46c6ff02a7fcaad35c74c872e1ceb37621c)) +- **FIX**(sensors_plus): Add protection of reserved samplingPeriod + value ([#2390](https://github.com/fluttercommunity/plus_plugins/issues/2390)). ([559faa18](https://github.com/fluttercommunity/plus_plugins/commit/559faa180b20e825918f920c373e6646b7931760)) +- **FEAT**(sensors_plus): Configurable sample + rate ([#2248](https://github.com/fluttercommunity/plus_plugins/issues/2248)). ([82ffe46c](https://github.com/fluttercommunity/plus_plugins/commit/82ffe46c6ff02a7fcaad35c74c872e1ceb37621c)) ## 1.1.3 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 1.1.2 - - **CHORE**: Version tagging using melos. +- **CHORE**: Version tagging using melos. ## 1.1.1 diff --git a/packages/sensors_plus/sensors_plus_platform_interface/lib/sensors_plus_platform_interface.dart b/packages/sensors_plus/sensors_plus_platform_interface/lib/sensors_plus_platform_interface.dart index a8ac66824f..bd1747963c 100644 --- a/packages/sensors_plus/sensors_plus_platform_interface/lib/sensors_plus_platform_interface.dart +++ b/packages/sensors_plus/sensors_plus_platform_interface/lib/sensors_plus_platform_interface.dart @@ -77,7 +77,8 @@ abstract class SensorsPlatform extends PlatformInterface { Duration samplingPeriod = SensorInterval.normalInterval, }) { throw UnimplementedError( - 'listenToAccelerometerEvents has not been implemented.'); + 'listenToAccelerometerEvents has not been implemented.', + ); } /// Returns a broadcast stream of events from the device gyroscope at the @@ -94,7 +95,8 @@ abstract class SensorsPlatform extends PlatformInterface { Duration samplingPeriod = SensorInterval.normalInterval, }) { throw UnimplementedError( - 'userAccelerometerEvents has not been implemented.'); + 'userAccelerometerEvents has not been implemented.', + ); } /// Returns a broadcast stream of events from the device magnetometer at the diff --git a/packages/sensors_plus/sensors_plus_platform_interface/lib/src/method_channel_sensors.dart b/packages/sensors_plus/sensors_plus_platform_interface/lib/src/method_channel_sensors.dart index a604345fd0..4c1e706dab 100644 --- a/packages/sensors_plus/sensors_plus_platform_interface/lib/src/method_channel_sensors.dart +++ b/packages/sensors_plus/sensors_plus_platform_interface/lib/src/method_channel_sensors.dart @@ -10,23 +10,29 @@ import 'package:sensors_plus_platform_interface/sensors_plus_platform_interface. /// A method channel -based implementation of the SensorsPlatform interface. class MethodChannelSensors extends SensorsPlatform { - static const MethodChannel _methodChannel = - MethodChannel('dev.fluttercommunity.plus/sensors/method'); + static const MethodChannel _methodChannel = MethodChannel( + 'dev.fluttercommunity.plus/sensors/method', + ); - static const EventChannel _accelerometerEventChannel = - EventChannel('dev.fluttercommunity.plus/sensors/accelerometer'); + static const EventChannel _accelerometerEventChannel = EventChannel( + 'dev.fluttercommunity.plus/sensors/accelerometer', + ); - static const EventChannel _userAccelerometerEventChannel = - EventChannel('dev.fluttercommunity.plus/sensors/user_accel'); + static const EventChannel _userAccelerometerEventChannel = EventChannel( + 'dev.fluttercommunity.plus/sensors/user_accel', + ); - static const EventChannel _gyroscopeEventChannel = - EventChannel('dev.fluttercommunity.plus/sensors/gyroscope'); + static const EventChannel _gyroscopeEventChannel = EventChannel( + 'dev.fluttercommunity.plus/sensors/gyroscope', + ); - static const EventChannel _magnetometerEventChannel = - EventChannel('dev.fluttercommunity.plus/sensors/magnetometer'); + static const EventChannel _magnetometerEventChannel = EventChannel( + 'dev.fluttercommunity.plus/sensors/magnetometer', + ); - static const EventChannel _barometerEventChannel = - EventChannel('dev.fluttercommunity.plus/sensors/barometer'); + static const EventChannel _barometerEventChannel = EventChannel( + 'dev.fluttercommunity.plus/sensors/barometer', + ); final logger = Logger('MethodChannelSensors'); Stream? _accelerometerEvents; @@ -43,26 +49,28 @@ class MethodChannelSensors extends SensorsPlatform { }) { var microseconds = samplingPeriod.inMicroseconds; if (microseconds >= 1 && microseconds <= 3) { - logger.warning('The SamplingPeriod is currently set to $microsecondsμs, ' - 'which is a reserved value in Android. Please consider changing it ' - 'to either 0 or 4μs. See https://developer.android.com/reference/' - 'android/hardware/SensorManager#registerListener(android.hardware.' - 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' - 'information'); + logger.warning( + 'The SamplingPeriod is currently set to $microsecondsμs, ' + 'which is a reserved value in Android. Please consider changing it ' + 'to either 0 or 4μs. See https://developer.android.com/reference/' + 'android/hardware/SensorManager#registerListener(android.hardware.' + 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' + 'information', + ); microseconds = 0; } _methodChannel.invokeMethod('setAccelerationSamplingPeriod', microseconds); _accelerometerEvents ??= _accelerometerEventChannel .receiveBroadcastStream() .map((dynamic event) { - final list = event.cast(); - return AccelerometerEvent( - list[0]!, - list[1]!, - list[2]!, - DateTime.fromMicrosecondsSinceEpoch(list[3]!.toInt()), - ); - }); + final list = event.cast(); + return AccelerometerEvent( + list[0]!, + list[1]!, + list[2]!, + DateTime.fromMicrosecondsSinceEpoch(list[3]!.toInt()), + ); + }); return _accelerometerEvents!; } @@ -74,17 +82,20 @@ class MethodChannelSensors extends SensorsPlatform { }) { var microseconds = samplingPeriod.inMicroseconds; if (microseconds >= 1 && microseconds <= 3) { - logger.warning('The SamplingPeriod is currently set to $microsecondsμs, ' - 'which is a reserved value in Android. Please consider changing it ' - 'to either 0 or 4μs. See https://developer.android.com/reference/' - 'android/hardware/SensorManager#registerListener(android.hardware.' - 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' - 'information'); + logger.warning( + 'The SamplingPeriod is currently set to $microsecondsμs, ' + 'which is a reserved value in Android. Please consider changing it ' + 'to either 0 or 4μs. See https://developer.android.com/reference/' + 'android/hardware/SensorManager#registerListener(android.hardware.' + 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' + 'information', + ); microseconds = 0; } _methodChannel.invokeMethod('setGyroscopeSamplingPeriod', microseconds); - _gyroscopeEvents ??= - _gyroscopeEventChannel.receiveBroadcastStream().map((dynamic event) { + _gyroscopeEvents ??= _gyroscopeEventChannel.receiveBroadcastStream().map(( + dynamic event, + ) { final list = event.cast(); return GyroscopeEvent( list[0]!, @@ -104,27 +115,31 @@ class MethodChannelSensors extends SensorsPlatform { }) { var microseconds = samplingPeriod.inMicroseconds; if (microseconds >= 1 && microseconds <= 3) { - logger.warning('The SamplingPeriod is currently set to $microsecondsμs, ' - 'which is a reserved value in Android. Please consider changing it ' - 'to either 0 or 4μs. See https://developer.android.com/reference/' - 'android/hardware/SensorManager#registerListener(android.hardware.' - 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' - 'information'); + logger.warning( + 'The SamplingPeriod is currently set to $microsecondsμs, ' + 'which is a reserved value in Android. Please consider changing it ' + 'to either 0 or 4μs. See https://developer.android.com/reference/' + 'android/hardware/SensorManager#registerListener(android.hardware.' + 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' + 'information', + ); microseconds = 0; } _methodChannel.invokeMethod( - 'setUserAccelerometerSamplingPeriod', microseconds); + 'setUserAccelerometerSamplingPeriod', + microseconds, + ); _userAccelerometerEvents ??= _userAccelerometerEventChannel .receiveBroadcastStream() .map((dynamic event) { - final list = event.cast(); - return UserAccelerometerEvent( - list[0]!, - list[1]!, - list[2]!, - DateTime.fromMicrosecondsSinceEpoch(list[3]!.toInt()), - ); - }); + final list = event.cast(); + return UserAccelerometerEvent( + list[0]!, + list[1]!, + list[2]!, + DateTime.fromMicrosecondsSinceEpoch(list[3]!.toInt()), + ); + }); return _userAccelerometerEvents!; } @@ -136,25 +151,28 @@ class MethodChannelSensors extends SensorsPlatform { }) { var microseconds = samplingPeriod.inMicroseconds; if (microseconds >= 1 && microseconds <= 3) { - logger.warning('The SamplingPeriod is currently set to $microsecondsμs, ' - 'which is a reserved value in Android. Please consider changing it ' - 'to either 0 or 4μs. See https://developer.android.com/reference/' - 'android/hardware/SensorManager#registerListener(android.hardware.' - 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' - 'information'); + logger.warning( + 'The SamplingPeriod is currently set to $microsecondsμs, ' + 'which is a reserved value in Android. Please consider changing it ' + 'to either 0 or 4μs. See https://developer.android.com/reference/' + 'android/hardware/SensorManager#registerListener(android.hardware.' + 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' + 'information', + ); microseconds = 0; } _methodChannel.invokeMethod('setMagnetometerSamplingPeriod', microseconds); - _magnetometerEvents ??= - _magnetometerEventChannel.receiveBroadcastStream().map((dynamic event) { - final list = event.cast(); - return MagnetometerEvent( - list[0]!, - list[1]!, - list[2]!, - DateTime.fromMicrosecondsSinceEpoch(list[3]!.toInt()), - ); - }); + _magnetometerEvents ??= _magnetometerEventChannel + .receiveBroadcastStream() + .map((dynamic event) { + final list = event.cast(); + return MagnetometerEvent( + list[0]!, + list[1]!, + list[2]!, + DateTime.fromMicrosecondsSinceEpoch(list[3]!.toInt()), + ); + }); return _magnetometerEvents!; } @@ -166,17 +184,20 @@ class MethodChannelSensors extends SensorsPlatform { }) { var microseconds = samplingPeriod.inMicroseconds; if (microseconds >= 1 && microseconds <= 3) { - logger.warning('The SamplingPeriod is currently set to $microsecondsμs, ' - 'which is a reserved value in Android. Please consider changing it ' - 'to either 0 or 4μs. See https://developer.android.com/reference/' - 'android/hardware/SensorManager#registerListener(android.hardware.' - 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' - 'information'); + logger.warning( + 'The SamplingPeriod is currently set to $microsecondsμs, ' + 'which is a reserved value in Android. Please consider changing it ' + 'to either 0 or 4μs. See https://developer.android.com/reference/' + 'android/hardware/SensorManager#registerListener(android.hardware.' + 'SensorEventListener,%20android.hardware.Sensor,%20int) for more ' + 'information', + ); microseconds = 0; } _methodChannel.invokeMethod('setBarometerSamplingPeriod', microseconds); - _barometerEvents ??= - _barometerEventChannel.receiveBroadcastStream().map((dynamic event) { + _barometerEvents ??= _barometerEventChannel.receiveBroadcastStream().map(( + dynamic event, + ) { final list = event.cast(); return BarometerEvent( list[0]!, diff --git a/packages/sensors_plus/sensors_plus_platform_interface/test/sensors_plus_platform_interface_test.dart b/packages/sensors_plus/sensors_plus_platform_interface/test/sensors_plus_platform_interface_test.dart index e0376121dc..83d3cc4acd 100644 --- a/packages/sensors_plus/sensors_plus_platform_interface/test/sensors_plus_platform_interface_test.dart +++ b/packages/sensors_plus/sensors_plus_platform_interface/test/sensors_plus_platform_interface_test.dart @@ -36,7 +36,8 @@ Stream userAccelerometerEventStream({ Duration samplingPeriod = SensorInterval.normalInterval, }) { return methodChannel.userAccelerometerEventStream( - samplingPeriod: samplingPeriod); + samplingPeriod: samplingPeriod, + ); } /// Returns a broadcast stream of events from the device magnetometer at the @@ -143,10 +144,7 @@ void main() { test('barometerEvents are streamed', () async { const channelName = 'dev.fluttercommunity.plus/sensors/barometer'; final date = DateTime.now(); - final sensorData = [ - 1000.0, - date.microsecondsSinceEpoch.toDouble(), - ]; + final sensorData = [1000.0, date.microsecondsSinceEpoch.toDouble()]; _initializeFakeMethodChannel('setBarometerSamplingPeriod'); _initializeFakeSensorChannel(channelName, sensorData); @@ -161,15 +159,16 @@ void _initializeFakeMethodChannel(String methodName) { const standardMethod = StandardMethodCodec(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMessageHandler('dev.fluttercommunity.plus/sensors/method', - (ByteData? message) async { - final methodCall = standardMethod.decodeMethodCall(message); - if (methodCall.method == methodName) { - return standardMethod.encodeSuccessEnvelope(null); - } else { - fail('Expected $methodName'); - } - }); + .setMockMessageHandler('dev.fluttercommunity.plus/sensors/method', ( + ByteData? message, + ) async { + final methodCall = standardMethod.decodeMethodCall(message); + if (methodCall.method == methodName) { + return standardMethod.encodeSuccessEnvelope(null); + } else { + fail('Expected $methodName'); + } + }); } void _initializeFakeSensorChannel(String channelName, List sensorData) { @@ -177,24 +176,20 @@ void _initializeFakeSensorChannel(String channelName, List sensorData) { void emitEvent(ByteData? event) { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .handlePlatformMessage( - channelName, - event, - (ByteData? reply) {}, - ); + .handlePlatformMessage(channelName, event, (ByteData? reply) {}); } TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMessageHandler(channelName, (ByteData? message) async { - final methodCall = standardMethod.decodeMethodCall(message); - if (methodCall.method == 'listen') { - emitEvent(standardMethod.encodeSuccessEnvelope(sensorData)); - emitEvent(null); - return standardMethod.encodeSuccessEnvelope(null); - } else if (methodCall.method == 'cancel') { - return standardMethod.encodeSuccessEnvelope(null); - } else { - fail('Expected listen or cancel'); - } - }); + final methodCall = standardMethod.decodeMethodCall(message); + if (methodCall.method == 'listen') { + emitEvent(standardMethod.encodeSuccessEnvelope(sensorData)); + emitEvent(null); + return standardMethod.encodeSuccessEnvelope(null); + } else if (methodCall.method == 'cancel') { + return standardMethod.encodeSuccessEnvelope(null); + } else { + fail('Expected listen or cancel'); + } + }); } diff --git a/packages/share_plus/share_plus/CHANGELOG.md b/packages/share_plus/share_plus/CHANGELOG.md index f43fba7d56..813dacc17a 100644 --- a/packages/share_plus/share_plus/CHANGELOG.md +++ b/packages/share_plus/share_plus/CHANGELOG.md @@ -1,60 +1,83 @@ ## 10.1.4 - - **FIX**(share_plus): fallback for shareXFiles() to use download on web ([#3388](https://github.com/fluttercommunity/plus_plugins/issues/3388)). ([95a12ee3](https://github.com/fluttercommunity/plus_plugins/commit/95a12ee3982dd61de5d07005de62f81c2e99eb08)) +- **FIX**(share_plus): fallback for shareXFiles() to use download on + web ([#3388](https://github.com/fluttercommunity/plus_plugins/issues/3388)). ([95a12ee3](https://github.com/fluttercommunity/plus_plugins/commit/95a12ee3982dd61de5d07005de62f81c2e99eb08)) ## 10.1.3 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) - - **FIX**(share_plus): A function declaration without a prototype is deprecated in all versions of C ([#3375](https://github.com/fluttercommunity/plus_plugins/issues/3375)). ([40f9c421](https://github.com/fluttercommunity/plus_plugins/commit/40f9c42138bf1c80e6283f46e12109a0e66c0816)) - - **FIX**(share_plus): Set correct Flutter and Dart versions requirements ([#3363](https://github.com/fluttercommunity/plus_plugins/issues/3363)). ([65616668](https://github.com/fluttercommunity/plus_plugins/commit/6561666885f547725f6e88ebaae498832b53efed)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **FIX**(share_plus): A function declaration without a prototype is deprecated in all versions of + C ([#3375](https://github.com/fluttercommunity/plus_plugins/issues/3375)). ([40f9c421](https://github.com/fluttercommunity/plus_plugins/commit/40f9c42138bf1c80e6283f46e12109a0e66c0816)) +- **FIX**(share_plus): Set correct Flutter and Dart versions + requirements ([#3363](https://github.com/fluttercommunity/plus_plugins/issues/3363)). ([65616668](https://github.com/fluttercommunity/plus_plugins/commit/6561666885f547725f6e88ebaae498832b53efed)) ## 10.1.2 - - **FIX**(share_plus): Update privacy manifest path ([#3349](https://github.com/fluttercommunity/plus_plugins/issues/3349)). ([d884a991](https://github.com/fluttercommunity/plus_plugins/commit/d884a9917769e11daa66c1aaa3ebd0d015506e77)) +- **FIX**(share_plus): Update privacy manifest + path ([#3349](https://github.com/fluttercommunity/plus_plugins/issues/3349)). ([d884a991](https://github.com/fluttercommunity/plus_plugins/commit/d884a9917769e11daa66c1aaa3ebd0d015506e77)) ## 10.1.1 - - **FIX**(share_plus): [#3322](https://github.com/fluttercommunity/plus_plugins/issues/3322) Downscale previews on iOS to avoid issues with huge images ([#3320](https://github.com/fluttercommunity/plus_plugins/issues/3320)). ([d8c95c2c](https://github.com/fluttercommunity/plus_plugins/commit/d8c95c2cffaf882cf0670cc5daf889eebd249a77)) +- **FIX**(share_plus): [#3322](https://github.com/fluttercommunity/plus_plugins/issues/3322) + Downscale previews on iOS to avoid issues with huge + images ([#3320](https://github.com/fluttercommunity/plus_plugins/issues/3320)). ([d8c95c2c](https://github.com/fluttercommunity/plus_plugins/commit/d8c95c2cffaf882cf0670cc5daf889eebd249a77)) ## 10.1.0 - - **FEAT**(share_plus): Add Swift Package Manager support ([#3169](https://github.com/fluttercommunity/plus_plugins/issues/3169)). ([b3970225](https://github.com/fluttercommunity/plus_plugins/commit/b3970225b80183548ecc5516a5c1a1ad61016860)) +- **FEAT**(share_plus): Add Swift Package Manager + support ([#3169](https://github.com/fluttercommunity/plus_plugins/issues/3169)). ([b3970225](https://github.com/fluttercommunity/plus_plugins/commit/b3970225b80183548ecc5516a5c1a1ad61016860)) ## 10.0.3 - - **FIX**(share_plus): `mime` compatible with v2 (v1 still supported) ([#3309](https://github.com/fluttercommunity/plus_plugins/issues/3309)). ([401db75e](https://github.com/fluttercommunity/plus_plugins/commit/401db75efa24c40fd96a05e79d12801f92666efd)) - - **FIX**(all): Clean up macOS Privacy Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) - - **FIX**(all): Add macOS Privacy Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) +- **FIX**(share_plus): `mime` compatible with v2 (v1 still + supported) ([#3309](https://github.com/fluttercommunity/plus_plugins/issues/3309)). ([401db75e](https://github.com/fluttercommunity/plus_plugins/commit/401db75efa24c40fd96a05e79d12801f92666efd)) +- **FIX**(all): Clean up macOS Privacy + Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) +- **FIX**(all): Add macOS Privacy + Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) ## 10.0.2 - - **FIX**(share_plus): [#2910](https://github.com/fluttercommunity/plus_plugins/issues/2910) Handle user dismissing dialog on shareUri() in web ([#3175](https://github.com/fluttercommunity/plus_plugins/issues/3175)). ([bba78118](https://github.com/fluttercommunity/plus_plugins/commit/bba781187b4af5682331ed90929c61c13137809a)) +- **FIX**(share_plus): [#2910](https://github.com/fluttercommunity/plus_plugins/issues/2910) Handle + user dismissing dialog on shareUri() in + web ([#3175](https://github.com/fluttercommunity/plus_plugins/issues/3175)). ([bba78118](https://github.com/fluttercommunity/plus_plugins/commit/bba781187b4af5682331ed90929c61c13137809a)) ## 10.0.1 -- **CHORE**(share_plus): Update to package:web to ^1.0.0 ([#3105](https://github.com/fluttercommunity/plus_plugins/pull/3105)). ([1f23910a](https://github.com/fluttercommunity/plus_plugins/commit/1f23910ab50fef2e499054f35cedfd14c578976a)) +- **CHORE**(share_plus): Update to package:web to + ^1.0.0 ([#3105](https://github.com/fluttercommunity/plus_plugins/pull/3105)). ([1f23910a](https://github.com/fluttercommunity/plus_plugins/commit/1f23910ab50fef2e499054f35cedfd14c578976a)) ## 10.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**(share_plus): Introduce optional parameter `nameOverride` to `shareXFiles`. ([#3077](https://github.com/fluttercommunity/plus_plugins/issues/3077)). ([f483bce7](https://github.com/fluttercommunity/plus_plugins/commit/f483bce77f50fc03e8c6c969864dd978e46f32da)) - - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) - - **DOCS**(share_plus): Update README.md ([#2903](https://github.com/fluttercommunity/plus_plugins/issues/2903)). ([2a547eb3](https://github.com/fluttercommunity/plus_plugins/commit/2a547eb3f0093160279fbc9de21dde3f3ff75c81)) +- **BREAKING** **FEAT**(share_plus): Introduce optional parameter `nameOverride` to + `shareXFiles`. ([#3077](https://github.com/fluttercommunity/plus_plugins/issues/3077)). ([f483bce7](https://github.com/fluttercommunity/plus_plugins/commit/f483bce77f50fc03e8c6c969864dd978e46f32da)) +- **REFACTOR**(all): Remove website files, configs, + mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **DOCS**(share_plus): Update + README.md ([#2903](https://github.com/fluttercommunity/plus_plugins/issues/2903)). ([2a547eb3](https://github.com/fluttercommunity/plus_plugins/commit/2a547eb3f0093160279fbc9de21dde3f3ff75c81)) ## 9.0.0 > Note: This release has breaking changes. - - **BREAKING** **REFACTOR**(share_plus): Share API cleanup ([#2832](https://github.com/fluttercommunity/plus_plugins/issues/2832)). ([fd0511ca](https://github.com/fluttercommunity/plus_plugins/commit/fd0511ca4d55db1e075e72af5a0832b5cfe81244)) +- **BREAKING** **REFACTOR**(share_plus): Share API + cleanup ([#2832](https://github.com/fluttercommunity/plus_plugins/issues/2832)). ([fd0511ca](https://github.com/fluttercommunity/plus_plugins/commit/fd0511ca4d55db1e075e72af5a0832b5cfe81244)) ## 8.0.3 - - **REFACTOR**(share_plus): Migrate Android example to use the new plugins declaration ([#2742](https://github.com/fluttercommunity/plus_plugins/issues/2742)). ([a73af898](https://github.com/fluttercommunity/plus_plugins/commit/a73af898ee9b73dcc53307186ac4c79e795b1277)) - - **FIX**(share_plus): Recover ShareSuccessManager state after error ([#2817](https://github.com/fluttercommunity/plus_plugins/issues/2817)). ([2b12d8a8](https://github.com/fluttercommunity/plus_plugins/commit/2b12d8a8ada0d3f00abda0467946bb241361d016)) - - **DOCS**(share_plus): Add info regarding localization on Apple to README ([#2764](https://github.com/fluttercommunity/plus_plugins/issues/2764)). ([43f9a305](https://github.com/fluttercommunity/plus_plugins/commit/43f9a3051652448868c5031a45276f9ff870a025)) - - **DOCS**(share_plus): remove typo from the changelog ([#2747](https://github.com/fluttercommunity/plus_plugins/issues/2747)). ([961c8e2d](https://github.com/fluttercommunity/plus_plugins/commit/961c8e2dbf2210947cbed898c90e2776322a0942)) +- **REFACTOR**(share_plus): Migrate Android example to use the new plugins + declaration ([#2742](https://github.com/fluttercommunity/plus_plugins/issues/2742)). ([a73af898](https://github.com/fluttercommunity/plus_plugins/commit/a73af898ee9b73dcc53307186ac4c79e795b1277)) +- **FIX**(share_plus): Recover ShareSuccessManager state after + error ([#2817](https://github.com/fluttercommunity/plus_plugins/issues/2817)). ([2b12d8a8](https://github.com/fluttercommunity/plus_plugins/commit/2b12d8a8ada0d3f00abda0467946bb241361d016)) +- **DOCS**(share_plus): Add info regarding localization on Apple to + README ([#2764](https://github.com/fluttercommunity/plus_plugins/issues/2764)). ([43f9a305](https://github.com/fluttercommunity/plus_plugins/commit/43f9a3051652448868c5031a45276f9ff870a025)) +- **DOCS**(share_plus): remove typo from the + changelog ([#2747](https://github.com/fluttercommunity/plus_plugins/issues/2747)). ([961c8e2d](https://github.com/fluttercommunity/plus_plugins/commit/961c8e2dbf2210947cbed898c90e2776322a0942)) ## 8.0.2 @@ -69,16 +92,26 @@ In this release plugin migrated to package:web, meaning that it now supports WAS > - Java 17 for Android part > - Gradle 8.4 for Android part -- **BREAKING** **FEAT**(share_plus): Migrate to package:web ([#2709](https://github.com/fluttercommunity/plus_plugins/issues/2709)). ([641e7905](https://github.com/fluttercommunity/plus_plugins/commit/641e7905b4055827f1481f036415095dc43afe5f)) -- **BREAKING** **BUILD**(share_plus): Target Java 17 on Android ([#2730](https://github.com/fluttercommunity/plus_plugins/issues/2730)). ([e6853a06](https://github.com/fluttercommunity/plus_plugins/commit/e6853a06fa110d69776a85684e302a7c900a6e07)) -- **BREAKING** **BUILD**(sensors_plus): Update to target and compile SDK 34 ([#2712](https://github.com/fluttercommunity/plus_plugins/pull/2712)). ([b752fc3](https://github.com/fluttercommunity/plus_plugins/commit/b752fc3bac2b7ce614faf0fbed010200d99a717b)) -- **FIX**(share_plus): Resolve deprecation warning in Android part ([#2717](https://github.com/fluttercommunity/plus_plugins/issues/2717)). ([5913ac72](https://github.com/fluttercommunity/plus_plugins/commit/5913ac72f6dfcb0f02c371907871805c940a03a8)) -- **FIX**(share_plus): add sharePositionOrigin parameter to shareUri ([#2517](https://github.com/fluttercommunity/plus_plugins/issues/2517)). ([f896d94e](https://github.com/fluttercommunity/plus_plugins/commit/f896d94e6c24551d9dc7d73d8fb05a0f283e0e83)) -- **FIX**(share_plus): Add missing call to result for shareUri on iOS ([#2616](https://github.com/fluttercommunity/plus_plugins/issues/2616)). ([65f23a5d](https://github.com/fluttercommunity/plus_plugins/commit/65f23a5d12ac988d7424a56b1d808f2983e0459f)) -- **FIX**(share_plus): Add iOS Privacy Info ([#2586](https://github.com/fluttercommunity/plus_plugins/issues/2586)). ([17fc2e05](https://github.com/fluttercommunity/plus_plugins/commit/17fc2e058f04168f17f5118bca24b02483af571b)) -- **FIX**(share_plus): Ensure subject is not null before calling putExtra(Intent.EXTRA_SUBJECT, subject) ([#2518](https://github.com/fluttercommunity/plus_plugins/issues/2518)). ([f0bbbefc](https://github.com/fluttercommunity/plus_plugins/commit/f0bbbefc712e01da20e8107e8d25b2005cf7b728)) -- **FEAT**(share_plus): Update min iOS target to 12 ([#2662](https://github.com/fluttercommunity/plus_plugins/issues/2662)). ([5cef2e50](https://github.com/fluttercommunity/plus_plugins/commit/5cef2e500cd10d55b749a6d53ce6e733fdb54d34)) -- **DOCS**(share_plus): Fix supported platforms in README ([#2510](https://github.com/fluttercommunity/plus_plugins/issues/2510)). ([6b4b855b](https://github.com/fluttercommunity/plus_plugins/commit/6b4b855bb6f3c2897e29d0d3ae4a0c0c99ff8c2f)) +- **BREAKING** **FEAT**(share_plus): Migrate to package: + web ([#2709](https://github.com/fluttercommunity/plus_plugins/issues/2709)). ([641e7905](https://github.com/fluttercommunity/plus_plugins/commit/641e7905b4055827f1481f036415095dc43afe5f)) +- **BREAKING** **BUILD**(share_plus): Target Java 17 on + Android ([#2730](https://github.com/fluttercommunity/plus_plugins/issues/2730)). ([e6853a06](https://github.com/fluttercommunity/plus_plugins/commit/e6853a06fa110d69776a85684e302a7c900a6e07)) +- **BREAKING** **BUILD**(sensors_plus): Update to target and compile SDK + 34 ([#2712](https://github.com/fluttercommunity/plus_plugins/pull/2712)). ([b752fc3](https://github.com/fluttercommunity/plus_plugins/commit/b752fc3bac2b7ce614faf0fbed010200d99a717b)) +- **FIX**(share_plus): Resolve deprecation warning in Android + part ([#2717](https://github.com/fluttercommunity/plus_plugins/issues/2717)). ([5913ac72](https://github.com/fluttercommunity/plus_plugins/commit/5913ac72f6dfcb0f02c371907871805c940a03a8)) +- **FIX**(share_plus): add sharePositionOrigin parameter to + shareUri ([#2517](https://github.com/fluttercommunity/plus_plugins/issues/2517)). ([f896d94e](https://github.com/fluttercommunity/plus_plugins/commit/f896d94e6c24551d9dc7d73d8fb05a0f283e0e83)) +- **FIX**(share_plus): Add missing call to result for shareUri on + iOS ([#2616](https://github.com/fluttercommunity/plus_plugins/issues/2616)). ([65f23a5d](https://github.com/fluttercommunity/plus_plugins/commit/65f23a5d12ac988d7424a56b1d808f2983e0459f)) +- **FIX**(share_plus): Add iOS Privacy + Info ([#2586](https://github.com/fluttercommunity/plus_plugins/issues/2586)). ([17fc2e05](https://github.com/fluttercommunity/plus_plugins/commit/17fc2e058f04168f17f5118bca24b02483af571b)) +- **FIX**(share_plus): Ensure subject is not null before calling putExtra(Intent.EXTRA_SUBJECT, + subject) ([#2518](https://github.com/fluttercommunity/plus_plugins/issues/2518)). ([f0bbbefc](https://github.com/fluttercommunity/plus_plugins/commit/f0bbbefc712e01da20e8107e8d25b2005cf7b728)) +- **FEAT**(share_plus): Update min iOS target to + 12 ([#2662](https://github.com/fluttercommunity/plus_plugins/issues/2662)). ([5cef2e50](https://github.com/fluttercommunity/plus_plugins/commit/5cef2e500cd10d55b749a6d53ce6e733fdb54d34)) +- **DOCS**(share_plus): Fix supported platforms in + README ([#2510](https://github.com/fluttercommunity/plus_plugins/issues/2510)). ([6b4b855b](https://github.com/fluttercommunity/plus_plugins/commit/6b4b855bb6f3c2897e29d0d3ae4a0c0c99ff8c2f)) ## 8.0.1 @@ -86,110 +119,131 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 8.0.0 -> Note: This release was retracted due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). +> Note: This release was retracted due +> to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). ## 7.2.2 - - **FIX**(share_plus): Ensure subject is not null before calling putExtra(Intent.EXTRA_SUBJECT, subject) ([#2518](https://github.com/fluttercommunity/plus_plugins/issues/2518)). ([f0bbbefc](https://github.com/fluttercommunity/plus_plugins/commit/f0bbbefc712e01da20e8107e8d25b2005cf7b728)) - - **DOCS**(share_plus): Fix supported platforms in README ([#2510](https://github.com/fluttercommunity/plus_plugins/issues/2510)). ([6b4b855b](https://github.com/fluttercommunity/plus_plugins/commit/6b4b855bb6f3c2897e29d0d3ae4a0c0c99ff8c2f)) +- **FIX**(share_plus): Ensure subject is not null before calling putExtra(Intent.EXTRA_SUBJECT, + subject) ([#2518](https://github.com/fluttercommunity/plus_plugins/issues/2518)). ([f0bbbefc](https://github.com/fluttercommunity/plus_plugins/commit/f0bbbefc712e01da20e8107e8d25b2005cf7b728)) +- **DOCS**(share_plus): Fix supported platforms in + README ([#2510](https://github.com/fluttercommunity/plus_plugins/issues/2510)). ([6b4b855b](https://github.com/fluttercommunity/plus_plugins/commit/6b4b855bb6f3c2897e29d0d3ae4a0c0c99ff8c2f)) ## 7.2.1 - - **CHORE**(share_plus): Update share_plus_platform_interface for compatibility with uuid 4.x +- **CHORE**(share_plus): Update share_plus_platform_interface for compatibility with uuid 4.x ## 7.2.0 -> Info: This release is a replacement for release 8.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. +> Info: This release is a replacement for release 8.0.0, which was retracted due to +> issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change +> was reverted the major release was also reverted in favor of this one. - - **FIX**(share_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2252](https://github.com/fluttercommunity/plus_plugins/issues/2252)). ([d4954f36](https://github.com/fluttercommunity/plus_plugins/commit/d4954f36b633e5894cfb4aff4acc995348ce3dca)) - - **FIX**(share_plus): Revert bump to compileSDK 34 ([#2234](https://github.com/fluttercommunity/plus_plugins/issues/2234)). ([6af2328d](https://github.com/fluttercommunity/plus_plugins/commit/6af2328da997b452758e6c78f3815bcf55ac24aa)) - - **FEAT**(share_plus): Remove deprecated VALID_ARCHS iOS property ([#2024](https://github.com/fluttercommunity/plus_plugins/issues/2024)). ([bb79888e](https://github.com/fluttercommunity/plus_plugins/commit/bb79888eda6425d8e772bb4bea47f4966610240f)) - - **DOCS**(share_plus): Fix usage code snippets ([#2106](https://github.com/fluttercommunity/plus_plugins/issues/2106)). ([346e07ea](https://github.com/fluttercommunity/plus_plugins/commit/346e07ea56088321f92530e4334edab0400f4c43)) +- **FIX**(share_plus): Change Kotlin version from 1.9.10 to + 1.7.22 ([#2252](https://github.com/fluttercommunity/plus_plugins/issues/2252)). ([d4954f36](https://github.com/fluttercommunity/plus_plugins/commit/d4954f36b633e5894cfb4aff4acc995348ce3dca)) +- **FIX**(share_plus): Revert bump to compileSDK + 34 ([#2234](https://github.com/fluttercommunity/plus_plugins/issues/2234)). ([6af2328d](https://github.com/fluttercommunity/plus_plugins/commit/6af2328da997b452758e6c78f3815bcf55ac24aa)) +- **FEAT**(share_plus): Remove deprecated VALID_ARCHS iOS + property ([#2024](https://github.com/fluttercommunity/plus_plugins/issues/2024)). ([bb79888e](https://github.com/fluttercommunity/plus_plugins/commit/bb79888eda6425d8e772bb4bea47f4966610240f)) +- **DOCS**(share_plus): Fix usage code + snippets ([#2106](https://github.com/fluttercommunity/plus_plugins/issues/2106)). ([346e07ea](https://github.com/fluttercommunity/plus_plugins/commit/346e07ea56088321f92530e4334edab0400f4c43)) ## 7.1.0 - - **FIX**(share_plus): Regenerate iOS and MacOS example apps ([#1869](https://github.com/fluttercommunity/plus_plugins/issues/1869)). ([5db20ba7](https://github.com/fluttercommunity/plus_plugins/commit/5db20ba7aebd7787a7e56df8e8e6bcb6f832f230)) - - **FEAT**(share_plus): Allow user to share URI with preview image on the iOS native share sheet ([#1779](https://github.com/fluttercommunity/plus_plugins/issues/1779)). ([c83b667e](https://github.com/fluttercommunity/plus_plugins/commit/c83b667eb12394feef69221eda0eab8716aa19d8)) - - **DOCS**(share_plus): Updated document with latest available method ([#1917](https://github.com/fluttercommunity/plus_plugins/issues/1917)). ([7fbe3de6](https://github.com/fluttercommunity/plus_plugins/commit/7fbe3de61b874b7d83d66f70c1e2928378707f86)) - - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) +- **FIX**(share_plus): Regenerate iOS and MacOS example + apps ([#1869](https://github.com/fluttercommunity/plus_plugins/issues/1869)). ([5db20ba7](https://github.com/fluttercommunity/plus_plugins/commit/5db20ba7aebd7787a7e56df8e8e6bcb6f832f230)) +- **FEAT**(share_plus): Allow user to share URI with preview image on the iOS native share + sheet ([#1779](https://github.com/fluttercommunity/plus_plugins/issues/1779)). ([c83b667e](https://github.com/fluttercommunity/plus_plugins/commit/c83b667eb12394feef69221eda0eab8716aa19d8)) +- **DOCS**(share_plus): Updated document with latest available + method ([#1917](https://github.com/fluttercommunity/plus_plugins/issues/1917)). ([7fbe3de6](https://github.com/fluttercommunity/plus_plugins/commit/7fbe3de61b874b7d83d66f70c1e2928378707f86)) +- **DOCS**(all): Fix example links on + pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) ## 7.0.2 -- **CHORE**(share_plus): Update file dependency constraints ([#1853](https://github.com/fluttercommunity/plus_plugins/pull/1853)). ([d8ff0cdb](https://github.com/fluttercommunity/plus_plugins/commit/d8ff0cdb665048c59c8acc5fecd1a9c099ee012f)) +- **CHORE**(share_plus): Update file dependency + constraints ([#1853](https://github.com/fluttercommunity/plus_plugins/pull/1853)). ([d8ff0cdb](https://github.com/fluttercommunity/plus_plugins/commit/d8ff0cdb665048c59c8acc5fecd1a9c099ee012f)) ## 7.0.1 - - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) - - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) - - **CHORE**(share_plus): Win32 dependency upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) +- **FIX**: Add jvm target compatibility to Kotlin + plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) +- **DOCS**(all): Update + READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) +- **CHORE**(share_plus): Win32 dependency + upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) ## 7.0.0 > Note: This release has breaking changes. - - **CHORE**(share_plus_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 - - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. - - **BREAKING** **CHORE**(share_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1773). - - **REFACTOR**(share_plus): Remove manual dependency override in example app. +- **CHORE**(share_plus_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to > + =2.18.0 <4.0.0 +- **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin ( + AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to + update at least to AGP 7.0 or newer. +- **BREAKING** **CHORE**(share_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec + file (#1773). +- **REFACTOR**(share_plus): Remove manual dependency override in example app. ## 6.3.4 - - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). +- **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). ## 6.3.3 - - **FIX**(share_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1706). - - **FIX**(share_plus_android): Fix strict compilation errors in MIME reduction function (#1650). +- **FIX**(share_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1706). +- **FIX**(share_plus_android): Fix strict compilation errors in MIME reduction function (#1650). ## 6.3.2 - - **FIX**(share_plus): Set exported=false for BroadcastReceiver on Android (#1613). - - **FIX**(package_info_plus): Make example app content scrollable (#1614). - - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). +- **FIX**(share_plus): Set exported=false for BroadcastReceiver on Android (#1613). +- **FIX**(package_info_plus): Make example app content scrollable (#1614). +- **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). ## 6.3.1 - - **FIX**: Fix the error of requestCode value range. (#1340). - - **FIX**: example broken on web (#1334). - - **DOCS**: Updates for READMEs and website pages (#1389). +- **FIX**: Fix the error of requestCode value range. (#1340). +- **FIX**: example broken on web (#1334). +- **DOCS**: Updates for READMEs and website pages (#1389). ## 6.3.0 - - **FIX**: remove `canLaunch` check (#1315). - - **FEAT**: Show destination for share with result in example, update example UI (#1314). +- **FIX**: remove `canLaunch` check (#1315). +- **FEAT**: Show destination for share with result in example, update example UI (#1314). ## 6.2.0 - - **FIX**: return correct share result on android (#1301). - - **FEAT**: remove direct dependence of url_launcher (#1295). - - **DOCS**: #1299 document XFile.fromData (#1300). +- **FIX**: return correct share result on android (#1301). +- **FEAT**: remove direct dependence of url_launcher (#1295). +- **DOCS**: #1299 document XFile.fromData (#1300). ## 6.1.0 - - **FIX**: export XFile (#1286). - - **FEAT**: share XFile created using File.fromData() (#1284). +- **FIX**: export XFile (#1286). +- **FEAT**: share XFile created using File.fromData() (#1284). ## 6.0.1 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 6.0.0 > Note: This release has breaking changes. - - **FIX**: lint warnings - add missing dependency for tests (#1233). - - **FIX**: Show NSSharingServicePicker asynchronously on main thread (#1223). - - **BREAKING** **REFACTOR**: two-package federated architecture (#1238). +- **FIX**: lint warnings - add missing dependency for tests (#1233). +- **FIX**: Show NSSharingServicePicker asynchronously on main thread (#1223). +- **BREAKING** **REFACTOR**: two-package federated architecture (#1238). ## 5.0.0 > Note: This release has breaking changes. - - **BREAKING** **FEAT**: Native share UI for Windows (#1158). +- **BREAKING** **FEAT**: Native share UI for Windows (#1158). ## 4.5.3 - - **CHORE**: Version tagging using melos. +- **CHORE**: Version tagging using melos. ## 4.5.2 @@ -212,24 +266,26 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 4.3.0 -- iOS: Throw PlatformException when iPad share dialog not appearing (sharePositionOrigin not in sourceView) +- iOS: Throw PlatformException when iPad share dialog not appearing (sharePositionOrigin not in + sourceView) ## 4.2.0 - iOS: Fix Instagram does not show up in provider list for web links - - issue #459 appear again - - put back NSURL for the shareText, when text is pure URL - - using LPMetadataProvider to get LPLinkMetadata make the user experience better + - issue #459 appear again + - put back NSURL for the shareText, when text is pure URL + - using LPMetadataProvider to get LPLinkMetadata make the user experience better ## 4.1.0 - iOS: Fix text sharing. - - Previously, the text was being encoded as a URL, this caused the share sheet to appear empty. - - Now the shared text is not encoded as a URL anymore but rather shared as plain text. - - Sharing text + subject + attachments should work on apps that support that (e.g. Mail app). - - Example: Sharing Text + Image on Telegram is possible and both are shared. - - Some apps still have limitations with sharing. For example, Gmail app does not support the subject field. - - Related issue: #730 + - Previously, the text was being encoded as a URL, this caused the share sheet to appear empty. + - Now the shared text is not encoded as a URL anymore but rather shared as plain text. + - Sharing text + subject + attachments should work on apps that support that (e.g. Mail app). + - Example: Sharing Text + Image on Telegram is possible and both are shared. + - Some apps still have limitations with sharing. For example, Gmail app does not support the + subject field. + - Related issue: #730 ## 4.0.10+1 @@ -331,7 +387,8 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 2.1.3 -- Update iOS share target to present on the top ViewController. This fixes "Unable to present" errors when the app is already presenting such as in an add to app scenario. +- Update iOS share target to present on the top ViewController. This fixes "Unable to present" + errors when the app is already presenting such as in an add to app scenario. ## 2.1.2 @@ -343,7 +400,8 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 2.1.0 -- Fixes #241 resolves issues with deprecations as of android API version 29 and replaces the requirement for external storage locations with an easy application cache usage. +- Fixes #241 resolves issues with deprecations as of android API version 29 and replaces the + requirement for external storage locations with an easy application cache usage. ## 2.0.3 @@ -402,7 +460,8 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 0.6.4+1 -- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). +- Declare API stability and compatibility with `1.0.0` (more details + at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). ## 0.6.4 @@ -549,7 +608,8 @@ In this release plugin migrated to package:web, meaning that it now supports WAS ## 0.2.0 -- Upgrade to new plugin registration. (https://groups.google.com/forum/#!topic/flutter-dev/zba1Ynf2OKM) +- Upgrade to new plugin + registration. (https://groups.google.com/forum/#!topic/flutter-dev/zba1Ynf2OKM) ## 0.1.0 diff --git a/packages/share_plus/share_plus/README.md b/packages/share_plus/share_plus/README.md index 282bea03a7..6eb2d2f5dd 100644 --- a/packages/share_plus/share_plus/README.md +++ b/packages/share_plus/share_plus/README.md @@ -14,11 +14,11 @@ on iOS, or equivalent platform content sharing methods. ## Platform Support -| Method | Android | iOS | MacOS | Web | Linux | Windows | -| :-----------: | :-----: | :-: | :---: | :-: | :---: | :----: | -| `share` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| `shareUri` | ✅ | ✅ | | | | | -| `shareXFiles` | ✅ | ✅ | ✅ | ✅ | | ✅ | +| Method | Android | iOS | MacOS | Web | Linux | Windows | +|:-------------:|:-------:|:---:|:-----:|:---:|:-----:|:-------:| +| `share` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `shareUri` | ✅ | ✅ | | | | | +| `shareXFiles` | ✅ | ✅ | ✅ | ✅ | | ✅ | Also compatible with Windows and Linux by using "mailto" to share text via Email. @@ -37,7 +37,8 @@ Sharing files is not supported on Linux. ## Usage -To use this plugin, add `share_plus` as a [dependency in your pubspec.yaml file](https://plus.fluttercommunity.dev/docs/overview). +To use this plugin, add `share_plus` as +a [dependency in your pubspec.yaml file](https://plus.fluttercommunity.dev/docs/overview). Import the library. @@ -50,43 +51,66 @@ import 'package:share_plus/share_plus.dart'; Invoke the static `share()` method anywhere in your Dart code. ```dart -Share.share('check out my website https://example.com'); +Share.share +('check out my website https://example.com +' +); ``` The `share` method also takes an optional `subject` that will be used when sharing to email. ```dart -Share.share('check out my website https://example.com', subject: 'Look what I made!'); +Share.share +('check out my website https://example.com +' +, subject: +' +Look what I made! +' +); ``` `share()` returns `status` object that allows to check the result of user action in the share sheet. ```dart -final result = await Share.share('check out my website https://example.com'); + +final result = await +Share.share +('check out my website https://example.com +' +); if (result.status == ShareResultStatus.success) { - print('Thank you for sharing my website!'); +print('Thank you for sharing my website!'); } ``` ### Share Files -To share one or multiple files, invoke the static `shareXFiles` method anywhere in your Dart code. The method returns a `ShareResult`. Optionally, you can pass `subject`, `text` and `sharePositionOrigin`. +To share one or multiple files, invoke the static `shareXFiles` method anywhere in your Dart code. +The method returns a `ShareResult`. Optionally, you can pass `subject`, `text` and +`sharePositionOrigin`. ```dart -final result = await Share.shareXFiles([XFile('${directory.path}/image.jpg')], text: 'Great picture'); + +final result = await +Share.shareXFiles +([XFile('${directory.path}/image.jpg')], text: 'Great picture'); if (result.status == ShareResultStatus.success) { - print('Thank you for sharing the picture!'); +print('Thank you for sharing the picture!'); } ``` ```dart -final result = await Share.shareXFiles([XFile('${directory.path}/image1.jpg'), XFile('${directory.path}/image2.jpg')]); + +final result = await +Share.shareXFiles +([XFile('${directory.path}/image1.jpg'), XFile('${directory.path}/image2.jpg')]); if (result.status == ShareResultStatus.dismissed) { - print('Did you not like the pictures?'); +print('Did you not like the pictures?'); } ``` @@ -96,9 +120,11 @@ See [Can I Use - Web Share API](https://caniuse.com/web-share) to understand which browsers are supported. This builds on the [`cross_file`](https://pub.dev/packages/cross_file) package. - ```dart -Share.shareXFiles([XFile('assets/hello.txt')], text: 'Great picture'); +Share.shareXFiles +([XFile('assets/hello.txt')], text: 'Great picture +' +); ``` File downloading fallback mechanism for web can be disabled by setting: @@ -109,16 +135,25 @@ Share.downloadFallbackEnabled = false; #### Share Data -You can also share files that you dynamically generate from its data using [`XFile.fromData`](https://pub.dev/documentation/share_plus/latest/share_plus/XFile/XFile.fromData.html). +You can also share files that you dynamically generate from its data using [ +`XFile.fromData`](https://pub.dev/documentation/share_plus/latest/share_plus/XFile/XFile.fromData.html). -To set the name of such files, use the `fileNameOverrides` parameter, otherwise the file name will be a random UUID string. +To set the name of such files, use the `fileNameOverrides` parameter, otherwise the file name will +be a random UUID string. ```dart -Share.shareXFiles([XFile.fromData(utf8.encode(text), mimeType: 'text/plain')], fileNameOverrides: ['myfile.txt']); +Share.shareXFiles +([XFile.fromData(utf8.encode(text), mimeType: 'text/plain')], fileNameOverrides: [ +' +myfile.txt +' +] +); ``` > [!CAUTION] -> The `name` parameter in the `XFile.fromData` method is ignored in most platforms. Use `fileNameOverrides` instead. +> The `name` parameter in the `XFile.fromData` method is ignored in most platforms. Use +`fileNameOverrides` instead. ### Share URI @@ -126,7 +161,12 @@ iOS supports fetching metadata from a URI when shared using `UIActivityViewContr This special method is only properly supported on iOS. ```dart -Share.shareUri(uri: uri); +Share.shareUri +( +uri +: +uri +); ``` ### Share Results @@ -136,45 +176,60 @@ All three methods return a `ShareResult` object which contains the following inf - `status`: a `ShareResultStatus` - `raw`: a `String` describing the share result, e.g. the opening app ID. -Note: `status` will be `ShareResultStatus.unavailable` if the platform does not support identifying the user action. +Note: `status` will be `ShareResultStatus.unavailable` if the platform does not support identifying +the user action. ## Known Issues ### Sharing data created with XFile.fromData -When sharing data created with `XFile.fromData`, the plugin will write a temporal file inside the cache directory of the app, so it can be shared. +When sharing data created with `XFile.fromData`, the plugin will write a temporal file inside the +cache directory of the app, so it can be shared. -Although the OS should take care of deleting those files, it is advised, that you clean up this data once in a while (e.g. on app start). +Although the OS should take care of deleting those files, it is advised, that you clean up this data +once in a while (e.g. on app start). -You can access this directory using [path_provider](https://pub.dev/packages/path_provider) [getTemporaryDirectory](https://pub.dev/documentation/path_provider/latest/path_provider/getTemporaryDirectory.html). +You can access this directory +using [path_provider](https://pub.dev/packages/path_provider) [getTemporaryDirectory](https://pub.dev/documentation/path_provider/latest/path_provider/getTemporaryDirectory.html). -Alternatively, don't use `XFile.fromData` and instead write the data down to a `File` with a path before sharing it, so you control when to delete it. +Alternatively, don't use `XFile.fromData` and instead write the data down to a `File` with a path +before sharing it, so you control when to delete it. ### Mobile platforms (Android and iOS) #### Sharing images + text -When attempting to share images with text, some apps may fail to properly accept the share action with them. +When attempting to share images with text, some apps may fail to properly accept the share action +with them. -For example, due to restrictions set up by Meta/Facebook this plugin isn't capable of sharing data reliably -to Facebook related apps on Android and iOS. This includes eg. sharing text to the Facebook Messenger. +For example, due to restrictions set up by Meta/Facebook this plugin isn't capable of sharing data +reliably +to Facebook related apps on Android and iOS. This includes eg. sharing text to the Facebook +Messenger. -If you require this functionality please check the native Facebook Sharing SDK ([https://developers.facebook.com/docs/sharing](https://developers.facebook.com/docs/sharing)) -or search for other Flutter plugins implementing this SDK. More information can be found in [this issue](https://github.com/fluttercommunity/plus_plugins/issues/413). +If you require this functionality please check the native Facebook Sharing +SDK ([https://developers.facebook.com/docs/sharing](https://developers.facebook.com/docs/sharing)) +or search for other Flutter plugins implementing this SDK. More information can be found +in [this issue](https://github.com/fluttercommunity/plus_plugins/issues/413). Other apps may also give problems when attempting to share content to them. -This is because 3rd party app developers do not properly implement the logic to receive share actions. +This is because 3rd party app developers do not properly implement the logic to receive share +actions. We cannot warranty that a 3rd party app will properly implement the share functionality. Therefore, **all bugs reported regarding compatibility with a specific app will be closed.** #### Localization in Apple platforms -It could happen that the Share sheet appears with a different language, [as reported here](https://github.com/fluttercommunity/plus_plugins/issues/2696). +It could happen that the Share sheet appears with a different +language, [as reported here](https://github.com/fluttercommunity/plus_plugins/issues/2696). -To fix this issue, you will have to setup the keys `CFBundleAllowMixedLocalizations` and `CFBundleDevelopmentRegion` in your project's `info.plist`. +To fix this issue, you will have to setup the keys `CFBundleAllowMixedLocalizations` and +`CFBundleDevelopmentRegion` in your project's `info.plist`. -For more information check the [CoreFoundationKeys](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html) documentation. +For more information check +the [CoreFoundationKeys](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html) +documentation. #### iPad @@ -189,22 +244,24 @@ For example: ```dart // Use Builder to get the widget context -Builder( - builder: (BuildContext context) { - return ElevatedButton( - onPressed: () => _onShare(context), - child: const Text('Share'), - ); - }, +Builder +( +builder: (BuildContext context) { +return ElevatedButton( +onPressed: () => _onShare(context), +child: const Text('Share'), +); +}, ), // _onShare method: final box = context.findRenderObject() as RenderBox?; await Share.share( - text, - subject: subject, - sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, +text, +subject: subject, +sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size +, ); ``` diff --git a/packages/share_plus/share_plus/android/build.gradle b/packages/share_plus/share_plus/android/build.gradle index 56b97cf921..4894ddd245 100644 --- a/packages/share_plus/share_plus/android/build.gradle +++ b/packages/share_plus/share_plus/android/build.gradle @@ -2,7 +2,7 @@ group 'dev.fluttercommunity.plus.share' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.7.22' + ext.kotlin_version = '2.1.10' repositories { google() mavenCentral() @@ -25,7 +25,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 namespace 'dev.fluttercommunity.plus.share' @@ -49,7 +49,7 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.13.1' + implementation 'androidx.core:core:1.15.0' implementation 'androidx.annotation:annotation:1.8.2' } } diff --git a/packages/share_plus/share_plus/android/gradle/wrapper/gradle-wrapper.properties b/packages/share_plus/share_plus/android/gradle/wrapper/gradle-wrapper.properties index e411586a54..2733ed5dc3 100644 --- a/packages/share_plus/share_plus/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/share_plus/share_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/share_plus/share_plus/android/src/main/AndroidManifest.xml b/packages/share_plus/share_plus/android/src/main/AndroidManifest.xml index 6644612b05..1a8d447580 100644 --- a/packages/share_plus/share_plus/android/src/main/AndroidManifest.xml +++ b/packages/share_plus/share_plus/android/src/main/AndroidManifest.xml @@ -1,23 +1,26 @@ + package="dev.fluttercommunity.plus.share"> + - - - - - - - - - - + + + + + + + + + + diff --git a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPendingIntent.kt b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPendingIntent.kt index 302ad4d874..91d3e9d7c1 100644 --- a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPendingIntent.kt +++ b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPendingIntent.kt @@ -11,7 +11,7 @@ import androidx.annotation.RequiresApi * * When the PendingIntent is sent, the system will instantiate this class and call `onReceive` on it. */ -internal class SharePlusPendingIntent: BroadcastReceiver() { +internal class SharePlusPendingIntent : BroadcastReceiver() { companion object { /** * Static member to access the result of the system instantiated instance diff --git a/packages/share_plus/share_plus/android/src/main/res/xml/flutter_share_file_paths.xml b/packages/share_plus/share_plus/android/src/main/res/xml/flutter_share_file_paths.xml index cb820aec00..8e139bd932 100644 --- a/packages/share_plus/share_plus/android/src/main/res/xml/flutter_share_file_paths.xml +++ b/packages/share_plus/share_plus/android/src/main/res/xml/flutter_share_file_paths.xml @@ -1,5 +1,7 @@ - - - + + + diff --git a/packages/share_plus/share_plus/example/android/app/build.gradle b/packages/share_plus/share_plus/example/android/app/build.gradle index 239a45415a..7d2e6c06df 100644 --- a/packages/share_plus/share_plus/example/android/app/build.gradle +++ b/packages/share_plus/share_plus/example/android/app/build.gradle @@ -22,7 +22,7 @@ if (flutterVersionName == null) { } android { - compileSdk 34 + compileSdk 35 namespace 'io.flutter.plugins.shareexample' @@ -38,7 +38,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.shareexample" minSdk 21 - targetSdk 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/packages/share_plus/share_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/share_plus/share_plus/example/android/gradle/wrapper/gradle-wrapper.properties index cae4528dfb..c0bc428bc1 100644 --- a/packages/share_plus/share_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/share_plus/share_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/packages/share_plus/share_plus/example/android/settings.gradle b/packages/share_plus/share_plus/example/android/settings.gradle index 5fad357a02..c45c7624c3 100644 --- a/packages/share_plus/share_plus/example/android/settings.gradle +++ b/packages/share_plus/share_plus/example/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.1" apply false + id "com.android.application" version "8.9.0" apply false } include ":app" diff --git a/packages/share_plus/share_plus/example/integration_test/share_plus_test.dart b/packages/share_plus/share_plus/example/integration_test/share_plus_test.dart index 18caa757f1..19cd7c3830 100644 --- a/packages/share_plus/share_plus/example/integration_test/share_plus_test.dart +++ b/packages/share_plus/share_plus/example/integration_test/share_plus_test.dart @@ -21,11 +21,15 @@ void main() { expect(Share.shareUri(Uri.parse('https://example.com')), isNotNull); }, skip: !Platform.isAndroid && !Platform.isIOS); - testWidgets('Can shareXFile created using File.fromData()', - (WidgetTester tester) async { + testWidgets('Can shareXFile created using File.fromData()', ( + WidgetTester tester, + ) async { final bytes = Uint8List.fromList([1, 2, 3, 4, 5, 6, 7, 8]); - final XFile file = - XFile.fromData(bytes, name: 'image.jpg', mimeType: 'image/jpeg'); + final XFile file = XFile.fromData( + bytes, + name: 'image.jpg', + mimeType: 'image/jpeg', + ); expect(Share.shareXFiles([file], text: "example"), isNotNull); }); diff --git a/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2d..e882ab9889 100644 --- a/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,122 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-App-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-App-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-App-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-App-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "Icon-App-20x20@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "Icon-App-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "Icon-App-40x40@2x.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "Icon-App-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon-App-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon-App-1024x1024@1x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2fd4..781d7cdcac 100644 --- a/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" + "idiom": "universal", + "filename": "LaunchImage.png", + "scale": "1x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" + "idiom": "universal", + "filename": "LaunchImage@2x.png", + "scale": "2x" }, { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" + "idiom": "universal", + "filename": "LaunchImage@3x.png", + "scale": "3x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md index 89c2725b70..d880e1f556 100644 --- a/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ b/packages/share_plus/share_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -1,5 +1,8 @@ # Launch Screen Assets -You can customize the launch screen with your own desired assets by replacing the image files in this directory. +You can customize the launch screen with your own desired assets by replacing the image files in +this directory. -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file +You can also do it by opening your Flutter project's Xcode project with +`open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and +dropping in the desired images. diff --git a/packages/share_plus/share_plus/example/lib/image_previews.dart b/packages/share_plus/share_plus/example/lib/image_previews.dart index a41d6b6ad5..a4db482280 100644 --- a/packages/share_plus/share_plus/example/lib/image_previews.dart +++ b/packages/share_plus/share_plus/example/lib/image_previews.dart @@ -23,10 +23,12 @@ class ImagePreviews extends StatelessWidget { final imageWidgets = []; for (var i = 0; i < imagePaths.length; i++) { - imageWidgets.add(_ImagePreview( - imagePaths[i], - onDelete: onDelete != null ? () => onDelete!(i) : null, - )); + imageWidgets.add( + _ImagePreview( + imagePaths[i], + onDelete: onDelete != null ? () => onDelete!(i) : null, + ), + ); } return SingleChildScrollView( @@ -50,10 +52,7 @@ class _ImagePreview extends StatelessWidget { child: Stack( children: [ ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 200, - maxHeight: 200, - ), + constraints: const BoxConstraints(maxWidth: 200, maxHeight: 200), child: kIsWeb ? Image.network(imagePath) : Image.file(imageFile), ), Positioned( @@ -61,9 +60,10 @@ class _ImagePreview extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(8.0), child: FloatingActionButton( - backgroundColor: Colors.red, - onPressed: onDelete, - child: const Icon(Icons.delete)), + backgroundColor: Colors.red, + onPressed: onDelete, + child: const Icon(Icons.delete), + ), ), ), ], diff --git a/packages/share_plus/share_plus/example/lib/main.dart b/packages/share_plus/share_plus/example/lib/main.dart index 913a6e33ce..d5b64e30ac 100644 --- a/packages/share_plus/share_plus/example/lib/main.dart +++ b/packages/share_plus/share_plus/example/lib/main.dart @@ -67,9 +67,10 @@ class DemoAppState extends State { hintText: 'Enter some text and/or link to share', ), maxLines: null, - onChanged: (String value) => setState(() { - text = value; - }), + onChanged: + (String value) => setState(() { + text = value; + }), ), const SizedBox(height: 16), TextField( @@ -79,9 +80,10 @@ class DemoAppState extends State { hintText: 'Enter subject to share (optional)', ), maxLines: null, - onChanged: (String value) => setState(() { - subject = value; - }), + onChanged: + (String value) => setState(() { + subject = value; + }), ), const SizedBox(height: 16), TextField( @@ -123,7 +125,8 @@ class DemoAppState extends State { extensions: ['jpg', 'jpeg', 'png', 'gif'], ); final file = await openFile( - acceptedTypeGroups: [typeGroup]); + acceptedTypeGroups: [typeGroup], + ); if (file != null) { setState(() { imagePaths.add(file.path); @@ -153,9 +156,10 @@ class DemoAppState extends State { foregroundColor: Theme.of(context).colorScheme.onPrimary, backgroundColor: Theme.of(context).colorScheme.primary, ), - onPressed: text.isEmpty && imagePaths.isEmpty - ? null - : () => _onShareWithResult(context), + onPressed: + text.isEmpty && imagePaths.isEmpty + ? null + : () => _onShareWithResult(context), child: const Text('Share'), ); }, @@ -183,9 +187,10 @@ class DemoAppState extends State { foregroundColor: Theme.of(context).colorScheme.onPrimary, backgroundColor: Theme.of(context).colorScheme.primary, ), - onPressed: fileName.isEmpty || text.isEmpty - ? null - : () => _onShareTextAsXFile(context), + onPressed: + fileName.isEmpty || text.isEmpty + ? null + : () => _onShareTextAsXFile(context), child: const Text('Share text as XFile'), ); }, @@ -248,21 +253,16 @@ class DemoAppState extends State { try { final data = await rootBundle.load('assets/flutter_logo.png'); final buffer = data.buffer; - final shareResult = await Share.shareXFiles( - [ - XFile.fromData( - buffer.asUint8List(data.offsetInBytes, data.lengthInBytes), - name: 'flutter_logo.png', - mimeType: 'image/png', - ), - ], - sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, - ); + final shareResult = await Share.shareXFiles([ + XFile.fromData( + buffer.asUint8List(data.offsetInBytes, data.lengthInBytes), + name: 'flutter_logo.png', + mimeType: 'image/png', + ), + ], sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size); scaffoldMessenger.showSnackBar(getResultSnackBar(shareResult)); } catch (e) { - scaffoldMessenger.showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); } } @@ -285,9 +285,7 @@ class DemoAppState extends State { scaffoldMessenger.showSnackBar(getResultSnackBar(shareResult)); } catch (e) { - scaffoldMessenger.showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); } } @@ -299,7 +297,7 @@ class DemoAppState extends State { children: [ Text("Share result: ${result.status}"), if (result.status == ShareResultStatus.success) - Text("Shared to: ${result.raw}") + Text("Shared to: ${result.raw}"), ], ), ); diff --git a/packages/share_plus/share_plus/example/linux/CMakeLists.txt b/packages/share_plus/share_plus/example/linux/CMakeLists.txt index 279007eb35..c460a20abe 100644 --- a/packages/share_plus/share_plus/example/linux/CMakeLists.txt +++ b/packages/share_plus/share_plus/example/linux/CMakeLists.txt @@ -9,19 +9,19 @@ cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif () # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -37,9 +37,9 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") # Application build add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) target_link_libraries(${BINARY_NAME} PRIVATE flutter) @@ -50,8 +50,8 @@ add_dependencies(${BINARY_NAME} flutter_assemble) # people trying to run the unbundled copy, put it in a subdirectory instead of # the default top-level location. set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) # Generated plugin build rules, which manage building the plugins and adding @@ -63,9 +63,9 @@ include(flutter/generated_plugins.cmake) # By default, "installing" just makes a relocatable bundle in the build # directory. set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () # Start with a clean build bundle directory every time. install(CODE " @@ -76,19 +76,19 @@ set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -97,10 +97,10 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () diff --git a/packages/share_plus/share_plus/example/linux/flutter/CMakeLists.txt b/packages/share_plus/share_plus/example/linux/flutter/CMakeLists.txt index 5b465c7ecf..03e4a7fe4a 100644 --- a/packages/share_plus/share_plus/example/linux/flutter/CMakeLists.txt +++ b/packages/share_plus/share_plus/example/linux/flutter/CMakeLists.txt @@ -12,9 +12,9 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # which isn't available in 3.10. function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) + foreach (element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) + endforeach (element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() @@ -35,38 +35,38 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO - PkgConfig::BLKID + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID ) add_dependencies(flutter flutter_assemble) @@ -75,15 +75,15 @@ add_dependencies(flutter flutter_assemble) # since currently there's no way to get a full input/output list from the # flutter tool. add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} ) diff --git a/packages/share_plus/share_plus/example/linux/main.cc b/packages/share_plus/share_plus/example/linux/main.cc index 8bc1561588..dbe6db8472 100644 --- a/packages/share_plus/share_plus/example/linux/main.cc +++ b/packages/share_plus/share_plus/example/linux/main.cc @@ -1,11 +1,12 @@ #include "my_application.h" int main(int argc, char **argv) { - // Only X11 is currently supported. - // Wayland support is being developed: - // https://github.com/flutter/flutter/issues/57932. - gdk_set_allowed_backends("x11"); + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); + g_autoptr(MyApplication) + app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); } diff --git a/packages/share_plus/share_plus/example/linux/my_application.cc b/packages/share_plus/share_plus/example/linux/my_application.cc index cef2f77145..20cf1fa128 100644 --- a/packages/share_plus/share_plus/example/linux/my_application.cc +++ b/packages/share_plus/share_plus/example/linux/my_application.cc @@ -5,41 +5,43 @@ #include "flutter/generated_plugin_registrant.h" struct _MyApplication { - GtkApplication parent_instance; + GtkApplication parent_instance; }; -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION +) // Implements GApplication::activate. static void my_application_activate(GApplication *application) { - GtkWindow *window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - - FlView *view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) + project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); } static void my_application_class_init(MyApplicationClass *klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->activate = my_application_activate; } -static void my_application_init(MyApplication *self) {} +static void my_application_init(MyApplication * self) {} MyApplication *my_application_new() { - return MY_APPLICATION(g_object_new( - my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); } diff --git a/packages/share_plus/share_plus/example/linux/my_application.h b/packages/share_plus/share_plus/example/linux/my_application.h index 3258a73cf4..5b081e77c6 100644 --- a/packages/share_plus/share_plus/example/linux/my_application.h +++ b/packages/share_plus/share_plus/example/linux/my_application.h @@ -4,7 +4,8 @@ #include G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) + GtkApplication +) /** * my_application_new: diff --git a/packages/share_plus/share_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/share_plus/share_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f19f..60e60c947e 100644 --- a/packages/share_plus/share_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/packages/share_plus/share_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ + "images": [ { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" }, { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" }, { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" }, { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" }, { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" }, { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } } diff --git a/packages/share_plus/share_plus/example/test_driver/share_plus_test.dart b/packages/share_plus/share_plus/example/test_driver/share_plus_test.dart index 8c663fb1db..a732616089 100644 --- a/packages/share_plus/share_plus/example/test_driver/share_plus_test.dart +++ b/packages/share_plus/share_plus/example/test_driver/share_plus_test.dart @@ -9,8 +9,10 @@ import 'package:flutter_driver/flutter_driver.dart'; Future main() async { final driver = await FlutterDriver.connect(); - final data = - await driver.requestData(null, timeout: const Duration(minutes: 1)); + final data = await driver.requestData( + null, + timeout: const Duration(minutes: 1), + ); await driver.close(); final Map result = jsonDecode(data); exit(result['result'] == 'true' ? 0 : 1); diff --git a/packages/share_plus/share_plus/example/web/index.html b/packages/share_plus/share_plus/example/web/index.html index 55bfed0d9d..7a7991533f 100644 --- a/packages/share_plus/share_plus/example/web/index.html +++ b/packages/share_plus/share_plus/example/web/index.html @@ -1,35 +1,35 @@ - - + Fore more details: + * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base + --> + - - - + + + - - - - - + + + + + - - + + - example - + example + - + diff --git a/packages/share_plus/share_plus/example/web/manifest.json b/packages/share_plus/share_plus/example/web/manifest.json index 8c012917da..037463cc72 100644 --- a/packages/share_plus/share_plus/example/web/manifest.json +++ b/packages/share_plus/share_plus/example/web/manifest.json @@ -1,23 +1,23 @@ { - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] } diff --git a/packages/share_plus/share_plus/example/windows/CMakeLists.txt b/packages/share_plus/share_plus/example/windows/CMakeLists.txt index abf90408ef..5d3a4fe2dc 100644 --- a/packages/share_plus/share_plus/example/windows/CMakeLists.txt +++ b/packages/share_plus/share_plus/example/windows/CMakeLists.txt @@ -9,17 +9,17 @@ set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Configure build options. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() +if (IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else () + if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif () +endif () set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") @@ -31,11 +31,11 @@ add_definitions(-DUNICODE -D_UNICODE) # Compilation settings that should be applied to most targets. function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") @@ -58,27 +58,27 @@ include(flutter/generated_plugins.cmake) set(BUILD_BUNDLE_DIR "$") # Make the "install" step default, as it's required to run. set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif () set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) + COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() +if (PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif () # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. @@ -87,9 +87,9 @@ install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) # Install the AOT library on non-Debug builds only. install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/share_plus/share_plus/example/windows/flutter/CMakeLists.txt b/packages/share_plus/share_plus/example/windows/flutter/CMakeLists.txt index 744f08a938..bc1c2f9f44 100644 --- a/packages/share_plus/share_plus/example/windows/flutter/CMakeLists.txt +++ b/packages/share_plus/share_plus/example/windows/flutter/CMakeLists.txt @@ -19,60 +19,60 @@ set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" + "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") add_dependencies(flutter flutter_assemble) # === Wrapper === list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" + "core_implementations.cc" + "standard_codec.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" + "plugin_registrar.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" + "flutter_engine.cc" + "flutter_view_controller.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") # Wrapper sources needed for a plugin. add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} ) apply_standard_settings(flutter_wrapper_plugin) set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_plugin flutter_assemble) # Wrapper sources needed for the runner. add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} ) apply_standard_settings(flutter_wrapper_app) target_link_libraries(flutter_wrapper_app PUBLIC flutter) target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" + "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_app flutter_assemble) @@ -83,20 +83,20 @@ add_dependencies(flutter_wrapper_app flutter_assemble) set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ - VERBATIM + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM ) add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} ) diff --git a/packages/share_plus/share_plus/example/windows/runner/CMakeLists.txt b/packages/share_plus/share_plus/example/windows/runner/CMakeLists.txt index 977e38b5d1..3fdcb0dd27 100644 --- a/packages/share_plus/share_plus/example/windows/runner/CMakeLists.txt +++ b/packages/share_plus/share_plus/example/windows/runner/CMakeLists.txt @@ -2,14 +2,14 @@ cmake_minimum_required(VERSION 3.15) project(runner LANGUAGES CXX) add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "run_loop.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" ) apply_standard_settings(${BINARY_NAME}) target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") diff --git a/packages/share_plus/share_plus/example/windows/runner/Runner.rc b/packages/share_plus/share_plus/example/windows/runner/Runner.rc index 9d72c23ad7..685b224df3 100644 --- a/packages/share_plus/share_plus/example/windows/runner/Runner.rc +++ b/packages/share_plus/share_plus/example/windows/runner/Runner.rc @@ -1,6 +1,7 @@ // Microsoft Visual C++ generated resource script. // #pragma code_page(65001) + #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS @@ -20,27 +21,27 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// + ///////////////////////////////////////////////////////////////////////////// + // + // TEXTINCLUDE + // -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END + 1 TEXTINCLUDE + BEGIN + "resource.h\0" + END -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END + 2 TEXTINCLUDE + BEGIN + "#include ""winres.h""\r\n" + "\0" + END -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END + 3 TEXTINCLUDE + BEGIN + "\r\n" + "\0" + END #endif // APSTUDIO_INVOKED @@ -73,37 +74,41 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEVERSION VERSION_AS_NUMBER +PRODUCTVERSION VERSION_AS_NUMBER +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG +FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L +FILEFLAGS 0x0L #endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0x0L BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "io.flutter.plugins" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2020 io.flutter.plugins. All rights reserved." "\0" - VALUE "OriginalFilename", "example.exe" "\0" - VALUE "ProductName", "example" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" + BLOCK +"StringFileInfo" +BEGIN + BLOCK +"040904e4" +BEGIN + VALUE +"CompanyName", "io.flutter.plugins" "\0" +VALUE "FileDescription", "A new Flutter project." "\0" +VALUE "FileVersion", VERSION_AS_STRING "\0" +VALUE "InternalName", "example" "\0" +VALUE "LegalCopyright", "Copyright (C) 2020 io.flutter.plugins. All rights reserved." "\0" +VALUE "OriginalFilename", "example.exe" "\0" +VALUE "ProductName", "example" "\0" +VALUE "ProductVersion", VERSION_AS_STRING "\0" +END END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END +BLOCK "VarFileInfo" +BEGIN + VALUE +"Translation", 0x409, 1252 END + END #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/packages/share_plus/share_plus/example/windows/runner/flutter_window.cpp b/packages/share_plus/share_plus/example/windows/runner/flutter_window.cpp index 0f0105d995..c0ae50a354 100644 --- a/packages/share_plus/share_plus/example/windows/runner/flutter_window.cpp +++ b/packages/share_plus/share_plus/example/windows/runner/flutter_window.cpp @@ -6,59 +6,64 @@ FlutterWindow::FlutterWindow(RunLoop *run_loop, const flutter::DartProject &project) - : run_loop_(run_loop), project_(project) {} + : run_loop_(run_loop), project_(project) {} FlutterWindow::~FlutterWindow() {} bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } + if (!Win32Window::OnCreate()) { + return false; + } - RECT frame = GetClientArea(); + RECT frame = GetClientArea(); - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - return true; + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; } void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); - flutter_controller_ = nullptr; - } + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } - Win32Window::OnDestroy(); + Win32Window::OnDestroy(); } LRESULT FlutterWindow::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opporutunity to handle window messages. - if (flutter_controller_) { - std::optional result = + LPARAM const lparam) + +noexcept { +// Give Flutter, including plugins, an opporutunity to handle window messages. +if (flutter_controller_) { +std::optional result = flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, lparam); - if (result) { - return *result; - } - } +if (result) { +return * +result; +} +} - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } +switch (message) { +case WM_FONTCHANGE: +flutter_controller_->engine()->ReloadSystemFonts(); +break; +} - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +return +Win32Window::MessageHandler(hwnd, message, wparam, lparam +); } diff --git a/packages/share_plus/share_plus/example/windows/runner/flutter_window.h b/packages/share_plus/share_plus/example/windows/runner/flutter_window.h index 69234d4f5e..da91a8f3f2 100644 --- a/packages/share_plus/share_plus/example/windows/runner/flutter_window.h +++ b/packages/share_plus/share_plus/example/windows/runner/flutter_window.h @@ -12,28 +12,33 @@ // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: - // Creates a new FlutterWindow driven by the |run_loop|, hosting a - // Flutter view running |project|. - explicit FlutterWindow(RunLoop *run_loop, - const flutter::DartProject &project); - virtual ~FlutterWindow(); + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + + virtual ~FlutterWindow(); protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; + // Win32Window: + bool OnCreate() override; + + void OnDestroy() override; + + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) + + noexcept override; private: - // The run loop driving events for this window. - RunLoop *run_loop_; + // The run loop driving events for this window. + RunLoop *run_loop_; - // The project to run. - flutter::DartProject project_; + // The project to run. + flutter::DartProject project_; - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; }; #endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/share_plus/share_plus/example/windows/runner/main.cpp b/packages/share_plus/share_plus/example/windows/runner/main.cpp index fc17fec614..b2218a2c48 100644 --- a/packages/share_plus/share_plus/example/windows/runner/main.cpp +++ b/packages/share_plus/share_plus/example/windows/runner/main.cpp @@ -6,31 +6,45 @@ #include "run_loop.h" #include "utils.h" -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - RunLoop run_loop; - - flutter::DartProject project(L"data"); - FlutterWindow window(&run_loop, project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"example", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - run_loop.Run(); - - ::CoUninitialize(); - return EXIT_SUCCESS; +int APIENTRY +wWinMain(_In_ +HINSTANCE instance, _In_opt_ +HINSTANCE prev, + _In_ +wchar_t *command_line, _In_ +int show_command +) { +// Attach to console when present (e.g., 'flutter run') or create a +// new console when running with a debugger. +if (! +::AttachConsole(ATTACH_PARENT_PROCESS) +&& ::IsDebuggerPresent()) { +CreateAndAttachConsole(); + +} + +// Initialize COM, so that it is available for use in the library and/or +// plugins. +::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED +); + +RunLoop run_loop; + +flutter::DartProject project(L"data"); +FlutterWindow window(&run_loop, project); +Win32Window::Point origin(10, 10); +Win32Window::Size size(1280, 720); +if (!window.CreateAndShow(L"example", origin, size)) { +return +EXIT_FAILURE; +} +window.SetQuitOnClose(true); + +run_loop. + +Run(); + +::CoUninitialize(); +return +EXIT_SUCCESS; } diff --git a/packages/share_plus/share_plus/example/windows/runner/run_loop.cpp b/packages/share_plus/share_plus/example/windows/runner/run_loop.cpp index 31b89f6229..6ee4580c2e 100644 --- a/packages/share_plus/share_plus/example/windows/runner/run_loop.cpp +++ b/packages/share_plus/share_plus/example/windows/runner/run_loop.cpp @@ -9,58 +9,58 @@ RunLoop::RunLoop() {} RunLoop::~RunLoop() {} void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - } } void RunLoop::RegisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.insert(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); } void RunLoop::UnregisterFlutterInstance( - flutter::FlutterEngine *flutter_instance) { - flutter_instances_.erase(flutter_instance); + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); } RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { - TimePoint next_event_time = TimePoint::max(); - for (auto instance : flutter_instances_) { - std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); - if (wait_duration != std::chrono::nanoseconds::max()) { - next_event_time = - std::min(next_event_time, TimePoint::clock::now() + wait_duration); + TimePoint next_event_time = TimePoint::max(); + for (auto instance: flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } } - } - return next_event_time; + return next_event_time; } diff --git a/packages/share_plus/share_plus/example/windows/runner/run_loop.h b/packages/share_plus/share_plus/example/windows/runner/run_loop.h index 7fe1aaccc2..5105e29d76 100644 --- a/packages/share_plus/share_plus/example/windows/runner/run_loop.h +++ b/packages/share_plus/share_plus/example/windows/runner/run_loop.h @@ -10,29 +10,31 @@ // as native messages. class RunLoop { public: - RunLoop(); - ~RunLoop(); + RunLoop(); - // Prevent copying - RunLoop(RunLoop const &) = delete; - RunLoop &operator=(RunLoop const &) = delete; + ~RunLoop(); - // Runs the run loop until the application quits. - void Run(); + // Prevent copying + RunLoop(RunLoop const &) = delete; - // Registers the given Flutter instance for event servicing. - void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + RunLoop &operator=(RunLoop const &) = delete; - // Unregisters the given Flutter instance from event servicing. - void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); private: - using TimePoint = std::chrono::steady_clock::time_point; + using TimePoint = std::chrono::steady_clock::time_point; - // Processes all currently pending messages for registered Flutter instances. - TimePoint ProcessFlutterMessages(); + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); - std::set flutter_instances_; + std::set flutter_instances_; }; #endif // RUNNER_RUN_LOOP_H_ diff --git a/packages/share_plus/share_plus/example/windows/runner/utils.cpp b/packages/share_plus/share_plus/example/windows/runner/utils.cpp index 37501e5db7..9ac126b9aa 100644 --- a/packages/share_plus/share_plus/example/windows/runner/utils.cpp +++ b/packages/share_plus/share_plus/example/windows/runner/utils.cpp @@ -8,15 +8,15 @@ #include void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } } diff --git a/packages/share_plus/share_plus/example/windows/runner/win32_window.cpp b/packages/share_plus/share_plus/example/windows/runner/win32_window.cpp index 9669d7fc6b..d2ac7322dd 100644 --- a/packages/share_plus/share_plus/example/windows/runner/win32_window.cpp +++ b/packages/share_plus/share_plus/example/windows/runner/win32_window.cpp @@ -6,33 +6,36 @@ namespace { -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; // The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; + static int g_active_window_count = 0; -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + using EnableNonClientDpiScaling = + BOOL __stdcall(HWND + hwnd); // Scale helper to convert logical scaler values to physical using passed in // scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} + int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); + } // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. // This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { + void EnableFullDpiSupportIfAvailable(HWND + hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); - } +} +auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); +if (enable_non_client_dpi_scaling != nullptr) { +enable_non_client_dpi_scaling(hwnd); +FreeLibrary(user32_module); +} } } // namespace @@ -40,197 +43,227 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { // Manages the Win32Window's window class registration. class WindowClassRegistrar { public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registar instance. - static WindowClassRegistrar *GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; } - return instance_; - } - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t *GetWindowClass(); + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); private: - WindowClassRegistrar() = default; + WindowClassRegistrar() = default; - static WindowClassRegistrar *instance_; + static WindowClassRegistrar *instance_; - bool class_registered_ = false; + bool class_registered_ = false; }; WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; const wchar_t *WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; } void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; } Win32Window::Win32Window() { ++g_active_window_count; } Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); + --g_active_window_count; + Destroy(); } bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, const Size &size) { - Destroy(); + Destroy(); - const wchar_t *window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); - if (!window) { - return false; - } + if (!window) { + return false; + } - return OnCreate(); + return OnCreate(); } // static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window *that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } +LRESULT CALLBACK +Win32Window::WndProc(HWND +const window, +UINT const message, + WPARAM +const wparam, +LPARAM const lparam +) noexcept { +if (message == WM_NCCREATE) { +auto window_struct = reinterpret_cast(lparam); +SetWindowLongPtr(window, GWLP_USERDATA, +reinterpret_cast +(window_struct +->lpCreateParams)); + +auto that = static_cast(window_struct->lpCreateParams); +EnableFullDpiSupportIfAvailable(window); +that-> +window_handle_ = window; +} else if ( +Win32Window *that = GetThisFromHandle(window) +) { +return that-> +MessageHandler(window, message, wparam, lparam +); +} - return DefWindowProc(window, message, wparam, lparam); +return +DefWindowProc(window, message, wparam, lparam +); } LRESULT -Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; + Win32Window::MessageHandler(HWND +hwnd, +UINT const message, WPARAM +const wparam, +LPARAM const lparam +) noexcept { +switch (message) { +case WM_DESTROY: +window_handle_ = nullptr; + +Destroy(); + +if (quit_on_close_) { +PostQuitMessage(0); +} +return 0; - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - } +case WM_DPICHANGED: { +auto newRectSize = reinterpret_cast(lparam); +LONG newWidth = newRectSize->right - newRectSize->left; +LONG newHeight = newRectSize->bottom - newRectSize->top; + +SetWindowPos(hwnd, nullptr, newRectSize +->left, newRectSize->top, newWidth, +newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - return DefWindowProc(window_handle_, message, wparam, lparam); +return 0; +} +case WM_SIZE: +RECT rect = GetClientArea(); +if (child_content_ != nullptr) { +// Size and position the child window. +MoveWindow(child_content_, rect +.left, rect.top, rect.right - rect.left, +rect.bottom - rect.top, TRUE); +} +return 0; + +case WM_ACTIVATE: +if (child_content_ != nullptr) { +SetFocus(child_content_); +} +return 0; +} + +return +DefWindowProc(window_handle_, message, wparam, lparam +); } void Win32Window::Destroy() { - OnDestroy(); + OnDestroy(); - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } } -Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); +Win32Window *Win32Window::GetThisFromHandle(HWND const window) + +noexcept { +return reinterpret_cast( +GetWindowLongPtr(window, GWLP_USERDATA +)); } -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); +void Win32Window::SetChildContent(HWND +content) { +child_content_ = content; +SetParent(content, window_handle_ +); +RECT frame = GetClientArea(); - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); +MoveWindow(content, frame +.left, frame.top, frame.right - frame.left, +frame.bottom - frame.top, true); - SetFocus(child_content_); +SetFocus(child_content_); } RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; } HWND Win32Window::GetHandle() { return window_handle_; } void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; + quit_on_close_ = quit_on_close; } bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; + // No-op; provided for subclasses. + return true; } void Win32Window::OnDestroy() { - // No-op; provided for subclasses. + // No-op; provided for subclasses. } diff --git a/packages/share_plus/share_plus/example/windows/runner/win32_window.h b/packages/share_plus/share_plus/example/windows/runner/win32_window.h index 7b518125bb..f8b5225436 100644 --- a/packages/share_plus/share_plus/example/windows/runner/win32_window.h +++ b/packages/share_plus/share_plus/example/windows/runner/win32_window.h @@ -12,84 +12,97 @@ // rendering and input handling class Win32Window { public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates and shows a win32 window with |title| and position and size using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring &title, const Point &origin, - const Size &size); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); + struct Point { + unsigned int x; + unsigned int y; -protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); + struct Size { + unsigned int width; + unsigned int height; - // Called when Destroy is called. - virtual void OnDestroy(); + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; -private: - friend class WindowClassRegistrar; + Win32Window(); + + virtual ~Win32Window(); - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); - // Retrieves a class instance pointer for |window| - static Win32Window *GetThisFromHandle(HWND const window) noexcept; + // Release OS resources associated with window. + void Destroy(); - bool quit_on_close_ = false; + // Inserts |content| into the window tree. + void SetChildContent(HWND content); - // window handle for top level window. - HWND window_handle_ = nullptr; + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); - // window handle for hosted content. - HWND child_content_ = nullptr; + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) + + noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK + WndProc(HWND + const window, + UINT const message, + WPARAM + const wparam, + LPARAM const lparam + ) + noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) + + noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; }; #endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/share_plus/share_plus/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m b/packages/share_plus/share_plus/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m index a3afbfa5c3..b6ab68fad6 100644 --- a/packages/share_plus/share_plus/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m +++ b/packages/share_plus/share_plus/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m @@ -8,35 +8,37 @@ static NSString *const PLATFORM_CHANNEL = @"dev.fluttercommunity.plus/share"; static UIViewController *RootViewController(void) { - if (@available(iOS 13, *)) { // UIApplication.keyWindow is deprecated - NSSet *scenes = [[UIApplication sharedApplication] connectedScenes]; - for (UIScene *scene in scenes) { - if ([scene isKindOfClass:[UIWindowScene class]]) { - NSArray *windows = ((UIWindowScene *)scene).windows; - for (UIWindow *window in windows) { - if (window.isKeyWindow) { - return window.rootViewController; - } + if (@available + (iOS + 13, *)) { // UIApplication.keyWindow is deprecated + NSSet *scenes = [[UIApplication sharedApplication] connectedScenes]; + for (UIScene *scene in scenes) { + if ([scene isKindOfClass:[UIWindowScene class]]) { + NSArray *windows = ((UIWindowScene *) scene).windows; + for (UIWindow *window in windows) { + if (window.isKeyWindow) { + return window.rootViewController; + } + } + } } - } + return nil; + } else { + return [UIApplication sharedApplication].keyWindow.rootViewController; } - return nil; - } else { - return [UIApplication sharedApplication].keyWindow.rootViewController; - } } static UIViewController * TopViewControllerForViewController(UIViewController *viewController) { - if (viewController.presentedViewController) { - return TopViewControllerForViewController( - viewController.presentedViewController); - } - if ([viewController isKindOfClass:[UINavigationController class]]) { - return TopViewControllerForViewController( - ((UINavigationController *)viewController).visibleViewController); - } - return viewController; + if (viewController.presentedViewController) { + return TopViewControllerForViewController( + viewController.presentedViewController); + } + if ([viewController isKindOfClass:[UINavigationController class]]) { + return TopViewControllerForViewController( + ((UINavigationController *) viewController).visibleViewController); + } + return viewController; } // We need the companion to avoid ARC deadlock @@ -53,21 +55,21 @@ - (id)initWithResult:(FlutterResult)result; @implementation UIActivityViewSuccessCompanion - (id)initWithResult:(FlutterResult)result { - if (self = [super init]) { - self.result = result; - self.completed = false; - } - return self; + if (self = [super init]) { + self.result = result; + self.completed = false; + } + return self; } // We use dealloc as the share-sheet might disappear (e.g. iCloud photo album // creation) and could then reappear if the user cancels - (void)dealloc { - if (self.completed) { - self.result(self.activityType); - } else { - self.result(@""); - } + if (self.completed) { + self.result(self.activityType); + } else { + self.result(@""); + } } @end @@ -99,343 +101,345 @@ - (instancetype)initWithFile:(NSString *)path subject:(NSString *)subject NS_DESIGNATED_INITIALIZER; - (instancetype)init - __attribute__((unavailable("Use initWithSubject:text: instead"))); +__attribute__((unavailable("Use initWithSubject:text: instead"))); @end @implementation SharePlusData - (instancetype)init { - [super doesNotRecognizeSelector:_cmd]; - return nil; + [super doesNotRecognizeSelector:_cmd]; + return nil; } - (instancetype)initWithSubject:(NSString *)subject text:(NSString *)text { - self = [super init]; - if (self) { - _subject = [subject isKindOfClass:NSNull.class] ? @"" : subject; - _text = text; - } - return self; + self = [super init]; + if (self) { + _subject = [subject isKindOfClass:NSNull.class] ? @"" : subject; + _text = text; + } + return self; } - (instancetype)initWithFile:(NSString *)path mimeType:(NSString *)mimeType { - self = [super init]; - if (self) { - _path = path; - _mimeType = mimeType; - } - return self; + self = [super init]; + if (self) { + _path = path; + _mimeType = mimeType; + } + return self; } - (instancetype)initWithFile:(NSString *)path mimeType:(NSString *)mimeType subject:(NSString *)subject { - self = [super init]; - if (self) { - _path = path; - _mimeType = mimeType; - _subject = [subject isKindOfClass:NSNull.class] ? @"" : subject; - } - return self; + self = [super init]; + if (self) { + _path = path; + _mimeType = mimeType; + _subject = [subject isKindOfClass:NSNull.class] ? @"" : subject; + } + return self; } - (id)activityViewControllerPlaceholderItem: - (UIActivityViewController *)activityViewController { - return [self - activityViewController:activityViewController - itemForActivityType:@"dev.fluttercommunity.share_plus.placeholder"]; + (UIActivityViewController *)activityViewController { + return [self + activityViewController:activityViewController + itemForActivityType:@"dev.fluttercommunity.share_plus.placeholder"]; } - (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(UIActivityType)activityType { - if (!_path || !_mimeType) { - return _text; - } - - // If the shared file is an image return an UIImage for the placeholder - // to show a preview. - if ([activityType - isEqualToString:@"dev.fluttercommunity.share_plus.placeholder"] && - [_mimeType hasPrefix:@"image/"]) { - UIImage *image = [UIImage imageWithContentsOfFile:_path]; - return image; - } + if (!_path || !_mimeType) { + return _text; + } - // Return an NSURL for the real share to conserve the file name - NSURL *url = [NSURL fileURLWithPath:_path]; - return url; + // If the shared file is an image return an UIImage for the placeholder + // to show a preview. + if ([activityType + isEqualToString:@"dev.fluttercommunity.share_plus.placeholder"] && + [_mimeType hasPrefix:@"image/"]) { + UIImage *image = [UIImage imageWithContentsOfFile:_path]; + return image; + } + + // Return an NSURL for the real share to conserve the file name + NSURL *url = [NSURL fileURLWithPath:_path]; + return url; } - (NSString *)activityViewController: - (UIActivityViewController *)activityViewController + (UIActivityViewController *)activityViewController subjectForActivityType:(UIActivityType)activityType { - return _subject; + return _subject; } - (UIImage *)activityViewController: - (UIActivityViewController *)activityViewController + (UIActivityViewController *)activityViewController thumbnailImageForActivityType:(UIActivityType)activityType suggestedSize:(CGSize)suggestedSize { - if (!_path || !_mimeType || ![_mimeType hasPrefix:@"image/"]) { - return nil; - } + if (!_path || !_mimeType || ![_mimeType hasPrefix:@"image/"]) { + return nil; + } - UIImage *image = [UIImage imageWithContentsOfFile:_path]; - return [self imageWithImage:image scaledToSize:suggestedSize]; + UIImage *image = [UIImage imageWithContentsOfFile:_path]; + return [self imageWithImage:image scaledToSize:suggestedSize]; } - (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { - UIGraphicsBeginImageContext(newSize); - [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; - UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return newImage; + UIGraphicsBeginImageContext(newSize); + [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImage; } - (LPLinkMetadata *)activityViewControllerLinkMetadata: - (UIActivityViewController *)activityViewController - API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0)) { - LPLinkMetadata *metadata = [[LPLinkMetadata alloc] init]; - - if ([_subject length] > 0) { - metadata.title = _subject; - } else if ([_text length] > 0) { - metadata.title = _text; - } - - if (_path) { - NSString *extesnion = [_path pathExtension]; - - unsigned long long rawSize = ( - [[[NSFileManager defaultManager] attributesOfItemAtPath:_path - error:nil] fileSize]); - NSString *readableSize = [NSByteCountFormatter - stringFromByteCount:rawSize - countStyle:NSByteCountFormatterCountStyleFile]; - - NSString *description = @""; - - if (![extesnion isEqualToString:@""]) { - description = - [description stringByAppendingString:[extesnion uppercaseString]]; - description = [description stringByAppendingString:@" • "]; - description = [description stringByAppendingString:readableSize]; - } else { - description = [description stringByAppendingString:readableSize]; + (UIActivityViewController *)activityViewController +API_AVAILABLE + +(macos(10.15), ios(13.0), watchos(6.0)) { + LPLinkMetadata *metadata = [[LPLinkMetadata alloc] init]; + + if ([_subject length] > 0) { + metadata.title = _subject; + } else if ([_text length] > 0) { + metadata.title = _text; } - // https://stackoverflow.com/questions/60563773/ios-13-share-sheet-changing-subtitle-item-description - metadata.originalURL = [NSURL fileURLWithPath:description]; - if (_mimeType && [_mimeType hasPrefix:@"image/"]) { - UIImage *image = [UIImage imageWithContentsOfFile:_path]; - metadata.imageProvider = [[NSItemProvider alloc] - initWithObject:[self imageWithImage:image - scaledToSize:CGSizeMake(120, 120)]]; + if (_path) { + NSString *extesnion = [_path pathExtension]; + + unsigned long long rawSize = ( + [[[NSFileManager defaultManager] attributesOfItemAtPath:_path + error:nil] fileSize]); + NSString *readableSize = [NSByteCountFormatter + stringFromByteCount:rawSize + countStyle:NSByteCountFormatterCountStyleFile]; + + NSString *description = @""; + + if (![extesnion isEqualToString:@""]) { + description = + [description stringByAppendingString:[extesnion uppercaseString]]; + description = [description stringByAppendingString:@" • "]; + description = [description stringByAppendingString:readableSize]; + } else { + description = [description stringByAppendingString:readableSize]; + } + + // https://stackoverflow.com/questions/60563773/ios-13-share-sheet-changing-subtitle-item-description + metadata.originalURL = [NSURL fileURLWithPath:description]; + if (_mimeType && [_mimeType hasPrefix:@"image/"]) { + UIImage *image = [UIImage imageWithContentsOfFile:_path]; + metadata.imageProvider = [[NSItemProvider alloc] + initWithObject:[self imageWithImage:image + scaledToSize:CGSizeMake(120, 120)]]; + } } - } - return metadata; + return metadata; } @end @implementation FPPSharePlusPlugin -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *shareChannel = - [FlutterMethodChannel methodChannelWithName:PLATFORM_CHANNEL - binaryMessenger:registrar.messenger]; - - [shareChannel - setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { - NSDictionary *arguments = [call arguments]; - NSNumber *originX = arguments[@"originX"]; - NSNumber *originY = arguments[@"originY"]; - NSNumber *originWidth = arguments[@"originWidth"]; - NSNumber *originHeight = arguments[@"originHeight"]; - - CGRect originRect = CGRectZero; - if (originX && originY && originWidth && originHeight) { - originRect = - CGRectMake([originX doubleValue], [originY doubleValue], - [originWidth doubleValue], [originHeight doubleValue]); - } - - if ([@"share" isEqualToString:call.method]) { - NSString *shareText = arguments[@"text"]; - NSString *shareSubject = arguments[@"subject"]; - - if (shareText.length == 0) { - result([FlutterError errorWithCode:@"error" - message:@"Non-empty text expected" - details:nil]); - return; - } - - UIViewController *rootViewController = RootViewController(); - if (!rootViewController) { - result([FlutterError errorWithCode:@"error" - message:@"No root view controller found" - details:nil]); - return; - } - UIViewController *topViewController = - TopViewControllerForViewController(rootViewController); - - [self shareText:shareText - subject:shareSubject - withController:topViewController - atSource:originRect - toResult:result]; - } else if ([@"shareFiles" isEqualToString:call.method]) { - NSArray *paths = arguments[@"paths"]; - NSArray *mimeTypes = arguments[@"mimeTypes"]; - NSString *subject = arguments[@"subject"]; - NSString *text = arguments[@"text"]; - - if (paths.count == 0) { - result([FlutterError errorWithCode:@"error" - message:@"Non-empty paths expected" - details:nil]); - return; - } - - for (NSString *path in paths) { - if (path.length == 0) { - result([FlutterError errorWithCode:@"error" - message:@"Each path must not be empty" - details:nil]); - return; - } - } - - UIViewController *rootViewController = RootViewController(); - if (!rootViewController) { - result([FlutterError errorWithCode:@"error" - message:@"No root view controller found" - details:nil]); - return; - } - UIViewController *topViewController = - TopViewControllerForViewController(rootViewController); - [self shareFiles:paths - withMimeType:mimeTypes - withSubject:subject - withText:text - withController:topViewController - atSource:originRect - toResult:result]; - } else if ([@"shareUri" isEqualToString:call.method]) { - NSString *uri = arguments[@"uri"]; - - if (uri.length == 0) { - result([FlutterError errorWithCode:@"error" - message:@"Non-empty uri expected" - details:nil]); - return; - } - - UIViewController *rootViewController = RootViewController(); - if (!rootViewController) { - result([FlutterError errorWithCode:@"error" - message:@"No root view controller found" - details:nil]); - return; - } - UIViewController *topViewController = - TopViewControllerForViewController(rootViewController); - - [self shareUri:uri - withController:topViewController - atSource:originRect - toResult:result]; - } else { - result(FlutterMethodNotImplemented); - } - }]; ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *shareChannel = + [FlutterMethodChannel methodChannelWithName:PLATFORM_CHANNEL + binaryMessenger:registrar.messenger]; + + [shareChannel + setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { + NSDictionary *arguments = [call arguments]; + NSNumber *originX = arguments[@"originX"]; + NSNumber *originY = arguments[@"originY"]; + NSNumber *originWidth = arguments[@"originWidth"]; + NSNumber *originHeight = arguments[@"originHeight"]; + + CGRect originRect = CGRectZero; + if (originX && originY && originWidth && originHeight) { + originRect = + CGRectMake([originX doubleValue], [originY doubleValue], + [originWidth doubleValue], [originHeight doubleValue]); + } + + if ([@"share" isEqualToString:call.method]) { + NSString *shareText = arguments[@"text"]; + NSString *shareSubject = arguments[@"subject"]; + + if (shareText.length == 0) { + result([FlutterError errorWithCode:@"error" + message:@"Non-empty text expected" + details:nil]); + return; + } + + UIViewController *rootViewController = RootViewController(); + if (!rootViewController) { + result([FlutterError errorWithCode:@"error" + message:@"No root view controller found" + details:nil]); + return; + } + UIViewController *topViewController = + TopViewControllerForViewController(rootViewController); + + [self shareText:shareText + subject:shareSubject + withController:topViewController + atSource:originRect + toResult:result]; + } else if ([@"shareFiles" isEqualToString:call.method]) { + NSArray *paths = arguments[@"paths"]; + NSArray *mimeTypes = arguments[@"mimeTypes"]; + NSString *subject = arguments[@"subject"]; + NSString *text = arguments[@"text"]; + + if (paths.count == 0) { + result([FlutterError errorWithCode:@"error" + message:@"Non-empty paths expected" + details:nil]); + return; + } + + for (NSString *path in paths) { + if (path.length == 0) { + result([FlutterError errorWithCode:@"error" + message:@"Each path must not be empty" + details:nil]); + return; + } + } + + UIViewController *rootViewController = RootViewController(); + if (!rootViewController) { + result([FlutterError errorWithCode:@"error" + message:@"No root view controller found" + details:nil]); + return; + } + UIViewController *topViewController = + TopViewControllerForViewController(rootViewController); + [self shareFiles:paths + withMimeType:mimeTypes + withSubject:subject + withText:text + withController:topViewController + atSource:originRect + toResult:result]; + } else if ([@"shareUri" isEqualToString:call.method]) { + NSString *uri = arguments[@"uri"]; + + if (uri.length == 0) { + result([FlutterError errorWithCode:@"error" + message:@"Non-empty uri expected" + details:nil]); + return; + } + + UIViewController *rootViewController = RootViewController(); + if (!rootViewController) { + result([FlutterError errorWithCode:@"error" + message:@"No root view controller found" + details:nil]); + return; + } + UIViewController *topViewController = + TopViewControllerForViewController(rootViewController); + + [self shareUri:uri + withController:topViewController + atSource:originRect + toResult:result]; + } else { + result(FlutterMethodNotImplemented); + } + }]; } -+ (void)share:(NSArray *)shareItems - withSubject:(NSString *)subject - withController:(UIViewController *)controller - atSource:(CGRect)origin - toResult:(FlutterResult)result { - UIActivityViewSuccessController *activityViewController = - [[UIActivityViewSuccessController alloc] initWithActivityItems:shareItems - applicationActivities:nil]; - - // Force subject when sharing a raw url or files - if (![subject isKindOfClass:[NSNull class]]) { - [activityViewController setValue:subject forKey:@"subject"]; - } - - activityViewController.popoverPresentationController.sourceView = - controller.view; - BOOL isCoordinateSpaceOfSourceView = - CGRectContainsRect(controller.view.frame, origin); - - // If device is e.g. an iPad then hasPopoverPresentationController is true - BOOL hasPopoverPresentationController = - [activityViewController popoverPresentationController] != NULL; - if (hasPopoverPresentationController && - (!isCoordinateSpaceOfSourceView || CGRectIsEmpty(origin))) { - NSString *sharePositionIssue = [NSString - stringWithFormat: - @"sharePositionOrigin: argument must be set, %@ must be non-zero " - @"and within coordinate space of source view: %@", - NSStringFromCGRect(origin), - NSStringFromCGRect(controller.view.bounds)]; - - result([FlutterError errorWithCode:@"error" - message:sharePositionIssue - details:nil]); - return; - } - - if (!CGRectIsEmpty(origin)) { - activityViewController.popoverPresentationController.sourceRect = origin; - } - - UIActivityViewSuccessCompanion *companion = - [[UIActivityViewSuccessCompanion alloc] initWithResult:result]; - activityViewController.companion = companion; - activityViewController.completionWithItemsHandler = - ^(UIActivityType activityType, BOOL completed, NSArray *returnedItems, - NSError *activityError) { - companion.activityType = activityType; - companion.completed = completed; - }; - - [controller presentViewController:activityViewController - animated:YES - completion:nil]; ++ (void) share:(NSArray *)shareItems + withSubject:(NSString *)subject +withController:(UIViewController *)controller + atSource:(CGRect)origin + toResult:(FlutterResult)result { + UIActivityViewSuccessController *activityViewController = + [[UIActivityViewSuccessController alloc] initWithActivityItems:shareItems + applicationActivities:nil]; + + // Force subject when sharing a raw url or files + if (![subject isKindOfClass:[NSNull class]]) { + [activityViewController setValue:subject forKey:@"subject"]; + } + + activityViewController.popoverPresentationController.sourceView = + controller.view; + BOOL isCoordinateSpaceOfSourceView = + CGRectContainsRect(controller.view.frame, origin); + + // If device is e.g. an iPad then hasPopoverPresentationController is true + BOOL hasPopoverPresentationController = + [activityViewController popoverPresentationController] != NULL; + if (hasPopoverPresentationController && + (!isCoordinateSpaceOfSourceView || CGRectIsEmpty(origin))) { + NSString *sharePositionIssue = [NSString + stringWithFormat: + @"sharePositionOrigin: argument must be set, %@ must be non-zero " + @"and within coordinate space of source view: %@", + NSStringFromCGRect(origin), + NSStringFromCGRect(controller.view.bounds)]; + + result([FlutterError errorWithCode:@"error" + message:sharePositionIssue + details:nil]); + return; + } + + if (!CGRectIsEmpty(origin)) { + activityViewController.popoverPresentationController.sourceRect = origin; + } + + UIActivityViewSuccessCompanion *companion = + [[UIActivityViewSuccessCompanion alloc] initWithResult:result]; + activityViewController.companion = companion; + activityViewController.completionWithItemsHandler = + ^(UIActivityType activityType, BOOL completed, NSArray *returnedItems, + NSError *activityError) { + companion.activityType = activityType; + companion.completed = completed; + }; + + [controller presentViewController:activityViewController + animated:YES + completion:nil]; } + (void)shareUri:(NSString *)uri - withController:(UIViewController *)controller - atSource:(CGRect)origin - toResult:(FlutterResult)result { - NSURL *data = [NSURL URLWithString:uri]; - [self share:@[ data ] - withSubject:nil - withController:controller - atSource:origin - toResult:result]; + withController:(UIViewController *)controller + atSource:(CGRect)origin + toResult:(FlutterResult)result { + NSURL *data = [NSURL URLWithString:uri]; + [self share:@[data] + withSubject:nil + withController:controller + atSource:origin + toResult:result]; } + (void)shareText:(NSString *)shareText - subject:(NSString *)subject - withController:(UIViewController *)controller - atSource:(CGRect)origin - toResult:(FlutterResult)result { - NSObject *data = [[SharePlusData alloc] initWithSubject:subject - text:shareText]; - [self share:@[ data ] - withSubject:subject - withController:controller - atSource:origin - toResult:result]; + subject:(NSString *)subject + withController:(UIViewController *)controller + atSource:(CGRect)origin + toResult:(FlutterResult)result { + NSObject *data = [[SharePlusData alloc] initWithSubject:subject + text:shareText]; + [self share:@[data] + withSubject:subject + withController:controller + atSource:origin + toResult:result]; } + (void)shareFiles:(NSArray *)paths @@ -445,25 +449,25 @@ + (void)shareFiles:(NSArray *)paths withController:(UIViewController *)controller atSource:(CGRect)origin toResult:(FlutterResult)result { - NSMutableArray *items = [[NSMutableArray alloc] init]; - - for (int i = 0; i < [paths count]; i++) { - NSString *path = paths[i]; - NSString *mimeType = mimeTypes[i]; - [items addObject:[[SharePlusData alloc] initWithFile:path - mimeType:mimeType - subject:subject]]; - } - if (text != nil) { - NSObject *data = [[SharePlusData alloc] initWithSubject:subject text:text]; - [items addObject:data]; - } - - [self share:items - withSubject:subject - withController:controller - atSource:origin - toResult:result]; + NSMutableArray *items = [[NSMutableArray alloc] init]; + + for (int i = 0; i < [paths count]; i++) { + NSString *path = paths[i]; + NSString *mimeType = mimeTypes[i]; + [items addObject:[[SharePlusData alloc] initWithFile:path + mimeType:mimeType + subject:subject]]; + } + if (text != nil) { + NSObject *data = [[SharePlusData alloc] initWithSubject:subject text:text]; + [items addObject:data]; + } + + [self share:items + withSubject:subject + withController:controller + atSource:origin + toResult:result]; } @end diff --git a/packages/share_plus/share_plus/lib/share_plus.dart b/packages/share_plus/share_plus/lib/share_plus.dart index e6e2f64a8b..e01098c5bd 100644 --- a/packages/share_plus/share_plus/lib/share_plus.dart +++ b/packages/share_plus/share_plus/lib/share_plus.dart @@ -41,10 +41,7 @@ class Share { Uri uri, { Rect? sharePositionOrigin, }) async { - return _platform.shareUri( - uri, - sharePositionOrigin: sharePositionOrigin, - ); + return _platform.shareUri(uri, sharePositionOrigin: sharePositionOrigin); } /// Summons the platform's share sheet to share text. diff --git a/packages/share_plus/share_plus/lib/src/share_plus_linux.dart b/packages/share_plus/share_plus/lib/src/share_plus_linux.dart index 03132bddc0..88bbbe35ec 100644 --- a/packages/share_plus/share_plus/lib/src/share_plus_linux.dart +++ b/packages/share_plus/share_plus/lib/src/share_plus_linux.dart @@ -26,7 +26,8 @@ class SharePlusLinuxPlugin extends SharePlatform { Rect? sharePositionOrigin, }) async { throw UnimplementedError( - 'shareUri() has not been implemented on Linux. Use share().'); + 'shareUri() has not been implemented on Linux. Use share().', + ); } /// Share text. @@ -45,8 +46,10 @@ class SharePlusLinuxPlugin extends SharePlatform { final uri = Uri( scheme: 'mailto', query: queryParameters.entries - .map((e) => - '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}') + .map( + (e) => + '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}', + ) .join('&'), ); diff --git a/packages/share_plus/share_plus/lib/src/share_plus_web.dart b/packages/share_plus/share_plus/lib/src/share_plus_web.dart index d0456d327c..704e661bf2 100644 --- a/packages/share_plus/share_plus/lib/src/share_plus_web.dart +++ b/packages/share_plus/share_plus/lib/src/share_plus_web.dart @@ -30,22 +30,14 @@ class SharePlusWebPlugin extends SharePlatform { }) : _navigator = debugNavigator ?? window.navigator; @override - Future shareUri( - Uri uri, { - Rect? sharePositionOrigin, - }) async { - final data = ShareData( - url: uri.toString(), - ); + Future shareUri(Uri uri, {Rect? sharePositionOrigin}) async { + final data = ShareData(url: uri.toString()); final bool canShare; try { canShare = _navigator.canShare(data); } on NoSuchMethodError catch (e) { - developer.log( - 'Share API is not supported in this User Agent.', - error: e, - ); + developer.log('Share API is not supported in this User Agent.', error: e); throw Exception('Navigator.canShare() is unavailable'); } @@ -61,10 +53,7 @@ class SharePlusWebPlugin extends SharePlatform { return _resultDismissed; } - developer.log( - 'Failed to share uri', - error: '${e.name}: ${e.message}', - ); + developer.log('Failed to share uri', error: '${e.name}: ${e.message}'); throw Exception('Navigator.share() failed: ${e.message}'); } @@ -80,24 +69,16 @@ class SharePlusWebPlugin extends SharePlatform { }) async { final ShareData data; if (subject != null && subject.isNotEmpty) { - data = ShareData( - title: subject, - text: text, - ); + data = ShareData(title: subject, text: text); } else { - data = ShareData( - text: text, - ); + data = ShareData(text: text); } final bool canShare; try { canShare = _navigator.canShare(data); } on NoSuchMethodError catch (e) { - developer.log( - 'Share API is not supported in this User Agent.', - error: e, - ); + developer.log('Share API is not supported in this User Agent.', error: e); // Navigator is not available or the webPage is not served on https final queryParameters = { @@ -109,8 +90,10 @@ class SharePlusWebPlugin extends SharePlatform { final uri = Uri( scheme: 'mailto', query: queryParameters.entries - .map((e) => - '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}') + .map( + (e) => + '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}', + ) .join('&'), ); @@ -139,10 +122,7 @@ class SharePlusWebPlugin extends SharePlatform { return _resultDismissed; } - developer.log( - 'Failed to share text', - error: '${e.name}: ${e.message}', - ); + developer.log('Failed to share text', error: '${e.name}: ${e.message}'); throw Exception('Navigator.share() failed: ${e.message}'); } @@ -163,7 +143,8 @@ class SharePlusWebPlugin extends SharePlatform { List? fileNameOverrides, }) async { assert( - fileNameOverrides == null || files.length == fileNameOverrides.length); + fileNameOverrides == null || files.length == fileNameOverrides.length, + ); final webFiles = []; for (var index = 0; index < files.length; index++) { final xFile = files[index]; @@ -174,36 +155,21 @@ class SharePlusWebPlugin extends SharePlatform { final ShareData data; if (text != null && text.isNotEmpty) { if (subject != null && subject.isNotEmpty) { - data = ShareData( - files: webFiles.toJS, - text: text, - title: subject, - ); + data = ShareData(files: webFiles.toJS, text: text, title: subject); } else { - data = ShareData( - files: webFiles.toJS, - text: text, - ); + data = ShareData(files: webFiles.toJS, text: text); } } else if (subject != null && subject.isNotEmpty) { - data = ShareData( - files: webFiles.toJS, - title: subject, - ); + data = ShareData(files: webFiles.toJS, title: subject); } else { - data = ShareData( - files: webFiles.toJS, - ); + data = ShareData(files: webFiles.toJS); } final bool canShare; try { canShare = _navigator.canShare(data); } on NoSuchMethodError catch (e) { - developer.log( - 'Share API is not supported in this User Agent.', - error: e, - ); + developer.log('Share API is not supported in this User Agent.', error: e); return _downloadIfFallbackEnabled( files, @@ -263,10 +229,11 @@ class SharePlusWebPlugin extends SharePlatform { for (final (index, file) in files.indexed) { final bytes = await file.readAsBytes(); - final anchor = document.createElement('a') as HTMLAnchorElement - ..href = Uri.dataFromBytes(bytes).toString() - ..style.display = 'none' - ..download = fileNameOverrides?.elementAt(index) ?? file.name; + final anchor = + document.createElement('a') as HTMLAnchorElement + ..href = Uri.dataFromBytes(bytes).toString() + ..style.display = 'none' + ..download = fileNameOverrides?.elementAt(index) ?? file.name; document.body!.children.add(anchor); anchor.click(); anchor.remove(); @@ -294,7 +261,4 @@ class SharePlusWebPlugin extends SharePlatform { } } -const _resultDismissed = ShareResult( - '', - ShareResultStatus.dismissed, -); +const _resultDismissed = ShareResult('', ShareResultStatus.dismissed); diff --git a/packages/share_plus/share_plus/lib/src/share_plus_windows.dart b/packages/share_plus/share_plus/lib/src/share_plus_windows.dart index 5a660e4763..e8da5ac8c3 100644 --- a/packages/share_plus/share_plus/lib/src/share_plus_windows.dart +++ b/packages/share_plus/share_plus/lib/src/share_plus_windows.dart @@ -31,7 +31,8 @@ class SharePlusWindowsPlugin extends SharePlatform { Rect? sharePositionOrigin, }) async { throw UnimplementedError( - 'shareUri() has not been implemented on Windows. Use share().'); + 'shareUri() has not been implemented on Windows. Use share().', + ); } /// Share text. @@ -50,8 +51,10 @@ class SharePlusWindowsPlugin extends SharePlatform { final uri = Uri( scheme: 'mailto', query: queryParameters.entries - .map((e) => - '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}') + .map( + (e) => + '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}', + ) .join('&'), ); diff --git a/packages/share_plus/share_plus/lib/src/windows_version_helper.dart b/packages/share_plus/share_plus/lib/src/windows_version_helper.dart index db0ee5aff8..a8281730a8 100644 --- a/packages/share_plus/share_plus/lib/src/windows_version_helper.dart +++ b/packages/share_plus/share_plus/lib/src/windows_version_helper.dart @@ -32,8 +32,9 @@ class VersionHelper { ..wProductType = 0 ..wReserved = 0; final rtlGetVersion = DynamicLibrary.open('ntdll.dll').lookupFunction< - Void Function(Pointer), - void Function(Pointer)>('RtlGetVersion'); + Void Function(Pointer), + void Function(Pointer) + >('RtlGetVersion'); rtlGetVersion(pointer); isWindows10RS5OrGreater = pointer.ref.dwBuildNumber >= kWindows10RS5BuildNumber; diff --git a/packages/share_plus/share_plus/test/share_plus_linux_test.dart b/packages/share_plus/share_plus/test/share_plus_linux_test.dart index 28fc82c00d..f49ea36119 100644 --- a/packages/share_plus/share_plus/test/share_plus_linux_test.dart +++ b/packages/share_plus/share_plus/test/share_plus_linux_test.dart @@ -30,7 +30,9 @@ void main() { final mock = MockUrlLauncherPlatform(); mock.canLaunchMockValue = false; - expect(() async => await SharePlusLinuxPlugin(mock).share('foo bar'), - throwsException); + expect( + () async => await SharePlusLinuxPlugin(mock).share('foo bar'), + throwsException, + ); }); } diff --git a/packages/share_plus/share_plus/test/share_plus_windows_test.dart b/packages/share_plus/share_plus/test/share_plus_windows_test.dart index 5701d93c54..58a252126c 100644 --- a/packages/share_plus/share_plus/test/share_plus_windows_test.dart +++ b/packages/share_plus/share_plus/test/share_plus_windows_test.dart @@ -7,23 +7,15 @@ import 'package:share_plus_platform_interface/share_plus_platform_interface.dart import 'url_launcher_mock.dart'; void main() { - test( - 'registered instance', - () { - SharePlusWindowsPlugin.registerWith(); - expect(SharePlatform.instance, isA()); - }, - skip: VersionHelper.instance.isWindows10RS5OrGreater, - ); + test('registered instance', () { + SharePlusWindowsPlugin.registerWith(); + expect(SharePlatform.instance, isA()); + }, skip: VersionHelper.instance.isWindows10RS5OrGreater); - test( - 'registered instance', - () { - SharePlusWindowsPlugin.registerWith(); - expect(SharePlatform.instance, isA()); - }, - skip: !VersionHelper.instance.isWindows10RS5OrGreater, - ); + test('registered instance', () { + SharePlusWindowsPlugin.registerWith(); + expect(SharePlatform.instance, isA()); + }, skip: !VersionHelper.instance.isWindows10RS5OrGreater); // These tests are only valid on Windows versions lower than 10.0.17763.0. @@ -58,8 +50,10 @@ void main() { final mock = MockUrlLauncherPlatform(); mock.canLaunchMockValue = false; - expect(() async => await SharePlusWindowsPlugin(mock).share('foo bar'), - throwsException); + expect( + () async => await SharePlusWindowsPlugin(mock).share('foo bar'), + throwsException, + ); }, skip: VersionHelper.instance.isWindows10RS5OrGreater, ); diff --git a/packages/share_plus/share_plus/windows/CMakeLists.txt b/packages/share_plus/share_plus/windows/CMakeLists.txt index de33928673..675c5a2d0e 100644 --- a/packages/share_plus/share_plus/windows/CMakeLists.txt +++ b/packages/share_plus/share_plus/windows/CMakeLists.txt @@ -14,16 +14,16 @@ set(PLUGIN_NAME "share_plus_plugin") # Any new source files that you add to the plugin should be added here. list(APPEND PLUGIN_SOURCES - "share_plus_plugin.cpp" - "share_plus_windows_plugin.h" + "share_plus_plugin.cpp" + "share_plus_windows_plugin.h" ) # Define the plugin library target. Its name must not be changed (see comment # on PLUGIN_NAME above). add_library(${PLUGIN_NAME} SHARED - "include/share_plus/share_plus_windows_plugin_c_api.h" - "share_plus_plugin_c_api.cpp" - ${PLUGIN_SOURCES} + "include/share_plus/share_plus_windows_plugin_c_api.h" + "share_plus_plugin_c_api.cpp" + ${PLUGIN_SOURCES} ) # Apply a standard set of build settings that are configured in the @@ -35,19 +35,19 @@ apply_standard_settings(${PLUGIN_NAME}) # between plugins. This should not be removed; any symbols that should be # exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. set_target_properties(${PLUGIN_NAME} PROPERTIES - CXX_VISIBILITY_PRESET hidden) + CXX_VISIBILITY_PRESET hidden) target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) # Source include directories and library dependencies. Add any plugin-specific # dependencies here. target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") + "${CMAKE_CURRENT_SOURCE_DIR}/include") target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an # external build triggered from this build file. set(share_plus_bundled_libraries - "" - PARENT_SCOPE + "" + PARENT_SCOPE ) diff --git a/packages/share_plus/share_plus/windows/include/share_plus/share_plus_windows_plugin_c_api.h b/packages/share_plus/share_plus/windows/include/share_plus/share_plus_windows_plugin_c_api.h index 760ce9a727..a44d63ae44 100644 --- a/packages/share_plus/share_plus/windows/include/share_plus/share_plus_windows_plugin_c_api.h +++ b/packages/share_plus/share_plus/windows/include/share_plus/share_plus_windows_plugin_c_api.h @@ -14,7 +14,7 @@ extern "C" { #endif FLUTTER_PLUGIN_EXPORT void SharePlusWindowsPluginCApiRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar); + FlutterDesktopPluginRegistrarRef registrar); #if defined(__cplusplus) } // extern "C" diff --git a/packages/share_plus/share_plus/windows/share_plus_plugin.cpp b/packages/share_plus/share_plus/windows/share_plus_plugin.cpp index 4fff212571..669194b78e 100644 --- a/packages/share_plus/share_plus/windows/share_plus_plugin.cpp +++ b/packages/share_plus/share_plus/windows/share_plus_plugin.cpp @@ -8,248 +8,248 @@ namespace share_plus_windows { -void SharePlusWindowsPlugin::RegisterWithRegistrar( - flutter::PluginRegistrarWindows *registrar) { - auto channel = - std::make_unique>( - registrar->messenger(), kSharePlusChannelName, - &flutter::StandardMethodCodec::GetInstance()); - auto plugin = std::make_unique(registrar); - channel->SetMethodCallHandler( - [plugin_pointer = plugin.get()](const auto &call, auto result) { - plugin_pointer->HandleMethodCall(call, std::move(result)); - }); + void SharePlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + auto channel = + std::make_unique < flutter::MethodChannel < flutter::EncodableValue >> ( + registrar->messenger(), kSharePlusChannelName, + &flutter::StandardMethodCodec::GetInstance()); + auto plugin = std::make_unique(registrar); + channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); - registrar->AddPlugin(std::move(plugin)); -} - -SharePlusWindowsPlugin::SharePlusWindowsPlugin( - flutter::PluginRegistrarWindows *registrar) - : registrar_(registrar) {} - -SharePlusWindowsPlugin::~SharePlusWindowsPlugin() { - if (data_transfer_manager_ != nullptr) { - data_transfer_manager_->remove_DataRequested(data_transfer_manager_token_); - data_transfer_manager_.Reset(); - } - if (data_transfer_manager_interop_ != nullptr) { - data_transfer_manager_interop_.Reset(); - } -} - -HWND SharePlusWindowsPlugin::GetWindow() { - return ::GetAncestor(registrar_->GetView()->GetNativeWindow(), GA_ROOT); -} + registrar->AddPlugin(std::move(plugin)); + } -WRL::ComPtr -SharePlusWindowsPlugin::GetDataTransferManager() { - using Microsoft::WRL::Wrappers::HStringReference; - ::RoGetActivationFactory( - HStringReference( - RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager) - .Get(), - IID_PPV_ARGS(&data_transfer_manager_interop_)); - data_transfer_manager_interop_->GetForWindow( - GetWindow(), IID_PPV_ARGS(&data_transfer_manager_)); - return data_transfer_manager_; -} + SharePlusWindowsPlugin::SharePlusWindowsPlugin( + flutter::PluginRegistrarWindows *registrar) + : registrar_(registrar) {} -HRESULT SharePlusWindowsPlugin::GetStorageFileFromPath( - wchar_t *path, WindowsStorage::IStorageFile **file) { - using Microsoft::WRL::Wrappers::HStringReference; - WRL::ComPtr factory = nullptr; - HRESULT hr = S_OK; - *file = nullptr; - if (!factory) { - hr = WindowsFoundation::GetActivationFactory( - HStringReference(RuntimeClass_Windows_Storage_StorageFile).Get(), - &factory); - } - if (SUCCEEDED(hr)) { - WRL::ComPtr< - WindowsFoundation::IAsyncOperation> - async_operation; - hr = factory->GetFileFromPathAsync(HStringReference(path).Get(), - &async_operation); - if (SUCCEEDED(hr)) { - WRL::ComPtr info; - hr = async_operation.As(&info); - if (SUCCEEDED(hr)) { - AsyncStatus status; - while (SUCCEEDED(hr = info->get_Status(&status)) && - status == AsyncStatus::Started) - SleepEx(0, TRUE); - if (FAILED(hr) || status != AsyncStatus::Completed) { - info->get_ErrorCode(&hr); - } else { - async_operation->GetResults(file); + SharePlusWindowsPlugin::~SharePlusWindowsPlugin() { + if (data_transfer_manager_ != nullptr) { + data_transfer_manager_->remove_DataRequested(data_transfer_manager_token_); + data_transfer_manager_.Reset(); + } + if (data_transfer_manager_interop_ != nullptr) { + data_transfer_manager_interop_.Reset(); } - } } - } - return hr; -} -void SharePlusWindowsPlugin::HandleMethodCall( - const flutter::MethodCall &method_call, - std::unique_ptr> result) { - if (method_call.method_name().compare(kShare) == 0) { - auto data_transfer_manager = GetDataTransferManager(); - auto args = std::get(*method_call.arguments()); - if (auto text_value = - std::get_if(&args[flutter::EncodableValue("text")])) { - share_text_ = *text_value; - } - if (auto subject_value = std::get_if( - &args[flutter::EncodableValue("subject")])) { - share_subject_ = *subject_value; + HWND SharePlusWindowsPlugin::GetWindow() { + return ::GetAncestor(registrar_->GetView()->GetNativeWindow(), GA_ROOT); } - auto callback = WRL::Callback>( - [&](auto &&, DataTransfer::IDataRequestedEventArgs *e) { - using Microsoft::WRL::Wrappers::HStringReference; - WRL::ComPtr request; - e->get_Request(&request); - WRL::ComPtr data; - request->get_Data(&data); - WRL::ComPtr properties; - data->get_Properties(&properties); - // The title is mandatory for Windows. - // Using |share_text_| as title. - auto text = Utf16FromUtf8(share_text_); - properties->put_Title(HStringReference(text.c_str()).Get()); - // If |share_subject_| is available, then set it as text since - // |share_text_| is already set as title. - if (share_subject_ && !share_subject_.value_or("").empty()) { - auto subject = Utf16FromUtf8(share_subject_.value_or("")); - properties->put_Description( - HStringReference(subject.c_str()).Get()); - data->SetText(HStringReference(subject.c_str()).Get()); - } - // If |share_subject_| is not available, then use |share_text_| as - // text aswell. - else { - data->SetText(HStringReference(text.c_str()).Get()); - } - return S_OK; - }); - data_transfer_manager->add_DataRequested(callback.Get(), - &data_transfer_manager_token_); - if (data_transfer_manager_interop_ != nullptr) { - data_transfer_manager_interop_->ShowShareUIForWindow(GetWindow()); - } - result->Success(flutter::EncodableValue(kShareResultUnavailable)); - } else if (method_call.method_name().compare(kShareFiles) == 0) { - auto data_transfer_manager = GetDataTransferManager(); - auto args = std::get(*method_call.arguments()); - if (auto text_value = - std::get_if(&args[flutter::EncodableValue("text")])) { - share_text_ = *text_value; - } - if (auto subject_value = std::get_if( - &args[flutter::EncodableValue("subject")])) { - share_subject_ = *subject_value; - } - if (auto paths = std::get_if( - &args[flutter::EncodableValue("paths")])) { - paths_.clear(); - for (auto &path : *paths) { - paths_.emplace_back(std::get(path)); - } + + WRL::ComPtr + SharePlusWindowsPlugin::GetDataTransferManager() { + using Microsoft::WRL::Wrappers::HStringReference; + ::RoGetActivationFactory( + HStringReference( + RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager) + .Get(), + IID_PPV_ARGS(&data_transfer_manager_interop_)); + data_transfer_manager_interop_->GetForWindow( + GetWindow(), IID_PPV_ARGS(&data_transfer_manager_)); + return data_transfer_manager_; } - if (auto mime_types = std::get_if( - &args[flutter::EncodableValue("mimeTypes")])) { - mime_types_.clear(); - for (auto &mime_type : *mime_types) { - mime_types_.emplace_back(std::get(mime_type)); - } + + HRESULT SharePlusWindowsPlugin::GetStorageFileFromPath( + wchar_t *path, WindowsStorage::IStorageFile **file) { + using Microsoft::WRL::Wrappers::HStringReference; + WRL::ComPtr factory = nullptr; + HRESULT hr = S_OK; + *file = nullptr; + if (!factory) { + hr = WindowsFoundation::GetActivationFactory( + HStringReference(RuntimeClass_Windows_Storage_StorageFile).Get(), + &factory); + } + if (SUCCEEDED(hr)) { + WRL::ComPtr < + WindowsFoundation::IAsyncOperation> + async_operation; + hr = factory->GetFileFromPathAsync(HStringReference(path).Get(), + &async_operation); + if (SUCCEEDED(hr)) { + WRL::ComPtr info; + hr = async_operation.As(&info); + if (SUCCEEDED(hr)) { + AsyncStatus status; + while (SUCCEEDED(hr = info->get_Status(&status)) && + status == AsyncStatus::Started) + SleepEx(0, TRUE); + if (FAILED(hr) || status != AsyncStatus::Completed) { + info->get_ErrorCode(&hr); + } else { + async_operation->GetResults(file); + } + } + } + } + return hr; } - auto callback = WRL::Callback>( - [&](auto &&, DataTransfer::IDataRequestedEventArgs *e) { - using Microsoft::WRL::Wrappers::HStringReference; - WRL::ComPtr request; - e->get_Request(&request); - WRL::ComPtr data; - request->get_Data(&data); - WRL::ComPtr properties; - data->get_Properties(&properties); - // The title is mandatory for Windows. - // Using |share_text_| as title if available. - if (!share_text_.empty()) { - auto text = Utf16FromUtf8(share_text_); - properties->put_Title(HStringReference(text.c_str()).Get()); - } - // Or use the file count string as title if there are multiple - // files & use the file name if a single file is shared. - // Same behavior may be seen in File Explorer. - else { - if (paths_.size() > 1) { - auto title = std::to_wstring(paths_.size()) + L" files"; - properties->put_Title(HStringReference(title.c_str()).Get()); - } else if (paths_.size() == 1) { - auto title = Utf16FromUtf8(paths_.front()); - properties->put_Title(HStringReference(title.c_str()).Get()); + + void SharePlusWindowsPlugin::HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr > result) { + if (method_call.method_name().compare(kShare) == 0) { + auto data_transfer_manager = GetDataTransferManager(); + auto args = std::get(*method_call.arguments()); + if (auto text_value = + std::get_if(&args[flutter::EncodableValue("text")])) { + share_text_ = *text_value; + } + if (auto subject_value = std::get_if( + &args[flutter::EncodableValue("subject")])) { + share_subject_ = *subject_value; + } + auto callback = WRL::Callback < WindowsFoundation::ITypedEventHandler < + DataTransfer::DataTransferManager *, + DataTransfer::DataRequestedEventArgs * >> ( + [&](auto &&, DataTransfer::IDataRequestedEventArgs *e) { + using Microsoft::WRL::Wrappers::HStringReference; + WRL::ComPtr request; + e->get_Request(&request); + WRL::ComPtr data; + request->get_Data(&data); + WRL::ComPtr properties; + data->get_Properties(&properties); + // The title is mandatory for Windows. + // Using |share_text_| as title. + auto text = Utf16FromUtf8(share_text_); + properties->put_Title(HStringReference(text.c_str()).Get()); + // If |share_subject_| is available, then set it as text since + // |share_text_| is already set as title. + if (share_subject_ && !share_subject_.value_or("").empty()) { + auto subject = Utf16FromUtf8(share_subject_.value_or("")); + properties->put_Description( + HStringReference(subject.c_str()).Get()); + data->SetText(HStringReference(subject.c_str()).Get()); + } + // If |share_subject_| is not available, then use |share_text_| as + // text aswell. + else { + data->SetText(HStringReference(text.c_str()).Get()); + } + return S_OK; + }); + data_transfer_manager->add_DataRequested(callback.Get(), + &data_transfer_manager_token_); + if (data_transfer_manager_interop_ != nullptr) { + data_transfer_manager_interop_->ShowShareUIForWindow(GetWindow()); + } + result->Success(flutter::EncodableValue(kShareResultUnavailable)); + } else if (method_call.method_name().compare(kShareFiles) == 0) { + auto data_transfer_manager = GetDataTransferManager(); + auto args = std::get(*method_call.arguments()); + if (auto text_value = + std::get_if(&args[flutter::EncodableValue("text")])) { + share_text_ = *text_value; + } + if (auto subject_value = std::get_if( + &args[flutter::EncodableValue("subject")])) { + share_subject_ = *subject_value; + } + if (auto paths = std::get_if( + &args[flutter::EncodableValue("paths")])) { + paths_.clear(); + for (auto &path: *paths) { + paths_.emplace_back(std::get(path)); + } } - } - // If |share_subject_| is available, then set it as text since - // |share_text_| is already set as title. - if (share_subject_ && !share_subject_.value_or("").empty()) { - auto subject = Utf16FromUtf8(share_subject_.value_or("")); - properties->put_Description( - HStringReference(subject.c_str()).Get()); - data->SetText(HStringReference(subject.c_str()).Get()); - } - // If |share_subject_| is not available, then use |share_text_| as - // text aswell. - else if (!share_text_.empty()) { - auto text = Utf16FromUtf8(share_text_); - data->SetText(HStringReference(text.c_str()).Get()); - } - // Add files to the data. - Vector storage_items; - for (const std::string &path : paths_) { - auto str = Utf16FromUtf8(path); - wchar_t *ptr = const_cast(str.c_str()); - WindowsStorage::IStorageFile *file = nullptr; - if (SUCCEEDED(GetStorageFileFromPath(ptr, &file)) && - file != nullptr) { - storage_items.Append( - reinterpret_cast(file)); + if (auto mime_types = std::get_if( + &args[flutter::EncodableValue("mimeTypes")])) { + mime_types_.clear(); + for (auto &mime_type: *mime_types) { + mime_types_.emplace_back(std::get(mime_type)); + } } - } - data->SetStorageItemsReadOnly(&storage_items); - return S_OK; - }); - data_transfer_manager->add_DataRequested(callback.Get(), - &data_transfer_manager_token_); - if (data_transfer_manager_interop_ != nullptr) { - data_transfer_manager_interop_->ShowShareUIForWindow(GetWindow()); + auto callback = WRL::Callback < WindowsFoundation::ITypedEventHandler < + DataTransfer::DataTransferManager *, + DataTransfer::DataRequestedEventArgs * >> ( + [&](auto &&, DataTransfer::IDataRequestedEventArgs *e) { + using Microsoft::WRL::Wrappers::HStringReference; + WRL::ComPtr request; + e->get_Request(&request); + WRL::ComPtr data; + request->get_Data(&data); + WRL::ComPtr properties; + data->get_Properties(&properties); + // The title is mandatory for Windows. + // Using |share_text_| as title if available. + if (!share_text_.empty()) { + auto text = Utf16FromUtf8(share_text_); + properties->put_Title(HStringReference(text.c_str()).Get()); + } + // Or use the file count string as title if there are multiple + // files & use the file name if a single file is shared. + // Same behavior may be seen in File Explorer. + else { + if (paths_.size() > 1) { + auto title = std::to_wstring(paths_.size()) + L" files"; + properties->put_Title(HStringReference(title.c_str()).Get()); + } else if (paths_.size() == 1) { + auto title = Utf16FromUtf8(paths_.front()); + properties->put_Title(HStringReference(title.c_str()).Get()); + } + } + // If |share_subject_| is available, then set it as text since + // |share_text_| is already set as title. + if (share_subject_ && !share_subject_.value_or("").empty()) { + auto subject = Utf16FromUtf8(share_subject_.value_or("")); + properties->put_Description( + HStringReference(subject.c_str()).Get()); + data->SetText(HStringReference(subject.c_str()).Get()); + } + // If |share_subject_| is not available, then use |share_text_| as + // text aswell. + else if (!share_text_.empty()) { + auto text = Utf16FromUtf8(share_text_); + data->SetText(HStringReference(text.c_str()).Get()); + } + // Add files to the data. + Vector storage_items; + for (const std::string &path: paths_) { + auto str = Utf16FromUtf8(path); + wchar_t *ptr = const_cast(str.c_str()); + WindowsStorage::IStorageFile *file = nullptr; + if (SUCCEEDED(GetStorageFileFromPath(ptr, &file)) && + file != nullptr) { + storage_items.Append( + reinterpret_cast(file)); + } + } + data->SetStorageItemsReadOnly(&storage_items); + return S_OK; + }); + data_transfer_manager->add_DataRequested(callback.Get(), + &data_transfer_manager_token_); + if (data_transfer_manager_interop_ != nullptr) { + data_transfer_manager_interop_->ShowShareUIForWindow(GetWindow()); + } + result->Success(flutter::EncodableValue(kShareResultUnavailable)); + } else { + result->NotImplemented(); + } } - result->Success(flutter::EncodableValue(kShareResultUnavailable)); - } else { - result->NotImplemented(); - } -} // Converts string encoded in UTF-8 to wstring. // Returns an empty |std::wstring| on failure. // Present as static helper method. -std::wstring SharePlusWindowsPlugin::Utf16FromUtf8(std::string string) { - int size_needed = - MultiByteToWideChar(CP_UTF8, 0, string.c_str(), -1, NULL, 0); - if (size_needed == 0) { - return std::wstring(); - } - std::wstring result(size_needed, 0); - int converted_length = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), -1, - &result[0], size_needed); - if (converted_length == 0) { - return std::wstring(); - } - return result; -} + std::wstring SharePlusWindowsPlugin::Utf16FromUtf8(std::string string) { + int size_needed = + MultiByteToWideChar(CP_UTF8, 0, string.c_str(), -1, NULL, 0); + if (size_needed == 0) { + return std::wstring(); + } + std::wstring result(size_needed, 0); + int converted_length = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), -1, + &result[0], size_needed); + if (converted_length == 0) { + return std::wstring(); + } + return result; + } } // namespace share_plus_windows diff --git a/packages/share_plus/share_plus/windows/share_plus_plugin_c_api.cpp b/packages/share_plus/share_plus/windows/share_plus_plugin_c_api.cpp index b33c00f915..4c5b97b5e9 100644 --- a/packages/share_plus/share_plus/windows/share_plus_plugin_c_api.cpp +++ b/packages/share_plus/share_plus/windows/share_plus_plugin_c_api.cpp @@ -5,8 +5,8 @@ #include "share_plus_windows_plugin.h" void SharePlusWindowsPluginCApiRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar) { - share_plus_windows::SharePlusWindowsPlugin::RegisterWithRegistrar( - flutter::PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar)); + FlutterDesktopPluginRegistrarRef registrar) { + share_plus_windows::SharePlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); } diff --git a/packages/share_plus/share_plus/windows/share_plus_windows_plugin.h b/packages/share_plus/share_plus/windows/share_plus_windows_plugin.h index 848be0091f..d82c09c92e 100644 --- a/packages/share_plus/share_plus/windows/share_plus_windows_plugin.h +++ b/packages/share_plus/share_plus/windows/share_plus_windows_plugin.h @@ -26,55 +26,56 @@ namespace DataTransfer = ABI::Windows::ApplicationModel::DataTransfer; namespace share_plus_windows { -class SharePlusWindowsPlugin : public flutter::Plugin { -public: - static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + class SharePlusWindowsPlugin : public flutter::Plugin { + public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); - SharePlusWindowsPlugin(flutter::PluginRegistrarWindows *registrar); + SharePlusWindowsPlugin(flutter::PluginRegistrarWindows *registrar); - virtual ~SharePlusWindowsPlugin(); + virtual ~SharePlusWindowsPlugin(); - SharePlusWindowsPlugin(const SharePlusWindowsPlugin &) = delete; - SharePlusWindowsPlugin &operator=(const SharePlusWindowsPlugin &) = delete; + SharePlusWindowsPlugin(const SharePlusWindowsPlugin &) = delete; -private: - static constexpr auto kSharePlusChannelName = - "dev.fluttercommunity.plus/share"; + SharePlusWindowsPlugin &operator=(const SharePlusWindowsPlugin &) = delete; - static constexpr auto kShareResultUnavailable = - "dev.fluttercommunity.plus/share/unavailable"; + private: + static constexpr auto kSharePlusChannelName = + "dev.fluttercommunity.plus/share"; - static constexpr auto kShare = "share"; - static constexpr auto kShareFiles = "shareFiles"; + static constexpr auto kShareResultUnavailable = + "dev.fluttercommunity.plus/share/unavailable"; - HWND GetWindow(); + static constexpr auto kShare = "share"; + static constexpr auto kShareFiles = "shareFiles"; - WRL::ComPtr GetDataTransferManager(); + HWND GetWindow(); - void HandleMethodCall( - const flutter::MethodCall &method_call, - std::unique_ptr> result); + WRL::ComPtr GetDataTransferManager(); - static HRESULT GetStorageFileFromPath(wchar_t *path, - WindowsStorage::IStorageFile **file); + void HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr > result); - static std::wstring SharePlusWindowsPlugin::Utf16FromUtf8(std::string string); + static HRESULT GetStorageFileFromPath(wchar_t *path, + WindowsStorage::IStorageFile **file); - flutter::PluginRegistrarWindows *registrar_ = nullptr; - WRL::ComPtr data_transfer_manager_interop_ = - nullptr; - WRL::ComPtr data_transfer_manager_ = - nullptr; - EventRegistrationToken data_transfer_manager_token_; + static std::wstring SharePlusWindowsPlugin::Utf16FromUtf8(std::string string); - // Present here to keep |std::string| in memory until data request callback - // from |IDataTransferManager| takes place. - // Subsequent calls on the platform channel will overwrite the existing value. - std::string share_text_ = ""; - std::optional share_subject_ = std::nullopt; - std::vector paths_ = {}; - std::vector mime_types_ = {}; -}; + flutter::PluginRegistrarWindows *registrar_ = nullptr; + WRL::ComPtr data_transfer_manager_interop_ = + nullptr; + WRL::ComPtr data_transfer_manager_ = + nullptr; + EventRegistrationToken data_transfer_manager_token_; + + // Present here to keep |std::string| in memory until data request callback + // from |IDataTransferManager| takes place. + // Subsequent calls on the platform channel will overwrite the existing value. + std::string share_text_ = ""; + std::optional share_subject_ = std::nullopt; + std::vector paths_ = {}; + std::vector mime_types_ = {}; + }; } // namespace share_plus_windows diff --git a/packages/share_plus/share_plus/windows/vector.h b/packages/share_plus/share_plus/windows/vector.h index 105e42c222..a255d6de63 100644 --- a/packages/share_plus/share_plus/windows/vector.h +++ b/packages/share_plus/share_plus/windows/vector.h @@ -33,22 +33,22 @@ using namespace Microsoft::WRL::Wrappers; // want to throw more varied types of exception. class HResultException { - HRESULT m_Hr; + HRESULT m_Hr; protected: - explicit HResultException(HRESULT hr) : m_Hr(hr) {} + explicit HResultException(HRESULT hr) : m_Hr(hr) {} public: - HRESULT GetHr() const { return m_Hr; } + HRESULT GetHr() const { return m_Hr; } - __declspec(noreturn) friend void ThrowHR(HRESULT); + __declspec(noreturn) friend void ThrowHR(HRESULT); }; // // Throws an exception for the given HRESULT. // __declspec(noreturn) __declspec(noinline) inline void ThrowHR(HRESULT hr) { - throw HResultException(hr); + throw HResultException(hr); } // @@ -60,16 +60,16 @@ __declspec(noreturn) __declspec(noinline) inline void ThrowHR(HRESULT hr) { // __declspec(noreturn) __declspec(noinline) inline void ThrowHR(HRESULT hr, HSTRING message) { - RoOriginateError(hr, message); + RoOriginateError(hr, message); - ThrowHR(hr); + ThrowHR(hr); } __declspec(noreturn) __declspec(noinline) inline void ThrowHR( - HRESULT hr, wchar_t const *message) { - using ::Microsoft::WRL::Wrappers::HStringReference; + HRESULT hr, wchar_t const *message) { + using ::Microsoft::WRL::Wrappers::HStringReference; - ThrowHR(hr, HStringReference(message).Get()); + ThrowHR(hr, HStringReference(message).Get()); } // @@ -79,28 +79,29 @@ __declspec(noreturn) __declspec(noinline) inline void ThrowHR( // ThrowIfFailed(myObj->MethodThatReturnsHRESULT()); // inline void ThrowIfFailed(HRESULT hr) { - if (FAILED(hr)) - ThrowHR(hr); + if (FAILED(hr)) + ThrowHR(hr); } // // Throws if the given pointer is null. // -template +template inline void ThrowIfNullPointer(T *ptr, HRESULT hrToThrow) { - if (ptr == nullptr) - ThrowHR(hrToThrow); + if (ptr == nullptr) + ThrowHR(hrToThrow); } -template inline void ThrowIfNegative(T value) { - if (value < 0) - ThrowHR(E_INVALIDARG); +template +inline void ThrowIfNegative(T value) { + if (value < 0) + ThrowHR(E_INVALIDARG); } inline void ThrowIfZeroOrNegative(uint32_t n) { - if (n <= 0) { - ThrowHR(E_INVALIDARG); - } + if (n <= 0) { + ThrowHR(E_INVALIDARG); + } } // @@ -108,8 +109,9 @@ inline void ThrowIfZeroOrNegative(uint32_t n) { // expected to be used at the beginning of methods to validate pointer // parameters that are marked as [in]. // -template inline void CheckInPointer(T *ptr) { - ThrowIfNullPointer(ptr, E_INVALIDARG); +template +inline void CheckInPointer(T *ptr) { + ThrowIfNullPointer(ptr, E_INVALIDARG); } // @@ -117,9 +119,10 @@ template inline void CheckInPointer(T *ptr) { // it to null. This is expected to be used at the beginning of methods to // validate out pointer parameters that are marked as [out]. // -template inline void CheckAndClearOutPointer(T **ptr) { - CheckInPointer(ptr); - *ptr = nullptr; +template +inline void CheckAndClearOutPointer(T **ptr) { + CheckInPointer(ptr); + *ptr = nullptr; } // @@ -131,431 +134,558 @@ template inline void CheckAndClearOutPointer(T **ptr) { // fails. // __declspec(noreturn) __declspec(noinline) inline void ThrowBadAlloc() { - throw std::bad_alloc(); + throw std::bad_alloc(); } inline void CheckMakeResult(bool result) { - if (!result) - ThrowBadAlloc(); + if (!result) + ThrowBadAlloc(); } // // Converts exceptions in the callable code into HRESULTs. // __declspec(noinline) inline HRESULT ThrownExceptionToHResult() { - try { - throw; - } catch (HResultException const &e) { - return e.GetHr(); - } catch (std::bad_alloc const &) { - return E_OUTOFMEMORY; - } catch (...) { - return E_UNEXPECTED; - } -} - -template HRESULT ExceptionBoundary(CALLABLE &&fn) { - try { - fn(); - return S_OK; - } catch (...) { - return ThrownExceptionToHResult(); - } + try { + throw; + } catch (HResultException const &e) { + return e.GetHr(); + } catch (std::bad_alloc const &) { + return E_OUTOFMEMORY; + } catch (...) { + return E_UNEXPECTED; + } +} + +template +HRESULT ExceptionBoundary(CALLABLE &&fn) { + try { + fn(); + return S_OK; + } catch (...) { + return ThrownExceptionToHResult(); + } } // Element traits describe how to store and manipulate the values inside a // collection. This default implementation is for value types. The same template // is specialized with more interesting versions for reference counted pointer // types and strings. -template struct ElementTraits { - typedef T ElementType; +template +struct ElementTraits { + typedef T ElementType; + + static ElementType Wrap(T const &value) { return value; } - static ElementType Wrap(T const &value) { return value; } + static void Unwrap(ElementType const &value, _Out_ T - static void Unwrap(ElementType const &value, _Out_ T *result) { - *result = value; - } + *result) { + *result = value; + } - static bool Equals(T const &value1, T const &value2) { - return value1 == value2; - } + static bool Equals(T const &value1, T const &value2) { + return value1 == value2; + } - static void CopyTo(T const &in, ElementType *out) { *out = in; } + static void CopyTo(T const &in, ElementType *out) { *out = in; } }; // Specialized element traits for reference counted pointer types. -template struct ElementTraits { - typedef Microsoft::WRL::ComPtr ElementType; +template +struct ElementTraits { + typedef Microsoft::WRL::ComPtr ElementType; - static ElementType Wrap(T *value) { return Microsoft::WRL::ComPtr(value); } + static ElementType Wrap(T *value) { return Microsoft::WRL::ComPtr(value); } - static void Unwrap(ElementType const &value, _Out_ T **result) { - ThrowIfFailed(value.CopyTo(result)); - } + static void Unwrap(ElementType const &value, _Out_ T - static bool Equals(Microsoft::WRL::ComPtr const &value1, T *value2) { - return value1.Get() == value2; - } + **result) { + ThrowIfFailed(value.CopyTo(result)); + } - static void CopyTo(Microsoft::WRL::ComPtr const &in, ElementType *out) { - in.CopyTo(out->GetAddressOf()); - } + static bool Equals(Microsoft::WRL::ComPtr const &value1, T *value2) { + return value1.Get() == value2; + } + + static void CopyTo(Microsoft::WRL::ComPtr const &in, ElementType *out) { + in.CopyTo(out->GetAddressOf()); + } }; // Specialized element traits for strings. -template <> struct ElementTraits { - typedef HString ElementType; - - static ElementType Wrap(HSTRING const &value) { - HString hstringValue; - hstringValue.Set(value); - return hstringValue; - } - - static void Unwrap(ElementType const &value, _Out_ HSTRING *result) { - value.CopyTo(result); - } - - static bool Equals(HString const &value1, HSTRING const &value2) { - int compareResult; - ThrowIfFailed( - WindowsCompareStringOrdinal(value1.Get(), value2, &compareResult)); - return compareResult == 0; - } - - static void CopyTo(HString const &in, ElementType *out) { - in.CopyTo(out->GetAddressOf()); - } +template<> +struct ElementTraits { + typedef HString ElementType; + + static ElementType Wrap(HSTRING const &value) { + HString hstringValue; + hstringValue.Set(value); + return hstringValue; + } + + static void Unwrap(ElementType const &value, _Out_ HSTRING + + *result) { + value.CopyTo(result); + } + + static bool Equals(HString const &value1, HSTRING const &value2) { + int compareResult; + ThrowIfFailed( + WindowsCompareStringOrdinal(value1.Get(), value2, &compareResult)); + return compareResult == 0; + } + + static void CopyTo(HString const &in, ElementType *out) { + in.CopyTo(out->GetAddressOf()); + } }; // Vector traits describe how the collection itself is implemented. // This default version just uses an STL vector. -template struct DefaultVectorTraits : public ElementTraits { - typedef std::vector InternalVectorType; +template +struct DefaultVectorTraits : public ElementTraits { + typedef std::vector InternalVectorType; - static unsigned GetSize(InternalVectorType const &vector) { - return (unsigned)vector.size(); - }; + static unsigned GetSize(InternalVectorType const &vector) { + return (unsigned) vector.size(); + }; - static void GetAt(InternalVectorType const &vector, unsigned index, - ElementType *element) { - if (index >= vector.size()) - ThrowHR(E_BOUNDS); + static void GetAt(InternalVectorType const &vector, unsigned index, + ElementType *element) { + if (index >= vector.size()) + ThrowHR(E_BOUNDS); - ElementTraits::CopyTo(vector[index], element); - return; - } + ElementTraits::CopyTo(vector[index], element); + return; + } - static void SetAt(InternalVectorType &vector, unsigned index, T const &item) { - if (index >= vector.size()) - ThrowHR(E_BOUNDS); + static void SetAt(InternalVectorType &vector, unsigned index, T const &item) { + if (index >= vector.size()) + ThrowHR(E_BOUNDS); - vector[index] = Wrap(item); - } + vector[index] = Wrap(item); + } - static void InsertAt(InternalVectorType &vector, unsigned index, - T const &item) { - if (index > vector.size()) - ThrowHR(E_BOUNDS); + static void InsertAt(InternalVectorType &vector, unsigned index, + T const &item) { + if (index > vector.size()) + ThrowHR(E_BOUNDS); - vector.insert(vector.begin() + index, Wrap(item)); - } + vector.insert(vector.begin() + index, Wrap(item)); + } - static void RemoveAt(InternalVectorType &vector, unsigned index) { - if (index >= vector.size()) - ThrowHR(E_BOUNDS); + static void RemoveAt(InternalVectorType &vector, unsigned index) { + if (index >= vector.size()) + ThrowHR(E_BOUNDS); - vector.erase(vector.begin() + index); - } + vector.erase(vector.begin() + index); + } - static void Append(InternalVectorType &vector, T const &item) { - vector.push_back(Wrap(item)); - } + static void Append(InternalVectorType &vector, T const &item) { + vector.push_back(Wrap(item)); + } - static void Clear(InternalVectorType &vector) { vector.clear(); } + static void Clear(InternalVectorType &vector) { vector.clear(); } }; // Implements the WinRT IVector interface. -template class Traits = DefaultVectorTraits> +template class Traits = DefaultVectorTraits> class Vector : public Microsoft::WRL::RuntimeClass< - ABI::Windows::Foundation::Collections::IVector, - ABI::Windows::Foundation::Collections::IIterable> { - InspectableClass(IVector::z_get_rc_name_impl(), BaseTrust); - -public: - // T_abi is often the same as T, but if T is a runtime class, T_abi will be - // the corresponding interface. - typedef typename ABI::Windows::Foundation::Internal::GetAbiType< - typename RuntimeClass::IVector::T_complex>::type T_abi; + ABI::Windows::Foundation::Collections::IVector < T>, + ABI::Windows::Foundation::Collections::IIterable> - // Specialize our traits class to use the ABI version of the type. - typedef Traits Traits; - -private: - // Fields. - typename Traits::InternalVectorType mVector; +{ +InspectableClass(IVector::z_get_rc_name_impl(), BaseTrust - bool isFixedSize; - bool isChanged; +); public: - // Constructs an empty vector. - Vector() : isFixedSize(false), isChanged(false) {} +// T_abi is often the same as T, but if T is a runtime class, T_abi will be +// the corresponding interface. +typedef typename ABI::Windows::Foundation::Internal::GetAbiType< + typename RuntimeClass::IVector::T_complex>::type T_abi; - // Constructs a vector of the specified size. - template - Vector(bool isFixedSize, Args &&...args) - : mVector(std::forward(args)...), isFixedSize(isFixedSize), - isChanged(false) {} +// Specialize our traits class to use the ABI version of the type. +typedef Traits Traits; - // Checks whether this vector is fixed or resizable. - bool IsFixedSize() const { return isFixedSize; } +private: +// Fields. +typename Traits::InternalVectorType mVector; - // Checks whether the contents of the vector have changed since the last call - // to SetChanged(false). - bool IsChanged() const { return isChanged; } +bool isFixedSize; +bool isChanged; - // Sets or clears the IsChanged flag. - void SetChanged(bool changed) { isChanged = changed; } +public: - // Expose direct access to the internal STL collection. This lets C++ owners - // bypass the ExceptionBoundary overhead of the public WinRT API surface. - typename Traits::InternalVectorType &InternalVector() { return mVector; } +// Constructs an empty vector. +Vector() : isFixedSize(false), isChanged(false) {} - virtual HRESULT STDMETHODCALLTYPE get_Size(_Out_ unsigned *size) { - return ExceptionBoundary([&] { - CheckInPointer(size); +// Constructs a vector of the specified size. +template +Vector(bool isFixedSize, Args &&...args) + : mVector(std::forward(args)...), isFixedSize(isFixedSize), + isChanged(false) {} - *size = Traits::GetSize(mVector); - }); - }; +// Checks whether this vector is fixed or resizable. +bool IsFixedSize() const { return isFixedSize; } - virtual HRESULT STDMETHODCALLTYPE GetAt(_In_opt_ unsigned index, - _Out_ T_abi *item) { - return ExceptionBoundary([&] { - CheckInPointer(item); - ZeroMemory(item, sizeof(*item)); +// Checks whether the contents of the vector have changed since the last call +// to SetChanged(false). +bool IsChanged() const { return isChanged; } - Traits::ElementType element; - Traits::GetAt(mVector, index, &element); - Traits::Unwrap(element, item); - }); - } +// Sets or clears the IsChanged flag. +void SetChanged(bool changed) { isChanged = changed; } - virtual HRESULT STDMETHODCALLTYPE IndexOf(_In_opt_ T_abi value, - _Out_ unsigned *index, - _Out_ boolean *found) { - return ExceptionBoundary([&] { - CheckInPointer(index); - CheckInPointer(found); +// Expose direct access to the internal STL collection. This lets C++ owners +// bypass the ExceptionBoundary overhead of the public WinRT API surface. +typename Traits::InternalVectorType &InternalVector() { return mVector; } - *index = 0; - *found = false; +virtual HRESULT STDMETHODCALLTYPE +get_Size(_Out_ +unsigned *size +) { +return ExceptionBoundary([&] { +CheckInPointer(size); - auto size = Traits::GetSize(mVector); +* +size = Traits::GetSize(mVector); +}); +}; - for (unsigned i = 0; i < size; i++) { - Traits::ElementType element; - Traits::GetAt(mVector, i, &element); +virtual HRESULT STDMETHODCALLTYPE +GetAt(_In_opt_ +unsigned index, + _Out_ +T_abi *item +) { +return ExceptionBoundary([&] { +CheckInPointer(item); +ZeroMemory(item, +sizeof(*item)); + +Traits::ElementType element; +Traits::GetAt(mVector, index, &element +); +Traits::Unwrap(element, item +); +}); +} - if (Traits::Equals(element, value)) { - *index = i; - *found = true; - break; - } - } - }); - } +virtual HRESULT STDMETHODCALLTYPE +IndexOf(_In_opt_ +T_abi value, + _Out_ +unsigned *index, + _Out_ +boolean *found +) { +return ExceptionBoundary([&] { +CheckInPointer(index); +CheckInPointer(found); + +* +index = 0; +* +found = false; + +auto size = Traits::GetSize(mVector); + +for ( +unsigned i = 0; +i **view +) { +return ExceptionBoundary([&] { +CheckAndClearOutPointer(view); + +auto vectorView = Microsoft::WRL::Make < VectorView < T, Vector +>>(this); +CheckMakeResult(vectorView); + +* +view = vectorView.Detach(); +}); +} - for (unsigned i = 0; i < count; i++) { - Traits::Append(mVector, value[i]); - } - } +virtual HRESULT STDMETHODCALLTYPE +First( + _Outptr_result_maybenull_ +ABI::Windows::Foundation::Collections::IIterator **first +) { +return ExceptionBoundary([&] { +CheckAndClearOutPointer(first); + +auto iterator = Microsoft::WRL::Make < VectorIterator < T, Vector +>>(this); +CheckMakeResult(iterator); + +* +first = iterator.Detach(); +}); +} +}; - isChanged = true; - }); - } +// Implements the WinRT IVectorView interface. +template +class VectorView : public Microsoft::WRL::RuntimeClass< + ABI::Windows::Foundation::Collections::IVectorView < T>, + ABI::Windows::Foundation::Collections::IIterable> - virtual HRESULT STDMETHODCALLTYPE GetView( - _Outptr_result_maybenull_ - ABI::Windows::Foundation::Collections::IVectorView **view) { - return ExceptionBoundary([&] { - CheckAndClearOutPointer(view); +{ +InspectableClass(IVectorView::z_get_rc_name_impl(), BaseTrust - auto vectorView = Microsoft::WRL::Make>(this); - CheckMakeResult(vectorView); +); - *view = vectorView.Detach(); - }); - } +// Fields. +Microsoft::WRL::ComPtr mVector; - virtual HRESULT STDMETHODCALLTYPE First( - _Outptr_result_maybenull_ - ABI::Windows::Foundation::Collections::IIterator **first) { - return ExceptionBoundary([&] { - CheckAndClearOutPointer(first); +public: - auto iterator = Microsoft::WRL::Make>(this); - CheckMakeResult(iterator); +// Constructor wraps around an existing Vector. +VectorView(TVector *vector) : mVector(vector) {} - *first = iterator.Detach(); - }); - } +virtual HRESULT STDMETHODCALLTYPE +get_Size(_Out_ +unsigned *size +) { +return mVector-> +get_Size(size); }; -// Implements the WinRT IVectorView interface. -template -class VectorView : public Microsoft::WRL::RuntimeClass< - ABI::Windows::Foundation::Collections::IVectorView, - ABI::Windows::Foundation::Collections::IIterable> { - InspectableClass(IVectorView::z_get_rc_name_impl(), BaseTrust); +virtual HRESULT STDMETHODCALLTYPE +GetAt(_In_opt_ +unsigned index, + _Out_ +typename TVector::T_abi *item +) { +return mVector-> +GetAt(index, item +); +} - // Fields. - Microsoft::WRL::ComPtr mVector; +virtual HRESULT STDMETHODCALLTYPE +IndexOf(_In_opt_ +typename TVector::T_abi value, + _Out_ +unsigned *index, + _Out_ +boolean *found +) { +return mVector-> +IndexOf(value, index, found +); +} -public: - // Constructor wraps around an existing Vector. - VectorView(TVector *vector) : mVector(vector) {} - - virtual HRESULT STDMETHODCALLTYPE get_Size(_Out_ unsigned *size) { - return mVector->get_Size(size); - }; - - virtual HRESULT STDMETHODCALLTYPE GetAt(_In_opt_ unsigned index, - _Out_ typename TVector::T_abi *item) { - return mVector->GetAt(index, item); - } - - virtual HRESULT STDMETHODCALLTYPE IndexOf(_In_opt_ - typename TVector::T_abi value, - _Out_ unsigned *index, - _Out_ boolean *found) { - return mVector->IndexOf(value, index, found); - } - - virtual HRESULT STDMETHODCALLTYPE First( - _Outptr_result_maybenull_ - ABI::Windows::Foundation::Collections::IIterator **first) { - return mVector->First(first); - } +virtual HRESULT STDMETHODCALLTYPE +First( + _Outptr_result_maybenull_ +ABI::Windows::Foundation::Collections::IIterator **first +) { +return mVector-> +First(first); +} }; // Implements the WinRT IIterator interface. -template +template class VectorIterator - : public Microsoft::WRL::RuntimeClass< - ABI::Windows::Foundation::Collections::IIterator> { - InspectableClass(IIterator::z_get_rc_name_impl(), BaseTrust); + : public Microsoft::WRL::RuntimeClass< + ABI::Windows::Foundation::Collections::IIterator < T>> + +{ +InspectableClass(IIterator::z_get_rc_name_impl(), BaseTrust - // Fields. - Microsoft::WRL::ComPtr mVector; - unsigned mPosition; +); + +// Fields. +Microsoft::WRL::ComPtr mVector; +unsigned mPosition; public: - // Constructor wraps around an existing Vector. - VectorIterator(TVector *vector) : mVector(vector), mPosition(0) {} - virtual HRESULT STDMETHODCALLTYPE - get_Current(_Out_ typename TVector::T_abi *current) { - return mVector->GetAt(mPosition, current); - } +// Constructor wraps around an existing Vector. +VectorIterator(TVector *vector) : mVector(vector), mPosition(0) {} - virtual HRESULT STDMETHODCALLTYPE get_HasCurrent(_Out_ boolean *hasCurrent) { - return ExceptionBoundary([&] { - CheckInPointer(hasCurrent); +virtual HRESULT STDMETHODCALLTYPE +get_Current(_Out_ +typename TVector::T_abi *current +) { +return mVector-> +GetAt(mPosition, current +); +} - *hasCurrent = - (mPosition < TVector::Traits::GetSize(mVector->InternalVector())); - }); - } +virtual HRESULT STDMETHODCALLTYPE +get_HasCurrent(_Out_ +boolean *hasCurrent +) { +return ExceptionBoundary([&] { +CheckInPointer(hasCurrent); + +* +hasCurrent = +(mPosition < TVector::Traits::GetSize(mVector->InternalVector())); +}); +} - virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ boolean *hasCurrent) { - return ExceptionBoundary([&] { - CheckInPointer(hasCurrent); +virtual HRESULT STDMETHODCALLTYPE +MoveNext(_Out_ +boolean *hasCurrent +) { +return ExceptionBoundary([&] { +CheckInPointer(hasCurrent); - auto size = TVector::Traits::GetSize(mVector->InternalVector()); +auto size = TVector::Traits::GetSize(mVector->InternalVector()); - if (mPosition >= size) { - ThrowHR(E_BOUNDS); - } +if (mPosition >= size) { +ThrowHR(E_BOUNDS); +} - mPosition++; - *hasCurrent = (mPosition < size); - }); - } +mPosition++; +* +hasCurrent = (mPosition < size); +}); +} }; diff --git a/packages/share_plus/share_plus_platform_interface/CHANGELOG.md b/packages/share_plus/share_plus_platform_interface/CHANGELOG.md index 5e0683705c..e27647da06 100644 --- a/packages/share_plus/share_plus_platform_interface/CHANGELOG.md +++ b/packages/share_plus/share_plus_platform_interface/CHANGELOG.md @@ -1,49 +1,57 @@ ## 5.0.2 - - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) +- **REFACTOR**(all): Use range of flutter_lints for broader + compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) ## 5.0.1 - - **FIX**(share_plus): `mime` compatible with v2 (v1 still supported) ([#3309](https://github.com/fluttercommunity/plus_plugins/issues/3309)). ([401db75e](https://github.com/fluttercommunity/plus_plugins/commit/401db75efa24c40fd96a05e79d12801f92666efd)) +- **FIX**(share_plus): `mime` compatible with v2 (v1 still + supported) ([#3309](https://github.com/fluttercommunity/plus_plugins/issues/3309)). ([401db75e](https://github.com/fluttercommunity/plus_plugins/commit/401db75efa24c40fd96a05e79d12801f92666efd)) ## 5.0.0 > Note: This release has breaking changes. - - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) - - **BREAKING** **FEAT**(share_plus): Introduce optional parameter `nameOverride` to `shareXFiles`. ([#3077](https://github.com/fluttercommunity/plus_plugins/issues/3077)). ([f483bce7](https://github.com/fluttercommunity/plus_plugins/commit/f483bce77f50fc03e8c6c969864dd978e46f32da)) +- **FIX**(all): changed homepage url in + pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) +- **BREAKING** **FEAT**(share_plus): Introduce optional parameter `nameOverride` to + `shareXFiles`. ([#3077](https://github.com/fluttercommunity/plus_plugins/issues/3077)). ([f483bce7](https://github.com/fluttercommunity/plus_plugins/commit/f483bce77f50fc03e8c6c969864dd978e46f32da)) ## 4.0.0 > Note: This release has breaking changes. - - **BREAKING** **REFACTOR**(share_plus): Share API cleanup ([#2832](https://github.com/fluttercommunity/plus_plugins/issues/2832)). ([fd0511ca](https://github.com/fluttercommunity/plus_plugins/commit/fd0511ca4d55db1e075e72af5a0832b5cfe81244)) +- **BREAKING** **REFACTOR**(share_plus): Share API + cleanup ([#2832](https://github.com/fluttercommunity/plus_plugins/issues/2832)). ([fd0511ca](https://github.com/fluttercommunity/plus_plugins/commit/fd0511ca4d55db1e075e72af5a0832b5cfe81244)) ## 3.4.0 - - **FIX**(share_plus): add sharePositionOrigin parameter to shareUri ([#2517](https://github.com/fluttercommunity/plus_plugins/issues/2517)). ([f896d94e](https://github.com/fluttercommunity/plus_plugins/commit/f896d94e6c24551d9dc7d73d8fb05a0f283e0e83)) - - **FEAT**(share_plus): Use XFile.name whenever possible, shorten UUID filenames, and improve I/O throughput ([#2713](https://github.com/fluttercommunity/plus_plugins/issues/2713)). ([734321b8](https://github.com/fluttercommunity/plus_plugins/commit/734321b82d51fc3201113a6ca645c9bebb0282a2)) +- **FIX**(share_plus): add sharePositionOrigin parameter to + shareUri ([#2517](https://github.com/fluttercommunity/plus_plugins/issues/2517)). ([f896d94e](https://github.com/fluttercommunity/plus_plugins/commit/f896d94e6c24551d9dc7d73d8fb05a0f283e0e83)) +- **FEAT**(share_plus): Use XFile.name whenever possible, shorten UUID filenames, and improve I/O + throughput ([#2713](https://github.com/fluttercommunity/plus_plugins/issues/2713)). ([734321b8](https://github.com/fluttercommunity/plus_plugins/commit/734321b82d51fc3201113a6ca645c9bebb0282a2)) ## 3.3.1 - - chore(deps): bump uuid from 3.0.7 to 4.0.0 +- chore(deps): bump uuid from 3.0.7 to 4.0.0 ## 3.3.0 - - **FEAT**(share_plus): Allow user to share URI with preview image on the iOS native share sheet ([#1779](https://github.com/fluttercommunity/plus_plugins/issues/1779)). ([c83b667e](https://github.com/fluttercommunity/plus_plugins/commit/c83b667eb12394feef69221eda0eab8716aa19d8)) +- **FEAT**(share_plus): Allow user to share URI with preview image on the iOS native share + sheet ([#1779](https://github.com/fluttercommunity/plus_plugins/issues/1779)). ([c83b667e](https://github.com/fluttercommunity/plus_plugins/commit/c83b667eb12394feef69221eda0eab8716aa19d8)) ## 3.2.1 - - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). +- **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). ## 3.2.0 - - **FIX**: export XFile (#1286). - - **FEAT**: share XFile created using File.fromData() (#1284). +- **FIX**: export XFile (#1286). +- **FEAT**: share XFile created using File.fromData() (#1284). ## 3.1.2 - - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). +- **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). ## 3.1.1 diff --git a/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart b/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart index bb7fa696c6..7c98066299 100644 --- a/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart +++ b/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart @@ -20,14 +20,12 @@ import 'package:uuid/uuid.dart'; class MethodChannelShare extends SharePlatform { /// [MethodChannel] used to communicate with the platform side. @visibleForTesting - static const MethodChannel channel = - MethodChannel('dev.fluttercommunity.plus/share'); + static const MethodChannel channel = MethodChannel( + 'dev.fluttercommunity.plus/share', + ); @override - Future shareUri( - Uri uri, { - Rect? sharePositionOrigin, - }) async { + Future shareUri(Uri uri, {Rect? sharePositionOrigin}) async { final params = {'uri': uri.toString()}; if (sharePositionOrigin != null) { @@ -37,7 +35,8 @@ class MethodChannelShare extends SharePlatform { params['originHeight'] = sharePositionOrigin.height; } - final result = await channel.invokeMethod('shareUri', params) ?? + final result = + await channel.invokeMethod('shareUri', params) ?? 'dev.fluttercommunity.plus/share/unavailable'; return ShareResult(result, _statusFromResult(result)); @@ -51,10 +50,7 @@ class MethodChannelShare extends SharePlatform { Rect? sharePositionOrigin, }) async { assert(text.isNotEmpty); - final params = { - 'text': text, - 'subject': subject, - }; + final params = {'text': text, 'subject': subject}; if (sharePositionOrigin != null) { params['originX'] = sharePositionOrigin.left; @@ -63,7 +59,8 @@ class MethodChannelShare extends SharePlatform { params['originHeight'] = sharePositionOrigin.height; } - final result = await channel.invokeMethod('share', params) ?? + final result = + await channel.invokeMethod('share', params) ?? 'dev.fluttercommunity.plus/share/unavailable'; return ShareResult(result, _statusFromResult(result)); @@ -86,18 +83,16 @@ class MethodChannelShare extends SharePlatform { final filesWithPath = await _getFiles(files, fileNameOverrides); assert(filesWithPath.every((element) => element.path.isNotEmpty)); - final mimeTypes = filesWithPath - .map((e) => e.mimeType ?? _mimeTypeForPath(e.path)) - .toList(); + final mimeTypes = + filesWithPath + .map((e) => e.mimeType ?? _mimeTypeForPath(e.path)) + .toList(); final paths = filesWithPath.map((e) => e.path).toList(); assert(paths.length == mimeTypes.length); assert(mimeTypes.every((element) => element.isNotEmpty)); - final params = { - 'paths': paths, - 'mimeTypes': mimeTypes, - }; + final params = {'paths': paths, 'mimeTypes': mimeTypes}; if (subject != null) params['subject'] = subject; if (text != null) params['text'] = text; @@ -109,7 +104,8 @@ class MethodChannelShare extends SharePlatform { params['originHeight'] = sharePositionOrigin.height; } - final result = await channel.invokeMethod('shareFiles', params) ?? + final result = + await channel.invokeMethod('shareFiles', params) ?? 'dev.fluttercommunity.plus/share/unavailable'; return ShareResult(result, _statusFromResult(result)); @@ -150,7 +146,8 @@ class MethodChannelShare extends SharePlatform { //Per Issue [#3032](https://github.com/fluttercommunity/plus_plugins/issues/3032): use overridden name when available. //Per Issue [#1548](https://github.com/fluttercommunity/plus_plugins/issues/1548): attempt to use XFile.name when available - final filename = nameOverride ?? + final filename = + nameOverride ?? (filenameNotEmptyOrHasValidExt ? file.name : "${const Uuid().v1().substring(10)}.$extension"); @@ -174,7 +171,7 @@ class MethodChannelShare extends SharePlatform { _getFile( files[index], nameOverride: fileNameOverrides?.elementAt(index), - ) + ), ]); } diff --git a/packages/share_plus/share_plus_platform_interface/lib/platform_interface/share_plus_platform.dart b/packages/share_plus/share_plus_platform_interface/lib/platform_interface/share_plus_platform.dart index f1840624ef..728c1d5530 100644 --- a/packages/share_plus/share_plus_platform_interface/lib/platform_interface/share_plus_platform.dart +++ b/packages/share_plus/share_plus_platform_interface/lib/platform_interface/share_plus_platform.dart @@ -32,14 +32,8 @@ class SharePlatform extends PlatformInterface { } /// Share uri. - Future shareUri( - Uri uri, { - Rect? sharePositionOrigin, - }) { - return _instance.shareUri( - uri, - sharePositionOrigin: sharePositionOrigin, - ); + Future shareUri(Uri uri, {Rect? sharePositionOrigin}) { + return _instance.shareUri(uri, sharePositionOrigin: sharePositionOrigin); } /// Share text with Result. diff --git a/packages/share_plus/share_plus_platform_interface/test/share_plus_platform_interface_test.dart b/packages/share_plus/share_plus_platform_interface/test/share_plus_platform_interface_test.dart index 03c796bddc..20b16ce5e1 100644 --- a/packages/share_plus/share_plus_platform_interface/test/share_plus_platform_interface_test.dart +++ b/packages/share_plus/share_plus_platform_interface/test/share_plus_platform_interface_test.dart @@ -23,12 +23,13 @@ void main() { mockChannel = MockMethodChannel(); // Re-pipe to mockito for easier verifies. TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(MethodChannelShare.channel, - (MethodCall call) async { - // The explicit type can be void as the only method call has a return type of void. - await mockChannel.invokeMethod(call.method, call.arguments); - return null; - }); + .setMockMethodCallHandler(MethodChannelShare.channel, ( + MethodCall call, + ) async { + // The explicit type can be void as the only method call has a return type of void. + await mockChannel.invokeMethod(call.method, call.arguments); + return null; + }); }); test('can set SharePlatform instance', () { @@ -38,15 +39,9 @@ void main() { final newInstanceId = identityHashCode(newInstance); expect(currentId, isNot(equals(newInstanceId))); - expect( - identityHashCode(SharePlatform.instance), - equals(currentId), - ); + expect(identityHashCode(SharePlatform.instance), equals(currentId)); SharePlatform.instance = newInstance; - expect( - identityHashCode(SharePlatform.instance), - equals(newInstanceId), - ); + expect(identityHashCode(SharePlatform.instance), equals(newInstanceId)); }); test('sharing empty fails', () { @@ -66,27 +61,31 @@ void main() { Uri.parse('https://pub.dev/packages/share_plus'), sharePositionOrigin: const Rect.fromLTWH(1.0, 2.0, 3.0, 4.0), ); - verify(mockChannel.invokeMethod('shareUri', { - 'uri': 'https://pub.dev/packages/share_plus', - 'originX': 1.0, - 'originY': 2.0, - 'originWidth': 3.0, - 'originHeight': 4.0, - })); + verify( + mockChannel.invokeMethod('shareUri', { + 'uri': 'https://pub.dev/packages/share_plus', + 'originX': 1.0, + 'originY': 2.0, + 'originWidth': 3.0, + 'originHeight': 4.0, + }), + ); await sharePlatform.share( 'some text to share', subject: 'some subject to share', sharePositionOrigin: const Rect.fromLTWH(1.0, 2.0, 3.0, 4.0), ); - verify(mockChannel.invokeMethod('share', { - 'text': 'some text to share', - 'subject': 'some subject to share', - 'originX': 1.0, - 'originY': 2.0, - 'originWidth': 3.0, - 'originHeight': 4.0, - })); + verify( + mockChannel.invokeMethod('share', { + 'text': 'some text to share', + 'subject': 'some subject to share', + 'originX': 1.0, + 'originY': 2.0, + 'originWidth': 3.0, + 'originHeight': 4.0, + }), + ); await withFile('tempfile-83649a.png', (File fd) async { await sharePlatform.shareXFiles( @@ -95,9 +94,8 @@ void main() { text: 'some text to share', sharePositionOrigin: const Rect.fromLTWH(1.0, 2.0, 3.0, 4.0), ); - verify(mockChannel.invokeMethod( - 'shareFiles', - { + verify( + mockChannel.invokeMethod('shareFiles', { 'paths': [fd.path], 'mimeTypes': ['image/png'], 'subject': 'some subject to share', @@ -106,28 +104,32 @@ void main() { 'originY': 2.0, 'originWidth': 3.0, 'originHeight': 4.0, - }, - )); + }), + ); }); }); test('sharing file sets correct mimeType', () async { await withFile('tempfile-83649b.png', (File fd) async { await sharePlatform.shareXFiles([XFile(fd.path)]); - verify(mockChannel.invokeMethod('shareFiles', { - 'paths': [fd.path], - 'mimeTypes': ['image/png'], - })); + verify( + mockChannel.invokeMethod('shareFiles', { + 'paths': [fd.path], + 'mimeTypes': ['image/png'], + }), + ); }); }); test('sharing file sets passed mimeType', () async { await withFile('tempfile-83649c.png', (File fd) async { await sharePlatform.shareXFiles([XFile(fd.path, mimeType: '*/*')]); - verify(mockChannel.invokeMethod('shareFiles', { - 'paths': [fd.path], - 'mimeTypes': ['*/*'], - })); + verify( + mockChannel.invokeMethod('shareFiles', { + 'paths': [fd.path], + 'mimeTypes': ['*/*'], + }), + ); }); }); @@ -156,21 +158,25 @@ void main() { subject: 'some subject to share', sharePositionOrigin: const Rect.fromLTWH(1.0, 2.0, 3.0, 4.0), ); - verify(mockChannel.invokeMethod('share', { - 'text': 'some text to share', - 'subject': 'some subject to share', - 'originX': 1.0, - 'originY': 2.0, - 'originWidth': 3.0, - 'originHeight': 4.0, - })); + verify( + mockChannel.invokeMethod('share', { + 'text': 'some text to share', + 'subject': 'some subject to share', + 'originX': 1.0, + 'originY': 2.0, + 'originWidth': 3.0, + 'originHeight': 4.0, + }), + ); await withFile('tempfile-83649e.png', (File fd) async { await sharePlatform.shareXFiles([XFile(fd.path)]); - verify(mockChannel.invokeMethod('shareFiles', { - 'paths': [fd.path], - 'mimeTypes': ['image/png'], - })); + verify( + mockChannel.invokeMethod('shareFiles', { + 'paths': [fd.path], + 'mimeTypes': ['image/png'], + }), + ); }); }); } @@ -190,8 +196,9 @@ Future withFile(String filename, Future Function(File fd) func) async { class MockMethodChannel extends Mock implements MethodChannel { @override Future invokeMethod(String method, [dynamic arguments]) async { - return super - .noSuchMethod(Invocation.method(#invokeMethod, [method, arguments])) + return super.noSuchMethod( + Invocation.method(#invokeMethod, [method, arguments]), + ) as dynamic; } }