├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── ws │ │ │ │ └── diye │ │ │ │ └── scrcpy_flutter │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── 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 ├── android_keycode.dart ├── cbc_cipher.dart ├── debug_control.dart ├── device_list.dart ├── main.dart └── scrcpy.dart ├── pubspec.lock ├── pubspec.yaml └── test └── widget_test.dart /.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: ffb2ecea5223acdd139a5039be2f9c796962833d 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scrcpy_flutter 2 | 3 | Scrcpy client base on flutter. 4 | 5 | ## Getting Started 6 | *Note: 16-char-key is requried for AES encryption if you need sceenshot feature, otherwise provide any string(16-char) while starting server.* 7 | 8 | 9 | - Windows 10 | 11 | 1. Use adb to push [server.jar](https://github.com/diyews/scrcpy/releases) to phone 12 | 13 | .\adb.exe push "C:\scrcpy-server-flutter.jar" /sdcard/scrcpy-server-flutter.jar 14 | 15 | 1. Use adb to start server (Replace `<16_char_key>` to your own) 16 | 17 |
18 | Click to expand! 19 | 20 | ``.\adb.exe shell CLASSPATH=/sdcard/scrcpy-server-flutter.jar nohup app_process / --nice-name=scrcpy_device_server com.genymobile.scrcpy.Server <16_char_key> error 0 8000000 0 -1 true - true true 0 false false - - false `>/dev/null 2`>`&1 `& `` 21 | 22 | (Above `powershell.exe` use `` ` `` to escape character, in `cmd.exe` it is `` ^ ``) 23 |
24 | 25 | - Unix 26 | 1. Use adb to push [server.jar](https://github.com/diyews/scrcpy/releases) to phone 27 | 28 | adb push ./scrcpy-server-flutter.jar /sdcard/scrcpy-server-flutter.jar 29 | 30 | 1. Use adb to start server (Replace `<16_char_key>` to your own) 31 | 32 | ``adb shell CLASSPATH=/sdcard/scrcpy-server-flutter.jar nohup app_process / --nice-name=scrcpy_device_server com.genymobile.scrcpy.Server <16_char_key> error 0 8000000 0 -1 true - true true 0 false false - - false >/dev/null 2>&1 & `` 33 | 34 | Then you are able to connect to the phone via app. 35 | 36 | ## How this app works 37 | App use tcp to connect to `scrcpy-server-flutter.jar`, server port `7007`. 38 | 39 | Server use port `7008` to start http server for serving screenshot. 40 | 41 | ## Trouble shooting 42 | 43 | 1. Server didn't start. 44 | 45 | You can check if server is running by typing `adb shell "ps -A | grep scrcpy_device_server"` 46 | 47 | Try to run command in the front to check if errors there whiling start server. (remove `nohup`, `&` and output redirect from the start script) 48 | 49 | `adb shell CLASSPATH=/sdcard/scrcpy-server-flutter.jar nohup app_process / --nice-name=scrcpy_device_server com.genymobile.scrcpy.Server <16_char_key> error 0 8000000 0 -1 true - true true 0 false false - - false` 50 | 51 | ## Preview 52 | ![scrcpy_flutter](https://user-images.githubusercontent.com/35769340/155541745-b1bf15d8-8269-46ae-9fc4-e7f90a559672.gif) 53 | 54 | -------------------------------------------------------------------------------- /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 30 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 "ws.diye.scrcpy_flutter" 47 | minSdkVersion 16 48 | targetSdkVersion 30 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 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 14 | 18 | 22 | 27 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/ws/diye/scrcpy_flutter/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package ws.diye.scrcpy_flutter 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /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/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/ephemeral/ 22 | Flutter/app.flx 23 | Flutter/app.zip 24 | Flutter/flutter_assets/ 25 | Flutter/flutter_export_environment.sh 26 | ServiceDefinitions.json 27 | Runner/GeneratedPluginRegistrant.* 28 | 29 | # Exceptions to above rules. 30 | !default.mode1v3 31 | !default.mode2v3 32 | !default.pbxuser 33 | !default.perspectivev3 34 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 97 | ); 98 | path = Runner; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 97C146ED1CF9000F007C117D /* Runner */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 107 | buildPhases = ( 108 | 9740EEB61CF901F6004384FC /* Run Script */, 109 | 97C146EA1CF9000F007C117D /* Sources */, 110 | 97C146EB1CF9000F007C117D /* Frameworks */, 111 | 97C146EC1CF9000F007C117D /* Resources */, 112 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = Runner; 120 | productName = Runner; 121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | 97C146E61CF9000F007C117D /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastUpgradeCheck = 1020; 131 | ORGANIZATIONNAME = ""; 132 | TargetAttributes = { 133 | 97C146ED1CF9000F007C117D = { 134 | CreatedOnToolsVersion = 7.3.1; 135 | LastSwiftMigration = 1100; 136 | }; 137 | }; 138 | }; 139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 140 | compatibilityVersion = "Xcode 9.3"; 141 | developmentRegion = en; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | Base, 146 | ); 147 | mainGroup = 97C146E51CF9000F007C117D; 148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 149 | projectDirPath = ""; 150 | projectRoot = ""; 151 | targets = ( 152 | 97C146ED1CF9000F007C117D /* Runner */, 153 | ); 154 | }; 155 | /* End PBXProject section */ 156 | 157 | /* Begin PBXResourcesBuildPhase section */ 158 | 97C146EC1CF9000F007C117D /* Resources */ = { 159 | isa = PBXResourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXResourcesBuildPhase section */ 170 | 171 | /* Begin PBXShellScriptBuildPhase section */ 172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 173 | isa = PBXShellScriptBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | inputPaths = ( 178 | ); 179 | name = "Thin Binary"; 180 | outputPaths = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 185 | }; 186 | 9740EEB61CF901F6004384FC /* Run Script */ = { 187 | isa = PBXShellScriptBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | ); 191 | inputPaths = ( 192 | ); 193 | name = "Run Script"; 194 | outputPaths = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | shellPath = /bin/sh; 198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 199 | }; 200 | /* End PBXShellScriptBuildPhase section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 97C146EA1CF9000F007C117D /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXSourcesBuildPhase section */ 213 | 214 | /* Begin PBXVariantGroup section */ 215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 216 | isa = PBXVariantGroup; 217 | children = ( 218 | 97C146FB1CF9000F007C117D /* Base */, 219 | ); 220 | name = Main.storyboard; 221 | sourceTree = ""; 222 | }; 223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C147001CF9000F007C117D /* Base */, 227 | ); 228 | name = LaunchScreen.storyboard; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXVariantGroup section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_COMMA = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 276 | MTL_ENABLE_DEBUG_INFO = NO; 277 | SDKROOT = iphoneos; 278 | SUPPORTED_PLATFORMS = iphoneos; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Profile; 283 | }; 284 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 285 | isa = XCBuildConfiguration; 286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | CLANG_ENABLE_MODULES = YES; 290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 291 | ENABLE_BITCODE = NO; 292 | INFOPLIST_FILE = Runner/Info.plist; 293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 294 | PRODUCT_BUNDLE_IDENTIFIER = ws.diye.scrcpyFlutter; 295 | PRODUCT_NAME = "$(TARGET_NAME)"; 296 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 297 | SWIFT_VERSION = 5.0; 298 | VERSIONING_SYSTEM = "apple-generic"; 299 | }; 300 | name = Profile; 301 | }; 302 | 97C147031CF9000F007C117D /* Debug */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_ANALYZER_NONNULL = YES; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 312 | CLANG_WARN_BOOL_CONVERSION = YES; 313 | CLANG_WARN_COMMA = YES; 314 | CLANG_WARN_CONSTANT_CONVERSION = YES; 315 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 317 | CLANG_WARN_EMPTY_BODY = YES; 318 | CLANG_WARN_ENUM_CONVERSION = YES; 319 | CLANG_WARN_INFINITE_RECURSION = YES; 320 | CLANG_WARN_INT_CONVERSION = YES; 321 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 322 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 323 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 325 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 326 | CLANG_WARN_STRICT_PROTOTYPES = YES; 327 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 328 | CLANG_WARN_UNREACHABLE_CODE = YES; 329 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 330 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 331 | COPY_PHASE_STRIP = NO; 332 | DEBUG_INFORMATION_FORMAT = dwarf; 333 | ENABLE_STRICT_OBJC_MSGSEND = YES; 334 | ENABLE_TESTABILITY = YES; 335 | GCC_C_LANGUAGE_STANDARD = gnu99; 336 | GCC_DYNAMIC_NO_PIC = NO; 337 | GCC_NO_COMMON_BLOCKS = YES; 338 | GCC_OPTIMIZATION_LEVEL = 0; 339 | GCC_PREPROCESSOR_DEFINITIONS = ( 340 | "DEBUG=1", 341 | "$(inherited)", 342 | ); 343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 345 | GCC_WARN_UNDECLARED_SELECTOR = YES; 346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 347 | GCC_WARN_UNUSED_FUNCTION = YES; 348 | GCC_WARN_UNUSED_VARIABLE = YES; 349 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 350 | MTL_ENABLE_DEBUG_INFO = YES; 351 | ONLY_ACTIVE_ARCH = YES; 352 | SDKROOT = iphoneos; 353 | TARGETED_DEVICE_FAMILY = "1,2"; 354 | }; 355 | name = Debug; 356 | }; 357 | 97C147041CF9000F007C117D /* Release */ = { 358 | isa = XCBuildConfiguration; 359 | buildSettings = { 360 | ALWAYS_SEARCH_USER_PATHS = NO; 361 | CLANG_ANALYZER_NONNULL = YES; 362 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 363 | CLANG_CXX_LIBRARY = "libc++"; 364 | CLANG_ENABLE_MODULES = YES; 365 | CLANG_ENABLE_OBJC_ARC = YES; 366 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 367 | CLANG_WARN_BOOL_CONVERSION = YES; 368 | CLANG_WARN_COMMA = YES; 369 | CLANG_WARN_CONSTANT_CONVERSION = YES; 370 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 371 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 372 | CLANG_WARN_EMPTY_BODY = YES; 373 | CLANG_WARN_ENUM_CONVERSION = YES; 374 | CLANG_WARN_INFINITE_RECURSION = YES; 375 | CLANG_WARN_INT_CONVERSION = YES; 376 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 377 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 378 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 379 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 380 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 381 | CLANG_WARN_STRICT_PROTOTYPES = YES; 382 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 383 | CLANG_WARN_UNREACHABLE_CODE = YES; 384 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 385 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 386 | COPY_PHASE_STRIP = NO; 387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 388 | ENABLE_NS_ASSERTIONS = NO; 389 | ENABLE_STRICT_OBJC_MSGSEND = YES; 390 | GCC_C_LANGUAGE_STANDARD = gnu99; 391 | GCC_NO_COMMON_BLOCKS = YES; 392 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 393 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 394 | GCC_WARN_UNDECLARED_SELECTOR = YES; 395 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 396 | GCC_WARN_UNUSED_FUNCTION = YES; 397 | GCC_WARN_UNUSED_VARIABLE = YES; 398 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 399 | MTL_ENABLE_DEBUG_INFO = NO; 400 | SDKROOT = iphoneos; 401 | SUPPORTED_PLATFORMS = iphoneos; 402 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 403 | TARGETED_DEVICE_FAMILY = "1,2"; 404 | VALIDATE_PRODUCT = YES; 405 | }; 406 | name = Release; 407 | }; 408 | 97C147061CF9000F007C117D /* Debug */ = { 409 | isa = XCBuildConfiguration; 410 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 411 | buildSettings = { 412 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 413 | CLANG_ENABLE_MODULES = YES; 414 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 415 | ENABLE_BITCODE = NO; 416 | INFOPLIST_FILE = Runner/Info.plist; 417 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 418 | PRODUCT_BUNDLE_IDENTIFIER = ws.diye.scrcpyFlutter; 419 | PRODUCT_NAME = "$(TARGET_NAME)"; 420 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 421 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 422 | SWIFT_VERSION = 5.0; 423 | VERSIONING_SYSTEM = "apple-generic"; 424 | }; 425 | name = Debug; 426 | }; 427 | 97C147071CF9000F007C117D /* Release */ = { 428 | isa = XCBuildConfiguration; 429 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 430 | buildSettings = { 431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 432 | CLANG_ENABLE_MODULES = YES; 433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 434 | ENABLE_BITCODE = NO; 435 | INFOPLIST_FILE = Runner/Info.plist; 436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 437 | PRODUCT_BUNDLE_IDENTIFIER = ws.diye.scrcpyFlutter; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 440 | SWIFT_VERSION = 5.0; 441 | VERSIONING_SYSTEM = "apple-generic"; 442 | }; 443 | name = Release; 444 | }; 445 | /* End XCBuildConfiguration section */ 446 | 447 | /* Begin XCConfigurationList section */ 448 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 449 | isa = XCConfigurationList; 450 | buildConfigurations = ( 451 | 97C147031CF9000F007C117D /* Debug */, 452 | 97C147041CF9000F007C117D /* Release */, 453 | 249021D3217E4FDB00AE95B9 /* Profile */, 454 | ); 455 | defaultConfigurationIsVisible = 0; 456 | defaultConfigurationName = Release; 457 | }; 458 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 459 | isa = XCConfigurationList; 460 | buildConfigurations = ( 461 | 97C147061CF9000F007C117D /* Debug */, 462 | 97C147071CF9000F007C117D /* Release */, 463 | 249021D4217E4FDB00AE95B9 /* Profile */, 464 | ); 465 | defaultConfigurationIsVisible = 0; 466 | defaultConfigurationName = Release; 467 | }; 468 | /* End XCConfigurationList section */ 469 | }; 470 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 471 | } 472 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyews/scrcpy-flutter/8eeda96c67c1ab5addf5cf5121a0a6601aa2c32c/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | scrcpy_flutter 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/android_keycode.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Key codes. 3 | */ 4 | class AndroidKeycode { 5 | /** Unknown key code. */ 6 | static const int AKEYCODE_UNKNOWN = 0; 7 | 8 | /** Soft Left key. 9 | * Usually situated below the display on phones and used as a multi-function 10 | * feature key for selecting a software defined function shown on the bottom left 11 | * of the display. */ 12 | static const int AKEYCODE_SOFT_LEFT = 1; 13 | 14 | /** Soft Right key. 15 | * Usually situated below the display on phones and used as a multi-function 16 | * feature key for selecting a software defined function shown on the bottom right 17 | * of the display. */ 18 | static const int AKEYCODE_SOFT_RIGHT = 2; 19 | 20 | /** Home key. 21 | * This key is handled by the framework and is never delivered to applications. */ 22 | static const int AKEYCODE_HOME = 3; 23 | 24 | /** Back key. */ 25 | static const int AKEYCODE_BACK = 4; 26 | 27 | /** Call key. */ 28 | static const int AKEYCODE_CALL = 5; 29 | 30 | /** End Call key. */ 31 | static const int AKEYCODE_ENDCALL = 6; 32 | 33 | /** '0' key. */ 34 | static const int AKEYCODE_0 = 7; 35 | 36 | /** '1' key. */ 37 | static const int AKEYCODE_1 = 8; 38 | 39 | /** '2' key. */ 40 | static const int AKEYCODE_2 = 9; 41 | 42 | /** '3' key. */ 43 | static const int AKEYCODE_3 = 10; 44 | 45 | /** '4' key. */ 46 | static const int AKEYCODE_4 = 11; 47 | 48 | /** '5' key. */ 49 | static const int AKEYCODE_5 = 12; 50 | 51 | /** '6' key. */ 52 | static const int AKEYCODE_6 = 13; 53 | 54 | /** '7' key. */ 55 | static const int AKEYCODE_7 = 14; 56 | 57 | /** '8' key. */ 58 | static const int AKEYCODE_8 = 15; 59 | 60 | /** '9' key. */ 61 | static const int AKEYCODE_9 = 16; 62 | 63 | /** '*' key. */ 64 | static const int AKEYCODE_STAR = 17; 65 | 66 | /** '#' key. */ 67 | static const int AKEYCODE_POUND = 18; 68 | 69 | /** Directional Pad Up key. 70 | * May also be synthesized from trackball motions. */ 71 | static const int AKEYCODE_DPAD_UP = 19; 72 | 73 | /** Directional Pad Down key. 74 | * May also be synthesized from trackball motions. */ 75 | static const int AKEYCODE_DPAD_DOWN = 20; 76 | 77 | /** Directional Pad Left key. 78 | * May also be synthesized from trackball motions. */ 79 | static const int AKEYCODE_DPAD_LEFT = 21; 80 | 81 | /** Directional Pad Right key. 82 | * May also be synthesized from trackball motions. */ 83 | static const int AKEYCODE_DPAD_RIGHT = 22; 84 | 85 | /** Directional Pad Center key. 86 | * May also be synthesized from trackball motions. */ 87 | static const int AKEYCODE_DPAD_CENTER = 23; 88 | 89 | /** Volume Up key. 90 | * Adjusts the speaker volume up. */ 91 | static const int AKEYCODE_VOLUME_UP = 24; 92 | 93 | /** Volume Down key. 94 | * Adjusts the speaker volume down. */ 95 | static const int AKEYCODE_VOLUME_DOWN = 25; 96 | 97 | /** Power key. */ 98 | static const int AKEYCODE_POWER = 26; 99 | 100 | /** Camera key. 101 | * Used to launch a camera application or take pictures. */ 102 | static const int AKEYCODE_CAMERA = 27; 103 | 104 | /** Clear key. */ 105 | static const int AKEYCODE_CLEAR = 28; 106 | 107 | /** 'A' key. */ 108 | static const int AKEYCODE_A = 29; 109 | 110 | /** 'B' key. */ 111 | static const int AKEYCODE_B = 30; 112 | 113 | /** 'C' key. */ 114 | static const int AKEYCODE_C = 31; 115 | 116 | /** 'D' key. */ 117 | static const int AKEYCODE_D = 32; 118 | 119 | /** 'E' key. */ 120 | static const int AKEYCODE_E = 33; 121 | 122 | /** 'F' key. */ 123 | static const int AKEYCODE_F = 34; 124 | 125 | /** 'G' key. */ 126 | static const int AKEYCODE_G = 35; 127 | 128 | /** 'H' key. */ 129 | static const int AKEYCODE_H = 36; 130 | 131 | /** 'I' key. */ 132 | static const int AKEYCODE_I = 37; 133 | 134 | /** 'J' key. */ 135 | static const int AKEYCODE_J = 38; 136 | 137 | /** 'K' key. */ 138 | static const int AKEYCODE_K = 39; 139 | 140 | /** 'L' key. */ 141 | static const int AKEYCODE_L = 40; 142 | 143 | /** 'M' key. */ 144 | static const int AKEYCODE_M = 41; 145 | 146 | /** 'N' key. */ 147 | static const int AKEYCODE_N = 42; 148 | 149 | /** 'O' key. */ 150 | static const int AKEYCODE_O = 43; 151 | 152 | /** 'P' key. */ 153 | static const int AKEYCODE_P = 44; 154 | 155 | /** 'Q' key. */ 156 | static const int AKEYCODE_Q = 45; 157 | 158 | /** 'R' key. */ 159 | static const int AKEYCODE_R = 46; 160 | 161 | /** 'S' key. */ 162 | static const int AKEYCODE_S = 47; 163 | 164 | /** 'T' key. */ 165 | static const int AKEYCODE_T = 48; 166 | 167 | /** 'U' key. */ 168 | static const int AKEYCODE_U = 49; 169 | 170 | /** 'V' key. */ 171 | static const int AKEYCODE_V = 50; 172 | 173 | /** 'W' key. */ 174 | static const int AKEYCODE_W = 51; 175 | 176 | /** 'X' key. */ 177 | static const int AKEYCODE_X = 52; 178 | 179 | /** 'Y' key. */ 180 | static const int AKEYCODE_Y = 53; 181 | 182 | /** 'Z' key. */ 183 | static const int AKEYCODE_Z = 54; 184 | 185 | /** ',' key. */ 186 | static const int AKEYCODE_COMMA = 55; 187 | 188 | /** '.' key. */ 189 | static const int AKEYCODE_PERIOD = 56; 190 | 191 | /** Left Alt modifier key. */ 192 | static const int AKEYCODE_ALT_LEFT = 57; 193 | 194 | /** Right Alt modifier key. */ 195 | static const int AKEYCODE_ALT_RIGHT = 58; 196 | 197 | /** Left Shift modifier key. */ 198 | static const int AKEYCODE_SHIFT_LEFT = 59; 199 | 200 | /** Right Shift modifier key. */ 201 | static const int AKEYCODE_SHIFT_RIGHT = 60; 202 | 203 | /** Tab key. */ 204 | static const int AKEYCODE_TAB = 61; 205 | 206 | /** Space key. */ 207 | static const int AKEYCODE_SPACE = 62; 208 | 209 | /** Symbol modifier key. 210 | * Used to enter alternate symbols. */ 211 | static const int AKEYCODE_SYM = 63; 212 | 213 | /** Explorer special function key. 214 | * Used to launch a browser application. */ 215 | static const int AKEYCODE_EXPLORER = 64; 216 | 217 | /** Envelope special function key. 218 | * Used to launch a mail application. */ 219 | static const int AKEYCODE_ENVELOPE = 65; 220 | 221 | /** Enter key. */ 222 | static const int AKEYCODE_ENTER = 66; 223 | 224 | /** Backspace key. 225 | * Deletes characters before the insertion point, unlike {@link AKEYCODE_FORWARD_DEL}. */ 226 | static const int AKEYCODE_DEL = 67; 227 | 228 | /** '`' (backtick) key. */ 229 | static const int AKEYCODE_GRAVE = 68; 230 | 231 | /** '-'. */ 232 | static const int AKEYCODE_MINUS = 69; 233 | 234 | /** '=' key. */ 235 | static const int AKEYCODE_EQUALS = 70; 236 | 237 | /** '[' key. */ 238 | static const int AKEYCODE_LEFT_BRACKET = 71; 239 | 240 | /** ']' key. */ 241 | static const int AKEYCODE_RIGHT_BRACKET = 72; 242 | 243 | /** '\' key. */ 244 | static const int AKEYCODE_BACKSLASH = 73; 245 | 246 | /** ';' key. */ 247 | static const int AKEYCODE_SEMICOLON = 74; 248 | 249 | /** ''' (apostrophe) key. */ 250 | static const int AKEYCODE_APOSTROPHE = 75; 251 | 252 | /** '/' key. */ 253 | static const int AKEYCODE_SLASH = 76; 254 | 255 | /** '@' key. */ 256 | static const int AKEYCODE_AT = 77; 257 | 258 | /** Number modifier key. 259 | * Used to enter numeric symbols. 260 | * This key is not {@link AKEYCODE_NUM_LOCK}; it is more like {@link AKEYCODE_ALT_LEFT}. */ 261 | static const int AKEYCODE_NUM = 78; 262 | 263 | /** Headset Hook key. 264 | * Used to hang up calls and stop media. */ 265 | static const int AKEYCODE_HEADSETHOOK = 79; 266 | 267 | /** Camera Focus key. 268 | * Used to focus the camera. */ 269 | static const int AKEYCODE_FOCUS = 80; 270 | 271 | /** '+' key. */ 272 | static const int AKEYCODE_PLUS = 81; 273 | 274 | /** Menu key. */ 275 | static const int AKEYCODE_MENU = 82; 276 | 277 | /** Notification key. */ 278 | static const int AKEYCODE_NOTIFICATION = 83; 279 | 280 | /** Search key. */ 281 | static const int AKEYCODE_SEARCH = 84; 282 | 283 | /** Play/Pause media key. */ 284 | static const int AKEYCODE_MEDIA_PLAY_PAUSE = 85; 285 | 286 | /** Stop media key. */ 287 | static const int AKEYCODE_MEDIA_STOP = 86; 288 | 289 | /** Play Next media key. */ 290 | static const int AKEYCODE_MEDIA_NEXT = 87; 291 | 292 | /** Play Previous media key. */ 293 | static const int AKEYCODE_MEDIA_PREVIOUS = 88; 294 | 295 | /** Rewind media key. */ 296 | static const int AKEYCODE_MEDIA_REWIND = 89; 297 | 298 | /** Fast Forward media key. */ 299 | static const int AKEYCODE_MEDIA_FAST_FORWARD = 90; 300 | 301 | /** Mute key. 302 | * Mutes the microphone, unlike {@link AKEYCODE_VOLUME_MUTE}. */ 303 | static const int AKEYCODE_MUTE = 91; 304 | 305 | /** Page Up key. */ 306 | static const int AKEYCODE_PAGE_UP = 92; 307 | 308 | /** Page Down key. */ 309 | static const int AKEYCODE_PAGE_DOWN = 93; 310 | 311 | /** Picture Symbols modifier key. 312 | * Used to switch symbol sets (Emoji, Kao-moji). */ 313 | static const int AKEYCODE_PICTSYMBOLS = 94; 314 | 315 | /** Switch Charset modifier key. 316 | * Used to switch character sets (Kanji, Katakana). */ 317 | static const int AKEYCODE_SWITCH_CHARSET = 95; 318 | 319 | /** A Button key. 320 | * On a game controller, the A button should be either the button labeled A 321 | * or the first button on the bottom row of controller buttons. */ 322 | static const int AKEYCODE_BUTTON_A = 96; 323 | 324 | /** B Button key. 325 | * On a game controller, the B button should be either the button labeled B 326 | * or the second button on the bottom row of controller buttons. */ 327 | static const int AKEYCODE_BUTTON_B = 97; 328 | 329 | /** C Button key. 330 | * On a game controller, the C button should be either the button labeled C 331 | * or the third button on the bottom row of controller buttons. */ 332 | static const int AKEYCODE_BUTTON_C = 98; 333 | 334 | /** X Button key. 335 | * On a game controller, the X button should be either the button labeled X 336 | * or the first button on the upper row of controller buttons. */ 337 | static const int AKEYCODE_BUTTON_X = 99; 338 | 339 | /** Y Button key. 340 | * On a game controller, the Y button should be either the button labeled Y 341 | * or the second button on the upper row of controller buttons. */ 342 | static const int AKEYCODE_BUTTON_Y = 100; 343 | 344 | /** Z Button key. 345 | * On a game controller, the Z button should be either the button labeled Z 346 | * or the third button on the upper row of controller buttons. */ 347 | static const int AKEYCODE_BUTTON_Z = 101; 348 | 349 | /** L1 Button key. 350 | * On a game controller, the L1 button should be either the button labeled L1 (or L) 351 | * or the top left trigger button. */ 352 | static const int AKEYCODE_BUTTON_L1 = 102; 353 | 354 | /** R1 Button key. 355 | * On a game controller, the R1 button should be either the button labeled R1 (or R) 356 | * or the top right trigger button. */ 357 | static const int AKEYCODE_BUTTON_R1 = 103; 358 | 359 | /** L2 Button key. 360 | * On a game controller, the L2 button should be either the button labeled L2 361 | * or the bottom left trigger button. */ 362 | static const int AKEYCODE_BUTTON_L2 = 104; 363 | 364 | /** R2 Button key. 365 | * On a game controller, the R2 button should be either the button labeled R2 366 | * or the bottom right trigger button. */ 367 | static const int AKEYCODE_BUTTON_R2 = 105; 368 | 369 | /** Left Thumb Button key. 370 | * On a game controller, the left thumb button indicates that the left (or only) 371 | * joystick is pressed. */ 372 | static const int AKEYCODE_BUTTON_THUMBL = 106; 373 | 374 | /** Right Thumb Button key. 375 | * On a game controller, the right thumb button indicates that the right 376 | * joystick is pressed. */ 377 | static const int AKEYCODE_BUTTON_THUMBR = 107; 378 | 379 | /** Start Button key. 380 | * On a game controller, the button labeled Start. */ 381 | static const int AKEYCODE_BUTTON_START = 108; 382 | 383 | /** Select Button key. 384 | * On a game controller, the button labeled Select. */ 385 | static const int AKEYCODE_BUTTON_SELECT = 109; 386 | 387 | /** Mode Button key. 388 | * On a game controller, the button labeled Mode. */ 389 | static const int AKEYCODE_BUTTON_MODE = 110; 390 | 391 | /** Escape key. */ 392 | static const int AKEYCODE_ESCAPE = 111; 393 | 394 | /** Forward Delete key. 395 | * Deletes characters ahead of the insertion point, unlike {@link AKEYCODE_DEL}. */ 396 | static const int AKEYCODE_FORWARD_DEL = 112; 397 | 398 | /** Left Control modifier key. */ 399 | static const int AKEYCODE_CTRL_LEFT = 113; 400 | 401 | /** Right Control modifier key. */ 402 | static const int AKEYCODE_CTRL_RIGHT = 114; 403 | 404 | /** Caps Lock key. */ 405 | static const int AKEYCODE_CAPS_LOCK = 115; 406 | 407 | /** Scroll Lock key. */ 408 | static const int AKEYCODE_SCROLL_LOCK = 116; 409 | 410 | /** Left Meta modifier key. */ 411 | static const int AKEYCODE_META_LEFT = 117; 412 | 413 | /** Right Meta modifier key. */ 414 | static const int AKEYCODE_META_RIGHT = 118; 415 | 416 | /** Function modifier key. */ 417 | static const int AKEYCODE_FUNCTION = 119; 418 | 419 | /** System Request / Print Screen key. */ 420 | static const int AKEYCODE_SYSRQ = 120; 421 | 422 | /** Break / Pause key. */ 423 | static const int AKEYCODE_BREAK = 121; 424 | 425 | /** Home Movement key. 426 | * Used for scrolling or moving the cursor around to the start of a line 427 | * or to the top of a list. */ 428 | static const int AKEYCODE_MOVE_HOME = 122; 429 | 430 | /** End Movement key. 431 | * Used for scrolling or moving the cursor around to the end of a line 432 | * or to the bottom of a list. */ 433 | static const int AKEYCODE_MOVE_END = 123; 434 | 435 | /** Insert key. 436 | * Toggles insert / overwrite edit mode. */ 437 | static const int AKEYCODE_INSERT = 124; 438 | 439 | /** Forward key. 440 | * Navigates forward in the history stack. Complement of {@link AKEYCODE_BACK}. */ 441 | static const int AKEYCODE_FORWARD = 125; 442 | 443 | /** Play media key. */ 444 | static const int AKEYCODE_MEDIA_PLAY = 126; 445 | 446 | /** Pause media key. */ 447 | static const int AKEYCODE_MEDIA_PAUSE = 127; 448 | 449 | /** Close media key. 450 | * May be used to close a CD tray, for example. */ 451 | static const int AKEYCODE_MEDIA_CLOSE = 128; 452 | 453 | /** Eject media key. 454 | * May be used to eject a CD tray, for example. */ 455 | static const int AKEYCODE_MEDIA_EJECT = 129; 456 | 457 | /** Record media key. */ 458 | static const int AKEYCODE_MEDIA_RECORD = 130; 459 | 460 | /** F1 key. */ 461 | static const int AKEYCODE_F1 = 131; 462 | 463 | /** F2 key. */ 464 | static const int AKEYCODE_F2 = 132; 465 | 466 | /** F3 key. */ 467 | static const int AKEYCODE_F3 = 133; 468 | 469 | /** F4 key. */ 470 | static const int AKEYCODE_F4 = 134; 471 | 472 | /** F5 key. */ 473 | static const int AKEYCODE_F5 = 135; 474 | 475 | /** F6 key. */ 476 | static const int AKEYCODE_F6 = 136; 477 | 478 | /** F7 key. */ 479 | static const int AKEYCODE_F7 = 137; 480 | 481 | /** F8 key. */ 482 | static const int AKEYCODE_F8 = 138; 483 | 484 | /** F9 key. */ 485 | static const int AKEYCODE_F9 = 139; 486 | 487 | /** F10 key. */ 488 | static const int AKEYCODE_F10 = 140; 489 | 490 | /** F11 key. */ 491 | static const int AKEYCODE_F11 = 141; 492 | 493 | /** F12 key. */ 494 | static const int AKEYCODE_F12 = 142; 495 | 496 | /** Num Lock key. 497 | * This is the Num Lock key; it is different from {@link AKEYCODE_NUM}. 498 | * This key alters the behavior of other keys on the numeric keypad. */ 499 | static const int AKEYCODE_NUM_LOCK = 143; 500 | 501 | /** Numeric keypad '0' key. */ 502 | static const int AKEYCODE_NUMPAD_0 = 144; 503 | 504 | /** Numeric keypad '1' key. */ 505 | static const int AKEYCODE_NUMPAD_1 = 145; 506 | 507 | /** Numeric keypad '2' key. */ 508 | static const int AKEYCODE_NUMPAD_2 = 146; 509 | 510 | /** Numeric keypad '3' key. */ 511 | static const int AKEYCODE_NUMPAD_3 = 147; 512 | 513 | /** Numeric keypad '4' key. */ 514 | static const int AKEYCODE_NUMPAD_4 = 148; 515 | 516 | /** Numeric keypad '5' key. */ 517 | static const int AKEYCODE_NUMPAD_5 = 149; 518 | 519 | /** Numeric keypad '6' key. */ 520 | static const int AKEYCODE_NUMPAD_6 = 150; 521 | 522 | /** Numeric keypad '7' key. */ 523 | static const int AKEYCODE_NUMPAD_7 = 151; 524 | 525 | /** Numeric keypad '8' key. */ 526 | static const int AKEYCODE_NUMPAD_8 = 152; 527 | 528 | /** Numeric keypad '9' key. */ 529 | static const int AKEYCODE_NUMPAD_9 = 153; 530 | 531 | /** Numeric keypad '/' key (for division). */ 532 | static const int AKEYCODE_NUMPAD_DIVIDE = 154; 533 | 534 | /** Numeric keypad '*' key (for multiplication). */ 535 | static const int AKEYCODE_NUMPAD_MULTIPLY = 155; 536 | 537 | /** Numeric keypad '-' key (for subtraction). */ 538 | static const int AKEYCODE_NUMPAD_SUBTRACT = 156; 539 | 540 | /** Numeric keypad '+' key (for addition). */ 541 | static const int AKEYCODE_NUMPAD_ADD = 157; 542 | 543 | /** Numeric keypad '.' key (for decimals or digit grouping). */ 544 | static const int AKEYCODE_NUMPAD_DOT = 158; 545 | 546 | /** Numeric keypad ',' key (for decimals or digit grouping). */ 547 | static const int AKEYCODE_NUMPAD_COMMA = 159; 548 | 549 | /** Numeric keypad Enter key. */ 550 | static const int AKEYCODE_NUMPAD_ENTER = 160; 551 | 552 | /** Numeric keypad '=' key. */ 553 | static const int AKEYCODE_NUMPAD_EQUALS = 161; 554 | 555 | /** Numeric keypad '(' key. */ 556 | static const int AKEYCODE_NUMPAD_LEFT_PAREN = 162; 557 | 558 | /** Numeric keypad ')' key. */ 559 | static const int AKEYCODE_NUMPAD_RIGHT_PAREN = 163; 560 | 561 | /** Volume Mute key. 562 | * Mutes the speaker, unlike {@link AKEYCODE_MUTE}. 563 | * This key should normally be implemented as a toggle such that the first press 564 | * mutes the speaker and the second press restores the original volume. */ 565 | static const int AKEYCODE_VOLUME_MUTE = 164; 566 | 567 | /** Info key. 568 | * Common on TV remotes to show additional information related to what is 569 | * currently being viewed. */ 570 | static const int AKEYCODE_INFO = 165; 571 | 572 | /** Channel up key. 573 | * On TV remotes, increments the television channel. */ 574 | static const int AKEYCODE_CHANNEL_UP = 166; 575 | 576 | /** Channel down key. 577 | * On TV remotes, decrements the television channel. */ 578 | static const int AKEYCODE_CHANNEL_DOWN = 167; 579 | 580 | /** Zoom in key. */ 581 | static const int AKEYCODE_ZOOM_IN = 168; 582 | 583 | /** Zoom out key. */ 584 | static const int AKEYCODE_ZOOM_OUT = 169; 585 | 586 | /** TV key. 587 | * On TV remotes, switches to viewing live TV. */ 588 | static const int AKEYCODE_TV = 170; 589 | 590 | /** Window key. 591 | * On TV remotes, toggles picture-in-picture mode or other windowing functions. */ 592 | static const int AKEYCODE_WINDOW = 171; 593 | 594 | /** Guide key. 595 | * On TV remotes, shows a programming guide. */ 596 | static const int AKEYCODE_GUIDE = 172; 597 | 598 | /** DVR key. 599 | * On some TV remotes, switches to a DVR mode for recorded shows. */ 600 | static const int AKEYCODE_DVR = 173; 601 | 602 | /** Bookmark key. 603 | * On some TV remotes, bookmarks content or web pages. */ 604 | static const int AKEYCODE_BOOKMARK = 174; 605 | 606 | /** Toggle captions key. 607 | * Switches the mode for closed-captioning text, for example during television shows. */ 608 | static const int AKEYCODE_CAPTIONS = 175; 609 | 610 | /** Settings key. 611 | * Starts the system settings activity. */ 612 | static const int AKEYCODE_SETTINGS = 176; 613 | 614 | /** TV power key. 615 | * On TV remotes, toggles the power on a television screen. */ 616 | static const int AKEYCODE_TV_POWER = 177; 617 | 618 | /** TV input key. 619 | * On TV remotes, switches the input on a television screen. */ 620 | static const int AKEYCODE_TV_INPUT = 178; 621 | 622 | /** Set-top-box power key. 623 | * On TV remotes, toggles the power on an external Set-top-box. */ 624 | static const int AKEYCODE_STB_POWER = 179; 625 | 626 | /** Set-top-box input key. 627 | * On TV remotes, switches the input mode on an external Set-top-box. */ 628 | static const int AKEYCODE_STB_INPUT = 180; 629 | 630 | /** A/V Receiver power key. 631 | * On TV remotes, toggles the power on an external A/V Receiver. */ 632 | static const int AKEYCODE_AVR_POWER = 181; 633 | 634 | /** A/V Receiver input key. 635 | * On TV remotes, switches the input mode on an external A/V Receiver. */ 636 | static const int AKEYCODE_AVR_INPUT = 182; 637 | 638 | /** Red "programmable" key. 639 | * On TV remotes, acts as a contextual/programmable key. */ 640 | static const int AKEYCODE_PROG_RED = 183; 641 | 642 | /** Green "programmable" key. 643 | * On TV remotes, actsas a contextual/programmable key. */ 644 | static const int AKEYCODE_PROG_GREEN = 184; 645 | 646 | /** Yellow "programmable" key. 647 | * On TV remotes, acts as a contextual/programmable key. */ 648 | static const int AKEYCODE_PROG_YELLOW = 185; 649 | 650 | /** Blue "programmable" key. 651 | * On TV remotes, acts as a contextual/programmable key. */ 652 | static const int AKEYCODE_PROG_BLUE = 186; 653 | 654 | /** App switch key. 655 | * Should bring up the application switcher dialog. */ 656 | static const int AKEYCODE_APP_SWITCH = 187; 657 | 658 | /** Generic Game Pad Button #1.*/ 659 | static const int AKEYCODE_BUTTON_1 = 188; 660 | 661 | /** Generic Game Pad Button #2.*/ 662 | static const int AKEYCODE_BUTTON_2 = 189; 663 | 664 | /** Generic Game Pad Button #3.*/ 665 | static const int AKEYCODE_BUTTON_3 = 190; 666 | 667 | /** Generic Game Pad Button #4.*/ 668 | static const int AKEYCODE_BUTTON_4 = 191; 669 | 670 | /** Generic Game Pad Button #5.*/ 671 | static const int AKEYCODE_BUTTON_5 = 192; 672 | 673 | /** Generic Game Pad Button #6.*/ 674 | static const int AKEYCODE_BUTTON_6 = 193; 675 | 676 | /** Generic Game Pad Button #7.*/ 677 | static const int AKEYCODE_BUTTON_7 = 194; 678 | 679 | /** Generic Game Pad Button #8.*/ 680 | static const int AKEYCODE_BUTTON_8 = 195; 681 | 682 | /** Generic Game Pad Button #9.*/ 683 | static const int AKEYCODE_BUTTON_9 = 196; 684 | 685 | /** Generic Game Pad Button #10.*/ 686 | static const int AKEYCODE_BUTTON_10 = 197; 687 | 688 | /** Generic Game Pad Button #11.*/ 689 | static const int AKEYCODE_BUTTON_11 = 198; 690 | 691 | /** Generic Game Pad Button #12.*/ 692 | static const int AKEYCODE_BUTTON_12 = 199; 693 | 694 | /** Generic Game Pad Button #13.*/ 695 | static const int AKEYCODE_BUTTON_13 = 200; 696 | 697 | /** Generic Game Pad Button #14.*/ 698 | static const int AKEYCODE_BUTTON_14 = 201; 699 | 700 | /** Generic Game Pad Button #15.*/ 701 | static const int AKEYCODE_BUTTON_15 = 202; 702 | 703 | /** Generic Game Pad Button #16.*/ 704 | static const int AKEYCODE_BUTTON_16 = 203; 705 | 706 | /** Language Switch key. 707 | * Toggles the current input language such as switching between English and Japanese on 708 | * a QWERTY keyboard. On some devices, the same function may be performed by 709 | * pressing Shift+Spacebar. */ 710 | static const int AKEYCODE_LANGUAGE_SWITCH = 204; 711 | 712 | /** Manner Mode key. 713 | * Toggles silent or vibrate mode on and off to make the device behave more politely 714 | * in certain settings such as on a crowded train. On some devices, the key may only 715 | * operate when long-pressed. */ 716 | static const int AKEYCODE_MANNER_MODE = 205; 717 | 718 | /** 3D Mode key. 719 | * Toggles the display between 2D and 3D mode. */ 720 | static const int AKEYCODE_3D_MODE = 206; 721 | 722 | /** Contacts special function key. 723 | * Used to launch an address book application. */ 724 | static const int AKEYCODE_CONTACTS = 207; 725 | 726 | /** Calendar special function key. 727 | * Used to launch a calendar application. */ 728 | static const int AKEYCODE_CALENDAR = 208; 729 | 730 | /** Music special function key. 731 | * Used to launch a music player application. */ 732 | static const int AKEYCODE_MUSIC = 209; 733 | 734 | /** Calculator special function key. 735 | * Used to launch a calculator application. */ 736 | static const int AKEYCODE_CALCULATOR = 210; 737 | 738 | /** Japanese full-width / half-width key. */ 739 | static const int AKEYCODE_ZENKAKU_HANKAKU = 211; 740 | 741 | /** Japanese alphanumeric key. */ 742 | static const int AKEYCODE_EISU = 212; 743 | 744 | /** Japanese non-conversion key. */ 745 | static const int AKEYCODE_MUHENKAN = 213; 746 | 747 | /** Japanese conversion key. */ 748 | static const int AKEYCODE_HENKAN = 214; 749 | 750 | /** Japanese katakana / hiragana key. */ 751 | static const int AKEYCODE_KATAKANA_HIRAGANA = 215; 752 | 753 | /** Japanese Yen key. */ 754 | static const int AKEYCODE_YEN = 216; 755 | 756 | /** Japanese Ro key. */ 757 | static const int AKEYCODE_RO = 217; 758 | 759 | /** Japanese kana key. */ 760 | static const int AKEYCODE_KANA = 218; 761 | 762 | /** Assist key. 763 | * Launches the global assist activity. Not delivered to applications. */ 764 | static const int AKEYCODE_ASSIST = 219; 765 | 766 | /** Brightness Down key. 767 | * Adjusts the screen brightness down. */ 768 | static const int AKEYCODE_BRIGHTNESS_DOWN = 220; 769 | 770 | /** Brightness Up key. 771 | * Adjusts the screen brightness up. */ 772 | static const int AKEYCODE_BRIGHTNESS_UP = 221; 773 | 774 | /** Audio Track key. 775 | * Switches the audio tracks. */ 776 | static const int AKEYCODE_MEDIA_AUDIO_TRACK = 222; 777 | 778 | /** Sleep key. 779 | * Puts the device to sleep. Behaves somewhat like {@link AKEYCODE_POWER} but it 780 | * has no effect if the device is already asleep. */ 781 | static const int AKEYCODE_SLEEP = 223; 782 | 783 | /** Wakeup key. 784 | * Wakes up the device. Behaves somewhat like {@link AKEYCODE_POWER} but it 785 | * has no effect if the device is already awake. */ 786 | static const int AKEYCODE_WAKEUP = 224; 787 | 788 | /** Pairing key. 789 | * Initiates peripheral pairing mode. Useful for pairing remote control 790 | * devices or game controllers, especially if no other input mode is 791 | * available. */ 792 | static const int AKEYCODE_PAIRING = 225; 793 | 794 | /** Media Top Menu key. 795 | * Goes to the top of media menu. */ 796 | static const int AKEYCODE_MEDIA_TOP_MENU = 226; 797 | 798 | /** '11' key. */ 799 | static const int AKEYCODE_11 = 227; 800 | 801 | /** '12' key. */ 802 | static const int AKEYCODE_12 = 228; 803 | 804 | /** Last Channel key. 805 | * Goes to the last viewed channel. */ 806 | static const int AKEYCODE_LAST_CHANNEL = 229; 807 | 808 | /** TV data service key. 809 | * Displays data services like weather, sports. */ 810 | static const int AKEYCODE_TV_DATA_SERVICE = 230; 811 | 812 | /** Voice Assist key. 813 | * Launches the global voice assist activity. Not delivered to applications. */ 814 | static const int AKEYCODE_VOICE_ASSIST = 231; 815 | 816 | /** Radio key. 817 | * Toggles TV service / Radio service. */ 818 | static const int AKEYCODE_TV_RADIO_SERVICE = 232; 819 | 820 | /** Teletext key. 821 | * Displays Teletext service. */ 822 | static const int AKEYCODE_TV_TELETEXT = 233; 823 | 824 | /** Number entry key. 825 | * Initiates to enter multi-digit channel nubmber when each digit key is assigned 826 | * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC 827 | * User Control Code. */ 828 | static const int AKEYCODE_TV_NUMBER_ENTRY = 234; 829 | 830 | /** Analog Terrestrial key. 831 | * Switches to analog terrestrial broadcast service. */ 832 | static const int AKEYCODE_TV_TERRESTRIAL_ANALOG = 235; 833 | 834 | /** Digital Terrestrial key. 835 | * Switches to digital terrestrial broadcast service. */ 836 | static const int AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236; 837 | 838 | /** Satellite key. 839 | * Switches to digital satellite broadcast service. */ 840 | static const int AKEYCODE_TV_SATELLITE = 237; 841 | 842 | /** BS key. 843 | * Switches to BS digital satellite broadcasting service available in Japan. */ 844 | static const int AKEYCODE_TV_SATELLITE_BS = 238; 845 | 846 | /** CS key. 847 | * Switches to CS digital satellite broadcasting service available in Japan. */ 848 | static const int AKEYCODE_TV_SATELLITE_CS = 239; 849 | 850 | /** BS/CS key. 851 | * Toggles between BS and CS digital satellite services. */ 852 | static const int AKEYCODE_TV_SATELLITE_SERVICE = 240; 853 | 854 | /** Toggle Network key. 855 | * Toggles selecting broacast services. */ 856 | static const int AKEYCODE_TV_NETWORK = 241; 857 | 858 | /** Antenna/Cable key. 859 | * Toggles broadcast input source between antenna and cable. */ 860 | static const int AKEYCODE_TV_ANTENNA_CABLE = 242; 861 | 862 | /** HDMI #1 key. 863 | * Switches to HDMI input #1. */ 864 | static const int AKEYCODE_TV_INPUT_HDMI_1 = 243; 865 | 866 | /** HDMI #2 key. 867 | * Switches to HDMI input #2. */ 868 | static const int AKEYCODE_TV_INPUT_HDMI_2 = 244; 869 | 870 | /** HDMI #3 key. 871 | * Switches to HDMI input #3. */ 872 | static const int AKEYCODE_TV_INPUT_HDMI_3 = 245; 873 | 874 | /** HDMI #4 key. 875 | * Switches to HDMI input #4. */ 876 | static const int AKEYCODE_TV_INPUT_HDMI_4 = 246; 877 | 878 | /** Composite #1 key. 879 | * Switches to composite video input #1. */ 880 | static const int AKEYCODE_TV_INPUT_COMPOSITE_1 = 247; 881 | 882 | /** Composite #2 key. 883 | * Switches to composite video input #2. */ 884 | static const int AKEYCODE_TV_INPUT_COMPOSITE_2 = 248; 885 | 886 | /** Component #1 key. 887 | * Switches to component video input #1. */ 888 | static const int AKEYCODE_TV_INPUT_COMPONENT_1 = 249; 889 | 890 | /** Component #2 key. 891 | * Switches to component video input #2. */ 892 | static const int AKEYCODE_TV_INPUT_COMPONENT_2 = 250; 893 | 894 | /** VGA #1 key. 895 | * Switches to VGA (analog RGB) input #1. */ 896 | static const int AKEYCODE_TV_INPUT_VGA_1 = 251; 897 | 898 | /** Audio description key. 899 | * Toggles audio description off / on. */ 900 | static const int AKEYCODE_TV_AUDIO_DESCRIPTION = 252; 901 | 902 | /** Audio description mixing volume up key. 903 | * Louden audio description volume as compared with normal audio volume. */ 904 | static const int AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253; 905 | 906 | /** Audio description mixing volume down key. 907 | * Lessen audio description volume as compared with normal audio volume. */ 908 | static const int AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254; 909 | 910 | /** Zoom mode key. 911 | * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */ 912 | static const int AKEYCODE_TV_ZOOM_MODE = 255; 913 | 914 | /** Contents menu key. 915 | * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control 916 | * Code */ 917 | static const int AKEYCODE_TV_CONTENTS_MENU = 256; 918 | 919 | /** Media context menu key. 920 | * Goes to the context menu of media contents. Corresponds to Media Context-sensitive 921 | * Menu (0x11) of CEC User Control Code. */ 922 | static const int AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257; 923 | 924 | /** Timer programming key. 925 | * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of 926 | * CEC User Control Code. */ 927 | static const int AKEYCODE_TV_TIMER_PROGRAMMING = 258; 928 | 929 | /** Help key. */ 930 | static const int AKEYCODE_HELP = 259; 931 | static const int AKEYCODE_NAVIGATE_PREVIOUS = 260; 932 | static const int AKEYCODE_NAVIGATE_NEXT = 261; 933 | static const int AKEYCODE_NAVIGATE_IN = 262; 934 | static const int AKEYCODE_NAVIGATE_OUT = 263; 935 | 936 | /** Primary stem key for Wear 937 | * Main power/reset button on watch. */ 938 | static const int AKEYCODE_STEM_PRIMARY = 264; 939 | 940 | /** Generic stem key 1 for Wear */ 941 | static const int AKEYCODE_STEM_1 = 265; 942 | 943 | /** Generic stem key 2 for Wear */ 944 | static const int AKEYCODE_STEM_2 = 266; 945 | 946 | /** Generic stem key 3 for Wear */ 947 | static const int AKEYCODE_STEM_3 = 267; 948 | 949 | /** Directional Pad Up-Left */ 950 | static const int AKEYCODE_DPAD_UP_LEFT = 268; 951 | 952 | /** Directional Pad Down-Left */ 953 | static const int AKEYCODE_DPAD_DOWN_LEFT = 269; 954 | 955 | /** Directional Pad Up-Right */ 956 | static const int AKEYCODE_DPAD_UP_RIGHT = 270; 957 | 958 | /** Directional Pad Down-Right */ 959 | static const int AKEYCODE_DPAD_DOWN_RIGHT = 271; 960 | 961 | /** Skip forward media key */ 962 | static const int AKEYCODE_MEDIA_SKIP_FORWARD = 272; 963 | 964 | /** Skip backward media key */ 965 | static const int AKEYCODE_MEDIA_SKIP_BACKWARD = 273; 966 | 967 | /** Step forward media key. 968 | * Steps media forward one from at a time. */ 969 | static const int AKEYCODE_MEDIA_STEP_FORWARD = 274; 970 | 971 | /** Step backward media key. 972 | * Steps media backward one from at a time. */ 973 | static const int AKEYCODE_MEDIA_STEP_BACKWARD = 275; 974 | 975 | /** Put device to sleep unless a wakelock is held. */ 976 | static const int AKEYCODE_SOFT_SLEEP = 276; 977 | 978 | /** Cut key. */ 979 | static const int AKEYCODE_CUT = 277; 980 | 981 | /** Copy key. */ 982 | static const int AKEYCODE_COPY = 278; 983 | 984 | /** Paste key. */ 985 | static const int AKEYCODE_PASTE = 279; 986 | 987 | /** fingerprint navigation key, up. */ 988 | static const int AKEYCODE_SYSTEM_NAVIGATION_UP = 280; 989 | 990 | /** fingerprint navigation key, down. */ 991 | static const int AKEYCODE_SYSTEM_NAVIGATION_DOWN = 281; 992 | 993 | /** fingerprint navigation key, left. */ 994 | static const int AKEYCODE_SYSTEM_NAVIGATION_LEFT = 282; 995 | 996 | /** fingerprint navigation key, right. */ 997 | static const int AKEYCODE_SYSTEM_NAVIGATION_RIGHT = 283; 998 | 999 | /** all apps */ 1000 | static const int AKEYCODE_ALL_APPS = 284; 1001 | } 1002 | -------------------------------------------------------------------------------- /lib/cbc_cipher.dart: -------------------------------------------------------------------------------- 1 | import 'dart:isolate'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:pointycastle/export.dart' hide State; 5 | import 'package:shared_preferences/shared_preferences.dart'; 6 | 7 | class CBCCipher { 8 | static Uint8List aesKey = Uint8List(0); 9 | 10 | static void setAESKey(Uint8List key, [bool isSync = true]) { 11 | aesKey = key; 12 | if (isSync) { 13 | CBCCipherIsolate.syncKey(); 14 | } 15 | } 16 | 17 | static Future initKey() async { 18 | final prefs = await SharedPreferences.getInstance(); 19 | final key = prefs.getString('encrypt_key') ?? ''; 20 | if (key.isNotEmpty) { 21 | setAESKey(Uint8List.fromList(key.codeUnits)); 22 | } 23 | } 24 | 25 | static Future initIsolate() async { 26 | final receivePort = ReceivePort(); 27 | await Isolate.spawn(_handler, receivePort.sendPort); 28 | final sendPort = await receivePort.first; 29 | CBCCipherIsolate.initSendPort(sendPort); 30 | await CBCCipherIsolate.syncKey(); 31 | } 32 | 33 | static Uint8List processBodyBytes(Uint8List bodyBytes) { 34 | final iv = Uint8List.sublistView(bodyBytes, 0, aesKey.length); 35 | final cipherText = Uint8List.sublistView(bodyBytes, aesKey.length); 36 | 37 | final cbc = CBCBlockCipher(AESFastEngine()) 38 | ..init(false, ParametersWithIV(KeyParameter(aesKey), iv)); 39 | 40 | final paddedPlainText = Uint8List(cipherText.length); 41 | 42 | /* decrypt take 100ms(cold), 50ms(medium), 15-30ms(hot) */ 43 | var offset = 0; 44 | while (offset < cipherText.length) { 45 | offset += cbc.processBlock(cipherText, offset, paddedPlainText, offset); 46 | } 47 | 48 | return Uint8List.sublistView( 49 | paddedPlainText, 0, paddedPlainText.length - paddedPlainText.last); 50 | } 51 | } 52 | 53 | class CBCCipherIsolate { 54 | static SendPort? _sendPort; 55 | 56 | static initSendPort(SendPort sendPort) { 57 | _sendPort = sendPort; 58 | } 59 | 60 | static Future syncKey() { 61 | return _send(_sendPort!, {'type': 'update_key', 'data': CBCCipher.aesKey}); 62 | } 63 | 64 | static Future processBodyBytesIsolate(Uint8List bodyBytes) { 65 | return _send(_sendPort!, {'type': 'decrypt', 'data': bodyBytes}); 66 | } 67 | } 68 | 69 | Future _send(SendPort port, msg) { 70 | final response = ReceivePort(); 71 | port.send([msg, response.sendPort]); 72 | return response.first; 73 | } 74 | 75 | Future _handler(SendPort sendPort) async { 76 | final port = ReceivePort(); 77 | sendPort.send(port.sendPort); 78 | 79 | await for (var msg in port) { 80 | final request = msg[0]; 81 | SendPort replyTo = msg[1]; 82 | 83 | switch (request['type']) { 84 | case 'update_key': 85 | CBCCipher.setAESKey(request['data'], false); 86 | replyTo.send('Done'); 87 | break; 88 | case 'decrypt': 89 | final decrypted = CBCCipher.processBodyBytes(request['data']); 90 | replyTo.send(decrypted); 91 | break; 92 | case 'test': 93 | replyTo.send('Done'); 94 | break; 95 | default: 96 | replyTo.send('Done'); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/debug_control.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | 5 | class DebugControl extends StatefulWidget { 6 | const DebugControl({Key? key}) : super(key: key); 7 | 8 | @override 9 | _DebugControlState createState() => _DebugControlState(); 10 | } 11 | 12 | class _DebugControlState extends State { 13 | static const platform = MethodChannel('samples.flutter.dev/battery'); 14 | 15 | int _counter = 0; 16 | 17 | void _incrementCounter() { 18 | setState(() { 19 | // This call to setState tells the Flutter framework that something has 20 | // changed in this State, which causes it to rerun the build method below 21 | // so that the display can reflect the updated values. If we changed 22 | // _counter without calling setState(), then the build method would not be 23 | // called again, and so nothing would appear to happen. 24 | _counter++; 25 | }); 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | final double devicePixelRatio = MediaQuery.of(context).devicePixelRatio; 31 | 32 | return Scaffold( 33 | body: GestureDetector( 34 | behavior: HitTestBehavior.opaque, 35 | onTapUp: (details) { 36 | print(details.globalPosition.dx * devicePixelRatio); 37 | print(details.globalPosition.dy * devicePixelRatio); 38 | platform.invokeMethod('tapEvent').then((value) { 39 | print(value); 40 | }); 41 | }, 42 | child: Center( 43 | // Center is a layout widget. It takes a single child and positions it 44 | // in the middle of the parent. 45 | child: Column( 46 | // Column is also a layout widget. It takes a list of children and 47 | // arranges them vertically. By default, it sizes itself to fit its 48 | // children horizontally, and tries to be as tall as its parent. 49 | // 50 | // Invoke "debug painting" (press "p" in the console, choose the 51 | // "Toggle Debug Paint" action from the Flutter Inspector in Android 52 | // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) 53 | // to see the wireframe for each widget. 54 | // 55 | // Column has various properties to control how it sizes itself and 56 | // how it positions its children. Here we use mainAxisAlignment to 57 | // center the children vertically; the main axis here is the vertical 58 | // axis because Columns are vertical (the cross axis would be 59 | // horizontal). 60 | mainAxisAlignment: MainAxisAlignment.center, 61 | children: [ 62 | Text( 63 | '$_counter', 64 | style: Theme.of(context).textTheme.headline4, 65 | ), 66 | ], 67 | ), 68 | ), 69 | ), 70 | floatingActionButton: FloatingActionButton( 71 | onPressed: _incrementCounter, 72 | tooltip: 'Increment', 73 | child: const Icon(Icons.add), 74 | ), // This trailing comma makes auto-formatting nicer for build methods. 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/device_list.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:http/http.dart' as http; 5 | import 'package:scrcpy_flutter/cbc_cipher.dart'; 6 | import 'package:scrcpy_flutter/scrcpy.dart'; 7 | import 'package:shared_preferences/shared_preferences.dart'; 8 | 9 | class DeviceList extends StatefulWidget { 10 | const DeviceList({Key? key, required this.refreshNotifier}) : super(key: key); 11 | final ChangeNotifier refreshNotifier; 12 | 13 | @override 14 | _DeviceListState createState() => _DeviceListState(); 15 | } 16 | 17 | class _DeviceListState extends State { 18 | List<_DeviceWidget> _deviceWidgetList = []; 19 | SharedPreferences? prefs; 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | 25 | SharedPreferences.getInstance().then((prefs) { 26 | this.prefs = prefs; 27 | final devicesStr = prefs.getString('queried_devices') ?? ''; 28 | if (devicesStr.isEmpty) { 29 | batchQueryWrapped(); 30 | } else if (CBCCipher.aesKey.isNotEmpty) { 31 | _deviceWidgetList.addAll(_DeviceWidget.jsonStringToList(devicesStr)); 32 | } 33 | 34 | /* clear and refresh */ 35 | widget.refreshNotifier.addListener(() async { 36 | _deviceWidgetList = []; 37 | prefs.remove('queried_devices'); 38 | batchQueryWrapped(); 39 | }); 40 | }); 41 | } 42 | 43 | batchQueryWrapped() { 44 | if (CBCCipher.aesKey.isNotEmpty) { 45 | batchQuery(); 46 | } 47 | } 48 | 49 | batchQuery() { 50 | final List prefixList = ['192.168.0', '192.168.1']; 51 | 52 | for (var element in prefixList) { 53 | for (var i = 1; i < 255; ++i) { 54 | query('$element.$i'); 55 | } 56 | } 57 | } 58 | 59 | query(String ip) async { 60 | try { 61 | final res = await http.get(Uri.parse('http://$ip:7008/huinyegrbizgn')); 62 | final bytes = CBCCipher.processBodyBytes(res.bodyBytes); 63 | final name = String.fromCharCodes(bytes); 64 | setState(() { 65 | _deviceWidgetList.add(_DeviceWidget(ip: ip, name: name)); 66 | }); 67 | prefs!.setString( 68 | 'queried_devices', _DeviceWidget.listToJsonString(_deviceWidgetList)); 69 | } catch (e) { 70 | /* ignore */ 71 | } 72 | } 73 | 74 | @override 75 | Widget build(BuildContext context) { 76 | return CBCCipher.aesKey.isNotEmpty 77 | ? GridView.count( 78 | crossAxisCount: 2, 79 | padding: const EdgeInsets.all(10), 80 | mainAxisSpacing: 10, 81 | crossAxisSpacing: 10, 82 | children: _deviceWidgetList, 83 | ) 84 | : const Center( 85 | child: Text('Please set key'), 86 | ); 87 | } 88 | } 89 | 90 | class _DeviceWidget extends StatefulWidget { 91 | final String name; 92 | final String ip; 93 | 94 | const _DeviceWidget({Key? key, required this.ip, this.name = ''}) 95 | : super(key: key); 96 | 97 | static String listToJsonString(List<_DeviceWidget> list) { 98 | return jsonEncode(list.map((e) => {"ip": e.ip, "name": e.name}).toList()); 99 | } 100 | 101 | static List<_DeviceWidget> jsonStringToList(String str) { 102 | return (jsonDecode(str) as List) 103 | .map((e) => _DeviceWidget( 104 | ip: e['ip']!, 105 | name: e['name']!, 106 | )) 107 | .toList(); 108 | } 109 | 110 | @override 111 | _DeviceWidgetState createState() => _DeviceWidgetState(); 112 | } 113 | 114 | class _DeviceWidgetState extends State<_DeviceWidget> { 115 | @override 116 | Widget build(BuildContext context) { 117 | return InkWell( 118 | onTap: () { 119 | Navigator.of(context).push(MaterialPageRoute( 120 | builder: (_) => Scrcpy( 121 | ip: widget.ip, 122 | ))); 123 | }, 124 | child: Container( 125 | alignment: Alignment.center, 126 | decoration: const BoxDecoration(color: Colors.black26), 127 | child: Column( 128 | mainAxisAlignment: MainAxisAlignment.center, 129 | children: [ 130 | Text(widget.name), 131 | const SizedBox( 132 | height: 2, 133 | ), 134 | Text( 135 | widget.ip, 136 | style: const TextStyle(color: Colors.black26, fontSize: 12), 137 | ), 138 | ], 139 | )), 140 | ); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/services.dart'; 6 | import 'package:scrcpy_flutter/cbc_cipher.dart'; 7 | import 'package:scrcpy_flutter/device_list.dart'; 8 | import 'package:scrcpy_flutter/scrcpy.dart'; 9 | import 'package:shared_preferences/shared_preferences.dart'; 10 | 11 | void main() async { 12 | WidgetsFlutterBinding.ensureInitialized(); 13 | await CBCCipher.initIsolate(); 14 | await CBCCipher.initKey(); 15 | runApp(const MyApp()); 16 | } 17 | 18 | class MyApp extends StatelessWidget { 19 | const MyApp({Key? key}) : super(key: key); 20 | 21 | // This widget is the root of your application. 22 | @override 23 | Widget build(BuildContext context) { 24 | return MaterialApp( 25 | title: 'Scrcpy flutter', 26 | theme: ThemeData( 27 | // This is the theme of your application. 28 | // 29 | // Try running your application with "flutter run". You'll see the 30 | // application has a blue toolbar. Then, without quitting the app, try 31 | // changing the primarySwatch below to Colors.green and then invoke 32 | // "hot reload" (press "r" in the console where you ran "flutter run", 33 | // or simply save your changes to "hot reload" in a Flutter IDE). 34 | // Notice that the counter didn't reset back to zero; the application 35 | // is not restarted. 36 | primarySwatch: Colors.blue, 37 | ), 38 | home: const MyHomePage(), 39 | debugShowCheckedModeBanner: false, 40 | ); 41 | } 42 | } 43 | 44 | class MyHomePage extends StatefulWidget { 45 | const MyHomePage({Key? key}) : super(key: key); 46 | 47 | // This widget is the home page of your application. It is stateful, meaning 48 | // that it has a State object (defined below) that contains fields that affect 49 | // how it looks. 50 | 51 | @override 52 | State createState() => _MyHomePageState(); 53 | } 54 | 55 | class _MyHomePageState extends State { 56 | SharedPreferences? prefs; 57 | final refreshDeviceNotifier = ChangeNotifier(); 58 | 59 | _MyHomePageState() { 60 | SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); 61 | } 62 | 63 | void _incrementCounter(BuildContext context) async { 64 | prefs ??= await SharedPreferences.getInstance(); 65 | String? ip = prefs!.getString('lastDeviceIP'); 66 | TextEditingController _controller = TextEditingController() 67 | ..text = (ip ?? '192.168.1.151'); 68 | showDialog( 69 | context: context, 70 | builder: (context) { 71 | return AlertDialog( 72 | title: Text('IP'), 73 | titlePadding: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), 74 | contentPadding: 75 | const EdgeInsets.symmetric(vertical: 2, horizontal: 8), 76 | content: TextField( 77 | controller: _controller, 78 | autofocus: true, 79 | ), 80 | actions: [ 81 | ElevatedButton( 82 | onPressed: () { 83 | Navigator.of(context).pop(_controller.value.text); 84 | }, 85 | child: Text('OK')) 86 | ], 87 | ); 88 | }, 89 | ).then((val) { 90 | print(val); 91 | if (val == null) return; 92 | prefs!.setString('lastDeviceIP', val); 93 | Navigator.of(context).push(MaterialPageRoute( 94 | builder: (_) => Scrcpy( 95 | ip: val, 96 | ))); 97 | }); 98 | } 99 | 100 | @override 101 | Widget build(BuildContext context) { 102 | // This method is rerun every time setState is called, for instance as done 103 | // by the _incrementCounter method above. 104 | // 105 | // The Flutter framework has been optimized to make rerunning build methods 106 | // fast, so that you can just rebuild anything that needs updating rather 107 | // than having to individually change instances of widgets. 108 | return Scaffold( 109 | appBar: AppBar( 110 | title: Text('X'), 111 | actions: [ 112 | IconButton( 113 | onPressed: () { 114 | refreshDeviceNotifier.notifyListeners(); 115 | }, 116 | icon: const Icon(Icons.refresh)), 117 | PopupMenuButton(itemBuilder: (_context) { 118 | return [ 119 | PopupMenuItem( 120 | child: const Text('Key'), 121 | onTap: () { 122 | Timer.run(() async { 123 | final result = await _openEditEncryptKeyDialog(context); 124 | if (result.isNotEmpty) { 125 | refreshDeviceNotifier.notifyListeners(); 126 | } 127 | }); 128 | }, 129 | ) 130 | ]; 131 | }), 132 | ], 133 | ), 134 | resizeToAvoidBottomInset: false, 135 | body: Center( 136 | // Center is a layout widget. It takes a single child and positions it 137 | // in the middle of the parent. 138 | child: DeviceList( 139 | refreshNotifier: refreshDeviceNotifier, 140 | ), 141 | ), 142 | floatingActionButton: FloatingActionButton( 143 | onPressed: () => _incrementCounter(context), 144 | tooltip: 'Increment', 145 | child: const Icon(Icons.add), 146 | ), // This trailing comma makes auto-formatting nicer for build methods. 147 | ); 148 | } 149 | } 150 | 151 | Future _openEditEncryptKeyDialog(BuildContext context) async { 152 | final prefs = await SharedPreferences.getInstance(); 153 | final String key = prefs.getString('encrypt_key') ?? ''; 154 | 155 | TextEditingController _controller = TextEditingController()..text = key; 156 | 157 | return showDialog( 158 | context: context, 159 | builder: (context) { 160 | return AlertDialog( 161 | title: const Text('Key(16 length)'), 162 | titlePadding: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), 163 | contentPadding: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), 164 | content: TextField( 165 | controller: _controller, 166 | autofocus: true, 167 | ), 168 | actions: [ 169 | ElevatedButton( 170 | onPressed: () { 171 | final text = _controller.text; 172 | prefs.setString('encrypt_key', text); 173 | CBCCipher.setAESKey(Uint8List.fromList(text.codeUnits)); 174 | Navigator.of(context).pop(text); 175 | }, 176 | child: const Text('OK')), 177 | ], 178 | ); 179 | }, 180 | ).then((value) { 181 | return value ?? ''; 182 | }); 183 | } 184 | -------------------------------------------------------------------------------- /lib/scrcpy.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | import 'dart:typed_data'; 4 | 5 | import 'package:floatingpanel/floatingpanel.dart'; 6 | import 'package:flutter/cupertino.dart'; 7 | import 'package:flutter/material.dart'; 8 | import 'package:http/http.dart' as http; 9 | 10 | import 'android_keycode.dart'; 11 | import 'cbc_cipher.dart'; 12 | 13 | class Scrcpy extends StatefulWidget { 14 | final String ip; 15 | 16 | const Scrcpy({Key? key, required this.ip}) : super(key: key); 17 | 18 | @override 19 | _ScrcpyState createState() => _ScrcpyState(); 20 | } 21 | 22 | class _ScrcpyState extends _ScrcpySocketState { 23 | final _ScreenShotModel _screenShotModel = _ScreenShotModel(); 24 | 25 | @override 26 | void dispose() { 27 | _screenShotModel.dispose(); 28 | 29 | super.dispose(); 30 | } 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | final double devicePixelRatio = MediaQuery.of(context).devicePixelRatio; 35 | 36 | return Scaffold( 37 | body: Stack( 38 | children: [ 39 | Center( 40 | child: OrientationBuilder(builder: (context, orientation) { 41 | if ((orientation == Orientation.portrait && 42 | deviceHeight < deviceWidth) || 43 | (orientation == Orientation.landscape && 44 | deviceHeight > deviceWidth)) { 45 | final int tmp = deviceHeight; 46 | deviceHeight = deviceWidth; 47 | deviceWidth = tmp; 48 | } 49 | return AspectRatio( 50 | aspectRatio: 51 | deviceWidth == 0 ? 9 / 16 : deviceWidth / deviceHeight, 52 | child: Listener( 53 | behavior: HitTestBehavior.opaque, 54 | onPointerUp: (details) { 55 | sendPointerEvent(details, devicePixelRatio, 1); 56 | }, 57 | onPointerMove: (details) { 58 | sendPointerEvent(details, devicePixelRatio, 2); 59 | }, 60 | onPointerDown: (details) { 61 | sendPointerEvent(details, devicePixelRatio, 0); 62 | }, 63 | child: LayoutBuilder(builder: (context, constraints) { 64 | touchableSize = 65 | Size(constraints.maxWidth, constraints.maxHeight); 66 | if (connected) { 67 | positionScale = deviceHeight / 68 | (touchableSize.height * devicePixelRatio); 69 | } 70 | return Container( 71 | decoration: const BoxDecoration(color: Colors.black26), 72 | child: Stack( 73 | children: [ 74 | Center( 75 | child: Text( 76 | centerText, 77 | style: Theme.of(context).textTheme.headline4, 78 | ), 79 | ), 80 | if (CBCCipher.aesKey.isNotEmpty) 81 | _ScreenShot( 82 | 'http://${widget.ip}:7008/ognahaonogna', 83 | screenShotModel: _screenShotModel, 84 | ) 85 | ], 86 | ), 87 | ); 88 | }), 89 | ), 90 | ); 91 | }), 92 | ), 93 | FloatBoxPanel( 94 | positionTop: 50, 95 | size: 50, 96 | backgroundColor: Theme.of(context).colorScheme.primary, 97 | dockType: DockType.inside, 98 | defaultDock: true, 99 | buttons: const [ 100 | Icons.arrow_back, 101 | Icons.home, 102 | Icons.menu, 103 | Icons.screenshot, 104 | Icons.video_camera_back_outlined, 105 | Icons.power_settings_new, 106 | ], 107 | onPressed: (int index) { 108 | switch (index) { 109 | case 0: 110 | sendBackEvent(); 111 | break; 112 | case 1: 113 | sendKeyEvent(AndroidKeycode.AKEYCODE_HOME); 114 | break; 115 | case 2: 116 | sendKeyEvent(AndroidKeycode.AKEYCODE_APP_SWITCH); 117 | break; 118 | case 3: 119 | _screenShotModel.setMode(_ScreenShotMode.one); 120 | break; 121 | case 4: 122 | _screenShotModel.setMode(_ScreenShotMode.videoLike); 123 | break; 124 | case 5: 125 | sendKeyEvent(AndroidKeycode.AKEYCODE_POWER); 126 | break; 127 | default: 128 | } 129 | }, 130 | ), 131 | ], 132 | ), 133 | ); 134 | } 135 | } 136 | 137 | abstract class _ScrcpySocketState extends State { 138 | static const int remotePort = 7007; 139 | String get ip => widget.ip; 140 | Socket? videoSocket; 141 | Socket? controlSocket; 142 | String deviceName = ''; 143 | int deviceWidth = 0; 144 | int deviceHeight = 0; 145 | bool connected = false; 146 | Size touchableSize = Size.zero; 147 | double positionScale = 0; 148 | String centerText = 'A'; 149 | 150 | @override 151 | initState() { 152 | super.initState(); 153 | 154 | try { 155 | setupSocket(); 156 | } catch (e) { 157 | centerText = 'Connect failed'; 158 | } 159 | } 160 | 161 | setupSocket() async { 162 | await Socket.connect(ip, remotePort).then((socket) { 163 | videoSocket = socket; 164 | socket.transform(genVideoStreamTransformer()).listen((event) { 165 | print(event); 166 | }); 167 | }); 168 | Socket.connect(ip, remotePort).then((socket) { 169 | controlSocket = socket; 170 | socket.listen((event) { 171 | print(event); 172 | }); 173 | }); 174 | } 175 | 176 | StreamTransformer genVideoStreamTransformer() { 177 | int headCurrentByteCount = 0; 178 | 179 | return StreamTransformer.fromHandlers( 180 | handleData: (data, sink) { 181 | print(data); 182 | sink.add(data); 183 | for (var i = 0; i < data.length; ++i) { 184 | var o = data[i]; 185 | // 69 = 1 + 64 + 4 186 | if (++headCurrentByteCount <= 69 && headCurrentByteCount > 1) { 187 | if (headCurrentByteCount <= 65 && o > 0) { 188 | deviceName += String.fromCharCode(o); 189 | } 190 | if (headCurrentByteCount == 66) { 191 | deviceWidth += o << 8; 192 | } 193 | if (headCurrentByteCount == 67) { 194 | deviceWidth += o; 195 | } 196 | if (headCurrentByteCount == 68) { 197 | deviceHeight += o << 8; 198 | } 199 | if (headCurrentByteCount == 69) { 200 | deviceHeight += o; 201 | print(deviceName); 202 | print(deviceWidth); 203 | print(deviceHeight); 204 | connected = true; 205 | centerText = deviceName; 206 | setState(() {}); 207 | } 208 | } 209 | } 210 | }, 211 | ); 212 | } 213 | 214 | sendPointerEvent(PointerEvent details, double devicePixelRatio, int type) { 215 | int x = 216 | (details.localPosition.dx * positionScale * devicePixelRatio).floor(); 217 | int y = 218 | (details.localPosition.dy * positionScale * devicePixelRatio).floor(); 219 | var bd = BytesBuilder(); 220 | bd.addByte(2); 221 | bd.addByte(type); 222 | bd.add(Uint8List(8)..buffer.asByteData().setInt64(0, 1, Endian.big)); 223 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, x, Endian.big)); 224 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, y, Endian.big)); 225 | bd.add( 226 | Uint8List(2)..buffer.asByteData().setInt16(0, deviceWidth, Endian.big)); 227 | bd.add(Uint8List(2) 228 | ..buffer.asByteData().setInt16(0, deviceHeight, Endian.big)); 229 | bd.add( 230 | Uint8List(2)..buffer.asByteData().setInt16(0, 255 * 255, Endian.big)); 231 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, 0, Endian.big)); 232 | controlSocket!.add(bd.toBytes()); 233 | } 234 | 235 | sendBackEvent() { 236 | var bd = BytesBuilder(); 237 | bd.addByte(4); 238 | bd.addByte(0); 239 | bd.addByte(4); 240 | bd.addByte(1); 241 | controlSocket!.add(bd.toBytes()); 242 | } 243 | 244 | sendKeyEvent(int keycode) { 245 | var bd = BytesBuilder(); 246 | bd.addByte(0); 247 | bd.addByte(0); 248 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, keycode, Endian.big)); 249 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, 0, Endian.big)); 250 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, 0, Endian.big)); 251 | 252 | bd.addByte(0); 253 | bd.addByte(1); 254 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, keycode, Endian.big)); 255 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, 0, Endian.big)); 256 | bd.add(Uint8List(4)..buffer.asByteData().setInt32(0, 0, Endian.big)); 257 | controlSocket!.add(bd.toBytes()); 258 | } 259 | 260 | @override 261 | void dispose() { 262 | super.dispose(); 263 | 264 | videoSocket?.destroy(); 265 | controlSocket?.destroy(); 266 | } 267 | } 268 | 269 | class _ScreenShot extends StatefulWidget { 270 | final String url; 271 | final _ScreenShotModel screenShotModel; 272 | 273 | const _ScreenShot(this.url, {Key? key, required this.screenShotModel}) 274 | : super(key: key); 275 | 276 | @override 277 | _ScreenShotState createState() => _ScreenShotState(); 278 | } 279 | 280 | class _ScreenShotState extends State<_ScreenShot> { 281 | bool running = false; 282 | late Future imageFuture; 283 | Uint8List imageBytes = Uint8List(0); 284 | 285 | @override 286 | void initState() { 287 | super.initState(); 288 | widget.screenShotModel.addListener(() { 289 | requestImage(); 290 | }); 291 | } 292 | 293 | @override 294 | void dispose() { 295 | super.dispose(); 296 | } 297 | 298 | requestImage() async { 299 | if (running) { 300 | return; 301 | } 302 | running = true; 303 | final timestamp = DateTime.now().millisecondsSinceEpoch; 304 | final res = await http.get(Uri.parse('${widget.url}?v=$timestamp')); 305 | if (!mounted) { 306 | running = false; 307 | return; 308 | } 309 | imageBytes = await CBCCipherIsolate.processBodyBytesIsolate(res.bodyBytes); 310 | setState(() {}); 311 | running = false; 312 | if (widget.screenShotModel.mode == _ScreenShotMode.one) { 313 | return; 314 | } 315 | return requestImage(); 316 | } 317 | 318 | @override 319 | Widget build(BuildContext context) { 320 | return imageBytes.isEmpty 321 | ? Container() 322 | : Image.memory( 323 | imageBytes, 324 | gaplessPlayback: true, 325 | ); 326 | } 327 | } 328 | 329 | enum _ScreenShotMode { one, videoLike } 330 | 331 | class _ScreenShotModel extends ChangeNotifier { 332 | _ScreenShotMode mode = _ScreenShotMode.one; 333 | 334 | setMode(_ScreenShotMode v) { 335 | mode = v; 336 | notifyListeners(); 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.8.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.15.0" 46 | convert: 47 | dependency: transitive 48 | description: 49 | name: convert 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "3.0.1" 53 | cupertino_icons: 54 | dependency: "direct main" 55 | description: 56 | name: cupertino_icons 57 | url: "https://pub.flutter-io.cn" 58 | source: hosted 59 | version: "1.0.3" 60 | fake_async: 61 | dependency: transitive 62 | description: 63 | name: fake_async 64 | url: "https://pub.flutter-io.cn" 65 | source: hosted 66 | version: "1.2.0" 67 | ffi: 68 | dependency: transitive 69 | description: 70 | name: ffi 71 | url: "https://pub.flutter-io.cn" 72 | source: hosted 73 | version: "1.1.2" 74 | file: 75 | dependency: transitive 76 | description: 77 | name: file 78 | url: "https://pub.flutter-io.cn" 79 | source: hosted 80 | version: "6.1.2" 81 | floatingpanel: 82 | dependency: "direct main" 83 | description: 84 | path: "." 85 | ref: a8f7f6a628e2cccc2e902f71969352c737bb1b83 86 | resolved-ref: a8f7f6a628e2cccc2e902f71969352c737bb1b83 87 | url: "https://github.com/diyews/floating_panel.git" 88 | source: git 89 | version: "1.1.3" 90 | flutter: 91 | dependency: "direct main" 92 | description: flutter 93 | source: sdk 94 | version: "0.0.0" 95 | flutter_lints: 96 | dependency: "direct dev" 97 | description: 98 | name: flutter_lints 99 | url: "https://pub.flutter-io.cn" 100 | source: hosted 101 | version: "1.0.4" 102 | flutter_test: 103 | dependency: "direct dev" 104 | description: flutter 105 | source: sdk 106 | version: "0.0.0" 107 | flutter_web_plugins: 108 | dependency: transitive 109 | description: flutter 110 | source: sdk 111 | version: "0.0.0" 112 | http: 113 | dependency: "direct main" 114 | description: 115 | name: http 116 | url: "https://pub.flutter-io.cn" 117 | source: hosted 118 | version: "0.13.4" 119 | http_parser: 120 | dependency: transitive 121 | description: 122 | name: http_parser 123 | url: "https://pub.flutter-io.cn" 124 | source: hosted 125 | version: "4.0.0" 126 | js: 127 | dependency: transitive 128 | description: 129 | name: js 130 | url: "https://pub.flutter-io.cn" 131 | source: hosted 132 | version: "0.6.3" 133 | lints: 134 | dependency: transitive 135 | description: 136 | name: lints 137 | url: "https://pub.flutter-io.cn" 138 | source: hosted 139 | version: "1.0.1" 140 | matcher: 141 | dependency: transitive 142 | description: 143 | name: matcher 144 | url: "https://pub.flutter-io.cn" 145 | source: hosted 146 | version: "0.12.10" 147 | meta: 148 | dependency: transitive 149 | description: 150 | name: meta 151 | url: "https://pub.flutter-io.cn" 152 | source: hosted 153 | version: "1.7.0" 154 | path: 155 | dependency: transitive 156 | description: 157 | name: path 158 | url: "https://pub.flutter-io.cn" 159 | source: hosted 160 | version: "1.8.0" 161 | path_provider_linux: 162 | dependency: transitive 163 | description: 164 | name: path_provider_linux 165 | url: "https://pub.flutter-io.cn" 166 | source: hosted 167 | version: "2.1.0" 168 | path_provider_platform_interface: 169 | dependency: transitive 170 | description: 171 | name: path_provider_platform_interface 172 | url: "https://pub.flutter-io.cn" 173 | source: hosted 174 | version: "2.0.1" 175 | path_provider_windows: 176 | dependency: transitive 177 | description: 178 | name: path_provider_windows 179 | url: "https://pub.flutter-io.cn" 180 | source: hosted 181 | version: "2.0.3" 182 | platform: 183 | dependency: transitive 184 | description: 185 | name: platform 186 | url: "https://pub.flutter-io.cn" 187 | source: hosted 188 | version: "3.0.2" 189 | plugin_platform_interface: 190 | dependency: transitive 191 | description: 192 | name: plugin_platform_interface 193 | url: "https://pub.flutter-io.cn" 194 | source: hosted 195 | version: "2.0.2" 196 | pointycastle: 197 | dependency: "direct main" 198 | description: 199 | name: pointycastle 200 | url: "https://pub.flutter-io.cn" 201 | source: hosted 202 | version: "3.4.0" 203 | process: 204 | dependency: transitive 205 | description: 206 | name: process 207 | url: "https://pub.flutter-io.cn" 208 | source: hosted 209 | version: "4.2.3" 210 | shared_preferences: 211 | dependency: "direct main" 212 | description: 213 | name: shared_preferences 214 | url: "https://pub.flutter-io.cn" 215 | source: hosted 216 | version: "2.0.8" 217 | shared_preferences_linux: 218 | dependency: transitive 219 | description: 220 | name: shared_preferences_linux 221 | url: "https://pub.flutter-io.cn" 222 | source: hosted 223 | version: "2.0.2" 224 | shared_preferences_macos: 225 | dependency: transitive 226 | description: 227 | name: shared_preferences_macos 228 | url: "https://pub.flutter-io.cn" 229 | source: hosted 230 | version: "2.0.2" 231 | shared_preferences_platform_interface: 232 | dependency: transitive 233 | description: 234 | name: shared_preferences_platform_interface 235 | url: "https://pub.flutter-io.cn" 236 | source: hosted 237 | version: "2.0.0" 238 | shared_preferences_web: 239 | dependency: transitive 240 | description: 241 | name: shared_preferences_web 242 | url: "https://pub.flutter-io.cn" 243 | source: hosted 244 | version: "2.0.2" 245 | shared_preferences_windows: 246 | dependency: transitive 247 | description: 248 | name: shared_preferences_windows 249 | url: "https://pub.flutter-io.cn" 250 | source: hosted 251 | version: "2.0.2" 252 | sky_engine: 253 | dependency: transitive 254 | description: flutter 255 | source: sdk 256 | version: "0.0.99" 257 | source_span: 258 | dependency: transitive 259 | description: 260 | name: source_span 261 | url: "https://pub.flutter-io.cn" 262 | source: hosted 263 | version: "1.8.1" 264 | stack_trace: 265 | dependency: transitive 266 | description: 267 | name: stack_trace 268 | url: "https://pub.flutter-io.cn" 269 | source: hosted 270 | version: "1.10.0" 271 | stream_channel: 272 | dependency: transitive 273 | description: 274 | name: stream_channel 275 | url: "https://pub.flutter-io.cn" 276 | source: hosted 277 | version: "2.1.0" 278 | string_scanner: 279 | dependency: transitive 280 | description: 281 | name: string_scanner 282 | url: "https://pub.flutter-io.cn" 283 | source: hosted 284 | version: "1.1.0" 285 | term_glyph: 286 | dependency: transitive 287 | description: 288 | name: term_glyph 289 | url: "https://pub.flutter-io.cn" 290 | source: hosted 291 | version: "1.2.0" 292 | test_api: 293 | dependency: transitive 294 | description: 295 | name: test_api 296 | url: "https://pub.flutter-io.cn" 297 | source: hosted 298 | version: "0.4.2" 299 | typed_data: 300 | dependency: transitive 301 | description: 302 | name: typed_data 303 | url: "https://pub.flutter-io.cn" 304 | source: hosted 305 | version: "1.3.0" 306 | vector_math: 307 | dependency: transitive 308 | description: 309 | name: vector_math 310 | url: "https://pub.flutter-io.cn" 311 | source: hosted 312 | version: "2.1.0" 313 | win32: 314 | dependency: transitive 315 | description: 316 | name: win32 317 | url: "https://pub.flutter-io.cn" 318 | source: hosted 319 | version: "2.2.9" 320 | xdg_directories: 321 | dependency: transitive 322 | description: 323 | name: xdg_directories 324 | url: "https://pub.flutter-io.cn" 325 | source: hosted 326 | version: "0.2.0" 327 | sdks: 328 | dart: ">=2.14.0 <3.0.0" 329 | flutter: ">=2.5.0" 330 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: scrcpy_flutter 2 | description: Scrcpy client base on flutter. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.12.0 <3.0.0" 22 | 23 | # Dependencies specify other packages that your package needs in order to work. 24 | # To automatically upgrade your package dependencies to the latest versions 25 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 26 | # dependencies can be manually updated by changing the version numbers below to 27 | # the latest version available on pub.dev. To see which dependencies have newer 28 | # versions available, run `flutter pub outdated`. 29 | dependencies: 30 | flutter: 31 | sdk: flutter 32 | 33 | 34 | # The following adds the Cupertino Icons font to your application. 35 | # Use with the CupertinoIcons class for iOS style icons. 36 | cupertino_icons: ^1.0.2 37 | 38 | floatingpanel: 39 | git: 40 | url: https://github.com/diyews/floating_panel.git 41 | ref: a8f7f6a628e2cccc2e902f71969352c737bb1b83 42 | shared_preferences: ^2.0.8 43 | http: ^0.13.4 44 | pointycastle: ^3.4.0 45 | 46 | dev_dependencies: 47 | flutter_test: 48 | sdk: flutter 49 | 50 | # The "flutter_lints" package below contains a set of recommended lints to 51 | # encourage good coding practices. The lint set provided by the package is 52 | # activated in the `analysis_options.yaml` file located at the root of your 53 | # package. See that file for information about deactivating specific lint 54 | # rules and activating additional ones. 55 | flutter_lints: ^1.0.0 56 | 57 | # For information on the generic Dart part of this file, see the 58 | # following page: https://dart.dev/tools/pub/pubspec 59 | 60 | # The following section is specific to Flutter. 61 | flutter: 62 | 63 | # The following line ensures that the Material Icons font is 64 | # included with your application, so that you can use the icons in 65 | # the material Icons class. 66 | uses-material-design: true 67 | 68 | # To add assets to your application, add an assets section, like this: 69 | # assets: 70 | # - images/a_dot_burr.jpeg 71 | # - images/a_dot_ham.jpeg 72 | 73 | # An image asset can refer to one or more resolution-specific "variants", see 74 | # https://flutter.dev/assets-and-images/#resolution-aware. 75 | 76 | # For details regarding adding assets from package dependencies, see 77 | # https://flutter.dev/assets-and-images/#from-packages 78 | 79 | # To add custom fonts to your application, add a fonts section here, 80 | # in this "flutter" section. Each entry in this list should have a 81 | # "family" key with the font family name, and a "fonts" key with a 82 | # list giving the asset and other descriptors for the font. For 83 | # example: 84 | # fonts: 85 | # - family: Schyler 86 | # fonts: 87 | # - asset: fonts/Schyler-Regular.ttf 88 | # - asset: fonts/Schyler-Italic.ttf 89 | # style: italic 90 | # - family: Trajan Pro 91 | # fonts: 92 | # - asset: fonts/TrajanPro.ttf 93 | # - asset: fonts/TrajanPro_Bold.ttf 94 | # weight: 700 95 | # 96 | # For details regarding fonts from package dependencies, 97 | # see https://flutter.dev/custom-fonts/#from-packages 98 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:scrcpy_flutter/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | --------------------------------------------------------------------------------