diff --git a/.gitignore b/.gitignore
index 750dafc..7e38965 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,9 @@
.DS_Store
.dart_tool/
-.idea
+
.packages
.pub/
build/
+
+.idea
diff --git a/.metadata b/.metadata
index 9ead207..782b4a7 100644
--- a/.metadata
+++ b/.metadata
@@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.
version:
- revision: 17813975a93f5f239dbe03a3cd8a88e756a40cbd
+ revision: 6135091de9f8f6befc2ec7f8835d28d43a21cd05
channel: master
project_type: plugin
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c2b39a..5342a4b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
## 0.0.1
1. 使用[DownloadManager](https://developer.android.com/reference/android/app/DownloadManager)进行下载
-2. 监听下载完成广播
+2. 监听下载完成广播
3. 适配[Android 6.0运行时权限]() 文件存储在app目录, 不需要申请运行时权限
4. 适配[Android 7.0FileProvider](https://developer.android.com/reference/android/support/v4/content/FileProvider)
5. 适配[Android 8.0安装权限]()
@@ -28,4 +28,8 @@
1.update README.MD
## 0.1.3
-1.fix issues[#3](https://github.com/mofada/flutter_update_app/issues/3)
\ No newline at end of file
+1.fix issues[#3](https://github.com/mofada/flutter_update_app/issues/3)
+
+## 0.1.4
+1. fix issues[#5](https://github.com/mofada/flutter_update_app/issues/5)
+2.change gradle version
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 261eeb9..ba75c69 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,201 +1 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+TODO: Add your license here.
diff --git a/README.md b/README.md
index e30559d..c2fd8f1 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,15 @@
# [update_app](https://pub.dev/packages/update_app)
-Update the app, pass in the updated address, and update the app.
-更新app, 传入更新的地址, 进行app更新
+Update the app, pass in the updated address, and update the app.
+更新app, 传入更新的地址, 进行app更新
-The Android part is implemented using DownloadManager. If the file has been downloaded, install it directly.
-Android部分使用DownloadManager实现.若文件已下载, 则直接安装.
+The Android part is implemented using DownloadManager. If the file has been downloaded, install it directly.
+Android部分使用DownloadManager实现.若文件已下载, 则直接安装.
-The Ios section does not support external updates, skip the App Store.
+The Ios section does not support external updates, skip the App Store.
Ios部分不支持外部更新, 跳转App Store.
## Experience demo(体验Demo)
-[download apk(下载APK)](apks/app-debug.apk)
+[download apk(下载APK)](apks/app-debug.apk)
![screen](images/screen.png)
@@ -23,17 +23,17 @@ UpdateApp.updateApp(url: "apkPath",appleId:"375380948",title:"通知标题",desc
# Features(特点)
## Android part(Android部分)
-1. Download using [DownloadManager](https://developer.android.com/reference/android/app/DownloadManager)
+1. Download using [DownloadManager](https://developer.android.com/reference/android/app/DownloadManager)
使用[DownloadManager](https://developer.android.com/reference/android/app/DownloadManager)进行下载
-2. Monitor download completion broadcast
- 监听下载完成广播
-3. Adapt [Android 6.0 Runtime Permissions](https://developer.android.com/training/permissions/requesting?hl=en) Files are stored in the app directory, no need to apply for runtime permissions
+2. Monitor download completion broadcast
+ 监听下载完成广播
+3. Adapt [Android 6.0 Runtime Permissions](https://developer.android.com/training/permissions/requesting?hl=en) Files are stored in the app directory, no need to apply for runtime permissions
适配[Android 6.0运行时权限](https://developer.android.com/training/permissions/requesting?hl=zh-cn) 文件存储在app目录, 不需要申请运行时权限
-4. Adapt [Android 7.0FileProvider](https://developer.android.com/reference/android/support/v4/content/FileProvider)
+4. Adapt [Android 7.0FileProvider](https://developer.android.com/reference/android/support/v4/content/FileProvider)
适配[Android 7.0FileProvider](https://developer.android.com/reference/android/support/v4/content/FileProvider)
-5. Adapt Android 8.0 installation permissions
+5. Adapt Android 8.0 installation permissions
适配Android 8.0安装权限
-6. Adapt [Android 9.0 Network Security Configuration] (https://developer.android.com/training/articles/security-config)
+6. Adapt [Android 9.0 Network Security Configuration] (https://developer.android.com/training/articles/security-config)
适配[Android 9.0网络安全配置](https://developer.android.com/training/articles/security-config)
## IOS section(IOS部分)
diff --git a/android/build.gradle b/android/build.gradle
index 813f07e..c2a52a6 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -2,44 +2,42 @@ group 'cn.mofada.update_app'
version '1.0-SNAPSHOT'
buildscript {
- ext.kotlin_version = '1.3.72'
- repositories {
- google()
- jcenter()
- }
+ ext.kotlin_version = '1.3.70'
+ repositories {
+ google()
+ jcenter()
+ }
- dependencies {
- classpath 'com.android.tools.build:gradle:4.0.0'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.0.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
}
rootProject.allprojects {
- repositories {
- google()
- jcenter()
- }
+ repositories {
+ google()
+ jcenter()
+ }
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
- compileSdkVersion 28
+ compileSdkVersion 28
- sourceSets {
- main.java.srcDirs += 'src/main/kotlin'
- }
- defaultConfig {
- minSdkVersion 16
-// testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
- lintOptions {
- disable 'InvalidPackage'
- }
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+ defaultConfig {
+ minSdkVersion 16
+ }
+ lintOptions {
+ disable 'InvalidPackage'
+ }
}
dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation 'androidx.core:core:1.1.0'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
diff --git a/android/gradle.properties b/android/gradle.properties
index 755300e..38c8d45 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
-
+android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 2130e76..f4e4472 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -23,5 +23,4 @@
android:resource="@xml/update_path" />
-
diff --git a/android/src/main/kotlin/cn/mofada/update_app/UpdateAppPlugin.kt b/android/src/main/kotlin/cn/mofada/update_app/UpdateAppPlugin.kt
index b1a0754..728bd6b 100644
--- a/android/src/main/kotlin/cn/mofada/update_app/UpdateAppPlugin.kt
+++ b/android/src/main/kotlin/cn/mofada/update_app/UpdateAppPlugin.kt
@@ -1,6 +1,8 @@
package cn.mofada.update_app
import android.content.Context
+import androidx.annotation.NonNull;
+
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
@@ -8,40 +10,50 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
-class UpdateAppPlugin : FlutterPlugin, MethodCallHandler {
+/** UpdateAppPlugin */
+public class UpdateAppPlugin : FlutterPlugin, MethodCallHandler {
private lateinit var channel: MethodChannel
private lateinit var context: Context
+
+ override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
+ channel = MethodChannel(flutterPluginBinding.flutterEngine.dartExecutor, sChannelName)
+ context = flutterPluginBinding.applicationContext
+ channel.setMethodCallHandler(this)
+ }
+
+ // This static function is optional and equivalent to onAttachedToEngine. It supports the old
+ // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
+ // plugin registration via this function while apps migrate to use the new Android APIs
+ // post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
+ //
+ // It is encouraged to share logic between onAttachedToEngine and registerWith to keep
+ // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
+ // depending on the user's project. onAttachedToEngine or registerWith must both be defined
+ // in the same class.
companion object {
+ private const val sChannelName = "cn.mofada.update_app"
+
@JvmStatic
fun registerWith(registrar: Registrar) {
- val channel = MethodChannel(registrar.messenger(), "cn.mofada.cn/update_app")
+ val channel = MethodChannel(registrar.messenger(), sChannelName)
val updateAppPlugin = UpdateAppPlugin()
- channel.setMethodCallHandler(updateAppPlugin)
//初始化上下文
updateAppPlugin.context = registrar.context()
+ channel.setMethodCallHandler(updateAppPlugin)
}
}
-
- override fun onMethodCall(call: MethodCall, result: Result) {
+ override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
"updateApp" -> result.success(downloadApp(call, context))
+ "getPlatformVersion" -> result.success("Android ${android.os.Build.VERSION.RELEASE}")
else -> result.notImplemented()
}
}
- override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
- channel = MethodChannel(flutterPluginBinding.flutterEngine.dartExecutor, "cn.mofada.cn/update_app")
- context = flutterPluginBinding.applicationContext
- channel.setMethodCallHandler(this)
- }
-
- override fun onDetachedFromEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
+ override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}
-
-
-
diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies
index c57e9bc..f065a71 100644
--- a/example/.flutter-plugins-dependencies
+++ b/example/.flutter-plugins-dependencies
@@ -1 +1 @@
-{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[],"android":[],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"update_app","dependencies":[]}],"date_created":"2020-06-03 21:12:52.035828","version":"1.17.2"}
\ No newline at end of file
+{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"update_app","path":"E:\\\\Flutter\\\\update_app\\\\","dependencies":[]}],"android":[{"name":"update_app","path":"E:\\\\Flutter\\\\update_app\\\\","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"update_app","dependencies":[]}],"date_created":"2020-06-18 23:42:36.501969","version":"1.19.0-3.0.pre.13"}
\ No newline at end of file
diff --git a/example/.gitignore b/example/.gitignore
index 2ddde2a..f3c2053 100644
--- a/example/.gitignore
+++ b/example/.gitignore
@@ -22,52 +22,23 @@
# Flutter/Dart/Pub related
**/doc/api/
+**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
+.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
-# Android related
-**/android/**/gradle-wrapper.jar
-**/android/.gradle
-**/android/captures/
-**/android/gradlew
-**/android/gradlew.bat
-**/android/local.properties
-**/android/**/GeneratedPluginRegistrant.java
+# Web related
+lib/generated_plugin_registrant.dart
-# iOS/XCode related
-**/ios/**/*.mode1v3
-**/ios/**/*.mode2v3
-**/ios/**/*.moved-aside
-**/ios/**/*.pbxuser
-**/ios/**/*.perspectivev3
-**/ios/**/*sync/
-**/ios/**/.sconsign.dblite
-**/ios/**/.tags*
-**/ios/**/.vagrant/
-**/ios/**/DerivedData/
-**/ios/**/Icon?
-**/ios/**/Pods/
-**/ios/**/.symlinks/
-**/ios/**/profile
-**/ios/**/xcuserdata
-**/ios/.generated/
-**/ios/Flutter/App.framework
-**/ios/Flutter/Flutter.framework
-**/ios/Flutter/Generated.xcconfig
-**/ios/Flutter/app.flx
-**/ios/Flutter/app.zip
-**/ios/Flutter/flutter_assets/
-**/ios/Flutter/flutter_export_environment.sh
-**/ios/ServiceDefinitions.json
-**/ios/Runner/GeneratedPluginRegistrant.*
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
# Exceptions to above rules.
-!**/ios/**/default.mode1v3
-!**/ios/**/default.mode2v3
-!**/ios/**/default.pbxuser
-!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
diff --git a/example/.metadata b/example/.metadata
index a4c4697..a19c24c 100644
--- a/example/.metadata
+++ b/example/.metadata
@@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.
version:
- revision: 17813975a93f5f239dbe03a3cd8a88e756a40cbd
+ revision: 6135091de9f8f6befc2ec7f8835d28d43a21cd05
channel: master
project_type: app
diff --git a/example/android/.gitignore b/example/android/.gitignore
index bc2100d..0a741cb 100644
--- a/example/android/.gitignore
+++ b/example/android/.gitignore
@@ -5,3 +5,7 @@ gradle-wrapper.jar
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
index ddb4728..253dc3c 100644
--- a/example/android/app/build.gradle
+++ b/example/android/app/build.gradle
@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
- compileSdkVersion 29
+ compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@@ -40,10 +40,9 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "cn.mofada.update_app_example"
minSdkVersion 16
- targetSdkVersion 29
+ targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -61,7 +60,4 @@ flutter {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'androidx.test:runner:1.1.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index 3d3f964..08be72a 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
-
+
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
+
+
+
+
diff --git a/example/android/app/src/main/kotlin/cn/mofada/example/MainActivity.kt b/example/android/app/src/main/kotlin/cn/mofada/example/MainActivity.kt
deleted file mode 100644
index 2fbdfcc..0000000
--- a/example/android/app/src/main/kotlin/cn/mofada/example/MainActivity.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package cn.mofada.example
-
-import io.flutter.embedding.android.FlutterActivity
-
-class MainActivity: FlutterActivity() {
-}
diff --git a/example/android/app/src/main/kotlin/cn/mofada/update_app_example/MainActivity.kt b/example/android/app/src/main/kotlin/cn/mofada/update_app_example/MainActivity.kt
index 236e2e5..e95b4c8 100644
--- a/example/android/app/src/main/kotlin/cn/mofada/update_app_example/MainActivity.kt
+++ b/example/android/app/src/main/kotlin/cn/mofada/update_app_example/MainActivity.kt
@@ -1,13 +1,6 @@
package cn.mofada.update_app_example
-import android.os.Bundle
-
-import io.flutter.app.FlutterActivity
-import io.flutter.plugins.GeneratedPluginRegistrant
+import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- GeneratedPluginRegistrant.registerWith(this)
- }
}
diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml
index 00fa441..1f83a33 100644
--- a/example/android/app/src/main/res/values/styles.xml
+++ b/example/android/app/src/main/res/values/styles.xml
@@ -1,8 +1,18 @@
+
+
+
diff --git a/example/android/build.gradle b/example/android/build.gradle
index fbd0572..3100ad2 100644
--- a/example/android/build.gradle
+++ b/example/android/build.gradle
@@ -1,5 +1,5 @@
buildscript {
- ext.kotlin_version = '1.3.10'
+ ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
index 1515360..38c8d45 100644
--- a/example/android/gradle.properties
+++ b/example/android/gradle.properties
@@ -1,5 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
-
+android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
-android.enableR8=true
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
index 1bb16a2..296b146 100644
--- a/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Tue Sep 24 10:09:30 CST 2019
+#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
diff --git a/example/android/settings.gradle b/example/android/settings.gradle
index 5a2f14f..d3b6a40 100644
--- a/example/android/settings.gradle
+++ b/example/android/settings.gradle
@@ -1,15 +1,15 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
include ':app'
-def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
-def plugins = new Properties()
-def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
-if (pluginsFile.exists()) {
- pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
-}
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
-plugins.each { name, path ->
- def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
- include ":$name"
- project(":$name").projectDir = pluginDirectory
-}
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/example/android/settings_aar.gradle b/example/android/settings_aar.gradle
deleted file mode 100644
index e7b4def..0000000
--- a/example/android/settings_aar.gradle
+++ /dev/null
@@ -1 +0,0 @@
-include ':app'
diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig
index e8efba1..592ceee 100644
--- a/example/ios/Flutter/Debug.xcconfig
+++ b/example/ios/Flutter/Debug.xcconfig
@@ -1,2 +1 @@
-#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig
index 399e934..592ceee 100644
--- a/example/ios/Flutter/Release.xcconfig
+++ b/example/ios/Flutter/Release.xcconfig
@@ -1,2 +1 @@
-#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
diff --git a/example/ios/Podfile b/example/ios/Podfile
deleted file mode 100644
index e5e1440..0000000
--- a/example/ios/Podfile
+++ /dev/null
@@ -1,77 +0,0 @@
-# Using a CDN with CocoaPods 1.7.2 or later can save a lot of time on pod installation, but it's experimental rather than the default.
-# source 'https://cdn.cocoapods.org/'
-
-# Uncomment this line to define a global platform for your project
-# platform :ios, '9.0'
-
-# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
-ENV['COCOAPODS_DISABLE_STATS'] = 'true'
-
-project 'Runner', {
- 'Debug' => :debug,
- 'Profile' => :release,
- 'Release' => :release,
-}
-
-def parse_KV_file(file, separator='=')
- file_abs_path = File.expand_path(file)
- if !File.exists? file_abs_path
- return [];
- end
- pods_ary = []
- skip_line_start_symbols = ["#", "/"]
- File.foreach(file_abs_path) { |line|
- next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
- plugin = line.split(pattern=separator)
- if plugin.length == 2
- podname = plugin[0].strip()
- path = plugin[1].strip()
- podpath = File.expand_path("#{path}", file_abs_path)
- pods_ary.push({:name => podname, :path => podpath});
- else
- puts "Invalid plugin specification: #{line}"
- end
- }
- return pods_ary
-end
-
-target 'Runner' do
- use_frameworks!
-
- # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
- # referring to absolute paths on developers' machines.
- system('rm -rf .symlinks')
- system('mkdir -p .symlinks/plugins')
-
- # Flutter Pods
- generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
- if generated_xcode_build_settings.empty?
- puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first."
- end
- generated_xcode_build_settings.map { |p|
- if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
- symlink = File.join('.symlinks', 'flutter')
- File.symlink(File.dirname(p[:path]), symlink)
- pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
- end
- }
-
- # Plugin Pods
- plugin_pods = parse_KV_file('../.flutter-plugins')
- plugin_pods.map { |p|
- symlink = File.join('.symlinks', 'plugins', p[:name])
- File.symlink(p[:path], symlink)
- pod p[:name], :path => File.join(symlink, 'ios')
- }
-end
-
-# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
-install! 'cocoapods', :disable_input_output_paths => true
-
-post_install do |installer|
- installer.pods_project.targets.each do |target|
- target.build_configurations.each do |config|
- config.build_settings['ENABLE_BITCODE'] = 'NO'
- end
- end
-end
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
deleted file mode 100644
index 4dc951c..0000000
--- a/example/ios/Podfile.lock
+++ /dev/null
@@ -1,22 +0,0 @@
-PODS:
- - Flutter (1.0.0)
- - update_app (0.0.1):
- - Flutter
-
-DEPENDENCIES:
- - Flutter (from `.symlinks/flutter/ios`)
- - update_app (from `.symlinks/plugins/update_app/ios`)
-
-EXTERNAL SOURCES:
- Flutter:
- :path: ".symlinks/flutter/ios"
- update_app:
- :path: ".symlinks/plugins/update_app/ios"
-
-SPEC CHECKSUMS:
- Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
- update_app: 6bb41a97486a79bfbe45148ee918e8d7b425e422
-
-PODFILE CHECKSUM: 10ae9c18d12c9ffc2275c9a159a3b1e281990db0
-
-COCOAPODS: 1.7.2
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index 6023877..78b58ea 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -9,12 +9,7 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
- 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
- 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
- 7BB60D588F4167455FFCB1AF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F62F87FA0C9242A65235C2CF /* Pods_Runner.framework */; };
- 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
- 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@@ -27,8 +22,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
- 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
- 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -39,22 +32,16 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
- 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
- 43FFC222A382B168690B0F96 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
- 76C18E67051AAAC09A15ED36 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
- 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- E72F1E7E6D49C95C8CD6C9B4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
- F62F87FA0C9242A65235C2CF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -62,39 +49,16 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
- 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
- 7BB60D588F4167455FFCB1AF /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
- 6C5F057EABDEC3E0D1F56827 /* Pods */ = {
- isa = PBXGroup;
- children = (
- 76C18E67051AAAC09A15ED36 /* Pods-Runner.debug.xcconfig */,
- 43FFC222A382B168690B0F96 /* Pods-Runner.release.xcconfig */,
- E72F1E7E6D49C95C8CD6C9B4 /* Pods-Runner.profile.xcconfig */,
- );
- path = Pods;
- sourceTree = "";
- };
- 8031791213FFC6F444836051 /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- F62F87FA0C9242A65235C2CF /* Pods_Runner.framework */,
- );
- name = Frameworks;
- sourceTree = "";
- };
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
- 3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
- 9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
@@ -108,8 +72,6 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
- 6C5F057EABDEC3E0D1F56827 /* Pods */,
- 8031791213FFC6F444836051 /* Frameworks */,
);
sourceTree = "";
};
@@ -128,7 +90,6 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
- 97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
@@ -137,13 +98,6 @@
path = Runner;
sourceTree = "";
};
- 97C146F11CF9000F007C117D /* Supporting Files */ = {
- isa = PBXGroup;
- children = (
- );
- name = "Supporting Files";
- sourceTree = "";
- };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -151,14 +105,12 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
- 3D11ADE11BB3CD0E0984CB45 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
- 29B0F899AB886EEA7EAD82B8 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -176,17 +128,16 @@
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
- ORGANIZATIONNAME = "The Chromium Authors";
+ ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
- DevelopmentTeam = RW3MAS32G6;
- LastSwiftMigration = 0910;
+ LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
- compatibilityVersion = "Xcode 3.2";
+ compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
@@ -218,21 +169,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
- 29B0F899AB886EEA7EAD82B8 /* [CP] Embed Pods Frameworks */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "[CP] Embed Pods Frameworks";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
- showEnvVarsInLog = 0;
- };
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -245,29 +181,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
- };
- 3D11ADE11BB3CD0E0984CB45 /* [CP] Check Pods Manifest.lock */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- );
- inputPaths = (
- "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
- "${PODS_ROOT}/Manifest.lock",
- );
- name = "[CP] Check Pods Manifest.lock";
- outputFileListPaths = (
- );
- outputPaths = (
- "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
- showEnvVarsInLog = 0;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
@@ -319,7 +233,6 @@
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -375,7 +288,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = RW3MAS32G6;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -390,14 +302,13 @@
PRODUCT_BUNDLE_IDENTIFIER = cn.mofada.updateAppExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -453,7 +364,6 @@
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -510,7 +420,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = RW3MAS32G6;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -526,7 +435,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
@@ -538,7 +447,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = RW3MAS32G6;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -553,7 +461,7 @@
PRODUCT_BUNDLE_IDENTIFIER = cn.mofada.updateAppExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata
index 21a3cc1..1d526a1 100644
--- a/example/ios/Runner.xcworkspace/contents.xcworkspacedata
+++ b/example/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -4,7 +4,4 @@
-
-
diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h
index 7335fdf..308a2a5 100644
--- a/example/ios/Runner/Runner-Bridging-Header.h
+++ b/example/ios/Runner/Runner-Bridging-Header.h
@@ -1 +1 @@
-#import "GeneratedPluginRegistrant.h"
\ No newline at end of file
+#import "GeneratedPluginRegistrant.h"
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 1a01142..5441173 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -1,7 +1,5 @@
import 'package:flutter/material.dart';
-import 'dart:async';
-import 'package:flutter/services.dart';
import 'package:update_app/update_app.dart';
void main() => runApp(MyApp());
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 7265fc9..d937b09 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -1,20 +1,6 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
- archive:
- dependency: transitive
- description:
- name: archive
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "2.0.13"
- args:
- dependency: transitive
- description:
- name: args
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "1.6.0"
async:
dependency: transitive
description:
@@ -36,34 +22,34 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.3"
- collection:
- dependency: transitive
- description:
- name: collection
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "1.14.12"
- convert:
+ clock:
dependency: transitive
description:
- name: convert
+ name: clock
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.1"
- crypto:
+ version: "1.0.1"
+ collection:
dependency: transitive
description:
- name: crypto
+ name: collection
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.4"
+ version: "1.14.12"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.1.2"
+ version: "0.1.3"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.0"
flutter:
dependency: "direct main"
description: flutter
@@ -74,13 +60,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
- image:
- dependency: transitive
- description:
- name: image
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "2.1.12"
matcher:
dependency: transitive
description:
@@ -101,21 +80,7 @@ packages:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.6.4"
- petitparser:
- dependency: transitive
- description:
- name: petitparser
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "2.4.0"
- quiver:
- dependency: transitive
- description:
- name: quiver
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "2.1.3"
+ version: "1.7.0"
sky_engine:
dependency: transitive
description: flutter
@@ -162,7 +127,7 @@ packages:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.2.15"
+ version: "0.2.16"
typed_data:
dependency: transitive
description:
@@ -171,7 +136,7 @@ packages:
source: hosted
version: "1.1.6"
update_app:
- dependency: "direct dev"
+ dependency: "direct main"
description:
path: ".."
relative: true
@@ -184,12 +149,6 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.8"
- xml:
- dependency: transitive
- description:
- name: xml
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "3.6.1"
sdks:
- dart: ">=2.6.0 <3.0.0"
+ dart: ">=2.7.0 <3.0.0"
+ flutter: ">=1.10.0"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 53e3311..4052a3c 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -1,25 +1,33 @@
name: update_app_example
description: Demonstrates how to use the update_app plugin.
-publish_to: 'none'
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
environment:
- sdk: ">=2.1.0 <3.0.0"
+ sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
+ update_app:
+ # When depending on this package from a real application you should use:
+ # update_app: ^x.y.z
+ # See https://dart.dev/tools/pub/dependencies#version-constraints
+ # The example app is bundled with the plugin so we use a path dependency on
+ # the parent directory to use the current plugin's version.
+ path: ../
+
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^0.1.2
+ cupertino_icons: ^0.1.3
dev_dependencies:
flutter_test:
sdk: flutter
- update_app:
- path: ../
-
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
@@ -33,8 +41,8 @@ flutter:
# To add assets to your application, add an assets section, like this:
# assets:
- # - images/a_dot_burr.jpeg
- # - images/a_dot_ham.jpeg
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
diff --git a/example/web/favicon.png b/example/web/favicon.png
deleted file mode 100644
index 8aaa46a..0000000
Binary files a/example/web/favicon.png and /dev/null differ
diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png
deleted file mode 100644
index b749bfe..0000000
Binary files a/example/web/icons/Icon-192.png and /dev/null differ
diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png
deleted file mode 100644
index 88cfd48..0000000
Binary files a/example/web/icons/Icon-512.png and /dev/null differ
diff --git a/example/web/index.html b/example/web/index.html
deleted file mode 100644
index 9b7a438..0000000
--- a/example/web/index.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- example
-
-
-
-
-
-
-
-
diff --git a/example/web/manifest.json b/example/web/manifest.json
deleted file mode 100644
index c638001..0000000
--- a/example/web/manifest.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "name": "example",
- "short_name": "example",
- "start_url": ".",
- "display": "minimal-ui",
- "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/example/windows/.gitignore b/example/windows/.gitignore
new file mode 100644
index 0000000..d492d0d
--- /dev/null
+++ b/example/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/ephemeral/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/example/windows/AppConfiguration.props b/example/windows/AppConfiguration.props
new file mode 100644
index 0000000..0c3db6d
--- /dev/null
+++ b/example/windows/AppConfiguration.props
@@ -0,0 +1,6 @@
+
+
+
+ update_app_example
+
+
diff --git a/example/windows/FlutterBuild.vcxproj b/example/windows/FlutterBuild.vcxproj
new file mode 100644
index 0000000..8ef93f9
--- /dev/null
+++ b/example/windows/FlutterBuild.vcxproj
@@ -0,0 +1,50 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Profile
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}
+ Flutter Build
+ 10.0
+
+
+
+ v141
+ v142
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "$(ProjectDir)scripts\prepare_dependencies" $(Configuration)
+ Running Flutter backend build
+ force_to_run_every_time
+
+
+
+
+
+
+
+
diff --git a/example/windows/Runner.sln b/example/windows/Runner.sln
new file mode 100644
index 0000000..7bfc8e0
--- /dev/null
+++ b/example/windows/Runner.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29709.97
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Runner", "Runner.vcxproj", "{5A827760-CF8B-408A-99A3-B6C0AD2271E7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} = {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Flutter Build", "FlutterBuild.vcxproj", "{6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Flutter Plugins", "Flutter Plugins", "{5C2E738A-1DD3-445A-AAC8-EEB9648DD07C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Profile|x64 = Profile|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Debug|x64.ActiveCfg = Debug|x64
+ {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Debug|x64.Build.0 = Debug|x64
+ {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Profile|x64.ActiveCfg = Profile|x64
+ {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Profile|x64.Build.0 = Profile|x64
+ {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Release|x64.ActiveCfg = Release|x64
+ {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Release|x64.Build.0 = Release|x64
+ {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Debug|x64.ActiveCfg = Debug|x64
+ {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Debug|x64.Build.0 = Debug|x64
+ {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Profile|x64.ActiveCfg = Profile|x64
+ {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Profile|x64.Build.0 = Profile|x64
+ {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Release|x64.ActiveCfg = Release|x64
+ {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B8A69CB0-A974-4774-9EBD-1E5EECACD186}
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ EndGlobalSection
+EndGlobal
\ No newline at end of file
diff --git a/example/windows/Runner.vcxproj b/example/windows/Runner.vcxproj
new file mode 100644
index 0000000..8e6c5ca
--- /dev/null
+++ b/example/windows/Runner.vcxproj
@@ -0,0 +1,262 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Profile
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {5A827760-CF8B-408A-99A3-B6C0AD2271E7}
+ update_app_example
+ 10.0
+
+
+
+ Application
+ true
+ v141
+ v142
+ Unicode
+
+
+ Application
+ false
+ v141
+ v142
+ true
+ Unicode
+
+
+ Application
+ false
+ v141
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\
+
+
+ $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\
+
+
+ $(ProjectDir)..\build\windows\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(ProjectDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\
+
+
+
+ Level4
+ Disabled
+ true
+ true
+ $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories)
+ _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
+ true
+ 4100
+
+
+ flutter_windows.dll.lib;%(AdditionalDependencies)
+ $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)"
+
+
+ Bundling dependencies
+ Dummy_Run_Always
+
+
+
+
+
+
+ Level4
+ MaxSpeed
+ true
+ true
+ true
+ true
+ $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories)
+ _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
+ true
+ 4100
+
+
+ true
+ true
+ flutter_windows.dll.lib;%(AdditionalDependencies)
+ $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)"
+
+
+ Bundling dependencies
+ Dummy_Run_Always
+
+
+
+
+
+
+ Level4
+ MaxSpeed
+ true
+ true
+ true
+ true
+ $(ProjectDir);$(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories)
+ _MBCS;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
+ true
+ 4100
+
+
+ true
+ true
+ flutter_windows.dll.lib;%(AdditionalDependencies)
+ $(FLUTTER_EPHEMERAL_DIR);$(OutDir)..\Plugins;%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)"
+
+
+ Bundling dependencies
+ Dummy_Run_Always
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)
+
+
diff --git a/example/windows/Runner.vcxproj.filters b/example/windows/Runner.vcxproj.filters
new file mode 100644
index 0000000..761db86
--- /dev/null
+++ b/example/windows/Runner.vcxproj.filters
@@ -0,0 +1,88 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {2761a4b5-57b2-4d50-a677-d20ddc17a7f1}
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files\Client Wrapper
+
+
+ Source Files\Client Wrapper
+
+
+ Source Files\Client Wrapper
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+
+
+
+ Resource Files
+
+
+
+
+ Resource Files
+
+
+
diff --git a/example/windows/flutter/.template_version b/example/windows/flutter/.template_version
new file mode 100644
index 0000000..00750ed
--- /dev/null
+++ b/example/windows/flutter/.template_version
@@ -0,0 +1 @@
+3
diff --git a/example/windows/flutter/GeneratedPlugins.props b/example/windows/flutter/GeneratedPlugins.props
new file mode 100644
index 0000000..d3d26c7
--- /dev/null
+++ b/example/windows/flutter/GeneratedPlugins.props
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..4bfa0f3
--- /dev/null
+++ b/example/windows/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,9 @@
+//
+// Generated file. Do not edit.
+//
+
+#include "generated_plugin_registrant.h"
+
+
+void RegisterPlugins(flutter::PluginRegistry* registry) {
+}
diff --git a/example/windows/flutter/generated_plugin_registrant.h b/example/windows/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..9846246
--- /dev/null
+++ b/example/windows/flutter/generated_plugin_registrant.h
@@ -0,0 +1,13 @@
+//
+// Generated file. Do not edit.
+//
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include
+
+// Registers Flutter plugins.
+void RegisterPlugins(flutter::PluginRegistry* registry);
+
+#endif // GENERATED_PLUGIN_REGISTRANT_
diff --git a/example/windows/runner/Runner.rc b/example/windows/runner/Runner.rc
new file mode 100644
index 0000000..5b41a82
--- /dev/null
+++ b/example/windows/runner/Runner.rc
@@ -0,0 +1,70 @@
+// Microsoft Visual C++ generated resource script.
+//
+#pragma code_page(65001)
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP_ICON ICON "resources\\app_icon.ico"
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/example/windows/runner/flutter_window.cpp b/example/windows/runner/flutter_window.cpp
new file mode 100644
index 0000000..fe980cf
--- /dev/null
+++ b/example/windows/runner/flutter_window.cpp
@@ -0,0 +1,29 @@
+#include "flutter_window.h"
+
+#include "flutter/generated_plugin_registrant.h"
+
+FlutterWindow::FlutterWindow(RunLoop* run_loop,
+ const flutter::DartProject& project)
+ : run_loop_(run_loop), project_(project) {}
+
+FlutterWindow::~FlutterWindow() {}
+
+void FlutterWindow::OnCreate() {
+ Win32Window::OnCreate();
+
+ // The size here is arbitrary since SetChildContent will resize it.
+ flutter_controller_ =
+ std::make_unique(100, 100, project_);
+ RegisterPlugins(flutter_controller_.get());
+ run_loop_->RegisterFlutterInstance(flutter_controller_.get());
+ SetChildContent(flutter_controller_->view()->GetNativeWindow());
+}
+
+void FlutterWindow::OnDestroy() {
+ if (flutter_controller_) {
+ run_loop_->UnregisterFlutterInstance(flutter_controller_.get());
+ flutter_controller_ = nullptr;
+ }
+
+ Win32Window::OnDestroy();
+}
diff --git a/example/windows/runner/flutter_window.h b/example/windows/runner/flutter_window.h
new file mode 100644
index 0000000..4f41e16
--- /dev/null
+++ b/example/windows/runner/flutter_window.h
@@ -0,0 +1,37 @@
+#ifndef FLUTTER_WINDOW_H_
+#define FLUTTER_WINDOW_H_
+
+#include
+#include
+
+#include "run_loop.h"
+#include "win32_window.h"
+
+#include
+
+// 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();
+
+ protected:
+ // Win32Window:
+ void OnCreate() override;
+ void OnDestroy() override;
+
+ private:
+ // The run loop driving events for this window.
+ RunLoop* run_loop_;
+
+ // The project to run.
+ flutter::DartProject project_;
+
+ // The Flutter instance hosted by this window.
+ std::unique_ptr flutter_controller_;
+};
+
+#endif // FLUTTER_WINDOW_H_
diff --git a/example/windows/runner/main.cpp b/example/windows/runner/main.cpp
new file mode 100644
index 0000000..11b48e9
--- /dev/null
+++ b/example/windows/runner/main.cpp
@@ -0,0 +1,37 @@
+#include
+#include
+#include
+
+#include "flutter_window.h"
+#include "run_loop.h"
+#include "utils.h"
+#include "window_configuration.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(kFlutterWindowOriginX, kFlutterWindowOriginY);
+ Win32Window::Size size(kFlutterWindowWidth, kFlutterWindowHeight);
+ if (!window.CreateAndShow(kFlutterWindowTitle, origin, size)) {
+ return EXIT_FAILURE;
+ }
+ window.SetQuitOnClose(true);
+
+ run_loop.Run();
+
+ ::CoUninitialize();
+ return EXIT_SUCCESS;
+}
diff --git a/example/windows/runner/resource.h b/example/windows/runner/resource.h
new file mode 100644
index 0000000..66a65d1
--- /dev/null
+++ b/example/windows/runner/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Runner.rc
+//
+#define IDI_APP_ICON 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/example/windows/runner/resources/app_icon.ico b/example/windows/runner/resources/app_icon.ico
new file mode 100644
index 0000000..c04e20c
Binary files /dev/null and b/example/windows/runner/resources/app_icon.ico differ
diff --git a/example/windows/runner/run_loop.cpp b/example/windows/runner/run_loop.cpp
new file mode 100644
index 0000000..f91d6d4
--- /dev/null
+++ b/example/windows/runner/run_loop.cpp
@@ -0,0 +1,70 @@
+#include "run_loop.h"
+
+#include
+// Don't stomp std::min/std::max
+#undef max
+#undef min
+
+#include
+
+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());
+ }
+ // 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::FlutterViewController* flutter_instance) {
+ flutter_instances_.insert(flutter_instance);
+}
+
+void RunLoop::UnregisterFlutterInstance(
+ flutter::FlutterViewController* flutter_instance) {
+ flutter_instances_.erase(flutter_instance);
+}
+
+RunLoop::TimePoint RunLoop::ProcessFlutterMessages() {
+ TimePoint next_event_time = TimePoint::max();
+ for (auto flutter_controller : flutter_instances_) {
+ std::chrono::nanoseconds wait_duration =
+ flutter_controller->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;
+}
diff --git a/example/windows/runner/run_loop.h b/example/windows/runner/run_loop.h
new file mode 100644
index 0000000..442a58e
--- /dev/null
+++ b/example/windows/runner/run_loop.h
@@ -0,0 +1,40 @@
+#ifndef RUN_LOOP_H_
+#define RUN_LOOP_H_
+
+#include
+
+#include
+#include
+
+// A runloop that will service events for Flutter instances as well
+// as native messages.
+class RunLoop {
+ public:
+ RunLoop();
+ ~RunLoop();
+
+ // Prevent copying
+ RunLoop(RunLoop const&) = delete;
+ RunLoop& operator=(RunLoop const&) = delete;
+
+ // Runs the run loop until the application quits.
+ void Run();
+
+ // Registers the given Flutter instance for event servicing.
+ void RegisterFlutterInstance(
+ flutter::FlutterViewController* flutter_instance);
+
+ // Unregisters the given Flutter instance from event servicing.
+ void UnregisterFlutterInstance(
+ flutter::FlutterViewController* flutter_instance);
+
+ private:
+ using TimePoint = std::chrono::steady_clock::time_point;
+
+ // Processes all currently pending messages for registered Flutter instances.
+ TimePoint ProcessFlutterMessages();
+
+ std::set flutter_instances_;
+};
+
+#endif // RUN_LOOP_H_
diff --git a/example/windows/runner/runner.exe.manifest b/example/windows/runner/runner.exe.manifest
new file mode 100644
index 0000000..c977c4a
--- /dev/null
+++ b/example/windows/runner/runner.exe.manifest
@@ -0,0 +1,20 @@
+
+
+
+
+ PerMonitorV2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/windows/runner/utils.cpp b/example/windows/runner/utils.cpp
new file mode 100644
index 0000000..37501e5
--- /dev/null
+++ b/example/windows/runner/utils.cpp
@@ -0,0 +1,22 @@
+#include "utils.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+void CreateAndAttachConsole() {
+ 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();
+ }
+}
diff --git a/example/windows/runner/utils.h b/example/windows/runner/utils.h
new file mode 100644
index 0000000..d247a66
--- /dev/null
+++ b/example/windows/runner/utils.h
@@ -0,0 +1,8 @@
+#ifndef CONSOLE_UTILS_H_
+#define CONSOLE_UTILS_H_
+
+// Creates a console for the process, and redirects stdout and stderr to
+// it for both the runner and the Flutter library.
+void CreateAndAttachConsole();
+
+#endif // CONSOLE_UTILS_H_
diff --git a/example/windows/runner/win32_window.cpp b/example/windows/runner/win32_window.cpp
new file mode 100644
index 0000000..677a9a6
--- /dev/null
+++ b/example/windows/runner/win32_window.cpp
@@ -0,0 +1,249 @@
+#include "win32_window.h"
+
+#include
+
+#include "resource.h"
+
+namespace {
+
+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;
+
+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);
+}
+
+// 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) {
+ 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);
+ }
+}
+
+} // namespace
+
+// 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();
+ }
+ return instance_;
+ }
+
+ // 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();
+
+ private:
+ WindowClassRegistrar() = default;
+
+ static WindowClassRegistrar* instance_;
+
+ 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;
+}
+
+void WindowClassRegistrar::UnregisterWindowClass() {
+ UnregisterClass(kWindowClassName, nullptr);
+ class_registered_ = false;
+}
+
+Win32Window::Win32Window() {
+ ++g_active_window_count;
+}
+
+Win32Window::~Win32Window() {
+ --g_active_window_count;
+ Destroy();
+}
+
+bool Win32Window::CreateAndShow(const std::wstring& title,
+ const Point& origin,
+ const Size& size) {
+ Destroy();
+
+ 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;
+
+ 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);
+
+ OnCreate();
+
+ return window != nullptr;
+}
+
+// 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);
+ }
+
+ return DefWindowProc(window, message, wparam, lparam);
+}
+
+LRESULT
+Win32Window::MessageHandler(HWND hwnd,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ auto window =
+ reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+
+ if (window == nullptr) {
+ return 0;
+ }
+
+ 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;
+ GetClientRect(hwnd, &rect);
+ 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;
+
+ // Messages that are directly forwarded to embedding.
+ case WM_FONTCHANGE:
+ SendMessage(child_content_, WM_FONTCHANGE, NULL, NULL);
+ return 0;
+ }
+
+ return DefWindowProc(window_handle_, message, wparam, lparam);
+}
+
+void Win32Window::Destroy() {
+ OnDestroy();
+
+ 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));
+}
+
+void Win32Window::SetChildContent(HWND content) {
+ child_content_ = content;
+ SetParent(content, window_handle_);
+ RECT frame;
+ GetClientRect(window_handle_, &frame);
+
+ MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
+ frame.bottom - frame.top, true);
+
+ SetFocus(child_content_);
+}
+
+HWND Win32Window::GetHandle() {
+ return window_handle_;
+}
+
+void Win32Window::SetQuitOnClose(bool quit_on_close) {
+ quit_on_close_ = quit_on_close;
+}
+
+void Win32Window::OnCreate() {
+ // No-op; provided for subclasses.
+}
+
+void Win32Window::OnDestroy() {
+ // No-op; provided for subclasses.
+}
diff --git a/example/windows/runner/win32_window.h b/example/windows/runner/win32_window.h
new file mode 100644
index 0000000..5cbb5d5
--- /dev/null
+++ b/example/windows/runner/win32_window.h
@@ -0,0 +1,96 @@
+#ifndef WIN32_WINDOW_H_
+#define WIN32_WINDOW_H_
+
+#include
+#include
+
+#include
+#include
+#include
+
+// A class abstraction for a high DPI-aware Win32 Window. Intended to be
+// inherited from by classes that wish to specialize with custom
+// 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);
+
+ 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.
+ virtual void 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 // WIN32_WINDOW_H_
diff --git a/example/windows/runner/window_configuration.cpp b/example/windows/runner/window_configuration.cpp
new file mode 100644
index 0000000..6d5d241
--- /dev/null
+++ b/example/windows/runner/window_configuration.cpp
@@ -0,0 +1,7 @@
+#include "window_configuration.h"
+
+const wchar_t* kFlutterWindowTitle = L"update_app_example";
+const unsigned int kFlutterWindowOriginX = 10;
+const unsigned int kFlutterWindowOriginY = 10;
+const unsigned int kFlutterWindowWidth = 1280;
+const unsigned int kFlutterWindowHeight = 720;
diff --git a/example/windows/runner/window_configuration.h b/example/windows/runner/window_configuration.h
new file mode 100644
index 0000000..ea5cead
--- /dev/null
+++ b/example/windows/runner/window_configuration.h
@@ -0,0 +1,18 @@
+#ifndef WINDOW_CONFIGURATION_
+#define WINDOW_CONFIGURATION_
+
+// This is a temporary approach to isolate changes that people are likely to
+// make to main.cpp, where the APIs are still in flux. This will reduce the
+// need to resolve conflicts or re-create changes slightly differently every
+// time the Windows Flutter API surface changes.
+//
+// Longer term there should be simpler configuration options for common
+// customizations like this, without requiring native code changes.
+
+extern const wchar_t* kFlutterWindowTitle;
+extern const unsigned int kFlutterWindowOriginX;
+extern const unsigned int kFlutterWindowOriginY;
+extern const unsigned int kFlutterWindowWidth;
+extern const unsigned int kFlutterWindowHeight;
+
+#endif // WINDOW_CONFIGURATION_
diff --git a/example/windows/scripts/bundle_assets_and_deps.bat b/example/windows/scripts/bundle_assets_and_deps.bat
new file mode 100644
index 0000000..9efa28f
--- /dev/null
+++ b/example/windows/scripts/bundle_assets_and_deps.bat
@@ -0,0 +1,44 @@
+@echo off
+
+set FLUTTER_CACHE_DIR=%~1
+set BUNDLE_DIR=%~2
+set PLUGIN_DIR=%~3
+set EXE_NAME=%~4
+set BUILD_MODE=%~5
+
+set DATA_DIR=%BUNDLE_DIR%data
+
+if not exist "%DATA_DIR%" call mkdir "%DATA_DIR%"
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+:: Write the executable name to the location expected by the Flutter tool.
+echo %EXE_NAME%>"%FLUTTER_CACHE_DIR%exe_filename"
+
+:: Copy the Flutter assets to the data directory.
+set FLUTTER_BUILD_DIR=%~dp0..\..\build\
+set ASSET_DIR_NAME=flutter_assets
+set TARGET_ASSET_DIR=%DATA_DIR%\%ASSET_DIR_NAME%
+if exist "%TARGET_ASSET_DIR%" call rmdir /s /q "%TARGET_ASSET_DIR%"
+if %errorlevel% neq 0 exit /b %errorlevel%
+call xcopy /s /e /i /q "%FLUTTER_BUILD_DIR%%ASSET_DIR_NAME%" "%TARGET_ASSET_DIR%"
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+:: Copy the icudtl.dat file from the Flutter tree to the data directory.
+call xcopy /y /d /q "%FLUTTER_CACHE_DIR%icudtl.dat" "%DATA_DIR%"
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+:: For non-debug modes, copy app.so into the data directory.
+if not %BUILD_MODE% == "Debug" (
+ call xcopy /y /d /q "%FLUTTER_BUILD_DIR%windows\app.so" "%DATA_DIR%"
+ if %errorlevel% neq 0 exit /b %errorlevel%
+)
+
+:: Copy the Flutter DLL to the target location.
+call xcopy /y /d /q "%FLUTTER_CACHE_DIR%flutter_windows.dll" "%BUNDLE_DIR%"
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+:: Copy any Plugin DLLs to the target location.
+if exist "%PLUGIN_DIR%" (
+ call xcopy /y /d /q "%PLUGIN_DIR%"*.dll "%BUNDLE_DIR%"
+ if %errorlevel% neq 0 exit /b %errorlevel%
+)
diff --git a/example/windows/scripts/prepare_dependencies.bat b/example/windows/scripts/prepare_dependencies.bat
new file mode 100644
index 0000000..d05238b
--- /dev/null
+++ b/example/windows/scripts/prepare_dependencies.bat
@@ -0,0 +1,5 @@
+@echo off
+
+:: Run flutter tool backend.
+set BUILD_MODE=%~1
+"%FLUTTER_ROOT%\packages\flutter_tools\bin\tool_backend" windows-x64 %BUILD_MODE%
diff --git a/ios/Classes/SwiftUpdateAppPlugin.swift b/ios/Classes/SwiftUpdateAppPlugin.swift
index 0b41611..bd45b20 100644
--- a/ios/Classes/SwiftUpdateAppPlugin.swift
+++ b/ios/Classes/SwiftUpdateAppPlugin.swift
@@ -2,47 +2,47 @@ import Flutter
import UIKit
public class SwiftUpdateAppPlugin: NSObject, FlutterPlugin {
- //Apple Store Link
- let appStoreLink = "https://itunes.apple.com/us/app/apple-store/id%@?mt=8"
+ public static func register(with registrar: FlutterPluginRegistrar) {
+ let channel = FlutterMethodChannel(name: "cn.mofada.update_app", binaryMessenger: registrar.messenger())
+ let instance = SwiftUpdateAppPlugin()
+ registrar.addMethodCallDelegate(instance, channel: channel)
+ }
- public static func register(with registrar: FlutterPluginRegistrar) {
- let channel = FlutterMethodChannel(name: "cn.mofada.cn/update_app", binaryMessenger: registrar.messenger())
- let instance = SwiftUpdateAppPlugin()
- registrar.addMethodCallDelegate(instance, channel: channel)
- }
+ public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
+ switch call.method {
+ case "updateApp":
+ goAppStore(call: call, result: result)
+ break;
+ case "getPlatformVersion"
+ result("iOS " + UIDevice.current.systemVersion)
+ break;
+ default:
+ result(FlutterMethodNotImplemented)
+ }
+ }
- public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
- switch call.method {
- case "updateApp":
- goAppStore(call: call, result: result)
- break;
- default:
- result(FlutterMethodNotImplemented)
- }
- }
+ // 跳转Apple Store
+ func goAppStore(call: FlutterMethodCall, result: @escaping FlutterResult) {
+ guard let args = call.arguments else {
+ return
+ }
- // 跳转Apple Store
- func goAppStore(call: FlutterMethodCall, result: @escaping FlutterResult) {
- guard let args = call.arguments else {
- return
- }
-
- if let arguments = args as? [String: Any],
- //获取Apple ID
- let appleId = arguments["appleId"] as? String {
- //拼接地址
- let appStoreUrl = URL(string: String(format: appStoreLink, appleId))
- if let url = appStoreUrl, UIApplication.shared.canOpenURL(url) {
- if #available(iOS 10.0, *) {
- UIApplication.shared.open(url, options: [:])
- } else {
- UIApplication.shared.openURL(url)
- }
- }
- result(true)
- } else {
- result(false)
- }
- }
+ if let arguments = args as? [String: Any],
+ //获取Apple ID
+ let appleId = arguments["appleId"] as? String {
+ //拼接地址
+ let appStoreUrl = URL(string: String(format: appStoreLink, appleId))
+ if let url = appStoreUrl, UIApplication.shared.canOpenURL(url) {
+ if #available(iOS 10.0, *) {
+ UIApplication.shared.open(url, options: [:])
+ } else {
+ UIApplication.shared.openURL(url)
+ }
+ }
+ result(true)
+ } else {
+ result(false)
+ }
+ }
}
diff --git a/ios/Classes/UpdateAppPlugin.m b/ios/Classes/UpdateAppPlugin.m
index 71471bb..677773c 100644
--- a/ios/Classes/UpdateAppPlugin.m
+++ b/ios/Classes/UpdateAppPlugin.m
@@ -1,5 +1,12 @@
#import "UpdateAppPlugin.h"
+#if __has_include()
#import
+#else
+// Support project import fallback if the generated compatibility header
+// is not copied when this plugin is created as a library.
+// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
+#import "update_app-Swift.h"
+#endif
@implementation UpdateAppPlugin
+ (void)registerWithRegistrar:(NSObject*)registrar {
diff --git a/ios/update_app.podspec b/ios/update_app.podspec
index 8a1c76c..7ac09cb 100644
--- a/ios/update_app.podspec
+++ b/ios/update_app.podspec
@@ -1,21 +1,23 @@
#
-# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
+# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
+# Run `pod lib lint update_app.podspec' to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'update_app'
s.version = '0.0.1'
- s.summary = 'update your app'
+ s.summary = 'A new Flutter plugin.'
s.description = <<-DESC
-update your app
+A new Flutter plugin.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
- s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
+ s.platform = :ios, '8.0'
- s.ios.deployment_target = '8.0'
+ # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
+ s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
+ s.swift_version = '5.0'
end
-
diff --git a/lib/update_app.dart b/lib/update_app.dart
index ae56ffc..256e85c 100644
--- a/lib/update_app.dart
+++ b/lib/update_app.dart
@@ -1,11 +1,16 @@
import 'dart:async';
-import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class UpdateApp {
static const MethodChannel _channel =
- const MethodChannel('cn.mofada.cn/update_app');
+ const MethodChannel('cn.mofada.update_app');
+
+ static Future get platformVersion async {
+ final String version = await _channel.invokeMethod('getPlatformVersion');
+ return version;
+ }
//更新app
static Future updateApp({
diff --git a/pubspec.lock b/pubspec.lock
index 414a5e8..edf4759 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,20 +1,6 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
- archive:
- dependency: transitive
- description:
- name: archive
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "2.0.13"
- args:
- dependency: transitive
- description:
- name: args
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "1.6.0"
async:
dependency: transitive
description:
@@ -36,27 +22,27 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.3"
- collection:
+ clock:
dependency: transitive
description:
- name: collection
+ name: clock
url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.14.12"
- convert:
+ version: "1.0.1"
+ collection:
dependency: transitive
description:
- name: convert
+ name: collection
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.1"
- crypto:
+ version: "1.14.12"
+ fake_async:
dependency: transitive
description:
- name: crypto
+ name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.4"
+ version: "1.1.0"
flutter:
dependency: "direct main"
description: flutter
@@ -67,13 +53,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
- image:
- dependency: transitive
- description:
- name: image
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "2.1.12"
matcher:
dependency: transitive
description:
@@ -94,21 +73,7 @@ packages:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.6.4"
- petitparser:
- dependency: transitive
- description:
- name: petitparser
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "2.4.0"
- quiver:
- dependency: transitive
- description:
- name: quiver
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "2.1.3"
+ version: "1.7.0"
sky_engine:
dependency: transitive
description: flutter
@@ -155,7 +120,7 @@ packages:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.2.15"
+ version: "0.2.16"
typed_data:
dependency: transitive
description:
@@ -170,12 +135,6 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.8"
- xml:
- dependency: transitive
- description:
- name: xml
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "3.6.1"
sdks:
- dart: ">=2.6.0 <3.0.0"
+ dart: ">=2.7.0 <3.0.0"
+ flutter: ">=1.10.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index d86140e..0feb7bb 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,13 +1,14 @@
name: update_app
-description: Update the app, pass in the updated address, and update the app.
- The Android part is implemented using DownloadManager.
+description: A new Flutter plugin.
version: 0.1.3
+author: fada
homepage: https://mofada.cn/
repository: https://github.com/mofada/flutter_update_app
issue_tracker: https://github.com/mofada/flutter_update_app/issues
environment:
- sdk: ">=2.1.0 <3.0.0"
+ sdk: ">=2.7.0 <3.0.0"
+ flutter: ">=1.10.0"
dependencies:
flutter:
@@ -23,20 +24,21 @@ dev_dependencies:
# The following section is specific to Flutter.
flutter:
# This section identifies this Flutter project as a plugin project.
- # The androidPackage and pluginClass identifiers should not ordinarily
+ # The 'pluginClass' and Android 'package' identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
- android:
- package: cn.mofada.update_app
- pluginClass: UpdateAppPlugin
- ios:
- pluginClass: UpdateAppPlugin
+ platforms:
+ android:
+ package: cn.mofada.update_app
+ pluginClass: UpdateAppPlugin
+ ios:
+ pluginClass: UpdateAppPlugin
# To add assets to your plugin package, add an assets section, like this:
# assets:
- # - images/a_dot_burr.jpeg
- # - images/a_dot_ham.jpeg
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
diff --git a/test/update_app_test.dart b/test/update_app_test.dart
index a9cfabc..14c87a4 100644
--- a/test/update_app_test.dart
+++ b/test/update_app_test.dart
@@ -5,6 +5,8 @@ import 'package:update_app/update_app.dart';
void main() {
const MethodChannel channel = MethodChannel('update_app');
+ TestWidgetsFlutterBinding.ensureInitialized();
+
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return '42';
@@ -16,8 +18,6 @@ void main() {
});
test('getPlatformVersion', () async {
- await UpdateApp.updateApp(
- url:
- "https://cdn.51bolema.com/2019/08/24/ffbf264bc36d404e81bb113fed72bacf.apk");
+ expect(await UpdateApp.platformVersion, '42');
});
}
diff --git a/windows/.gitignore b/windows/.gitignore
new file mode 100644
index 0000000..b3eb2be
--- /dev/null
+++ b/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/windows/PluginInfo.props b/windows/PluginInfo.props
new file mode 100644
index 0000000..7d49879
--- /dev/null
+++ b/windows/PluginInfo.props
@@ -0,0 +1,14 @@
+
+
+
+
+ update_app
+
+
+
+
+
+ $(FlutterPluginName)
+
+
+
diff --git a/windows/plugin.vcxproj b/windows/plugin.vcxproj
new file mode 100644
index 0000000..a574bc0
--- /dev/null
+++ b/windows/plugin.vcxproj
@@ -0,0 +1,247 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Profile
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ CD12AE71-D0BE-495F-8A2A-988F4470117D
+ Win32Proj
+ update_app
+ 10.0
+ update_app
+
+
+
+ DynamicLibrary
+ true
+ v141
+ v142
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v141
+ v142
+ true
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v141
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)..\build\windows\$(Platform)\$(Configuration)\Plugins\
+ $(SolutionDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\
+
+
+ $(ProjectName)_plugin
+
+
+ false
+ $(SolutionDir)..\build\windows\$(Platform)\$(Configuration)\Plugins\
+ $(SolutionDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\
+
+
+ $(ProjectName)_plugin
+
+
+ false
+ $(SolutionDir)..\build\windows\$(Platform)\$(Configuration)\Plugins\
+ $(SolutionDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\
+
+ $(ProjectName)_plugin
+
+
+
+ NotUsing
+ Level4
+ Disabled
+ true
+ _DEBUG;FLUTTER_PLUGIN_IMPL;_WINDOWS;_USRDLL;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
+ true
+ false
+ true
+ 4100
+ $(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ flutter_windows.dll.lib;%(AdditionalDependencies)
+ $(FLUTTER_EPHEMERAL_DIR);%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NotUsing
+ Level4
+ MaxSpeed
+ true
+ true
+ true
+ NDEBUG;FLUTTER_PLUGIN_IMPL;_WINDOWS;_USRDLL;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
+ true
+ false
+ true
+ 4100
+ $(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ true
+ true
+ flutter_windows.dll.lib;%(AdditionalDependencies)
+ $(FLUTTER_EPHEMERAL_DIR);%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NotUsing
+ Level4
+ MaxSpeed
+ true
+ true
+ true
+ NDEBUG;FLUTTER_PLUGIN_IMPL;_WINDOWS;_USRDLL;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
+ true
+ false
+ true
+ 4100
+ $(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ true
+ true
+ flutter_windows.dll.lib;%(AdditionalDependencies)
+ $(FLUTTER_EPHEMERAL_DIR);%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/windows/plugin.vcxproj.filters b/windows/plugin.vcxproj.filters
new file mode 100644
index 0000000..0f8c708
--- /dev/null
+++ b/windows/plugin.vcxproj.filters
@@ -0,0 +1,45 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {dbe2dac9-4a21-4849-bef5-2069d695609d}
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Source Files
+
+
+
+
+ Source Files\cpp_client_wrapper
+
+
+ Source Files\cpp_client_wrapper
+
+
+ Source Files\cpp_client_wrapper
+
+
+ Source Files
+
+
+
diff --git a/windows/update_app_plugin.cpp b/windows/update_app_plugin.cpp
new file mode 100644
index 0000000..a13fd2d
--- /dev/null
+++ b/windows/update_app_plugin.cpp
@@ -0,0 +1,89 @@
+#include "update_app_plugin.h"
+
+// This must be included before many other Windows headers.
+#include
+
+// For getPlatformVersion; remove unless needed for your plugin implementation.
+#include
+
+#include
+#include
+#include
+
+#include