diff --git a/.ci/Dockerfile-LinuxDesktop b/.ci/Dockerfile-LinuxDesktop new file mode 100644 index 000000000000..63e4516e26fc --- /dev/null +++ b/.ci/Dockerfile-LinuxDesktop @@ -0,0 +1,31 @@ +FROM cirrusci/flutter:stable + +RUN sudo apt-get update -y + +RUN sudo apt-get install -y --no-install-recommends gnupg + +# Add repo for gcloud sdk and install it +RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | \ + sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list + +RUN curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | \ + sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - + +RUN sudo apt-get update && sudo apt-get install -y google-cloud-sdk && \ + gcloud config set core/disable_usage_reporting true && \ + gcloud config set component_manager/disable_update_check true + +# Install xvfb to allow running headless +RUN sudo apt-get install -y xvfb libegl1-mesa +# Install Linux desktop build tool requirements. +RUN sudo apt-get install -y clang cmake ninja-build file pkg-config +# Install necessary libraries. +RUN sudo apt-get install -y libgtk-3-dev + +# Add repo for Google Chrome and install it, for url_launcher tests. +RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - +RUN echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | sudo tee /etc/apt/sources.list.d/google-chrome.list +RUN sudo apt-get update && sudo apt-get install -y --no-install-recommends google-chrome-stable +# Make it the default so http: has a handler. +RUN sudo apt-get install -y xdg-utils +RUN xdg-settings set default-web-browser google-chrome.desktop diff --git a/.ci/dev/README.md b/.ci/dev/README.md new file mode 100644 index 000000000000..d266afbf2687 --- /dev/null +++ b/.ci/dev/README.md @@ -0,0 +1,19 @@ +This directory contains resources that the Flutter team uses during +the development of plugins. + +## Luci builder file +`try_builders.json` contains the supported luci try builders +for plugins. It follows format: +```json +{ + "builders":[ + { + "name":"yyy", + "repo":"plugins", + "enabled":true + } + ] +} +``` +This file will be mainly used in [`flutter/cocoon`](https://github.com/flutter/cocoon) +to trigger/update pre-submit luci tasks. diff --git a/.ci/dev/try_builders.json b/.ci/dev/try_builders.json new file mode 100644 index 000000000000..6334a3d64fa4 --- /dev/null +++ b/.ci/dev/try_builders.json @@ -0,0 +1,9 @@ +{ + "builders":[ + { + "name":"Windows Plugins", + "repo":"plugins", + "enabled":true + } + ] +} diff --git a/.cirrus.yml b/.cirrus.yml index af37fc630c2f..98cd6276e0e6 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,9 +1,13 @@ task: + # don't run on release tags since it creates O(n^2) tasks where n is the number of plugins + only_if: $CIRRUS_TAG == '' use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_PR == '' container: dockerfile: .ci/Dockerfile cpu: 8 memory: 16G + env: + INTEGRATION_TEST_PATH: "./packages/integration_test" upgrade_script: - flutter channel stable - flutter upgrade @@ -14,7 +18,7 @@ task: matrix: - name: publishable script: - - flutter channel stable + - flutter channel master - ./script/check_publish.sh - name: format install_script: @@ -43,11 +47,26 @@ task: - if [[ "$CHANNEL" -eq "stable" ]]; then find . | grep _web$ | xargs rm -rf; fi - flutter channel $CHANNEL - ./script/build_all_plugins_app.sh apk + - name: integration_web_smoke_test + # Tests integration example test in web. + only_if: "changesInclude('.cirrus.yml', 'packages/integration_test/**') || $CIRRUS_PR == ''" + install_script: + - flutter config --enable-web + - git clone https://github.com/flutter/web_installers.git + - cd web_installers/packages/web_drivers/ + - pub get + - dart lib/web_driver_installer.dart chromedriver --install-only + - ./chromedriver/chromedriver --port=4444 & + test_script: + - cd $INTEGRATION_TEST_PATH/example/ + - flutter drive -v --driver=test_driver/integration_test.dart --target=integration_test/example_test.dart -d web-server --release --browser-name=chrome - name: build-apks+java-test+firebase-test-lab env: matrix: - PLUGIN_SHARDING: "--shardIndex 0 --shardCount 2" - PLUGIN_SHARDING: "--shardIndex 1 --shardCount 2" + PLUGIN_SHARDING: "--shardIndex 0 --shardCount 4" + PLUGIN_SHARDING: "--shardIndex 1 --shardCount 4" + PLUGIN_SHARDING: "--shardIndex 2 --shardCount 4" + PLUGIN_SHARDING: "--shardIndex 3 --shardCount 4" matrix: CHANNEL: "master" CHANNEL: "stable" @@ -74,17 +93,44 @@ task: - echo "This user does not have permission to run Firebase Test Lab tests." - else - echo $GCLOUD_FIREBASE_TESTLAB_KEY > ${HOME}/gcloud-service-key.json - - ./script/incremental_build.sh firebase-test-lab + - ./script/incremental_build.sh firebase-test-lab --device model=flame,version=29 --device model=starqlteue,version=26 - fi - export CIRRUS_CHANGE_MESSAGE=`cat /tmp/cirrus_change_message.txt` - export CIRRUS_COMMIT_MESSAGE=`cat /tmp/cirrus_commit_message.txt` task: + # don't run on release tags since it creates O(n^2) tasks where n is the number of plugins + only_if: $CIRRUS_TAG == '' + use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_PR == '' + container: + dockerfile: .ci/Dockerfile-LinuxDesktop + cpu: 8 + memory: 16G + env: + INTEGRATION_TEST_PATH: "./packages/integration_test" + upgrade_script: + - flutter channel stable + - flutter upgrade + - flutter channel master + - flutter upgrade + - git fetch origin master + activate_script: pub global activate flutter_plugin_tools + matrix: + - name: build-linux+drive-examples + install_script: + - flutter config --enable-linux-desktop + build_script: + # TODO(stuartmorgan): Include stable once Linux is supported on stable. + - flutter channel master + - ./script/incremental_build.sh build-examples --linux + - xvfb-run ./script/incremental_build.sh drive-examples --linux + +task: + # don't run on release tags since it creates O(n^2) tasks where n is the number of plugins + only_if: $CIRRUS_TAG == '' use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true' osx_instance: - image: mojave-xcode-11.2.1-flutter - setup_script: - - pod repo update + image: catalina-xcode-11.3.1-flutter upgrade_script: - flutter channel stable - flutter upgrade @@ -94,7 +140,7 @@ task: activate_script: pub global activate flutter_plugin_tools create_simulator_script: - xcrun simctl list - - xcrun simctl create Flutter-iPhone com.apple.CoreSimulator.SimDeviceType.iPhone-X com.apple.CoreSimulator.SimRuntime.iOS-13-2 | xargs xcrun simctl boot + - xcrun simctl create Flutter-iPhone com.apple.CoreSimulator.SimDeviceType.iPhone-X com.apple.CoreSimulator.SimRuntime.iOS-13-3 | xargs xcrun simctl boot matrix: - name: build_all_plugins_ipa script: @@ -104,10 +150,20 @@ task: - flutter channel $CHANNEL - ./script/build_all_plugins_app.sh ios --no-codesign - name: lint_darwin_plugins - script: ./script/lint_darwin_plugins.sh + env: + matrix: + PLUGIN_SHARDING: "--shardIndex 0 --shardCount 2" + PLUGIN_SHARDING: "--shardIndex 1 --shardCount 2" + script: + # TODO(jmagman): Lint macOS podspecs but skip any that fail library validation. + - find . -name "*.podspec" | xargs grep -l "osx" | xargs rm + # Skip the dummy podspecs used to placate the tool. + - find . -name "*_web*.podspec" -o -name "*_mac*.podspec" | xargs rm + - ./script/incremental_build.sh podspecs - name: build-ipas+drive-examples env: PATH: $PATH:/usr/local/bin + PLUGINS_TO_SKIP_XCTESTS: "battery/battery,camera/camera,connectivity/connectivity,device_info/device_info,espresso,google_maps_flutter/google_maps_flutter,google_sign_in/google_sign_in,in_app_purchase,integration_test,ios_platform_images,local_auth,package_info,path_provider/path_provider,quick_actions,sensors,shared_preferences/shared_preferences,url_launcher/url_launcher,video_player/video_player,webview_flutter,wifi_info_flutter/wifi_info_flutter" matrix: PLUGIN_SHARDING: "--shardIndex 0 --shardCount 4" PLUGIN_SHARDING: "--shardIndex 1 --shardCount 4" @@ -124,3 +180,29 @@ task: - flutter channel $CHANNEL - ./script/incremental_build.sh build-examples --ipa - ./script/incremental_build.sh drive-examples + - ./script/incremental_build.sh xctest --target RunnerUITests --skip $PLUGINS_TO_SKIP_XCTESTS +task: + # don't run on release tags since it creates O(n^2) tasks where n is the number of plugins + only_if: $CIRRUS_TAG == '' + use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true' + osx_instance: + image: catalina-xcode-11.3.1-flutter + setup_script: + - flutter config --enable-macos-desktop + upgrade_script: + - flutter channel master + - flutter upgrade + - git fetch origin master + activate_script: pub global activate flutter_plugin_tools + matrix: + - name: build_all_plugins_app + script: + - flutter channel master + - ./script/build_all_plugins_app.sh macos + - name: build-apps+drive-examples + env: + PATH: $PATH:/usr/local/bin + build_script: + - flutter channel master + - ./script/incremental_build.sh build-examples --macos --no-ipa + - ./script/incremental_build.sh drive-examples --macos diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000000..f6cb8ad931f5 --- /dev/null +++ b/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/.gitignore b/.gitignore index 54133a3b3a84..d7560505f166 100644 --- a/.gitignore +++ b/.gitignore @@ -16,12 +16,13 @@ Podfile.lock Pods/ .symlinks/ **/Flutter/App.framework/ +**/Flutter/ephemeral/ **/Flutter/Flutter.framework/ **/Flutter/Generated.xcconfig **/Flutter/flutter_assets/ + ServiceDefinitions.json xcuserdata/ -*.xcworkspace **/DerivedData/ local.properties @@ -33,9 +34,12 @@ gradle-wrapper.jar .flutter-plugins-dependencies *.iml +generated_plugin_registrant.dart GeneratedPluginRegistrant.h GeneratedPluginRegistrant.m +generated_plugin_registrant.cc GeneratedPluginRegistrant.java +GeneratedPluginRegistrant.swift build/ .flutter-plugins diff --git a/AUTHORS b/AUTHORS index ed6942ae1a6e..51345c9a3481 100644 --- a/AUTHORS +++ b/AUTHORS @@ -43,4 +43,19 @@ Audrius Karosevicius Lukasz Piliszczuk SoundReply Solutions GmbH Rafal Wachol -Pau Picas \ No newline at end of file +Pau Picas +Christian Weder +Alexandru Tuca +Christian Weder +Rhodes Davis Jr. +Luigi Agosti +Quentin Le Guennec +Koushik Ravikumar +Nissim Dsilva +Giancarlo Rocha +Ryo Miyake +Théo Champion +Kazuki Yamaguchi +Eitan Schwartz +Chris Rutkowski +Juan Alvarez diff --git a/CODEOWNERS b/CODEOWNERS index ff5bf7b654a3..160c0d5a3d10 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -4,20 +4,23 @@ # These names are just suggestions. It is fine to have your changes # reviewed by someone else. -packages/android_alarm_manager/* @bkonyi -packages/android_intent/* @mklim -packages/battery/* @amirh -packages/camera/* @bparrishMines @mklim -packages/connectivity/* @cyanglaz -packages/google_maps_flutter/* @iskakaushik -packages/google_sign_in/* @cyanglaz @mehmetf -packages/image_picker/* @cyanglaz -packages/in_app_purchase/* @mklim @cyanglaz -packages/instrumentation_adapter/* @collinjackson @digiter -packages/package_info/* @cyanglaz -packages/path_provider/* @collinjackson -packages/quick_actions/* @collinjackson -packages/shared_preferences/* @collinjackson -packages/url_launcher/* @mklim -packages/video_player/* @iskakaushik @cyanglaz -packages/webview_flutter/* @amirh +packages/android_alarm_manager/** @bkonyi +packages/android_intent/** @mklim @matthew-carroll +packages/battery/** @amirh @matthew-carroll +packages/camera/** @bparrishMines +packages/connectivity/** @cyanglaz @matthew-carroll +packages/device_info/** @matthew-carroll +packages/espresso/** @collinjackson @adazh +packages/file_selector/** @ditman +packages/google_maps_flutter/** @cyanglaz +packages/google_sign_in/** @cyanglaz @mehmetf +packages/image_picker/** @cyanglaz +packages/integration_test/** @dnfield +packages/in_app_purchase/** @mklim @cyanglaz @LHLL +packages/ios_platform_images/** @gaaclarke +packages/package_info/** @cyanglaz @matthew-carroll +packages/path_provider/** @matthew-carroll +packages/shared_preferences/** @matthew-carroll +packages/url_launcher/** @mklim +packages/video_player/** @iskakaushik @cyanglaz +packages/webview_flutter/** @amirh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f58dfea6a065..b278b43e524f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,28 @@ USB and debugging enabled on that device. * `cd packages/battery/example` * `flutter run` +## Setting up XCUITests + +Sometimes, XCUITests are useful when integration testing a plugin that has native UI on iOS (e.g image_picker, in_app_purchase, camera, share, local_auth etc). Most of the time, XCUITests are not necessary, consider using [integration_test](https://pub.dev/packages/integration_test) if the tests are not focused on iOS system UI. + +If XCUITests has always been set up for the plugin, a RunnerUITests folder under `/example/ios` directory can be found. +If XCUITests has not been set up for the plugin, follow these steps to set it up: + +1. Open /example/ios/Runner.xcworkspace using XCode. +1. Create a new "UI Testing Bundle". +1. In the target options window, populate details as following, then click on "Finish". + * In the "product name" field, type in "RunnerUITests" (this is the test target name our CI looks for.). + * In the "Team" field, select "None". + * In the Organization Name field, type in "Flutter". This should usually be pre-populated. + * In the organization identifer field, type in "com.google". This should usually be pre-populated. + * In the Language field, select "Objective-C". + * In the Project field, select the xcodeproj "Runner" (blue color). + * In the Target to be Tested, select xcworkspace "Runner" (white color). +1. A RunnerUITests folder should be created and you can start hacking in `RunnerUITests.m`. +1. To enable the test on CI, the plugin needs to be removed from the "skip" list: + * Open `./cirrus.yml` and find PLUGINS_TO_SKIP_XCTESTS. + * Remove the plugin name from the list. + ## Running the tests ### Integration tests @@ -84,6 +106,26 @@ cd android ./gradlew test ``` +### XCTests (iOS) + +XCUnitTests are typically configured to run with cocoapods in this repo. To run all the XCUnitTests for a plugin: + +```console +cd ios +pod lib lint --allow-warnings +``` + +XCUITests aren't usually configured with cocoapods in this repo. They are configured in a xcode workspace target named RunnerUITests. +To run all the XCUITests in a plugin, follow the steps in a regular iOS development workflow [here](https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/05-running_tests.html) + +For convenience, a [flutter_plugin_tools](https://pub.dev/packages/flutter_plugin_tools) command `xctest` could also be used to run all the XCUITests in the repo: + +```console +pub global activate flutter_plugin_tools +cd /packages +pub global run flutter_plugin_tools xctest --target RunnerUITests --skip +``` + ## Contributing code We gladly accept contributions via GitHub pull requests. diff --git a/LICENSE b/LICENSE index 7b995420294b..a6d6c0749818 100644 --- a/LICENSE +++ b/LICENSE @@ -1,27 +1,25 @@ Copyright 2017 The Chromium Authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index aeb03ffa23ac..42c64e1c6a50 100644 --- a/README.md +++ b/README.md @@ -36,25 +36,31 @@ and send a [pull request](https://github.com/flutter/plugins/pulls). ## Plugins These are the available plugins in this repository. -| Plugin | Pub | -|--------|-----| -| [android_alarm_manager](./packages/android_alarm_manager/) | [![pub package](https://img.shields.io/pub/v/android_alarm_manager.svg)](https://pub.dev/packages/android_alarm_manager) | -| [android_intent](./packages/android_intent/) | [![pub package](https://img.shields.io/pub/v/android_intent.svg)](https://pub.dev/packages/android_intent) | -| [battery](./packages/battery/) | [![pub package](https://img.shields.io/pub/v/battery.svg)](https://pub.dev/packages/battery) | -| [camera](./packages/camera/) | [![pub package](https://img.shields.io/pub/v/camera.svg)](https://pub.dev/packages/camera) | -| [connectivity](./packages/connectivity/) | [![pub package](https://img.shields.io/pub/v/connectivity.svg)](https://pub.dev/packages/connectivity) | -| [device_info](./packages/device_info/) | [![pub package](https://img.shields.io/pub/v/device_info.svg)](https://pub.dev/packages/device_info) | -| [google_maps_flutter](./packages/google_maps_flutter) | [![pub package](https://img.shields.io/pub/v/google_maps_flutter.svg)](https://pub.dev/packages/google_maps_flutter) | -| [google_sign_in](./packages/google_sign_in/) | [![pub package](https://img.shields.io/pub/v/google_sign_in.svg)](https://pub.dev/packages/google_sign_in) | -| [image_picker](./packages/image_picker/) | [![pub package](https://img.shields.io/pub/v/image_picker.svg)](https://pub.dev/packages/image_picker) | -| [in_app_purchase](./packages/in_app_purchase/) | [![pub package](https://img.shields.io/pub/v/in_app_purchase.svg)](https://pub.dev/packages/in_app_purchase) | -| [local_auth](./packages/local_auth/) | [![pub package](https://img.shields.io/pub/v/local_auth.svg)](https://pub.dev/packages/local_auth) | -| [package_info](./packages/package_info/) | [![pub package](https://img.shields.io/pub/v/package_info.svg)](https://pub.dev/packages/package_info) | -| [path_provider](./packages/path_provider/) | [![pub package](https://img.shields.io/pub/v/path_provider.svg)](https://pub.dev/packages/path_provider) | -| [quick_actions](./packages/quick_actions/) | [![pub package](https://img.shields.io/pub/v/quick_actions.svg)](https://pub.dev/packages/quick_actions) | -| [sensors](./packages/sensors/) | [![pub package](https://img.shields.io/pub/v/sensors.svg)](https://pub.dev/packages/sensors) | -| [share](./packages/share/) | [![pub package](https://img.shields.io/pub/v/share.svg)](https://pub.dev/packages/share) | -| [shared_preferences](./packages/shared_preferences/) | [![pub package](https://img.shields.io/pub/v/shared_preferences.svg)](https://pub.dev/packages/shared_preferences) | -| [url_launcher](./packages/url_launcher/) | [![pub package](https://img.shields.io/pub/v/url_launcher.svg)](https://pub.dev/packages/url_launcher) | -| [video_player](./packages/video_player/) | [![pub package](https://img.shields.io/pub/v/video_player.svg)](https://pub.dev/packages/video_player) | -| [webview_flutter](./packages/webview_flutter/) | [![pub package](https://img.shields.io/pub/v/webview_flutter.svg)](https://pub.dev/packages/webview_flutter) | +| Plugin | Pub | Points | Popularity | Likes | +|--------|-----|--------|------------|-------| +| [android_alarm_manager](./packages/android_alarm_manager/) | [![pub package](https://img.shields.io/pub/v/android_alarm_manager.svg)](https://pub.dev/packages/android_alarm_manager) | [![pub points](https://badges.bar/android_alarm_manager/pub%20points)](https://pub.dev/packages/android_alarm_manager/score) | [![popularity](https://badges.bar/android_alarm_manager/popularity)](https://pub.dev/packages/android_alarm_manager/score) | [![likes](https://badges.bar/android_alarm_manager/likes)](https://pub.dev/packages/android_alarm_manager/score) | +| [android_intent](./packages/android_intent/) | [![pub package](https://img.shields.io/pub/v/android_intent.svg)](https://pub.dev/packages/android_intent) | [![pub points](https://badges.bar/android_intent/pub%20points)](https://pub.dev/packages/android_intent/score) | [![popularity](https://badges.bar/android_intent/popularity)](https://pub.dev/packages/android_intent/score) | [![likes](https://badges.bar/android_intent/likes)](https://pub.dev/packages/android_intent/score) | +| [battery](./packages/battery/) | [![pub package](https://img.shields.io/pub/v/battery.svg)](https://pub.dev/packages/battery) | [![pub points](https://badges.bar/battery/pub%20points)](https://pub.dev/packages/battery/score) | [![popularity](https://badges.bar/battery/popularity)](https://pub.dev/packages/battery/score) | [![likes](https://badges.bar/battery/likes)](https://pub.dev/packages/battery/score) | +| [camera](./packages/camera/) | [![pub package](https://img.shields.io/pub/v/camera.svg)](https://pub.dev/packages/camera) | [![pub points](https://badges.bar/camera/pub%20points)](https://pub.dev/packages/camera/score) | [![popularity](https://badges.bar/camera/popularity)](https://pub.dev/packages/camera/score) | [![likes](https://badges.bar/camera/likes)](https://pub.dev/packages/camera/score) | +| [connectivity](./packages/connectivity/) | [![pub package](https://img.shields.io/pub/v/connectivity.svg)](https://pub.dev/packages/connectivity) | [![pub points](https://badges.bar/connectivity/pub%20points)](https://pub.dev/packages/connectivity/score) | [![popularity](https://badges.bar/connectivity/popularity)](https://pub.dev/packages/connectivity/score) | [![likes](https://badges.bar/connectivity/likes)](https://pub.dev/packages/connectivity/score) | +| [device_info](./packages/device_info/) | [![pub package](https://img.shields.io/pub/v/device_info.svg)](https://pub.dev/packages/device_info) | [![pub points](https://badges.bar/device_info/pub%20points)](https://pub.dev/packages/device_info/score) | [![popularity](https://badges.bar/device_info/popularity)](https://pub.dev/packages/device_info/score) | [![likes](https://badges.bar/device_info/likes)](https://pub.dev/packages/device_info/score) | +| [e2e (Discontinued, use integration_test)](./packages/e2e/) | [![pub package](https://img.shields.io/pub/v/e2e.svg)](https://pub.dev/packages/e2e) | [![pub points](https://badges.bar/e2e/pub%20points)](https://pub.dev/packages/e2e/score) | [![popularity](https://badges.bar/e2e/popularity)](https://pub.dev/packages/e2e/score) | [![likes](https://badges.bar/e2e/likes)](https://pub.dev/packages/e2e/score) | +| [espresso](./packages/espresso/) | [![pub package](https://img.shields.io/pub/v/espresso.svg)](https://pub.dev/packages/espresso) | [![pub points](https://badges.bar/espresso/pub%20points)](https://pub.dev/packages/espresso/score) | [![popularity](https://badges.bar/espresso/popularity)](https://pub.dev/packages/espresso/score) | [![likes](https://badges.bar/espresso/likes)](https://pub.dev/packages/espresso/score) | +| [flutter_plugin_android_lifecycle](./packages/flutter_plugin_android_lifecycle/) | [![pub package](https://img.shields.io/pub/v/flutter_plugin_android_lifecycle.svg)](https://pub.dev/packages/flutter_plugin_android_lifecycle) | [![pub points](https://badges.bar/flutter_plugin_android_lifecycle/pub%20points)](https://pub.dev/packages/flutter_plugin_android_lifecycle/score) | [![popularity](https://badges.bar/flutter_plugin_android_lifecycle/popularity)](https://pub.dev/packages/flutter_plugin_android_lifecycle/score) | [![likes](https://badges.bar/flutter_plugin_android_lifecycle/likes)](https://pub.dev/packages/flutter_plugin_android_lifecycle/score) | +| [google_maps_flutter](./packages/google_maps_flutter) | [![pub package](https://img.shields.io/pub/v/google_maps_flutter.svg)](https://pub.dev/packages/google_maps_flutter) | [![pub points](https://badges.bar/google_maps_flutter/pub%20points)](https://pub.dev/packages/google_maps_flutter/score) | [![popularity](https://badges.bar/google_maps_flutter/popularity)](https://pub.dev/packages/google_maps_flutter/score) | [![likes](https://badges.bar/google_maps_flutter/likes)](https://pub.dev/packages/google_maps_flutter/score) | +| [google_sign_in](./packages/google_sign_in/) | [![pub package](https://img.shields.io/pub/v/google_sign_in.svg)](https://pub.dev/packages/google_sign_in) | [![pub points](https://badges.bar/google_sign_in/pub%20points)](https://pub.dev/packages/google_sign_in/score) | [![popularity](https://badges.bar/google_sign_in/popularity)](https://pub.dev/packages/google_sign_in/score) | [![likes](https://badges.bar/google_sign_in/likes)](https://pub.dev/packages/google_sign_in/score) | +| [image_picker](./packages/image_picker/) | [![pub package](https://img.shields.io/pub/v/image_picker.svg)](https://pub.dev/packages/image_picker) | [![pub points](https://badges.bar/image_picker/pub%20points)](https://pub.dev/packages/image_picker/score) | [![popularity](https://badges.bar/image_picker/popularity)](https://pub.dev/packages/image_picker/score) | [![likes](https://badges.bar/image_picker/likes)](https://pub.dev/packages/image_picker/score) | +| [integration_test](./packages/integration_test/) | [![pub package](https://img.shields.io/pub/v/integration_test.svg)](https://pub.dev/packages/integration_test) | [![pub points](https://badges.bar/integration_test/pub%20points)](https://pub.dev/packages/integration_test/score) | [![popularity](https://badges.bar/integration_test/popularity)](https://pub.dev/packages/integration_test/score) | [![likes](https://badges.bar/integration_test/likes)](https://pub.dev/packages/integration_test/score) | +| [in_app_purchase](./packages/in_app_purchase/) | [![pub package](https://img.shields.io/pub/v/in_app_purchase.svg)](https://pub.dev/packages/in_app_purchase) | [![pub points](https://badges.bar/in_app_purchase/pub%20points)](https://pub.dev/packages/in_app_purchase/score) | [![popularity](https://badges.bar/in_app_purchase/popularity)](https://pub.dev/packages/in_app_purchase/score) | [![likes](https://badges.bar/in_app_purchase/likes)](https://pub.dev/packages/in_app_purchase/score) | +| [ios_platform_images](./packages/ios_platform_images/) | [![pub package](https://img.shields.io/pub/v/ios_platform_images.svg)](https://pub.dev/packages/ios_platform_images) | [![pub points](https://badges.bar/ios_platform_images/pub%20points)](https://pub.dev/packages/ios_platform_images/score) | [![popularity](https://badges.bar/ios_platform_images/popularity)](https://pub.dev/packages/ios_platform_images/score) | [![likes](https://badges.bar/ios_platform_images/likes)](https://pub.dev/packages/ios_platform_images/score) | +| [local_auth](./packages/local_auth/) | [![pub package](https://img.shields.io/pub/v/local_auth.svg)](https://pub.dev/packages/local_auth) | [![pub points](https://badges.bar/local_auth/pub%20points)](https://pub.dev/packages/local_auth/score) | [![popularity](https://badges.bar/local_auth/popularity)](https://pub.dev/packages/local_auth/score) | [![likes](https://badges.bar/local_auth/likes)](https://pub.dev/packages/local_auth/score) | +| [package_info](./packages/package_info/) | [![pub package](https://img.shields.io/pub/v/package_info.svg)](https://pub.dev/packages/package_info) | [![pub points](https://badges.bar/package_info/pub%20points)](https://pub.dev/packages/package_info/score) | [![popularity](https://badges.bar/package_info/popularity)](https://pub.dev/packages/package_info/score) | [![likes](https://badges.bar/package_info/likes)](https://pub.dev/packages/package_info/score) | +| [path_provider](./packages/path_provider/) | [![pub package](https://img.shields.io/pub/v/path_provider.svg)](https://pub.dev/packages/path_provider) | [![pub points](https://badges.bar/path_provider/pub%20points)](https://pub.dev/packages/path_provider/score) | [![popularity](https://badges.bar/path_provider/popularity)](https://pub.dev/packages/path_provider/score) | [![likes](https://badges.bar/path_provider/likes)](https://pub.dev/packages/path_provider/score) | +| [plugin_platform_interface](./packages/plugin_platform_interface/) | [![pub package](https://img.shields.io/pub/v/plugin_platform_interface.svg)](https://pub.dev/packages/plugin_platform_interface) | [![pub points](https://badges.bar/plugin_platform_interface/pub%20points)](https://pub.dev/packages/plugin_platform_interface/score) | [![popularity](https://badges.bar/plugin_platform_interface/popularity)](https://pub.dev/packages/plugin_platform_interface/score) | [![likes](https://badges.bar/plugin_platform_interface/likes)](https://pub.dev/packages/plugin_platform_interface/score) | +| [quick_actions](./packages/quick_actions/) | [![pub package](https://img.shields.io/pub/v/quick_actions.svg)](https://pub.dev/packages/quick_actions) | [![pub points](https://badges.bar/quick_actions/pub%20points)](https://pub.dev/packages/quick_actions/score) | [![popularity](https://badges.bar/quick_actions/popularity)](https://pub.dev/packages/quick_actions/score) | [![likes](https://badges.bar/quick_actions/likes)](https://pub.dev/packages/quick_actions/score) | +| [sensors](./packages/sensors/) | [![pub package](https://img.shields.io/pub/v/sensors.svg)](https://pub.dev/packages/sensors) | [![pub points](https://badges.bar/sensors/pub%20points)](https://pub.dev/packages/sensors/score) | [![popularity](https://badges.bar/sensors/popularity)](https://pub.dev/packages/sensors/score) | [![likes](https://badges.bar/sensors/likes)](https://pub.dev/packages/sensors/score) | +| [share](./packages/share/) | [![pub package](https://img.shields.io/pub/v/share.svg)](https://pub.dev/packages/share) | [![pub points](https://badges.bar/share/pub%20points)](https://pub.dev/packages/share/score) | [![popularity](https://badges.bar/share/popularity)](https://pub.dev/packages/share/score) | [![likes](https://badges.bar/share/likes)](https://pub.dev/packages/share/score) | +| [shared_preferences](./packages/shared_preferences/) | [![pub package](https://img.shields.io/pub/v/shared_preferences.svg)](https://pub.dev/packages/shared_preferences) | [![pub points](https://badges.bar/shared_preferences/pub%20points)](https://pub.dev/packages/shared_preferences/score) | [![popularity](https://badges.bar/shared_preferences/popularity)](https://pub.dev/packages/shared_preferences/score) | [![likes](https://badges.bar/shared_preferences/likes)](https://pub.dev/packages/shared_preferences/score) | +| [url_launcher](./packages/url_launcher/) | [![pub package](https://img.shields.io/pub/v/url_launcher.svg)](https://pub.dev/packages/url_launcher) | [![pub points](https://badges.bar/url_launcher/pub%20points)](https://pub.dev/packages/url_launcher/score) | [![popularity](https://badges.bar/url_launcher/popularity)](https://pub.dev/packages/url_launcher/score) | [![likes](https://badges.bar/url_launcher/likes)](https://pub.dev/packages/url_launcher/score) | +| [video_player](./packages/video_player/) | [![pub package](https://img.shields.io/pub/v/video_player.svg)](https://pub.dev/packages/video_player) | [![pub points](https://badges.bar/video_player/pub%20points)](https://pub.dev/packages/video_player/score) | [![popularity](https://badges.bar/video_player/popularity)](https://pub.dev/packages/video_player/score) | [![likes](https://badges.bar/video_player/likes)](https://pub.dev/packages/video_player/score) | +| [webview_flutter](./packages/webview_flutter/) | [![pub package](https://img.shields.io/pub/v/webview_flutter.svg)](https://pub.dev/packages/webview_flutter) | [![pub points](https://badges.bar/webview_flutter/pub%20points)](https://pub.dev/packages/webview_flutter/score) | [![popularity](https://badges.bar/webview_flutter/popularity)](https://pub.dev/packages/webview_flutter/score) | [![likes](https://badges.bar/webview_flutter/likes)](https://pub.dev/packages/webview_flutter/score) | diff --git a/analysis_options.yaml b/analysis_options.yaml index 3a657c0e2408..b1261f36fac9 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:pedantic/analysis_options.yaml +include: package:pedantic/analysis_options.1.8.0.yaml analyzer: exclude: # Ignore generated files diff --git a/packages/android_alarm_manager/CHANGELOG.md b/packages/android_alarm_manager/CHANGELOG.md index 055086daf6d2..023a140fbcc9 100644 --- a/packages/android_alarm_manager/CHANGELOG.md +++ b/packages/android_alarm_manager/CHANGELOG.md @@ -1,3 +1,78 @@ +## 0.4.5+17 + +* Update Dart SDK constraint in example. + +## 0.4.5+16 + +* Remove unnecessary workaround from test. + +## 0.4.5+15 + +* Update android compileSdkVersion to 29. + +## 0.4.5+14 + +* Keep handling deprecated Android v1 classes for backward compatibility. + +## 0.4.5+13 + +* Android Code Inspection and Clean up. + +## 0.4.5+12 + +* Update package:e2e reference to use the local version in the flutter/plugins + repository. + +## 0.4.5+11 + +* Update lower bound of dart dependency to 2.1.0. + +## 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). + +## 0.4.5+9 + +* Fix CocoaPods podspec lint warnings. + +## 0.4.5+8 + +* Remove `MainActivity` references in android example app and tests. + +## 0.4.5+7 + +* Update minimum Flutter version to 1.12.13+hotfix.5 +* Clean up various Android workarounds no longer needed after framework v1.12. +* Complete v2 embedding support. + +## 0.4.5+6 + +* Replace deprecated `getFlutterEngine` call on Android. + +## 0.4.5+5 + +* Added an Espresso test. + +## 0.4.5+4 + +* Make the pedantic dev_dependency explicit. + +## 0.4.5+3 + +* Fixed issue where callback lookup would fail while running in the background. + +## 0.4.5+2 + +* Remove the deprecated `author:` field from pubspec.yaml +* Migrate the plugin to the pubspec platforms manifest. +* Require Flutter SDK 1.10.0 or greater. + +## 0.4.5+1 + +* Loosen Flutter version restriction to 1.9.1. **NOTE: plugin registration + for the background isolate will not work correctly for applications using the + V2 Flutter Android embedding for Flutter versions lower than 1.12.** + ## 0.4.5 * Add support for Flutter Android embedding V2 diff --git a/packages/android_alarm_manager/LICENSE b/packages/android_alarm_manager/LICENSE index c89293372cf3..a6d6c0749818 100644 --- a/packages/android_alarm_manager/LICENSE +++ b/packages/android_alarm_manager/LICENSE @@ -1,27 +1,25 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Copyright 2017 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/android_alarm_manager/README.md b/packages/android_alarm_manager/README.md index 33a98b71aab1..e7c7f6ee2713 100644 --- a/packages/android_alarm_manager/README.md +++ b/packages/android_alarm_manager/README.md @@ -5,6 +5,13 @@ A Flutter plugin for accessing the Android AlarmManager service, and running Dart code in the background when alarms fire. +**Please set your constraint to `android_alarm_manager: '>=0.4.y+x <2.0.0'`** + +## Backward compatible 1.0.0 version is coming +The plugin has reached a stable API, we guarantee that version `1.0.0` will be backward compatible with `0.4.y+z`. +Please use `android_alarm_manager: '>=0.4.y+x <2.0.0'` as your dependency constraint to allow a smoother ecosystem migration. +For more details see: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0 + ## Getting Started After importing this plugin to your project as usual, add the following to your @@ -59,11 +66,21 @@ will not run in the same isolate as the main application. Unlike threads, isolat 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 + If alarm callbacks will need access to other Flutter plugins, including the -alarm manager plugin itself, it is necessary to teach the background service how -to initialize plugins. This is done by giving the `AlarmService` a callback to call -in the application's `onCreate` method. See the example's +alarm manager plugin itself, it may be necessary to inform the background service how +to initialize plugins depending on which Flutter Android embedding the application is +using. + +### Flutter Android Embedding V1 + +For the Flutter Android Embedding V1, the background service must be provided a +callback to register plugins with the background isolate. This is done by giving +the `AlarmService` a callback to call the application's `onCreate` method. See the example's [Application overrides](https://github.com/flutter/plugins/blob/master/packages/android_alarm_manager/example/android/app/src/main/java/io/flutter/plugins/androidalarmmanagerexample/Application.java). + In particular, its `Application` class is as follows: ```java @@ -92,6 +109,17 @@ Which must be reflected in the application's `AndroidManifest.xml`. E.g.: **Note:** Not calling `AlarmService.setPluginRegistrant` will result in an exception being thrown when an alarm eventually fires. +### Flutter Android Embedding V2 (Flutter Version >= 1.12) + +For the Flutter Android Embedding V2, plugins are registered with the background +isolate via reflection so `AlarmService.setPluginRegistrant` does not need to be +called. + +**NOTE: this plugin is not completely compatible with the V2 embedding on +Flutter versions < 1.12 as the background isolate will not automatically +register plugins. This can be resolved by running `flutter upgrade` to upgrade +to the latest Flutter version.** + For help getting started with Flutter, view our online [documentation](http://flutter.io/). diff --git a/packages/android_alarm_manager/android/build.gradle b/packages/android_alarm_manager/android/build.gradle index 52da12479a40..5bbaf2291994 100644 --- a/packages/android_alarm_manager/android/build.gradle +++ b/packages/android_alarm_manager/android/build.gradle @@ -1,5 +1,6 @@ group 'io.flutter.plugins.androidalarmmanager' version '1.0-SNAPSHOT' +def args = ["-Xlint:deprecation","-Xlint:unchecked","-Werror"] buildscript { repositories { @@ -19,10 +20,14 @@ rootProject.allprojects { } } +project.getTasks().withType(JavaCompile){ + options.compilerArgs.addAll(args) +} + apply plugin: 'com.android.library' android { - compileSdkVersion 28 + compileSdkVersion 29 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,29 +45,3 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' api 'androidx.core:core:1.0.1' } - -// TODO(bkonyi): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348 -afterEvaluate { - def containsEmbeddingDependencies = false - for (def configuration : configurations.all) { - for (def dependency : configuration.dependencies) { - if (dependency.group == 'io.flutter' && - dependency.name.startsWith('flutter_embedding') && - dependency.isTransitive()) - { - containsEmbeddingDependencies = true - break - } - } - } - if (!containsEmbeddingDependencies) { - android { - dependencies { - def lifecycle_version = "1.1.1" - api 'android.arch.lifecycle:runtime:$lifecycle_version' - api 'android.arch.lifecycle:common:$lifecycle_version' - api 'android.arch.lifecycle:common-java8:$lifecycle_version' - } - } - } -} diff --git a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AlarmService.java b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AlarmService.java index fb6e7f85b317..3287789f6c3d 100644 --- a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AlarmService.java +++ b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AlarmService.java @@ -13,11 +13,9 @@ import android.util.Log; import androidx.core.app.AlarmManagerCompat; import androidx.core.app.JobIntentService; -import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -76,9 +74,8 @@ public static void startBackgroundIsolate(Context context, long callbackHandle) synchronized (alarmQueue) { // Handle all the alarm events received before the Dart isolate was // initialized, then clear the queue. - Iterator i = alarmQueue.iterator(); - while (i.hasNext()) { - flutterBackgroundExecutor.executeDartCallbackInBackgroundIsolate(i.next(), null); + for (Intent intent : alarmQueue) { + flutterBackgroundExecutor.executeDartCallbackInBackgroundIsolate(intent, null); } alarmQueue.clear(); } @@ -93,15 +90,18 @@ public static void setCallbackDispatcher(Context context, long callbackHandle) { } /** - * Sets the {@link PluginRegistrantCallback} used to register the plugins used by an application - * with the newly spawned background isolate. + * Sets the {@link io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback} used to + * register the plugins used by an application with the newly spawned background isolate. * *

This should be invoked in {@link Application.onCreate} with {@link * GeneratedPluginRegistrant} in applications using the V1 embedding API in order to use other * plugins in the background isolate. For applications using the V2 embedding API, it is not - * necessary to set a {@link PluginRegistrantCallback} as plugins are registered automatically. + * necessary to set a {@link io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback} as + * plugins are registered automatically. */ - public static void setPluginRegistrant(PluginRegistrantCallback callback) { + @SuppressWarnings("deprecation") + public static void setPluginRegistrant( + io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback callback) { // Indirectly set in FlutterBackgroundExecutor for backwards compatibility. FlutterBackgroundExecutor.setPluginRegistrant(callback); } @@ -231,7 +231,7 @@ public static void cancel(Context context, int requestCode) { } private static String getPersistentAlarmKey(int requestCode) { - return "android_alarm_manager/persistent_alarm_" + Integer.toString(requestCode); + return "android_alarm_manager/persistent_alarm_" + requestCode; } private static void addPersistentAlarm( @@ -276,13 +276,14 @@ private static void addPersistentAlarm( } private static void clearPersistentAlarm(Context context, int requestCode) { + String request = String.valueOf(requestCode); SharedPreferences p = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0); synchronized (persistentAlarmsLock) { Set persistentAlarms = p.getStringSet(PERSISTENT_ALARMS_SET_KEY, null); - if ((persistentAlarms == null) || !persistentAlarms.contains(requestCode)) { + if ((persistentAlarms == null) || !persistentAlarms.contains(request)) { return; } - persistentAlarms.remove(requestCode); + persistentAlarms.remove(request); String key = getPersistentAlarmKey(requestCode); p.edit().remove(key).putStringSet(PERSISTENT_ALARMS_SET_KEY, persistentAlarms).apply(); @@ -301,14 +302,12 @@ public static void reschedulePersistentAlarms(Context context) { return; } - Iterator it = persistentAlarms.iterator(); - while (it.hasNext()) { - int requestCode = Integer.parseInt(it.next()); + for (String persistentAlarm : persistentAlarms) { + int requestCode = Integer.parseInt(persistentAlarm); String key = getPersistentAlarmKey(requestCode); String json = p.getString(key, null); if (json == null) { - Log.e( - TAG, "Data for alarm request code " + Integer.toString(requestCode) + " is invalid."); + Log.e(TAG, "Data for alarm request code " + requestCode + " is invalid."); continue; } try { diff --git a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AndroidAlarmManagerPlugin.java b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AndroidAlarmManagerPlugin.java index 9db627022f72..557913a626d5 100644 --- a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AndroidAlarmManagerPlugin.java +++ b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/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; import io.flutter.plugin.common.JSONMethodCodec; @@ -13,8 +14,6 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry.Registrar; -import io.flutter.view.FlutterNativeView; import org.json.JSONArray; import org.json.JSONException; @@ -28,8 +27,8 @@ *

  • The Dart side of this plugin sends the Android side a "AlarmService.start" message, along * with a Dart callback handle for a Dart callback that should be immediately invoked by a * background Dart isolate. - *
  • The Android side of this plugin spins up a background {@link FlutterNativeView}, which - * includes a background Dart isolate. + *
  • The Android side of this plugin spins up a background {@link FlutterEngine}, which includes + * a background Dart isolate. *
  • The Android side of this plugin instructs the new background Dart isolate to execute the * callback that was received in the "AlarmService.start" message. *
  • The Dart side of this plugin, running within the new background isolate, executes the @@ -49,12 +48,13 @@ public class AndroidAlarmManagerPlugin implements FlutterPlugin, MethodCallHandl /** * Registers this plugin with an associated Flutter execution context, represented by the given - * {@link Registrar}. + * {@link io.flutter.plugin.common.PluginRegistry.Registrar}. * *

    Once this method is executed, an instance of {@code AndroidAlarmManagerPlugin} will be * connected to, and running against, the associated Flutter execution context. */ - public static void registerWith(Registrar registrar) { + @SuppressWarnings("deprecation") + public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) { if (instance == null) { instance = new AndroidAlarmManagerPlugin(); } @@ -63,8 +63,7 @@ public static void registerWith(Registrar registrar) { @Override public void onAttachedToEngine(FlutterPluginBinding binding) { - onAttachedToEngine( - binding.getApplicationContext(), binding.getFlutterEngine().getDartExecutor()); + onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger()); } public void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger) { @@ -108,37 +107,43 @@ public void onMethodCall(MethodCall call, Result result) { String method = call.method; Object arguments = call.arguments; try { - if (method.equals("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); - } else if (method.equals("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); - } else if (method.equals("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); - } else if (method.equals("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); - } else { - result.notImplemented(); + 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); diff --git a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/FlutterBackgroundExecutor.java b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/FlutterBackgroundExecutor.java index c7eebc2332bf..86010ff3f089 100644 --- a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/FlutterBackgroundExecutor.java +++ b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/FlutterBackgroundExecutor.java @@ -19,9 +19,7 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback; import io.flutter.view.FlutterCallbackInformation; -import io.flutter.view.FlutterMain; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; @@ -32,7 +30,10 @@ public class FlutterBackgroundExecutor implements MethodCallHandler { private static final String TAG = "FlutterBackgroundExecutor"; private static final String CALLBACK_HANDLE_KEY = "callback_handle"; - private static PluginRegistrantCallback pluginRegistrantCallback; + + @SuppressWarnings("deprecation") + private static io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback + pluginRegistrantCallback; /** * The {@link MethodChannel} that connects the Android side of this plugin with the background @@ -45,14 +46,16 @@ public class FlutterBackgroundExecutor implements MethodCallHandler { private AtomicBoolean isCallbackDispatcherReady = new AtomicBoolean(false); /** - * Sets the {@code PluginRegistrantCallback} used to register plugins with the newly spawned - * isolate. + * Sets the {@code io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback} used to + * register plugins with the newly spawned isolate. * *

    Note: this is only necessary for applications using the V1 engine embedding API as plugins * are automatically registered via reflection in the V2 engine embedding API. If not set, alarm * callbacks will not be able to utilize functionality from other plugins. */ - public static void setPluginRegistrant(PluginRegistrantCallback callback) { + @SuppressWarnings("deprecation") + public static void setPluginRegistrant( + io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback callback) { pluginRegistrantCallback = callback; } @@ -78,7 +81,6 @@ private void 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 @@ -102,7 +104,7 @@ public void onMethodCall(MethodCall call, Result result) { *

    The isolate is configured as follows: * *