├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .metadata ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ ├── AndroidManifest.xml │ │ ├── ic_launcher-playstore.png │ │ └── res │ │ │ └── values │ │ │ └── ic_launcher_background.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── ic_launcher-playstore.png │ │ ├── java │ │ │ └── com │ │ │ │ └── appmanager │ │ │ │ └── etherium │ │ │ │ └── switch_up │ │ │ │ ├── BootUpReceiver.kt │ │ │ │ ├── ForegroundService.kt │ │ │ │ ├── HomeWatcher.kt │ │ │ │ ├── NativeActivity.kt │ │ │ │ ├── PinCodeActivity.kt │ │ │ │ └── Window.kt │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── applockFlutter │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ ├── launch_background.xml │ │ │ └── shape.xml │ │ │ ├── layout │ │ │ ├── activity_native.xml │ │ │ ├── list_view.xml │ │ │ ├── lock_view.xml │ │ │ ├── notification_small.xml │ │ │ └── pin_activity.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values-land │ │ │ └── dimens.xml │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ ├── values-w1240dp │ │ │ └── dimens.xml │ │ │ ├── values-w600dp │ │ │ └── dimens.xml │ │ │ └── values │ │ │ ├── dimens.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── profile │ │ └── AndroidManifest.xml │ │ └── release │ │ ├── ic_launcher-playstore.png │ │ └── res │ │ └── values │ │ └── ic_launcher_background.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── images │ └── appLogo.png └── jsonFiles │ ├── 102600-pink-no-data.json │ └── lf30_editor_uzfk5vpa.json ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── executables │ ├── controllers │ │ ├── apps_controller.dart │ │ ├── home_screen_controller.dart │ │ ├── method_channel_controller.dart │ │ ├── password_controller.dart │ │ ├── permission_controller.dart │ │ └── service_controller.dart │ └── repositories │ │ └── auth_repo.dart ├── main.dart ├── models │ └── application_model.dart ├── screens │ ├── home.dart │ ├── search.dart │ ├── set_passcode.dart │ ├── splash.dart │ └── unlocked_apps.dart ├── services │ ├── constant.dart │ ├── extra_methods.dart │ ├── init.dart │ └── themes.dart └── widgets │ ├── ask_permission_dialog.dart │ ├── confirmation_dialog.dart │ ├── custom_dialog.dart │ └── pass_confirm_dialog.dart ├── pubspec.lock ├── pubspec.yaml └── test └── widget_test.dart /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | # - testing 7 | push: 8 | branches: 9 | - main 10 | # - testing 11 | jobs: 12 | build: 13 | name: Build APK 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v1 17 | - uses: actions/setup-java@v1 18 | with: 19 | java-version: '17' 20 | - uses: subosito/flutter-action@v1 21 | with: 22 | flutter-version: '3.19.3' 23 | channel: 'stable' 24 | - run: flutter doctor 25 | - run: flutter pub get 26 | ## - run: flutter test 27 | ## build and upload production apk 28 | # - run: flutter build apk --release 29 | # - uses: actions/upload-artifact@v3 30 | # with: 31 | # name: production-apk 32 | # path: build/app/outputs/flutter-apk/app-release.apk 33 | # build and upload development apk 34 | - run: flutter build apk --debug 35 | - uses: actions/upload-artifact@v3 36 | with: 37 | name: development-apk 38 | path: build/app/outputs/flutter-apk/app-debug.apk 39 | # build and upload development abb 40 | # - run: flutter build appbundle --flavor production -t lib/main_production.dart 41 | # - uses: actions/upload-artifact@v3 42 | # with: 43 | # name: development-abb 44 | # path: build/app/outputs/bundle/production/Release/app-production-release.aab 45 | # push artifatcs to release 46 | - name: Push to Releases 47 | uses: ncipollo/release-action@v1 48 | with: 49 | artifacts: "build/app/outputs/flutter-apk/*" 50 | tag: v1.0.${{ github.run_number }} 51 | token: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: c860cba910319332564e1e9d470a17074c1f2dfd 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "interactive" 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # app_lock_flutter 2 | 3 | app_lock_flutter 4 | 5 | - This is a applock application based on flutter and it is only for Android. 6 | - app_lock_flutter depends on method channels to trigger background services in MainActivity.kt, also uses Getx state management. 7 | - it uses USAGE_STATS to trigger application activities. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | https://user-images.githubusercontent.com/56929825/210130784-6cc095a8-af96-4ce6-a5db-025b91e4e45c.mp4 24 | 25 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 33 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.applockFlutter" 47 | minSdkVersion 26 48 | targetSdkVersion 33 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | 58 | } 59 | 60 | } 61 | buildFeatures { 62 | viewBinding true 63 | } 64 | } 65 | 66 | flutter { 67 | source '../..' 68 | } 69 | 70 | dependencies { 71 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 72 | implementation 'androidx.appcompat:appcompat:1.5.0' 73 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 74 | implementation 'androidx.cardview:cardview:1.0.0' 75 | implementation 'com.google.android.material:material:1.4.0' 76 | implementation 'androidx.navigation:navigation-fragment-ktx:2.5.2' 77 | implementation 'androidx.navigation:navigation-ui-ktx:2.5.2' 78 | 79 | implementation 'com.andrognito.pinlockview:pinlockview:2.1.0' 80 | } 81 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/debug/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ninad7n/AppLockFlutter/2181bbb59d2ca034524148ed2cc1f61c6ef73ac2/android/app/src/debug/ic_launcher-playstore.png -------------------------------------------------------------------------------- /android/app/src/debug/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 23 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 63 | 64 | 66 | 67 | 68 | 70 | 71 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /android/app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ninad7n/AppLockFlutter/2181bbb59d2ca034524148ed2cc1f61c6ef73ac2/android/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /android/app/src/main/java/com/appmanager/etherium/switch_up/BootUpReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.applockFlutter 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.SharedPreferences 7 | 8 | class BootUpReceiver : BroadcastReceiver() { 9 | override fun onReceive(context: Context, intent: Intent?) { 10 | val saveAppData: SharedPreferences = context.getSharedPreferences("save_app_data", Context.MODE_PRIVATE) 11 | if(saveAppData.getString("is_stopped","STOP") =="1"){ 12 | context.startService(Intent(context, ForegroundService::class.java)) 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /android/app/src/main/java/com/appmanager/etherium/switch_up/ForegroundService.kt: -------------------------------------------------------------------------------- 1 | package com.applockFlutter 2 | 3 | import android.app.NotificationChannel 4 | import android.app.NotificationManager 5 | import android.app.Service 6 | import android.app.usage.UsageEvents 7 | import android.app.usage.UsageStatsManager 8 | import android.content.* 9 | import android.os.Handler 10 | import android.os.IBinder 11 | import android.os.Looper 12 | import android.view.View 13 | import androidx.core.app.NotificationCompat 14 | import java.util.* 15 | 16 | 17 | class ForegroundService : Service() { 18 | override fun onBind(intent: Intent): IBinder? { 19 | throw UnsupportedOperationException("") 20 | } 21 | var timer: Timer = Timer() 22 | var isTimerStarted = false 23 | var timerReload:Long = 500 24 | var currentAppActivityList = arrayListOf() 25 | private var mHomeWatcher = HomeWatcher(this) 26 | 27 | override fun onCreate() { 28 | super.onCreate() 29 | val channelId = "AppLock-10" 30 | val channel = NotificationChannel( 31 | channelId, 32 | "Channel human readable title", 33 | NotificationManager.IMPORTANCE_DEFAULT 34 | ) 35 | (getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel( 36 | channel 37 | ) 38 | val notification = NotificationCompat.Builder(this, channelId) 39 | .setContentTitle("") 40 | .setContentText("").build() 41 | startForeground(1, notification) 42 | startMyOwnForeground() 43 | 44 | } 45 | 46 | override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { 47 | return super.onStartCommand(intent, flags, startId) 48 | } 49 | 50 | private fun startMyOwnForeground() { 51 | val window = Window(this) 52 | mHomeWatcher.setOnHomePressedListener(object : HomeWatcher.OnHomePressedListener { 53 | override fun onHomePressed() { 54 | println("onHomePressed") 55 | currentAppActivityList.clear() 56 | if(window.isOpen()){ 57 | window.close() 58 | } 59 | } 60 | override fun onHomeLongPressed() { 61 | println("onHomeLongPressed") 62 | currentAppActivityList.clear() 63 | if(window.isOpen()){ 64 | window.close() 65 | } 66 | } 67 | }) 68 | mHomeWatcher.startWatch() 69 | timerRun(window) 70 | } 71 | 72 | override fun onDestroy() { 73 | timer.cancel() 74 | mHomeWatcher.stopWatch() 75 | super.onDestroy() 76 | } 77 | 78 | private fun timerRun(window:Window){ 79 | timer.scheduleAtFixedRate(object : TimerTask() { 80 | override fun run() { 81 | isTimerStarted = true 82 | isServiceRunning(window) 83 | } 84 | }, 0, timerReload) 85 | } 86 | 87 | 88 | fun isServiceRunning(window:Window) { 89 | 90 | val saveAppData: SharedPreferences = applicationContext.getSharedPreferences("save_app_data", Context.MODE_PRIVATE) 91 | val lockedAppList: List<*> = saveAppData.getString("app_data", "AppList")!!.replace("[", "").replace("]", "").split(",") 92 | 93 | val mUsageStatsManager = getSystemService(USAGE_STATS_SERVICE) as UsageStatsManager 94 | val time = System.currentTimeMillis() 95 | 96 | val usageEvents = mUsageStatsManager.queryEvents(time - timerReload, time) 97 | val event = UsageEvents.Event() 98 | 99 | run breaking@{ 100 | while (usageEvents.hasNextEvent()) { 101 | usageEvents.getNextEvent(event) 102 | for (element in lockedAppList) if(event.packageName.toString().trim() == element.toString().trim()){ 103 | println("${event.className} $element ${event.eventType}-----------Event Type") 104 | if(event.eventType == UsageEvents.Event.ACTIVITY_RESUMED && currentAppActivityList.isEmpty()) { 105 | currentAppActivityList.add(event.className) 106 | println("$currentAppActivityList-----List--added") 107 | window.txtView!!.visibility = View.INVISIBLE 108 | Handler(Looper.getMainLooper()).post { 109 | window.open() 110 | } 111 | return@breaking 112 | }else if(event.eventType == UsageEvents.Event.ACTIVITY_RESUMED){ 113 | if(!currentAppActivityList.contains(event.className)){ 114 | currentAppActivityList.add(event.className) 115 | println("$currentAppActivityList-----List--added") 116 | } 117 | }else if(event.eventType == UsageEvents.Event.ACTIVITY_STOPPED ){ 118 | if(currentAppActivityList.contains(event.className)){ 119 | currentAppActivityList.remove(event.className) 120 | println("$currentAppActivityList-----List--remained") 121 | } 122 | } 123 | } 124 | } 125 | } 126 | } 127 | } 128 | 129 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appmanager/etherium/switch_up/HomeWatcher.kt: -------------------------------------------------------------------------------- 1 | package com.applockFlutter 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.IntentFilter 7 | import android.util.Log 8 | 9 | class HomeWatcher(private val mContext: Context) { 10 | private val mFilter: IntentFilter 11 | private var mListener: OnHomePressedListener? = null 12 | public var mReceiver: InnerReceiver? = null 13 | 14 | fun setOnHomePressedListener(listener: OnHomePressedListener?) { 15 | mListener = listener 16 | mReceiver = InnerReceiver() 17 | } 18 | 19 | fun startWatch() { 20 | if (mReceiver != null) { 21 | mContext.registerReceiver(mReceiver, mFilter) 22 | } 23 | } 24 | 25 | fun stopWatch() { 26 | if (mReceiver != null) { 27 | mContext.unregisterReceiver(mReceiver) 28 | } 29 | } 30 | 31 | interface OnHomePressedListener { 32 | fun onHomePressed() 33 | fun onHomeLongPressed() 34 | } 35 | 36 | 37 | inner class InnerReceiver : BroadcastReceiver() { 38 | val SYSTEM_DIALOG_REASON_KEY = "reason" 39 | val SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps" 40 | val SYSTEM_DIALOG_REASON_HOME_KEY = "homekey" 41 | override fun onReceive(context: Context, intent: Intent) { 42 | val action = intent.action 43 | if (action == Intent.ACTION_CLOSE_SYSTEM_DIALOGS) { 44 | val reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY) 45 | if (reason != null) { 46 | Log.e(TAG, "action:-$action,reason:-$reason") 47 | if (mListener != null) { 48 | if (reason == SYSTEM_DIALOG_REASON_HOME_KEY) { 49 | mListener!!.onHomePressed() 50 | } else if (reason == SYSTEM_DIALOG_REASON_RECENT_APPS) { 51 | mListener!!.onHomeLongPressed() 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | companion object { 60 | const val TAG = "hg" 61 | } 62 | 63 | init { 64 | mFilter = IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) 65 | } 66 | } -------------------------------------------------------------------------------- /android/app/src/main/java/com/appmanager/etherium/switch_up/NativeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.applockFlutter 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Bundle 5 | import androidx.appcompat.app.AppCompatActivity 6 | 7 | 8 | class NativeActivity : AppCompatActivity() { 9 | 10 | @SuppressLint("SetTextI18n") 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(savedInstanceState) 13 | setContentView(R.layout.activity_native) 14 | 15 | } 16 | } -------------------------------------------------------------------------------- /android/app/src/main/java/com/appmanager/etherium/switch_up/PinCodeActivity.kt: -------------------------------------------------------------------------------- 1 | import android.annotation.SuppressLint 2 | import android.content.Context 3 | import android.util.Log 4 | import androidx.core.content.ContextCompat 5 | import com.andrognito.pinlockview.IndicatorDots 6 | import com.andrognito.pinlockview.PinLockListener 7 | import com.andrognito.pinlockview.PinLockView 8 | import com.applockFlutter.R 9 | 10 | 11 | class PinCodeActivity( 12 | private val context: Context 13 | ) { 14 | 15 | var pinCode: String = "" 16 | 17 | private var mPinLockView: PinLockView? = null 18 | 19 | private var mIndicatorDots: IndicatorDots? = null 20 | private val mPinLockListener: PinLockListener = object : PinLockListener { 21 | @SuppressLint("LogConditional") 22 | override fun onComplete(pin: String) { 23 | Log.d(TAG, "Pin complete: $pin") 24 | pinCode = pin 25 | } 26 | 27 | override fun onEmpty() { 28 | Log.d(TAG, "Pin empty") 29 | pinCode = "" 30 | } 31 | 32 | @SuppressLint("LogConditional") 33 | override fun onPinChange(pinLength: Int, intermediatePin: String) { 34 | pinCode = intermediatePin 35 | Log.d( 36 | TAG, 37 | "Pin changed, new length $pinLength with intermediate pin $intermediatePin" 38 | ) 39 | } 40 | } 41 | 42 | init { 43 | try{ 44 | // setContentView(R.layout.pin_activity) 45 | // mPinLockView = findViewById(R.id.pin_lock_view) 46 | // mIndicatorDots = findViewById(R.id.indicator_dots) 47 | mPinLockView!!.attachIndicatorDots(mIndicatorDots) 48 | mPinLockView!!.setPinLockListener(mPinLockListener) 49 | println("Pincode class Activated--2") 50 | // mPinLockView.setCustomKeySet(new int[]{2, 3, 1, 5, 9, 6, 7, 0, 8, 4}); 51 | // mPinLockView.enableLayoutShuffling(); 52 | mPinLockView!!.pinLength = 6 53 | mPinLockView!!.textColor = ContextCompat.getColor(context, R.color.ic_launcher_background) 54 | mIndicatorDots!!.indicatorType = IndicatorDots.IndicatorType.FILL_WITH_ANIMATION 55 | 56 | } catch (e: Exception) { 57 | e.printStackTrace() 58 | } 59 | } 60 | 61 | // override fun onCreate(savedInstanceState: Bundle?) { 62 | // super.onCreate(savedInstanceState) 63 | //// requestWindowFeature(Window.FEATURE_NO_TITLE) 64 | //// window.setFlags( 65 | //// WindowManager.LayoutParams.FLAG_FULLSCREEN, 66 | //// WindowManager.LayoutParams.FLAG_FULLSCREEN 67 | //// ) 68 | // println("Pincode class Activated") 69 | // try{ 70 | //// setContentView(R.layout.pin_activity) 71 | // mPinLockView = findViewById(R.id.pin_lock_view) 72 | // mIndicatorDots = findViewById(R.id.indicator_dots) 73 | // mPinLockView!!.attachIndicatorDots(mIndicatorDots) 74 | // mPinLockView!!.setPinLockListener(mPinLockListener) 75 | // println("Pincode class Activated--2") 76 | //// mPinLockView.setCustomKeySet(new int[]{2, 3, 1, 5, 9, 6, 7, 0, 8, 4}); 77 | //// mPinLockView.enableLayoutShuffling(); 78 | // mPinLockView!!.pinLength = 6 79 | // mPinLockView!!.textColor = ContextCompat.getColor(this, R.color.white) 80 | // mIndicatorDots!!.indicatorType = IndicatorDots.IndicatorType.FILL_WITH_ANIMATION 81 | // 82 | // } catch (e: Exception) { 83 | // e.printStackTrace() 84 | // } 85 | // } 86 | 87 | 88 | // override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { 89 | // super.onCreate(savedInstanceState, persistentState) 90 | // requestWindowFeature(Window.FEATURE_NO_TITLE) 91 | //// window.setFlags( 92 | //// WindowManager.LayoutParams.FLAG_FULLSCREEN, 93 | //// WindowManager.LayoutParams.FLAG_FULLSCREEN 94 | //// ) 95 | // println("Pincode class Activated") 96 | // try{ 97 | // setContentView(R.layout.pin_activity) 98 | // mPinLockView = findViewById(R.id.pin_lock_view) 99 | // mIndicatorDots = findViewById(R.id.indicator_dots) 100 | // mPinLockView!!.attachIndicatorDots(mIndicatorDots) 101 | // mPinLockView!!.setPinLockListener(mPinLockListener) 102 | // println("Pincode class Activated--2") 103 | //// mPinLockView.setCustomKeySet(new int[]{2, 3, 1, 5, 9, 6, 7, 0, 8, 4}); 104 | //// mPinLockView.enableLayoutShuffling(); 105 | // mPinLockView!!.pinLength = 6 106 | // mPinLockView!!.textColor = ContextCompat.getColor(this, R.color.white) 107 | // mIndicatorDots!!.indicatorType = IndicatorDots.IndicatorType.FILL_WITH_ANIMATION 108 | // 109 | // } catch (e: Exception) { 110 | // e.printStackTrace() 111 | // } 112 | // } 113 | 114 | companion object { 115 | const val TAG = "PinLockView" 116 | } 117 | } 118 | //override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { 119 | // super.onCreate(savedInstanceState, persistentState) 120 | // requestWindowFeature(Window.FEATURE_NO_TITLE) 121 | //// window.setFlags( 122 | //// WindowManager.LayoutParams.FLAG_FULLSCREEN, 123 | //// WindowManager.LayoutParams.FLAG_FULLSCREEN 124 | //// ) 125 | // println("Pincode class Activated") 126 | // try{ 127 | // setContentView(R.layout.pin_activity) 128 | // mPinLockView = findViewById(R.id.pin_lock_view) 129 | // mIndicatorDots = findViewById(R.id.indicator_dots) 130 | // mPinLockView!!.attachIndicatorDots(mIndicatorDots) 131 | // mPinLockView!!.setPinLockListener(mPinLockListener) 132 | //// mPinLockView.setCustomKeySet(new int[]{2, 3, 1, 5, 9, 6, 7, 0, 8, 4}); 133 | //// mPinLockView.enableLayoutShuffling(); 134 | // mPinLockView!!.pinLength = 6 135 | // mPinLockView!!.textColor = ContextCompat.getColor(this, R.color.white) 136 | // mIndicatorDots!!.indicatorType = IndicatorDots.IndicatorType.FILL_WITH_ANIMATION 137 | // 138 | // } catch (e: Exception) { 139 | // e.printStackTrace() 140 | // } 141 | //} -------------------------------------------------------------------------------- /android/app/src/main/java/com/appmanager/etherium/switch_up/Window.kt: -------------------------------------------------------------------------------- 1 | package com.applockFlutter 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.content.SharedPreferences 6 | import android.graphics.PixelFormat 7 | import android.os.Handler 8 | import android.os.Looper 9 | import android.util.Log 10 | import android.view.* 11 | import android.widget.TextView 12 | import androidx.core.content.ContextCompat 13 | import com.andrognito.pinlockview.IndicatorDots 14 | import com.andrognito.pinlockview.PinLockListener 15 | import com.andrognito.pinlockview.PinLockView 16 | import com.applockFlutter.R 17 | 18 | 19 | @SuppressLint("InflateParams") 20 | class Window( 21 | private val context: Context 22 | ) { 23 | private val mView: View 24 | var pinCode: String = "" 25 | var txtView: TextView? = null 26 | private var mParams: WindowManager.LayoutParams? = null 27 | private val mWindowManager: WindowManager 28 | private val layoutInflater: LayoutInflater 29 | 30 | private var mPinLockView: PinLockView? = null 31 | private var mIndicatorDots: IndicatorDots? = null 32 | private val mPinLockListener: PinLockListener = object : PinLockListener { 33 | 34 | @SuppressLint("LogConditional") 35 | override fun onComplete(pin: String) { 36 | Log.d(PinCodeActivity.TAG, "Pin complete: $pin") 37 | pinCode = pin 38 | doneButton() 39 | } 40 | 41 | override fun onEmpty() { 42 | Log.d(PinCodeActivity.TAG, "Pin empty") 43 | } 44 | 45 | @SuppressLint("LogConditional") 46 | override fun onPinChange(pinLength: Int, intermediatePin: String) {} 47 | } 48 | 49 | fun open() { 50 | try { 51 | if (mView.windowToken == null) { 52 | if (mView.parent == null) { 53 | mWindowManager.addView(mView, mParams) 54 | } 55 | } 56 | } catch (e: Exception) { 57 | e.printStackTrace() 58 | } 59 | } 60 | 61 | fun isOpen():Boolean{ 62 | return (mView.windowToken != null && mView.parent != null) 63 | } 64 | 65 | fun close() { 66 | try { 67 | Handler(Looper.getMainLooper()).postDelayed({ 68 | (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).removeView(mView) 69 | mView.invalidate() 70 | },500) 71 | 72 | } catch (e: Exception) { 73 | e.printStackTrace() 74 | } 75 | } 76 | 77 | fun doneButton(){ 78 | try { 79 | mPinLockView!!.resetPinLockView() 80 | val saveAppData: SharedPreferences = context.getSharedPreferences("save_app_data", Context.MODE_PRIVATE) 81 | val dta: String = saveAppData.getString("password", "PASSWORD")!! 82 | if(pinCode == dta){ 83 | println("$pinCode---------------pincode") 84 | close() 85 | }else{ 86 | txtView!!.visibility = View.VISIBLE 87 | } 88 | } catch (e: Exception) { 89 | println("$e---------------doneButton") 90 | } 91 | } 92 | 93 | init { 94 | 95 | mParams = WindowManager.LayoutParams( 96 | WindowManager.LayoutParams.MATCH_PARENT, 97 | WindowManager.LayoutParams.MATCH_PARENT, 98 | WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 99 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, 100 | PixelFormat.TRANSLUCENT 101 | ) 102 | layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater 103 | mView = layoutInflater.inflate(R.layout.pin_activity, null) 104 | 105 | mParams!!.gravity = Gravity.CENTER 106 | mWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager 107 | 108 | mPinLockView = mView.findViewById(R.id.pin_lock_view) 109 | mIndicatorDots = mView.findViewById(R.id.indicator_dots) 110 | txtView = mView.findViewById(R.id.alertError) as TextView 111 | 112 | 113 | 114 | mPinLockView!!.attachIndicatorDots(mIndicatorDots) 115 | mPinLockView!!.setPinLockListener(mPinLockListener) 116 | mPinLockView!!.pinLength = 6 117 | mPinLockView!!.textColor = ContextCompat.getColor(context, R.color.ic_launcher_background) 118 | mIndicatorDots!!.indicatorType = IndicatorDots.IndicatorType.FILL_WITH_ANIMATION 119 | 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/applockFlutter/MainActivity.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("DEPRECATION") 2 | 3 | package com.applockFlutter 4 | 5 | import android.annotation.SuppressLint 6 | import android.app.AppOpsManager 7 | import android.content.Context 8 | import android.content.Intent 9 | import android.content.SharedPreferences 10 | import android.content.pm.ApplicationInfo 11 | import android.content.pm.PackageManager 12 | import android.os.Bundle 13 | import android.provider.Settings 14 | import androidx.core.content.ContextCompat 15 | import io.flutter.embedding.android.FlutterActivity 16 | import io.flutter.embedding.engine.FlutterEngine 17 | import io.flutter.plugin.common.MethodChannel 18 | import io.flutter.plugins.GeneratedPluginRegistrant 19 | import java.util.* 20 | 21 | 22 | class MainActivity: FlutterActivity() { 23 | private val channel = "flutter.native/helper" 24 | private var appInfo: List? = null 25 | private var lockedAppList: List = emptyList() 26 | private var saveAppData: SharedPreferences? = null 27 | 28 | override fun onCreate(savedInstanceState: Bundle?) { 29 | super.onCreate(savedInstanceState) 30 | saveAppData = applicationContext.getSharedPreferences("save_app_data", Context.MODE_PRIVATE) 31 | GeneratedPluginRegistrant.registerWith(FlutterEngine(this)) 32 | MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, channel).setMethodCallHandler { call, result -> 33 | when { 34 | call.method.equals("addToLockedApps") -> { 35 | val args = call.arguments as HashMap<*, *> 36 | println("$args ----- ARGS") 37 | val greetings = showCustomNotification(args) 38 | result.success(greetings) 39 | } 40 | call.method.equals("setPasswordInNative") -> { 41 | val args = call.arguments 42 | val editor: SharedPreferences.Editor = saveAppData!!.edit() 43 | editor.putString("password", "$args") 44 | editor.apply() 45 | result.success("Success") 46 | } 47 | call.method.equals("checkOverlayPermission") -> { 48 | result.success(Settings.canDrawOverlays(this)) 49 | } 50 | call.method.equals("stopForeground") -> { 51 | stopForegroundService() 52 | } 53 | call.method.equals("askOverlayPermission") -> { 54 | result.success(checkOverlayPermission()) 55 | } 56 | call.method.equals("askUsageStatsPermission") -> { 57 | if (!isAccessGranted()) { 58 | val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS) 59 | startActivity(intent) 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | @SuppressLint("CommitPrefEdits", "LaunchActivityFromNotification") 67 | private fun showCustomNotification(args: HashMap<*, *>):String { 68 | lockedAppList = emptyList() 69 | // val mContentView = RemoteViews(packageName, R.layout.list_view) 70 | 71 | appInfo = packageManager.getInstalledApplications(PackageManager.GET_META_DATA) 72 | 73 | val arr : ArrayList> = args["app_list"] as ArrayList> 74 | 75 | for (element in arr){ 76 | run breaking@{ 77 | for (i in appInfo!!.indices){ 78 | if(appInfo!![i].packageName.toString() == element["package_name"].toString()){ 79 | val ogList = lockedAppList 80 | lockedAppList = ogList + appInfo!![i] 81 | return@breaking 82 | } 83 | } 84 | } 85 | } 86 | 87 | 88 | var packageData:List = emptyList() 89 | 90 | for(element in lockedAppList){ 91 | val ogList = packageData 92 | packageData = ogList + element.packageName 93 | } 94 | 95 | val editor: SharedPreferences.Editor = saveAppData!!.edit() 96 | editor.remove("app_data") 97 | editor.putString("app_data", "$packageData") 98 | editor.apply() 99 | 100 | startForegroundService() 101 | 102 | return "Success" 103 | } 104 | 105 | private fun setIfServiceClosed(data:String){ 106 | val editor: SharedPreferences.Editor = saveAppData!!.edit() 107 | editor.putString("is_stopped",data) 108 | editor.apply() 109 | } 110 | 111 | private fun startForegroundService() { 112 | if (Settings.canDrawOverlays(this)) { 113 | setIfServiceClosed("1") 114 | ContextCompat.startForegroundService(this, Intent(this, ForegroundService::class.java)) 115 | } 116 | } 117 | 118 | private fun stopForegroundService(){ 119 | setIfServiceClosed("0") 120 | stopService( Intent(this, ForegroundService::class.java)) 121 | } 122 | 123 | private fun checkOverlayPermission():Boolean { 124 | if (!Settings.canDrawOverlays(this)) { 125 | val myIntent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION) 126 | startActivity(myIntent) 127 | } 128 | return Settings.canDrawOverlays(this) 129 | } 130 | 131 | private fun isAccessGranted(): Boolean { 132 | return try { 133 | val packageManager = packageManager 134 | val applicationInfo = packageManager.getApplicationInfo( 135 | packageName, 0 136 | ) 137 | val appOpsManager: AppOpsManager = getSystemService(APP_OPS_SERVICE) as AppOpsManager 138 | val mode = appOpsManager.checkOpNoThrow( 139 | AppOpsManager.OPSTR_GET_USAGE_STATS, 140 | applicationInfo.uid, applicationInfo.packageName 141 | ) 142 | mode == AppOpsManager.MODE_ALLOWED 143 | } catch (e: PackageManager.NameNotFoundException) { 144 | false 145 | } 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/layout/activity_native.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | -------------------------------------------------------------------------------- /android/app/src/main/res/layout/list_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 20 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /android/app/src/main/res/layout/lock_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 22 | 23 | 33 | 34 |