├── ios ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── 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-1024x1024@1x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── project.pbxproj ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist └── .gitignore ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png ├── manifest.json └── index.html ├── android ├── gradle.properties ├── app │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── 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 │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable-v21 │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── values-night │ │ │ │ │ └── styles.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── layout │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle └── build.gradle ├── .metadata ├── lib ├── provider │ └── StatusConexaoProvider.dart ├── main.dart ├── HomePage.dart ├── components │ ├── ButtonSingle.dart │ ├── ButtonDouble.dart │ ├── CustomAppBar.dart │ └── VoiceButtonPage.dart ├── ListaBluetooth.dart ├── SelecionarDispositivo.dart └── ControlePrincipal.dart ├── .vscode └── launch.json ├── README.md ├── .gitignore ├── analysis_options.yaml ├── pubspec.yaml └── pubspec.lock /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/web/favicon.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/web/icons/Icon-512.png -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/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/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/layout/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.layout 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThierrySilva/Flutter-Arduino-Bluetooth/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.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/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /lib/provider/StatusConexaoProvider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; 3 | 4 | class StatusConexaoProvider extends ChangeNotifier { 5 | BluetoothDevice? device = null; 6 | 7 | BluetoothDevice? get getDevice => device; 8 | 9 | setDevice(BluetoothDevice? deviceReceived) { 10 | device = deviceReceived; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use o IntelliSense para saber mais sobre os atributos possíveis. 3 | // Focalizar para exibir as descrições dos atributos existentes. 4 | // Para obter mais informações, acesse: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "layout", 9 | "request": "launch", 10 | "type": "dart" 11 | }, 12 | { 13 | "name": "layout (profile mode)", 14 | "request": "launch", 15 | "type": "dart", 16 | "flutterMode": "profile" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # layout 2 | 3 | A simple flutter projet to connect arduino using bluetooth module. 4 | In this project you'll be to send simple caracters to bluetooth module (HC-06 or HC-05) or send caracters using voice command. 5 | But feel free to change it, lets help each other !!! 6 | 7 | ## References 8 | https://pub.dev/packages/flutter_bluetooth_serial 9 | 10 | https://pub.dev/packages/flutter_speech 11 | 12 | ## Inside the app 13 | 14 | ![foto1](https://user-images.githubusercontent.com/43972737/149673136-cc335658-5730-42a5-8ee9-eb19d7b94382.jpg) 15 | 16 | 17 | ![foto2](https://user-images.githubusercontent.com/43972737/149673147-d42ca14d-50ac-436d-b539-cf14d0907c7c.jpg) 18 | 19 | 20 | ![foto3](https://user-images.githubusercontent.com/43972737/149673158-71e4c70f-82d7-4885-95eb-6d46946347c6.jpg) 21 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart' 2 | show BuildContext, MaterialApp, StatelessWidget, Widget, runApp; 3 | import 'package:layout/SelecionarDispositivo.dart'; 4 | import 'package:layout/HomePage.dart'; 5 | import 'package:provider/provider.dart'; 6 | import 'provider/StatusConexaoProvider.dart'; 7 | 8 | void main() { 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | // This widget is the root of your application. 14 | @override 15 | Widget build(BuildContext context) { 16 | return MultiProvider( 17 | providers: [ 18 | ChangeNotifierProvider.value( 19 | value: StatusConexaoProvider()), 20 | ], 21 | child: MaterialApp( 22 | title: 'Xerocasa', 23 | initialRoute: '/', 24 | routes: { 25 | '/': (context) => HomePage(), 26 | '/selectDevice': (context) => const SelecionarDispositivoPage(), 27 | }, 28 | )); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "layout", 3 | "short_name": "layout", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | layout 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 | -------------------------------------------------------------------------------- /lib/HomePage.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: file_names 2 | 3 | import 'package:flutter/cupertino.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:layout/SelecionarDispositivo.dart'; 6 | import 'package:layout/ControlePrincipal.dart'; 7 | import 'package:provider/provider.dart'; 8 | import 'components/CustomAppBar.dart'; 9 | import 'provider/StatusConexaoProvider.dart'; 10 | 11 | class HomePage extends StatelessWidget { 12 | const HomePage({Key? key}) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | onPressBluetooth() { 17 | return (() async { 18 | Navigator.of(context).pushReplacement(MaterialPageRoute( 19 | settings: const RouteSettings(name: 'selectDevice'), 20 | builder: (context) => const SelecionarDispositivoPage())); 21 | }); 22 | } 23 | 24 | return Scaffold( 25 | appBar: CustomAppBar( 26 | Title: 'Remote Arduino', 27 | isBluetooth: true, 28 | isDiscovering: false, 29 | onPress: onPressBluetooth, 30 | ), 31 | body: Center( 32 | child: Padding( 33 | padding: const EdgeInsets.only(top: 5, left: 5, right: 5), 34 | child: Consumer( 35 | builder: (context, StatusConnectionProvider, widget) { 36 | return (StatusConnectionProvider.device == null 37 | ? Row( 38 | mainAxisAlignment: MainAxisAlignment.center, 39 | children: [ 40 | const Icon(Icons.bluetooth_disabled_sharp, size: 50), 41 | const Text( 42 | "Bluetooth Disconnected", 43 | style: TextStyle( 44 | fontSize: 20, 45 | ), 46 | ) 47 | ], 48 | ) 49 | : ControlePrincipalPage( 50 | server: StatusConnectionProvider.device)); 51 | }), 52 | ), 53 | ), 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /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 "com.example.layout" 47 | minSdkVersion 19 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 | -------------------------------------------------------------------------------- /lib/components/ButtonSingle.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'dart:async'; 4 | import 'dart:convert'; 5 | import 'dart:typed_data'; 6 | 7 | import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; 8 | 9 | class ButtonSingleComponent extends StatefulWidget { 10 | final String? buttonName; 11 | final String? comandOn; 12 | final Color? colorButton; 13 | final BluetoothConnection? connection; 14 | final int clientID; 15 | const ButtonSingleComponent( 16 | {Key? key, 17 | this.buttonName, 18 | this.comandOn, 19 | this.connection, 20 | required this.clientID, 21 | this.colorButton}) 22 | : super(key: key); 23 | _ButtonState createState() => _ButtonState(); 24 | } 25 | 26 | class _Message { 27 | int whom; 28 | String text; 29 | 30 | _Message(this.whom, this.text); 31 | } 32 | 33 | class _ButtonState extends State { 34 | bool buttonClicado = false; 35 | final TextEditingController textEditingController = TextEditingController(); 36 | List<_Message> messages = <_Message>[]; 37 | 38 | Widget build(BuildContext context) { 39 | return (Container( 40 | height: 60, 41 | width: 80, 42 | child: FlatButton( 43 | onPressed: () { 44 | _sendMessage(widget.comandOn!); 45 | }, 46 | child: Text( 47 | widget.buttonName!, 48 | style: TextStyle(color: Colors.white, fontSize: 25), 49 | ), 50 | color: widget.colorButton!, 51 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), 52 | ))); 53 | } 54 | 55 | _sendMessage(text) async { 56 | text = text.trim(); 57 | textEditingController.clear(); 58 | 59 | if (text.length > 0) { 60 | try { 61 | widget.connection!.output 62 | .add(Uint8List.fromList(utf8.encode(text + "\r\n"))); 63 | await widget.connection!.output.allSent; 64 | 65 | setState(() { 66 | messages.add(_Message(widget.clientID, text)); 67 | }); 68 | } catch (e) { 69 | setState(() {}); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /lib/components/ButtonDouble.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'dart:async'; 4 | import 'dart:convert'; 5 | import 'dart:typed_data'; 6 | import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; 7 | 8 | class ButtonDoubleComponent extends StatefulWidget { 9 | final String? buttonName; 10 | final String? comandOn; 11 | final String? comandOff; 12 | final BluetoothConnection? connection; 13 | final int clientID; 14 | const ButtonDoubleComponent( 15 | {Key? key, 16 | this.buttonName, 17 | this.comandOn, 18 | this.comandOff, 19 | this.connection, 20 | required this.clientID}) 21 | : super(key: key); 22 | _ButtonState createState() => _ButtonState(); 23 | } 24 | 25 | class _Message { 26 | int whom; 27 | String text; 28 | 29 | _Message(this.whom, this.text); 30 | } 31 | 32 | class _ButtonState extends State { 33 | bool buttonClicado = false; 34 | final TextEditingController textEditingController = TextEditingController(); 35 | List<_Message> messages = <_Message>[]; 36 | 37 | _changeButtonColor() { 38 | setState(() { 39 | buttonClicado = !buttonClicado; 40 | }); 41 | } 42 | 43 | Widget build(BuildContext context) { 44 | return (Container( 45 | height: 60, 46 | width: 90, 47 | child: FlatButton( 48 | onPressed: () { 49 | _sendMessage(buttonClicado ? widget.comandOn! : widget.comandOff!); 50 | _changeButtonColor(); 51 | }, 52 | child: Text( 53 | widget.buttonName!, 54 | style: TextStyle(color: Colors.white), 55 | ), 56 | color: buttonClicado 57 | ? Color.fromRGBO(237, 46, 39, 1) 58 | : Color.fromRGBO(0, 0, 0, 1), 59 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), 60 | ))); 61 | } 62 | 63 | _sendMessage(text) async { 64 | text = text.trim(); 65 | textEditingController.clear(); 66 | 67 | if (text.length > 0) { 68 | try { 69 | widget.connection!.output 70 | .add(Uint8List.fromList(utf8.encode(text + "\r\n"))); 71 | await widget.connection!.output.allSent; 72 | 73 | setState(() { 74 | messages.add(_Message(widget.clientID, text)); 75 | }); 76 | } catch (e) { 77 | setState(() {}); 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/ListaBluetooth.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: file_names 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; 5 | 6 | class ListaBluetoothPage extends ListTile { 7 | ListaBluetoothPage({ 8 | Key? key, 9 | @required BluetoothDevice? device, 10 | int? rssi, 11 | GestureTapCallback? onTap, 12 | GestureLongPressCallback? onLongPress, 13 | bool enabled = true, 14 | }) : super( 15 | key: key, 16 | onTap: onTap, 17 | onLongPress: onLongPress, 18 | enabled: enabled, 19 | leading: const Icon( 20 | Icons.devices), // @TODO . !BluetoothClass! class aware icon 21 | title: Text(device!.name ?? "Unknown device"), 22 | subtitle: Text(device.address.toString()), 23 | trailing: Row( 24 | mainAxisSize: MainAxisSize.min, 25 | children: [ 26 | rssi != null 27 | ? Container( 28 | margin: const EdgeInsets.all(8.0), 29 | child: DefaultTextStyle( 30 | style: _computeTextStyle(rssi), 31 | child: Column( 32 | mainAxisSize: MainAxisSize.min, 33 | children: [ 34 | Text(rssi.toString()), 35 | const Text('dBm'), 36 | ], 37 | ), 38 | ), 39 | ) 40 | : const SizedBox(width: 0, height: 0), 41 | device.isConnected 42 | ? const Icon(Icons.import_export) 43 | : const SizedBox(width: 0, height: 0), 44 | device.isBonded 45 | ? const Icon(Icons.link) 46 | : const SizedBox(width: 0, height: 0), 47 | ], 48 | ), 49 | ); 50 | 51 | static TextStyle _computeTextStyle(int rssi) { 52 | /**/ if (rssi >= -35) { 53 | return TextStyle(color: Colors.greenAccent[700]); 54 | } else if (rssi >= -45) { 55 | return TextStyle( 56 | color: Color.lerp( 57 | Colors.greenAccent[700], Colors.lightGreen, -(rssi + 35) / 10)); 58 | } else if (rssi >= -55) { 59 | return TextStyle( 60 | color: Color.lerp( 61 | Colors.lightGreen, Colors.lime[600], -(rssi + 45) / 10)); 62 | } else if (rssi >= -65) { 63 | return TextStyle( 64 | color: Color.lerp(Colors.lime[600], Colors.amber, -(rssi + 55) / 10)); 65 | } else if (rssi >= -75) { 66 | return TextStyle( 67 | color: Color.lerp( 68 | Colors.amber, Colors.deepOrangeAccent, -(rssi + 65) / 10)); 69 | } else if (rssi >= -85) { 70 | return TextStyle( 71 | color: Color.lerp( 72 | Colors.deepOrangeAccent, Colors.redAccent, -(rssi + 75) / 10)); 73 | } else { 74 | return const TextStyle(color: Colors.redAccent); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/components/CustomAppBar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; 3 | import 'package:layout/HomePage.dart'; 4 | import 'package:layout/provider/StatusConexaoProvider.dart'; 5 | import 'package:provider/provider.dart'; 6 | 7 | class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { 8 | final String? Title; 9 | final bool? isBluetooth; 10 | final bool? isDiscovering; 11 | final Function? onPress; 12 | 13 | const CustomAppBar({ 14 | Key? key, 15 | @required this.Title, 16 | this.isBluetooth, 17 | this.isDiscovering, 18 | this.onPress, 19 | }) : super(key: key); 20 | @override 21 | Size get preferredSize => const Size.fromHeight(100); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | DisconnectarBluetooth() { 26 | Provider.of(context, listen: false) 27 | .setDevice(null); 28 | } 29 | 30 | return AppBar( 31 | toolbarHeight: 100.0, 32 | shape: RoundedRectangleBorder( 33 | borderRadius: BorderRadius.vertical(bottom: Radius.circular(5))), 34 | title: new Center( 35 | child: Row( 36 | children: [ 37 | new Text(Title!, textAlign: TextAlign.center), 38 | ], 39 | )), 40 | backgroundColor: Color.fromRGBO(237, 46, 39, 1), 41 | actions: [ 42 | Padding( 43 | padding: const EdgeInsets.only(right: 8.0), 44 | child: Container( 45 | height: 60, 46 | width: 60, 47 | child: Consumer( 48 | builder: (context, StatusConnectionProvider, widget) { 49 | return (isBluetooth! 50 | ? ElevatedButton( 51 | onPressed: StatusConnectionProvider.device != null 52 | ? () { 53 | Provider.of(context, 54 | listen: false) 55 | .setDevice(null); 56 | Navigator.of(context).pushReplacement( 57 | MaterialPageRoute( 58 | settings: const RouteSettings(name: '/'), 59 | builder: (context) => 60 | const HomePage())); // push it back in 61 | } 62 | : onPress!(), 63 | child: Icon(StatusConnectionProvider.device != null 64 | ? Icons.bluetooth_connected 65 | : Icons.bluetooth_disabled), 66 | style: ElevatedButton.styleFrom( 67 | shape: CircleBorder(), 68 | primary: StatusConnectionProvider.device != null 69 | ? Color.fromRGBO(15, 171, 118, 1) 70 | : Colors.black), 71 | ) 72 | : SizedBox.shrink()); 73 | }), 74 | ), 75 | ) 76 | ], 77 | ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /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.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 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: layout 2 | description: A new Flutter project. 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 | flutter_bluetooth_serial: ^0.3.2 33 | 34 | 35 | # The following adds the Cupertino Icons font to your application. 36 | # Use with the CupertinoIcons class for iOS style icons. 37 | cupertino_icons: ^1.0.2 38 | scoped_model: ^2.0.0-nullsafety.0 39 | flutter_speech: ^2.0.0 40 | provider: ^6.0.1 41 | 42 | dev_dependencies: 43 | flutter_test: 44 | sdk: flutter 45 | 46 | # The "flutter_lints" package below contains a set of recommended lints to 47 | # encourage good coding practices. The lint set provided by the package is 48 | # activated in the `analysis_options.yaml` file located at the root of your 49 | # package. See that file for information about deactivating specific lint 50 | # rules and activating additional ones. 51 | flutter_lints: ^1.0.0 52 | 53 | # For information on the generic Dart part of this file, see the 54 | # following page: https://dart.dev/tools/pub/pubspec 55 | 56 | # The following section is specific to Flutter. 57 | flutter: 58 | 59 | # The following line ensures that the Material Icons font is 60 | # included with your application, so that you can use the icons in 61 | # the material Icons class. 62 | uses-material-design: true 63 | 64 | # To add assets to your application, add an assets section, like this: 65 | # assets: 66 | # - images/a_dot_burr.jpeg 67 | # - images/a_dot_ham.jpeg 68 | 69 | # An image asset can refer to one or more resolution-specific "variants", see 70 | # https://flutter.dev/assets-and-images/#resolution-aware. 71 | 72 | # For details regarding adding assets from package dependencies, see 73 | # https://flutter.dev/assets-and-images/#from-packages 74 | 75 | # To add custom fonts to your application, add a fonts section here, 76 | # in this "flutter" section. Each entry in this list should have a 77 | # "family" key with the font family name, and a "fonts" key with a 78 | # list giving the asset and other descriptors for the font. For 79 | # example: 80 | # fonts: 81 | # - family: Schyler 82 | # fonts: 83 | # - asset: fonts/Schyler-Regular.ttf 84 | # - asset: fonts/Schyler-Italic.ttf 85 | # style: italic 86 | # - family: Trajan Pro 87 | # fonts: 88 | # - asset: fonts/TrajanPro.ttf 89 | # - asset: fonts/TrajanPro_Bold.ttf 90 | # weight: 700 91 | # 92 | # For details regarding fonts from package dependencies, 93 | # see https://flutter.dev/custom-fonts/#from-packages 94 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | layout 30 | 31 | 32 | 33 | 36 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /lib/SelecionarDispositivo.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: file_names 2 | 3 | import 'dart:async'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; 6 | import 'package:layout/ListaBluetooth.dart'; 7 | import 'package:layout/HomePage.dart'; 8 | import 'package:layout/provider/StatusConexaoProvider.dart'; 9 | import 'package:provider/provider.dart'; 10 | import 'components/CustomAppBar.dart'; 11 | 12 | class SelecionarDispositivoPage extends StatefulWidget { 13 | /// If true, on page start there is performed discovery upon the bonded devices. 14 | /// Then, if they are not avaliable, they would be disabled from the selection. 15 | final bool checkAvailability; 16 | 17 | const SelecionarDispositivoPage({this.checkAvailability = true}); 18 | 19 | @override 20 | _SelecionarDispositivoPage createState() => _SelecionarDispositivoPage(); 21 | } 22 | 23 | enum _DeviceAvailability { 24 | no, 25 | maybe, 26 | yes, 27 | } 28 | 29 | class _DeviceWithAvailability extends BluetoothDevice { 30 | BluetoothDevice? device; 31 | _DeviceAvailability? availability; 32 | int? rssi; 33 | 34 | _DeviceWithAvailability(this.device, this.availability, [this.rssi]) 35 | : super(address: device!.address); 36 | } 37 | 38 | class _SelecionarDispositivoPage extends State { 39 | List<_DeviceWithAvailability> devices = <_DeviceWithAvailability>[]; 40 | 41 | // Availability 42 | StreamSubscription? _discoveryStreamSubscription; 43 | bool? _isDiscovering; 44 | 45 | _SelecionarDispositivoPage(); 46 | 47 | @override 48 | void initState() { 49 | super.initState(); 50 | 51 | _isDiscovering = widget.checkAvailability; 52 | 53 | if (_isDiscovering!) { 54 | _startDiscovery(); 55 | } 56 | 57 | // Setup a list of the bonded devices 58 | FlutterBluetoothSerial.instance 59 | .getBondedDevices() 60 | .then((List bondedDevices) { 61 | setState(() { 62 | devices = bondedDevices 63 | .map( 64 | (device) => _DeviceWithAvailability( 65 | device, 66 | widget.checkAvailability 67 | ? _DeviceAvailability.maybe 68 | : _DeviceAvailability.yes, 69 | ), 70 | ) 71 | .toList(); 72 | }); 73 | }); 74 | } 75 | 76 | void _startDiscovery() { 77 | _discoveryStreamSubscription = 78 | FlutterBluetoothSerial.instance.startDiscovery().listen((r) { 79 | setState(() { 80 | Iterator i = devices.iterator; 81 | while (i.moveNext()) { 82 | var _device = i.current; 83 | if (_device.device == r.device) { 84 | _device.availability = _DeviceAvailability.yes; 85 | _device.rssi = r.rssi; 86 | } 87 | } 88 | }); 89 | }); 90 | 91 | _discoveryStreamSubscription!.onDone(() { 92 | setState(() { 93 | _isDiscovering = false; 94 | }); 95 | }); 96 | } 97 | 98 | @override 99 | void dispose() { 100 | // Avoid memory leak (`setState` after dispose) and cancel discovery 101 | _discoveryStreamSubscription?.cancel(); 102 | 103 | super.dispose(); 104 | } 105 | 106 | @override 107 | Widget build(BuildContext context) { 108 | List list = devices 109 | .map( 110 | (_device) => ListaBluetoothPage( 111 | device: _device.device, 112 | onTap: () { 113 | Provider.of(context, listen: false) 114 | .setDevice(_device.device!); 115 | Navigator.of(context).pushReplacement(MaterialPageRoute( 116 | settings: const RouteSettings(name: '/'), 117 | builder: (context) => HomePage())); 118 | }, 119 | ), 120 | ) 121 | .toList(); 122 | return Scaffold( 123 | appBar: CustomAppBar( 124 | Title: 'Bluetooh list', 125 | isBluetooth: false, 126 | isDiscovering: false, 127 | onPress: () {}, 128 | ), 129 | body: ListView( 130 | children: list, 131 | ), 132 | ); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /lib/components/VoiceButtonPage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/widgets.dart'; 4 | import 'dart:async'; 5 | import 'dart:convert'; 6 | import 'dart:typed_data'; 7 | import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; 8 | import 'package:flutter_speech/flutter_speech.dart'; 9 | 10 | 11 | class VoiceButtonComponent extends StatefulWidget { 12 | final BluetoothConnection? connection; 13 | final int clientID; 14 | final String? languageSelected; 15 | const VoiceButtonComponent({ 16 | Key? key, 17 | this.connection, 18 | this.languageSelected, 19 | required this.clientID, 20 | }) : super(key: key); 21 | _VoiceButtonState createState() => _VoiceButtonState(); 22 | } 23 | 24 | class Language { 25 | final String name; 26 | final String code; 27 | 28 | const Language(this.name, this.code); 29 | } 30 | 31 | const languages = const [ 32 | const Language('English', 'en_US'), 33 | const Language('Español', 'es_ES'), 34 | const Language('Portugues', 'pt_BR'), 35 | ]; 36 | 37 | class _Message { 38 | int whom; 39 | String text; 40 | 41 | _Message(this.whom, this.text); 42 | } 43 | 44 | 45 | class _VoiceButtonState extends State { 46 | bool buttonClicado = false; 47 | final TextEditingController textEditingController = TextEditingController(); 48 | List<_Message> messages = <_Message>[]; 49 | 50 | late SpeechRecognition _speech; 51 | bool _speechRecognitionAvailable = false; 52 | bool _isListening = false; 53 | 54 | @override 55 | initState() { 56 | super.initState(); 57 | activateSpeechRecognizer(); 58 | } 59 | 60 | void activateSpeechRecognizer() { 61 | print('_MyAppState.activateSpeechRecognizer... '); 62 | _speech = SpeechRecognition(); 63 | _speech.setAvailabilityHandler(onSpeechAvailability); 64 | _speech.setRecognitionStartedHandler(onRecognitionStarted); 65 | _speech.setRecognitionResultHandler(onRecognitionResult); 66 | _speech.setRecognitionCompleteHandler(onRecognitionComplete); 67 | _speech.setErrorHandler(errorHandler); 68 | _speech.activate(languages.firstWhere((l) => l.code == (widget.languageSelected == null ? 'pt_BR' : widget.languageSelected!)).code).then((res) { 69 | setState(() => _speechRecognitionAvailable = res); 70 | }); 71 | } 72 | 73 | _sendMessage(text) async { 74 | text = text.trim(); 75 | textEditingController.clear(); 76 | 77 | if (text.length > 0) { 78 | try { 79 | widget.connection!.output 80 | .add(Uint8List.fromList(utf8.encode(text + "\r\n"))); 81 | await widget.connection!.output.allSent; 82 | 83 | setState(() { 84 | messages.add(_Message(widget.clientID, text)); 85 | }); 86 | } catch (e) { 87 | setState(() {}); 88 | } 89 | } 90 | } 91 | 92 | 93 | void start() => _speech.activate( 94 | languages.firstWhere((l) => l.code == (widget.languageSelected == null ? 'pt_BR' : widget.languageSelected!)).code).then((_) { 95 | return _speech.listen().then((result) { 96 | print('_MyAppState.start => result $result'); 97 | setState(() { 98 | _isListening = result; 99 | }); 100 | }); 101 | }); 102 | 103 | void cancel() => 104 | _speech.cancel().then((_) => setState(() => _isListening = false)); 105 | 106 | void stop() => _speech.stop().then((_) { 107 | setState(() => _isListening = false); 108 | }); 109 | 110 | void onSpeechAvailability(bool result) => 111 | setState(() => _speechRecognitionAvailable = result); 112 | 113 | 114 | void onRecognitionStarted() { 115 | setState(() => _isListening = true); 116 | } 117 | 118 | void onRecognitionResult(String text) { 119 | print('_MyAppState.onRecognitionResult... $text'); 120 | _sendMessage(text); 121 | } 122 | 123 | void onRecognitionComplete(String text) { 124 | print('_MyAppState.onRecognitionComplete... $text'); 125 | setState(() => _isListening = false); 126 | } 127 | 128 | void errorHandler() => activateSpeechRecognizer(); 129 | 130 | Widget build(BuildContext context) { 131 | return (ElevatedButton( 132 | onPressed: _speechRecognitionAvailable && !_isListening 133 | ? () => start() 134 | : null, 135 | child: Icon( 136 | _isListening 137 | ? Icons.settings_voice 138 | : Icons.settings_voice_outlined, 139 | ), 140 | style: ElevatedButton.styleFrom( 141 | shape: CircleBorder(), 142 | primary: _isListening 143 | ? Color.fromRGBO(255, 255, 0, 1) 144 | : Colors.black), 145 | 146 | )); 147 | } 148 | 149 | 150 | 151 | } -------------------------------------------------------------------------------- /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.dartlang.org" 9 | source: hosted 10 | version: "2.8.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | cupertino_icons: 47 | dependency: "direct main" 48 | description: 49 | name: cupertino_icons 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.0.4" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.2.0" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_bluetooth_serial: 66 | dependency: "direct main" 67 | description: 68 | name: flutter_bluetooth_serial 69 | url: "https://pub.dartlang.org" 70 | source: hosted 71 | version: "0.3.2" 72 | flutter_lints: 73 | dependency: "direct dev" 74 | description: 75 | name: flutter_lints 76 | url: "https://pub.dartlang.org" 77 | source: hosted 78 | version: "1.0.4" 79 | flutter_speech: 80 | dependency: "direct main" 81 | description: 82 | name: flutter_speech 83 | url: "https://pub.dartlang.org" 84 | source: hosted 85 | version: "2.0.0" 86 | flutter_test: 87 | dependency: "direct dev" 88 | description: flutter 89 | source: sdk 90 | version: "0.0.0" 91 | lints: 92 | dependency: transitive 93 | description: 94 | name: lints 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.0.1" 98 | matcher: 99 | dependency: transitive 100 | description: 101 | name: matcher 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "0.12.10" 105 | meta: 106 | dependency: transitive 107 | description: 108 | name: meta 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "1.7.0" 112 | nested: 113 | dependency: transitive 114 | description: 115 | name: nested 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "1.0.0" 119 | path: 120 | dependency: transitive 121 | description: 122 | name: path 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "1.8.0" 126 | provider: 127 | dependency: "direct main" 128 | description: 129 | name: provider 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "6.0.1" 133 | scoped_model: 134 | dependency: "direct main" 135 | description: 136 | name: scoped_model 137 | url: "https://pub.dartlang.org" 138 | source: hosted 139 | version: "2.0.0-nullsafety.0" 140 | sky_engine: 141 | dependency: transitive 142 | description: flutter 143 | source: sdk 144 | version: "0.0.99" 145 | source_span: 146 | dependency: transitive 147 | description: 148 | name: source_span 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.8.1" 152 | stack_trace: 153 | dependency: transitive 154 | description: 155 | name: stack_trace 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.10.0" 159 | stream_channel: 160 | dependency: transitive 161 | description: 162 | name: stream_channel 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "2.1.0" 166 | string_scanner: 167 | dependency: transitive 168 | description: 169 | name: string_scanner 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.1.0" 173 | term_glyph: 174 | dependency: transitive 175 | description: 176 | name: term_glyph 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.2.0" 180 | test_api: 181 | dependency: transitive 182 | description: 183 | name: test_api 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "0.4.2" 187 | typed_data: 188 | dependency: transitive 189 | description: 190 | name: typed_data 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "1.3.0" 194 | vector_math: 195 | dependency: transitive 196 | description: 197 | name: vector_math 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "2.1.0" 201 | sdks: 202 | dart: ">=2.12.0 <3.0.0" 203 | flutter: ">=1.24.0-1.0.pre" 204 | -------------------------------------------------------------------------------- /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 = com.example.layout; 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 = com.example.layout; 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 = com.example.layout; 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 | -------------------------------------------------------------------------------- /lib/ControlePrincipal.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: file_names 2 | import 'dart:typed_data'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart'; 5 | import 'package:layout/components/ButtonDouble.dart'; 6 | import 'package:layout/components/ButtonSingle.dart'; 7 | 8 | import 'components/VoiceButtonPage.dart'; 9 | 10 | class ControlePrincipalPage extends StatefulWidget { 11 | final BluetoothDevice? server; 12 | const ControlePrincipalPage({this.server}); 13 | 14 | @override 15 | _ControlePrincipalPage createState() => _ControlePrincipalPage(); 16 | } 17 | 18 | class _Message { 19 | int whom; 20 | String text; 21 | 22 | _Message(this.whom, this.text); 23 | } 24 | 25 | class _ControlePrincipalPage extends State { 26 | static const clientID = 0; 27 | BluetoothConnection? connection; 28 | String? language; 29 | 30 | // ignore: deprecated_member_use 31 | List<_Message> messages = <_Message>[]; 32 | String _messageBuffer = ''; 33 | 34 | final TextEditingController textEditingController = TextEditingController(); 35 | final ScrollController listScrollController = ScrollController(); 36 | 37 | bool isConnecting = true; 38 | bool get isConnected => connection != null && connection!.isConnected; 39 | 40 | bool isDisconnecting = false; 41 | bool buttonClicado = false; 42 | 43 | List _languages = ['en_US', 'es_ES', 'pt_BR']; 44 | 45 | @override 46 | void initState() { 47 | super.initState(); 48 | 49 | BluetoothConnection.toAddress(widget.server!.address).then((_connection) { 50 | print('Connected to device'); 51 | connection = _connection; 52 | setState(() { 53 | 54 | isConnecting = false; 55 | isDisconnecting = false; 56 | }); 57 | 58 | connection!.input!.listen(_onDataReceived).onDone(() { 59 | // Example: Detect which side closed the connection 60 | // There should be `isDisconnecting` flag to show are we are (locally) 61 | // in middle of disconnecting process, should be set before calling 62 | // `dispose`, `finish` or `close`, which all causes to disconnect. 63 | // If we except the disconnection, `onDone` should be fired as result. 64 | // If we didn't except this (no flag set), it means closing by remote. 65 | if (isDisconnecting) { 66 | print('Disconnected localy!'); 67 | } else { 68 | print('Disconnected remote!'); 69 | } 70 | if (mounted) { 71 | setState(() {}); 72 | } 73 | }); 74 | }).catchError((error) { 75 | print('Failed to connect, something is wrong!'); 76 | print(error); 77 | }); 78 | } 79 | 80 | @override 81 | void dispose() { 82 | // Avoid memory leak (`setState` after dispose) and disconnect 83 | if (isConnected) { 84 | isDisconnecting = true; 85 | connection!.dispose(); 86 | connection = null; 87 | } 88 | 89 | super.dispose(); 90 | } 91 | 92 | @override 93 | Widget build(BuildContext context) { 94 | messages.map((_message) { 95 | return Row( 96 | children: [ 97 | Container( 98 | child: Text( 99 | (text) { 100 | return text == '/shrug' ? '¯\\_(ツ)_/¯' : text; 101 | }(_message.text.trim()), 102 | style: const TextStyle(color: Colors.white)), 103 | padding: const EdgeInsets.all(12.0), 104 | margin: const EdgeInsets.only(bottom: 8.0, left: 8.0, right: 8.0), 105 | width: 222.0, 106 | decoration: BoxDecoration( 107 | color: 108 | _message.whom == clientID ? Colors.blueAccent : Colors.grey, 109 | borderRadius: BorderRadius.circular(7.0)), 110 | ), 111 | ], 112 | mainAxisAlignment: _message.whom == clientID 113 | ? MainAxisAlignment.end 114 | : MainAxisAlignment.start, 115 | ); 116 | }).toList(); 117 | 118 | return SingleChildScrollView( 119 | child: Padding( 120 | padding: const EdgeInsets.only(top: 10), 121 | child: Center( 122 | child: SizedBox( 123 | height: MediaQuery.of(context).size.height, 124 | width: MediaQuery.of(context).size.width, 125 | child: Column( 126 | children: [ 127 | Padding( 128 | padding: const EdgeInsets.only(bottom: 20), 129 | child: Row( 130 | mainAxisAlignment: MainAxisAlignment.center, 131 | children: [ 132 | Column(children: [ 133 | Container( 134 | height: 60, width: 90, child: SizedBox.shrink()) 135 | ]), 136 | const SizedBox(width: 30), 137 | Column(children: [ 138 | Container( 139 | height: 60, 140 | width: 90, 141 | child: VoiceButtonComponent( 142 | connection: connection, 143 | clientID: clientID, 144 | languageSelected: language), 145 | ), 146 | ]), 147 | const SizedBox(width: 30), 148 | Column( 149 | crossAxisAlignment: CrossAxisAlignment.end, 150 | children: [ 151 | Container( 152 | child: DropdownButton( 153 | value: language == null ? 'pt_BR' : language, 154 | icon: const Icon(Icons.keyboard_arrow_down), 155 | items: _languages.map((String items) { 156 | return DropdownMenuItem( 157 | value: items, 158 | child: Text(items), 159 | ); 160 | }).toList(), 161 | // After selecting the desired option,it will 162 | // change button value to selected value 163 | onChanged: (String? newValue) { 164 | setState(() { 165 | language = newValue!; 166 | }); 167 | }, 168 | ), 169 | ) 170 | ]), 171 | ]), 172 | ), 173 | Padding( 174 | padding: const EdgeInsets.only(bottom: 20), 175 | child: Row( 176 | mainAxisAlignment: MainAxisAlignment.center, 177 | children: [ 178 | Column(children: [ 179 | ButtonDoubleComponent( 180 | buttonName: "A/B", 181 | comandOn: 'a', 182 | comandOff: 'b', 183 | clientID: clientID, 184 | connection: connection, 185 | ), 186 | ]), 187 | const SizedBox(width: 30), 188 | Column(children: [ 189 | ButtonDoubleComponent( 190 | buttonName: "C/D", 191 | comandOn: 'c', 192 | comandOff: 'd', 193 | clientID: clientID, 194 | connection: connection, 195 | ), 196 | ]), 197 | const SizedBox(width: 30), 198 | Column(children: [ 199 | ButtonDoubleComponent( 200 | buttonName: "E/F", 201 | comandOn: 'e', 202 | comandOff: 'f', 203 | clientID: clientID, 204 | connection: connection, 205 | ), 206 | ]), 207 | ]), 208 | ), 209 | Padding( 210 | padding: const EdgeInsets.only(bottom: 20), 211 | child: Row( 212 | mainAxisAlignment: MainAxisAlignment.center, 213 | children: [ 214 | Column(children: [ 215 | ButtonDoubleComponent( 216 | buttonName: "G/H", 217 | comandOn: 'g', 218 | comandOff: 'h', 219 | clientID: clientID, 220 | connection: connection, 221 | ), 222 | ]), 223 | const SizedBox(width: 30), 224 | Column(children: [ 225 | ButtonDoubleComponent( 226 | buttonName: "I/J", 227 | comandOn: 'i', 228 | comandOff: 'j', 229 | clientID: clientID, 230 | connection: connection, 231 | ), 232 | ]), 233 | const SizedBox(width: 30), 234 | Column(children: [ 235 | ButtonDoubleComponent( 236 | buttonName: "K/L", 237 | comandOn: 'k', 238 | comandOff: 'l', 239 | clientID: clientID, 240 | connection: connection, 241 | ), 242 | ]), 243 | ]), 244 | ), 245 | Padding( 246 | padding: const EdgeInsets.only(bottom: 20), 247 | child: Row( 248 | mainAxisAlignment: MainAxisAlignment.center, 249 | children: [ 250 | Column(children: [ 251 | ButtonDoubleComponent( 252 | buttonName: "M/N", 253 | comandOn: 'm', 254 | comandOff: 'n', 255 | clientID: clientID, 256 | connection: connection, 257 | ), 258 | ]), 259 | const SizedBox(width: 30), 260 | Column(children: [ 261 | ButtonDoubleComponent( 262 | buttonName: "O/P", 263 | comandOn: 'o', 264 | comandOff: 'p', 265 | clientID: clientID, 266 | connection: connection, 267 | ), 268 | ]), 269 | const SizedBox(width: 30), 270 | Column(children: [ 271 | ButtonDoubleComponent( 272 | buttonName: "Q/R", 273 | comandOn: 'q', 274 | comandOff: 'r', 275 | clientID: clientID, 276 | connection: connection, 277 | ), 278 | ]), 279 | ]), 280 | ), 281 | Padding( 282 | padding: const EdgeInsets.only(bottom: 20), 283 | child: Row( 284 | mainAxisAlignment: MainAxisAlignment.center, 285 | children: [ 286 | Column(children: [ 287 | ButtonDoubleComponent( 288 | buttonName: "S/T", 289 | comandOn: 's', 290 | comandOff: 't', 291 | clientID: clientID, 292 | connection: connection, 293 | ), 294 | ]), 295 | const SizedBox(width: 30), 296 | Column(children: [ 297 | ButtonDoubleComponent( 298 | buttonName: "U/V", 299 | comandOn: 'u', 300 | comandOff: 'v', 301 | clientID: clientID, 302 | connection: connection, 303 | ), 304 | ]), 305 | const SizedBox(width: 30), 306 | Column(children: [ 307 | ButtonDoubleComponent( 308 | buttonName: "W/X", 309 | comandOn: 'w', 310 | comandOff: 'x', 311 | clientID: clientID, 312 | connection: connection, 313 | ), 314 | ]), 315 | ]), 316 | ), 317 | Padding( 318 | padding: const EdgeInsets.only(bottom: 20), 319 | child: Row( 320 | mainAxisAlignment: MainAxisAlignment.center, 321 | children: [ 322 | Column(children: [ 323 | ButtonDoubleComponent( 324 | buttonName: "Y/Z", 325 | comandOn: 'y', 326 | comandOff: 'z', 327 | clientID: clientID, 328 | connection: connection, 329 | ), 330 | ]), 331 | const SizedBox(width: 30), 332 | Column(children: [ 333 | ButtonDoubleComponent( 334 | buttonName: "0/1", 335 | comandOn: '0', 336 | comandOff: '1', 337 | clientID: clientID, 338 | connection: connection, 339 | ), 340 | ]), 341 | const SizedBox(width: 30), 342 | Column(children: [ 343 | ButtonDoubleComponent( 344 | buttonName: "2/3", 345 | comandOn: '2', 346 | comandOff: '3', 347 | clientID: clientID, 348 | connection: connection, 349 | ), 350 | ]), 351 | ]), 352 | ), 353 | Padding( 354 | padding: const EdgeInsets.only(bottom: 20), 355 | child: Row( 356 | mainAxisAlignment: MainAxisAlignment.center, 357 | children: [ 358 | Column(children: [ 359 | ButtonDoubleComponent( 360 | buttonName: "4/5", 361 | comandOn: '4', 362 | comandOff: '5', 363 | clientID: clientID, 364 | connection: connection, 365 | ), 366 | ]), 367 | const SizedBox(width: 30), 368 | Column(children: [ 369 | ButtonDoubleComponent( 370 | buttonName: "6/7", 371 | comandOn: '6', 372 | comandOff: '7', 373 | clientID: clientID, 374 | connection: connection, 375 | ), 376 | ]), 377 | const SizedBox(width: 30), 378 | Column(children: [ 379 | ButtonDoubleComponent( 380 | buttonName: "8/9", 381 | comandOn: '8', 382 | comandOff: '9', 383 | clientID: clientID, 384 | connection: connection, 385 | ), 386 | ]), 387 | ]), 388 | ), 389 | Padding( 390 | padding: const EdgeInsets.only(top: 30), 391 | child: Row( 392 | mainAxisAlignment: MainAxisAlignment.center, 393 | children: [ 394 | Column(children: [ 395 | ButtonSingleComponent( 396 | buttonName: "+", 397 | comandOn: '+', 398 | colorButton: Color.fromRGBO(238, 57, 61, 1), 399 | clientID: clientID, 400 | connection: connection, 401 | ), 402 | ]), 403 | const SizedBox(width: 10), 404 | Column(children: [ 405 | ButtonSingleComponent( 406 | buttonName: "-", 407 | comandOn: '-', 408 | colorButton: Color.fromRGBO(8, 164, 113, 1), 409 | clientID: clientID, 410 | connection: connection, 411 | ), 412 | ]), 413 | const SizedBox(width: 10), 414 | Column(children: [ 415 | ButtonSingleComponent( 416 | buttonName: "*", 417 | comandOn: '*', 418 | colorButton: Color.fromRGBO(239, 206, 45, 1), 419 | clientID: clientID, 420 | connection: connection, 421 | ), 422 | ]), 423 | const SizedBox(width: 10), 424 | Column(children: [ 425 | ButtonSingleComponent( 426 | buttonName: "/", 427 | comandOn: '/', 428 | colorButton: Color.fromRGBO(49, 86, 188, 1), 429 | clientID: clientID, 430 | connection: connection, 431 | ), 432 | ]), 433 | ]), 434 | ), 435 | ], 436 | ), 437 | ), 438 | ), 439 | ), 440 | ); 441 | } 442 | 443 | void _onDataReceived(Uint8List data) { 444 | // Allocate buffer for parsed data 445 | int backspacesCounter = 0; 446 | for (var byte in data) { 447 | if (byte == 8 || byte == 127) { 448 | backspacesCounter++; 449 | } 450 | } 451 | Uint8List buffer = Uint8List(data.length - backspacesCounter); 452 | int bufferIndex = buffer.length; 453 | 454 | // Apply backspace control character 455 | backspacesCounter = 0; 456 | for (int i = data.length - 1; i >= 0; i--) { 457 | if (data[i] == 8 || data[i] == 127) { 458 | backspacesCounter++; 459 | } else { 460 | if (backspacesCounter > 0) { 461 | backspacesCounter--; 462 | } else { 463 | buffer[--bufferIndex] = data[i]; 464 | } 465 | } 466 | } 467 | 468 | // Create message if there is new line character 469 | String dataString = String.fromCharCodes(buffer); 470 | int index = buffer.indexOf(13); 471 | if (~index != 0) { 472 | setState(() { 473 | messages.add( 474 | _Message( 475 | 1, 476 | backspacesCounter > 0 477 | ? _messageBuffer.substring( 478 | 0, _messageBuffer.length - backspacesCounter) 479 | : _messageBuffer + dataString.substring(0, index), 480 | ), 481 | ); 482 | _messageBuffer = dataString.substring(index); 483 | }); 484 | } else { 485 | _messageBuffer = (backspacesCounter > 0 486 | ? _messageBuffer.substring( 487 | 0, _messageBuffer.length - backspacesCounter) 488 | : _messageBuffer + dataString); 489 | } 490 | } 491 | } 492 | --------------------------------------------------------------------------------