diff --git a/.gitignore b/.gitignore index ede84a7..2e529dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,47 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp .DS_Store -.dart_tool/ +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +# .vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies .packages +.pub-cache/ .pub/ +/build/ +/pubspec.lock -build/ +# Symbolication related +app.*.symbols -# IntelliJ -*.iml -.idea/workspace.xml -.idea/tasks.xml -.idea/gradle.xml -.idea/assetWizardSettings.xml -.idea/dictionaries -.idea/libraries -.idea/caches +# Obfuscation related +app.*.map.json +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release *.cxx app/.cxx/* diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index ad830cd..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index dc7311b..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.idea/runConfigurations/example_lib_main_dart.xml b/.idea/runConfigurations/example_lib_main_dart.xml deleted file mode 100644 index 5fd9159..0000000 --- a/.idea/runConfigurations/example_lib_main_dart.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.metadata b/.metadata deleted file mode 100644 index 9fc7ede..0000000 --- a/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: 0b8abb4724aa590dd0f429683339b1e045a1594d - channel: stable - -project_type: plugin diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b52e76..7456464 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,14 @@ * [BUGFIX] Null check fix (thanks @WeiCongcong ) +# 3.8.2 + +* Update compileSdkVersion to 31 for issue with flutter 3.24.0 version upgrade + +# 3.8.1 + +* Update rxdart constraints to `>=0.27.0 <0.28.0` + ## 3.8.0 * [BUGFIX] No signature of method: build_…android() applicable for argument types: (build_…_run_closure2) ( #24 ) thanks @ghostman2013 diff --git a/android/src/main/kotlin/org/jezequel/secure_application/SecureApplicationPlugin.kt b/android/src/main/kotlin/org/jezequel/secure_application/SecureApplicationPlugin.kt index a77098b..d3828bb 100644 --- a/android/src/main/kotlin/org/jezequel/secure_application/SecureApplicationPlugin.kt +++ b/android/src/main/kotlin/org/jezequel/secure_application/SecureApplicationPlugin.kt @@ -49,7 +49,7 @@ public class SecureApplicationPlugin: FlutterPlugin, MethodCallHandler, Activity } - override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { instance = SecureApplicationPlugin() val channel = MethodChannel(flutterPluginBinding.binaryMessenger, "secure_application") channel.setMethodCallHandler(instance) @@ -60,18 +60,26 @@ public class SecureApplicationPlugin: FlutterPlugin, MethodCallHandler, Activity // not used for now but might be used to add some features in the future } - override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { - if (call.method == "secure") { - activity?.window?.addFlags(LayoutParams.FLAG_SECURE) - result.success(true) - } else if (call.method == "open") { - activity?.window?.clearFlags(LayoutParams.FLAG_SECURE) - result.success(true) - } else { - result.success(true) + override fun onMethodCall(call: MethodCall, result: Result) { + when (call.method) { + "secure" -> { + activity?.window?.addFlags(LayoutParams.FLAG_SECURE) + result.success(true) + } + "open" -> { + activity?.window?.clearFlags(LayoutParams.FLAG_SECURE) + result.success(true) + } + "opacity" -> { + // Implementation available only on ios + result.success(true) + } + else -> { + result.notImplemented() + } } } - override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index dd04a30..4d3226a 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M -org.gradle.java.home=C:\\Program Files\\Android\\Android Studio\\jbr android.useAndroidX=true android.enableJetifier=true \ No newline at end of file diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 9367d48..1dc6cf7 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 13.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 1e8c3c9..10f3c9b 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 1a3f02c..2ba27dd 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2,21 +2,27 @@ PODS: - Flutter (1.0.0) - secure_application (0.0.1): - Flutter + - url_launcher_ios (0.0.1): + - Flutter DEPENDENCIES: - Flutter (from `Flutter`) - secure_application (from `.symlinks/plugins/secure_application/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) EXTERNAL SOURCES: Flutter: :path: Flutter secure_application: :path: ".symlinks/plugins/secure_application/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: - Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 secure_application: 27d424e8c2e770f63e38e280b5a51f921aa9b0c8 + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe -PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c +PODFILE CHECKSUM: cc1f88378b4bfcf93a6ce00d2c587857c6008d3b -COCOAPODS: 1.10.1 +COCOAPODS: 1.16.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index d605d68..15db2c3 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -121,7 +121,6 @@ 502301990184875FCF6A4E97 /* Pods-Runner.release.xcconfig */, 17B764A4A20FF79E31940E05 /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -156,7 +155,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -217,10 +216,12 @@ }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -231,6 +232,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -340,7 +342,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -356,10 +358,14 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = DZA2GZYF9B; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.jezequel.example; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.secure.application.kuama; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -414,7 +420,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -463,11 +469,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -480,10 +487,14 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = DZA2GZYF9B; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.jezequel.example; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.secure.application.kuama; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -499,10 +510,14 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = DZA2GZYF9B; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.jezequel.example; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.secure.application.kuama; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140c..fc5ae03 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ @@ -45,11 +46,13 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 70693e4..b636303 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index a060db6..279cab4 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable @@ -22,6 +24,8 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + UIApplicationSupportsIndirectInputEvents + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/example/lib/main.dart b/example/lib/main.dart index 268619f..8e83cda 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:secure_application/secure_application.dart'; +import 'package:url_launcher/url_launcher.dart'; void main() => runApp(MaterialApp(home: MyApp())); @@ -88,6 +89,13 @@ class _MyAppState extends State { child: Scaffold( appBar: AppBar( title: const Text('Secure Window Example'), + actions: [ + IconButton( + onPressed: () => + launchUrl(Uri.parse('https://example.com')), + icon: const Icon(Icons.share), + ), + ], ), body: Center( child: Builder(builder: (context) { diff --git a/example/pubspec.lock b/example/pubspec.lock index 835d2d2..001fa3e 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" flutter: dependency: "direct main" description: flutter @@ -84,26 +84,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" matcher: dependency: transitive description: @@ -136,6 +136,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" rxdart: dependency: transitive description: @@ -150,7 +158,7 @@ packages: path: ".." relative: true source: path - version: "4.0.1" + version: "4.1.1" sky_engine: dependency: transitive description: flutter @@ -200,18 +208,82 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "5c8b6c2d89a78f5a1cca70a73d9d5f86c701b36b42f9c9dac7bad592113c28e9" + url: "https://pub.dev" + source: hosted + version: "6.3.24" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7 + url: "https://pub.dev" + source: hosted + version: "6.3.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f + url: "https://pub.dev" + source: hosted + version: "3.2.3" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + url: "https://pub.dev" + source: hosted + version: "3.1.4" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -220,6 +292,14 @@ packages: url: "https://pub.dev" source: hosted version: "14.3.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" sdks: - dart: ">=3.7.0-0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.9.0 <4.0.0" + flutter: ">=3.35.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 7e6665f..2841ff0 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -15,6 +15,9 @@ dependencies: secure_application: path: ../ + + url_launcher: ^6.1.10 + dev_dependencies: flutter_test: sdk: flutter diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart deleted file mode 100644 index 2a64818..0000000 --- a/example/test/widget_test.dart +++ /dev/null @@ -1,10 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - - - -void main() {} diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc index 3a931bf..d0dcaa2 100644 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -7,8 +7,11 @@ #include "generated_plugin_registrant.h" #include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { SecureApplicationPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("SecureApplicationPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake index b331b9c..8dd4cd0 100644 --- a/example/windows/flutter/generated_plugins.cmake +++ b/example/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST secure_application + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/ios/Classes/SwiftSecureApplicationPlugin.swift b/ios/Classes/SwiftSecureApplicationPlugin.swift index 2fab50e..c4435cc 100644 --- a/ios/Classes/SwiftSecureApplicationPlugin.swift +++ b/ios/Classes/SwiftSecureApplicationPlugin.swift @@ -3,10 +3,9 @@ import UIKit public class SwiftSecureApplicationPlugin: NSObject, FlutterPlugin { var secured = false; + var secureView = UIVisualEffectView() var opacity: CGFloat = 0.2; - var backgroundTask: UIBackgroundTaskIdentifier! - internal let registrar: FlutterPluginRegistrar init(registrar: FlutterPluginRegistrar) { @@ -20,82 +19,63 @@ public class SwiftSecureApplicationPlugin: NSObject, FlutterPlugin { let instance = SwiftSecureApplicationPlugin(registrar: registrar) registrar.addMethodCallDelegate(instance, channel: channel) } - - public func applicationWillResignActive(_ application: UIApplication) { - if ( secured ) { - self.registerBackgroundTask() - UIApplication.shared.ignoreSnapshotOnNextApplicationLaunch() - if let window = UIApplication.shared.windows.filter({ (w) -> Bool in - return w.isHidden == false - }).first { - if let existingView = window.viewWithTag(99699), let existingBlurrView = window.viewWithTag(99698) { - window.bringSubviewToFront(existingView) - window.bringSubviewToFront(existingBlurrView) - return - } else { - let colorView = UIView(frame: window.bounds); - colorView.tag = 99699 - colorView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - colorView.backgroundColor = UIColor(white: 1, alpha: opacity) - window.addSubview(colorView) - window.bringSubviewToFront(colorView) - - let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.extraLight) - let blurEffectView = UIVisualEffectView(effect: blurEffect) - blurEffectView.frame = window.bounds - blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - - blurEffectView.tag = 99698 - - window.addSubview(blurEffectView) - window.bringSubviewToFront(blurEffectView) - window.snapshotView(afterScreenUpdates: true) - RunLoop.current.run(until: Date(timeIntervalSinceNow:0.5)) - } - } - self.endBackgroundTask() - } - } - func registerBackgroundTask() { - self.backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in - self?.endBackgroundTask() - } - assert(self.backgroundTask != UIBackgroundTaskIdentifier.invalid) + + public func applicationWillEnterForeground(_ application: UIApplication) { + self.unlockApp() } - func endBackgroundTask() { - print("Background task ended.") - UIApplication.shared.endBackgroundTask(backgroundTask) - backgroundTask = UIBackgroundTaskIdentifier.invalid + public func applicationWillResignActive(_ application: UIApplication) { + if !secured { return } + self.lockApp() } - + + public func applicationDidBecomeActive(_ application: UIApplication) { + self.unlockApp() + } + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - if (call.method == "secure") { + switch (call.method) { + case "secure": secured = true; + result(nil) + case "open": + secured = false; + self.unlockApp() + result(nil) + case "opacity": if let args = call.arguments as? Dictionary, - let opacity = args["opacity"] as? NSNumber { + let opacity = args["opacity"] as? NSNumber { self.opacity = opacity as! CGFloat } - } else if (call.method == "open") { - secured = false; - } else if (call.method == "opacity") { - if let args = call.arguments as? Dictionary, - let opacity = args["opacity"] as? NSNumber { - self.opacity = opacity as! CGFloat - } - } else if (call.method == "unlock") { - if let window = UIApplication.shared.windows.filter({ (w) -> Bool in - return w.isHidden == false - }).first, let view = window.viewWithTag(99699), let blurrView = window.viewWithTag(99698) { - UIView.animate(withDuration: 0.5, animations: { - view.alpha = 0.0 - blurrView.alpha = 0.0 - }, completion: { finished in - view.removeFromSuperview() - blurrView.removeFromSuperview() - - }) - } + result(nil) + default: + result(FlutterMethodNotImplemented) } } + + private func unlockApp() { + UIView.animate(withDuration: 0.3, animations: { [weak self] in + guard let self else { return } + self.secureView.backgroundColor = UIColor(white: 1, alpha: 0.0) + self.secureView.effect = nil + }, completion: { [weak self] (_) in + guard let self else { return } + self.secureView.removeFromSuperview() + }) + } + + private func lockApp() { + let window = UIApplication.shared.windows.first + + if let window, !self.secureView.isDescendant(of: window) { + self.secureView.frame = window.bounds + UIView.animate(withDuration: 0.3) { [weak self] in + guard let self else { return } + self.secureView.backgroundColor = UIColor(white: 1, alpha: self.opacity) + self.secureView.effect = UIBlurEffect(style: .light) + } + window.addSubview(self.secureView) + window.snapshotView(afterScreenUpdates: true) + } + } } diff --git a/lib/secure_application.dart b/lib/secure_application.dart index 70acb6d..446ff62 100644 --- a/lib/secure_application.dart +++ b/lib/secure_application.dart @@ -1,16 +1,16 @@ import 'dart:async'; import 'package:flutter/widgets.dart'; +import 'package:secure_application/secure_application_controller.dart'; import 'package:secure_application/secure_application_native.dart'; import 'package:secure_application/secure_application_provider.dart'; import 'package:secure_application/secure_application_state.dart'; -import 'package:secure_application/secure_application_controller.dart'; export './secure_application.dart'; -export './secure_gate.dart'; +export './secure_application_controller.dart'; export './secure_application_provider.dart'; export './secure_application_state.dart'; -export './secure_application_controller.dart'; +export './secure_gate.dart'; /// Widget that will manage Secure Gates and visibility protection for your app content /// @@ -22,6 +22,8 @@ class SecureApplication extends StatefulWidget { /// This will remove IOs glass effect from native automatically. To set to true (default) if you don't want to manage it /// you can play with the [nativeRemoveDelay] to avoid iOS unsecure flicker + @Deprecated( + 'It is handled internally on ios getting the same behavior as on android. This flag will no longer have any effect') final bool autoUnlockNative; /// Method will be called when the user switch back to your application @@ -83,7 +85,6 @@ class _SecureApplicationState extends State return _secureApplicationController!; } - bool _removeNativeOnNextFrame = false; @override void initState() { _authStreamSubscription = @@ -116,17 +117,12 @@ class _SecureApplicationState extends State void didChangeAppLifecycleState(AppLifecycleState state) async { switch (state) { case AppLifecycleState.resumed: - if (mounted) { - setState(() => _removeNativeOnNextFrame = true); - } else { - _removeNativeOnNextFrame = true; - } if (!secureApplicationController.paused) { if (secureApplicationController.secured && secureApplicationController.value.locked) { if (widget.onNeedUnlock != null) { secureApplicationController.pause(); - var authStatus = + final authStatus = await widget.onNeedUnlock!(secureApplicationController); if (authStatus != null) secureApplicationController.sendAuthenticationEvent(authStatus); @@ -138,7 +134,6 @@ class _SecureApplicationState extends State } secureApplicationController.resumed(); } - super.didChangeAppLifecycleState(state); break; case AppLifecycleState.paused: if (!secureApplicationController.paused) { @@ -146,22 +141,15 @@ class _SecureApplicationState extends State secureApplicationController.lock(); } } - super.didChangeAppLifecycleState(state); break; default: - super.didChangeAppLifecycleState(state); break; } + super.didChangeAppLifecycleState(state); } @override Widget build(BuildContext context) { - if (_removeNativeOnNextFrame && widget.autoUnlockNative) { - Future.delayed(Duration(milliseconds: widget.nativeRemoveDelay)) - .then((_) => SecureApplicationNative.unlock()); - - _removeNativeOnNextFrame = false; - } return SecureApplicationProvider( secureData: secureApplicationController, child: widget.child, diff --git a/lib/secure_application_controller.dart b/lib/secure_application_controller.dart index 648ece8..f5baaa0 100644 --- a/lib/secure_application_controller.dart +++ b/lib/secure_application_controller.dart @@ -94,7 +94,6 @@ class SecureApplicationController /// content under [SecureGate] will not be visible void lock() { - SecureApplicationNative.lock(); if (!value.locked) { value = value.copyWith(locked: true); notifyListeners(); @@ -108,8 +107,6 @@ class SecureApplicationController /// Use when you want your user to see content under [SecureGate] void unlock() { - SecureApplicationNative - .unlock(); //lock from native is removed when resumed but why not! if (value.locked) { value = value.copyWith(locked: false); notifyListeners(); @@ -119,7 +116,6 @@ class SecureApplicationController /// temporary prevent the app from locking if use leave and come back to the app void pause() { - SecureApplicationNative.lock(); if (!value.paused) { value = value.copyWith(paused: true); notifyListeners(); @@ -142,7 +138,7 @@ class SecureApplicationController /// App will be secured and content will not be visible if user switch app /// - /// on Android this will also prevent scrensshot/screen recording + /// on Android this will also prevent screenshot/screen recording void secure() { SecureApplicationNative.secure(); if (!value.secured) { diff --git a/lib/secure_application_native.dart b/lib/secure_application_native.dart index 34f4e20..2448f67 100644 --- a/lib/secure_application_native.dart +++ b/lib/secure_application_native.dart @@ -6,13 +6,17 @@ class SecureApplicationNative { static const MethodChannel _channel = const MethodChannel('secure_application'); + /// Implemented only in windows static void registerForEvents(VoidCallback lock, VoidCallback unlock) { _channel.setMethodCallHandler( (call) => secureApplicationHandler(call, lock, unlock)); } - static Future secureApplicationHandler( - MethodCall methodCall, lock, unlock) async { + static Future secureApplicationHandler( + MethodCall methodCall, + VoidCallback lock, + VoidCallback unlock, + ) async { switch (methodCall.method) { case 'lock': lock(); @@ -25,23 +29,28 @@ class SecureApplicationNative { } } - static Future secure() { + /// App will be secured and content will not be visible if user switch app + /// + /// on Android this will also prevent screenshot/screen recording + static Future secure() { return _channel.invokeMethod('secure'); } - static Future open() { + /// App will no longer be secured and content will be visible if user switch app + static Future open() { return _channel.invokeMethod('open'); } - static Future lock() { - return _channel.invokeMethod('lock'); - } + /// Temporary prevent the app from locking if use leave and come back to the app + @Deprecated('It never did anything') + static Future lock() async {} - static Future unlock() { - return _channel.invokeMethod('unlock'); - } + /// Use when you want your user to see content + @Deprecated('It never did anything') + static Future unlock() async {} - static Future opacity(double opacity) { - return _channel.invokeMethod('opacity', {"opacity": opacity}); + /// Only work on ios + static Future opacity(double opacity) { + return _channel.invokeMethod('opacity', {'opacity': opacity}); } } diff --git a/lib/secure_application_state.dart b/lib/secure_application_state.dart index ee66078..6987504 100644 --- a/lib/secure_application_state.dart +++ b/lib/secure_application_state.dart @@ -7,6 +7,7 @@ class SecureApplicationState { final bool secured; final bool paused; final bool authenticated; + SecureApplicationState({ this.locked = false, this.secured = false, diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index 8c979bb..0000000 --- a/pubspec.lock +++ /dev/null @@ -1,210 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 - url: "https://pub.dev" - source: hosted - version: "2.12.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" - url: "https://pub.dev" - source: hosted - version: "1.3.2" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_plugin_android_lifecycle: - dependency: "direct main" - description: - name: flutter_plugin_android_lifecycle - sha256: "5a1e6fb2c0561958d7e4c33574674bda7b77caaca7a33b758876956f2902eea3" - url: "https://pub.dev" - source: hosted - version: "2.0.27" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec - url: "https://pub.dev" - source: hosted - version: "10.0.8" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 - url: "https://pub.dev" - source: hosted - version: "3.0.9" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" - source: hosted - version: "1.16.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - rxdart: - dependency: "direct main" - description: - name: rxdart - sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" - url: "https://pub.dev" - source: hosted - version: "0.28.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd - url: "https://pub.dev" - source: hosted - version: "0.7.4" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" - url: "https://pub.dev" - source: hosted - version: "14.3.1" -sdks: - dart: ">=3.7.0-0 <4.0.0" - flutter: ">=3.27.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1f19783..e694ab0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: secure_application description: Secure app content visibility when user leave app. It will hide content in the app switcher and display a frost barrier above locked content when the user get backs -version: 4.1.0 +version: 4.1.1 homepage: https://github.com/neckaros/secure_application environment: