├── .gitignore
├── .metadata
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── example
├── .gitignore
├── .metadata
├── README.md
├── analysis_options.yaml
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── example
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v21
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── values-night
│ │ │ │ └── styles.xml
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ ├── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ │ └── LaunchImage.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ └── README.md
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ └── Runner-Bridging-Header.h
│ └── RunnerTests
│ │ └── RunnerTests.swift
├── lib
│ └── main.dart
├── macos
│ ├── .gitignore
│ ├── Flutter
│ │ ├── Flutter-Debug.xcconfig
│ │ ├── Flutter-Release.xcconfig
│ │ └── GeneratedPluginRegistrant.swift
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── app_icon_1024.png
│ │ │ │ ├── app_icon_128.png
│ │ │ │ ├── app_icon_16.png
│ │ │ │ ├── app_icon_256.png
│ │ │ │ ├── app_icon_32.png
│ │ │ │ ├── app_icon_512.png
│ │ │ │ └── app_icon_64.png
│ │ ├── Base.lproj
│ │ │ └── MainMenu.xib
│ │ ├── Configs
│ │ │ ├── AppInfo.xcconfig
│ │ │ ├── Debug.xcconfig
│ │ │ ├── Release.xcconfig
│ │ │ └── Warnings.xcconfig
│ │ ├── DebugProfile.entitlements
│ │ ├── Info.plist
│ │ ├── MainFlutterWindow.swift
│ │ └── Release.entitlements
│ └── RunnerTests
│ │ └── RunnerTests.swift
└── pubspec.yaml
├── lib
├── cast.dart
├── cast_channel
│ ├── cast_channel.idl
│ ├── cast_channel.pb.dart
│ ├── cast_channel.pbenum.dart
│ ├── cast_channel.pbjson.dart
│ ├── cast_channel.pbserver.dart
│ └── cast_channel.proto
├── device.dart
├── discovery_service.dart
├── session.dart
├── session_manager.dart
└── socket.dart
├── pubspec.lock
└── pubspec.yaml
/.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 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | build/
32 |
33 | # Android related
34 | **/android/**/gradle-wrapper.jar
35 | **/android/.gradle
36 | **/android/captures/
37 | **/android/gradlew
38 | **/android/gradlew.bat
39 | **/android/local.properties
40 | **/android/**/GeneratedPluginRegistrant.java
41 |
42 | # iOS/XCode related
43 | **/ios/**/*.mode1v3
44 | **/ios/**/*.mode2v3
45 | **/ios/**/*.moved-aside
46 | **/ios/**/*.pbxuser
47 | **/ios/**/*.perspectivev3
48 | **/ios/**/*sync/
49 | **/ios/**/.sconsign.dblite
50 | **/ios/**/.tags*
51 | **/ios/**/.vagrant/
52 | **/ios/**/DerivedData/
53 | **/ios/**/Icon?
54 | **/ios/**/Pods/
55 | **/ios/**/.symlinks/
56 | **/ios/**/profile
57 | **/ios/**/xcuserdata
58 | **/ios/.generated/
59 | **/ios/Flutter/App.framework
60 | **/ios/Flutter/Flutter.framework
61 | **/ios/Flutter/Flutter.podspec
62 | **/ios/Flutter/Generated.xcconfig
63 | **/ios/Flutter/app.flx
64 | **/ios/Flutter/app.zip
65 | **/ios/Flutter/flutter_assets/
66 | **/ios/Flutter/flutter_export_environment.sh
67 | **/ios/ServiceDefinitions.json
68 | **/ios/Runner/GeneratedPluginRegistrant.*
69 |
70 | # Exceptions to above rules.
71 | !**/ios/**/default.mode1v3
72 | !**/ios/**/default.mode2v3
73 | !**/ios/**/default.pbxuser
74 | !**/ios/**/default.perspectivev3
75 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
76 |
--------------------------------------------------------------------------------
/.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: f7a6a7906be96d2288f5d63a5a54c515a6e987fe
8 | channel: stable
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [2.1.0]
2 |
3 | * Remove upper version limit for `bonsoir`
4 |
5 | ## [2.0.0]
6 |
7 | * Upgrade dependency `bonsoir` to 3.0.0
8 | * Upgrade to Dart 3
9 |
10 | ## [1.1.1]
11 |
12 | * Upgrade dependency `bonsoir`
13 |
14 | ## [1.1.0]
15 |
16 | * Replace dependency `multicast_dns` (not working on iOS) by `bonsoir`
17 |
18 | ## [1.0.0]
19 |
20 | * Migrate to null safety
21 | * Replace dependency `mdns_plugin` (doesn't support null safety) by `multicast_dns`
22 |
23 | ## [0.3.0]
24 |
25 | * Add the possibility to use your own requestId
26 |
27 | ## [0.2.0]
28 |
29 | * Improve service discovery #1
30 |
31 | ## [0.1.1]
32 |
33 | * Add `kNamespaceMedia` to `CastSession`
34 |
35 | ## [0.1.0]
36 |
37 | * First release
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 Jonathan VUKOVICH
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://pub.dev/packages/cast)
2 | [](https://pub.dev/packages/cast)
3 | [](https://pub.dev/packages/cast)
4 |
5 | # cast
6 |
7 | Dart package to discover and connect with Chromecast devices
8 |
9 | ## Installation
10 |
11 | Add this to your package's pubspec.yaml file:
12 |
13 | ```
14 | dependencies:
15 | cast: ^2.1.0
16 | ```
17 |
18 | ### iOS
19 |
20 | Required iOS 13 minimum.
21 | Since iOS 14 a few more steps are required https://developers.google.com/cast/docs/ios_sender/ios_permissions_changes
22 |
23 | In `ios/Runner/Info.plist` add:
24 |
25 | ```xml
26 | NSBonjourServices
27 |
28 | _googlecast._tcp
29 | _YOUR_APP_ID._googlecast._tcp
30 |
31 |
32 | NSLocalNetworkUsageDescription
33 | ${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi
34 | network.
35 | ```
36 |
37 | ## Usage
38 |
39 | List devices:
40 |
41 | ```
42 | Widget build(BuildContext context) {
43 | return FutureBuilder>(
44 | future: CastDiscoveryService().search(),
45 | builder: (context, snapshot) {
46 | if (snapshot.hasError) {
47 | return Center(
48 | child: Text(
49 | 'Error: ${snapshot.error.toString()}',
50 | ),
51 | );
52 | } else if (!snapshot.hasData) {
53 | return Center(
54 | child: CircularProgressIndicator(),
55 | );
56 | }
57 |
58 | if (snapshot.data!.isEmpty) {
59 | return Column(
60 | children: [
61 | Center(
62 | child: Text(
63 | 'No Chromecast founded',
64 | ),
65 | ),
66 | ],
67 | );
68 | }
69 |
70 | return Column(
71 | children: snapshot.data!.map((device) {
72 | return ListTile(
73 | title: Text(device.name),
74 | onTap: () {
75 | _connectToYourApp(context, device);
76 | },
77 | );
78 | }).toList(),
79 | );
80 | },
81 | );
82 | }
83 | ```
84 |
85 | Connect to device:
86 |
87 | ```
88 | Future _connect(BuildContext context, CastDevice object) async {
89 | final session = await CastSessionManager().startSession(object);
90 |
91 | session.stateStream.listen((state) {
92 | if (state == CastSessionState.connected) {
93 | _sendMessage(session);
94 | }
95 | });
96 |
97 | session.messageStream.listen((message) {
98 | print('receive message: $message');
99 | });
100 |
101 | session.sendMessage(CastSession.kNamespaceReceiver, {
102 | 'type': 'LAUNCH',
103 | 'appId': 'YouTube', // set the appId of your app here
104 | });
105 | }
106 | ```
107 |
108 | `CastSessionManager` is used to keep track of all sessions.
109 |
110 | Send message:
111 |
112 | ```
113 | void _sendMessage(CastSession session) {
114 | session.sendMessage('urn:x-cast:namespace-of-the-app', {
115 | 'type': 'sample',
116 | });
117 | }
118 | ```
119 |
120 | Except for the launch message, you should wait until the session have a connected state before sending message.
121 |
122 | ## Note
123 |
124 | Some informations about the protocol used https://docs.rs/crate/gcast/0.1.5/source/PROTOCOL.md
125 |
126 | $ pub global activate protoc_plugin
127 | $ export PATH="$PATH":"$HOME/.pub-cache/bin"
128 | $ protoc -I=./lib/cast_channel --dart_out=./lib/cast_channel ./lib/cast_channel/cast_channel.proto --plugin "pub run protoc_plugin"
129 |
130 | ## Author
131 |
132 | - [Jonathan VUKOVICH](https://github.com/johnvuko)
133 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:pedantic/analysis_options.yaml
2 |
3 | analyzer:
4 | exclude:
5 | - lib/cast_channel/*
6 |
7 | # https://dart-lang.github.io/linter/lints/
8 | linter:
9 | rules:
10 | # Error Rules
11 | avoid_empty_else: true
12 | avoid_relative_lib_imports: true
13 | avoid_returning_null_for_future: true
14 | avoid_slow_async_io: true
15 | avoid_types_as_parameter_names: true
16 | control_flow_in_finally: true
17 | empty_statements: true
18 | no_adjacent_strings_in_list: true
19 | no_duplicate_case_values: true
20 | prefer_void_to_null: true
21 | unnecessary_statements: true
22 | unrelated_type_equality_checks: true
23 | # Style Rules
24 | always_declare_return_types: true
25 | annotate_overrides: true
26 | avoid_field_initializers_in_const_classes: true
27 | avoid_renaming_method_parameters: true
28 | avoid_void_async: true
29 | directives_ordering: true
30 | unnecessary_await_in_return: true
31 | sort_pub_dependencies: true
32 | omit_local_variable_types: false
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | pubspec.lock
2 |
3 | # Miscellaneous
4 | *.class
5 | *.log
6 | *.pyc
7 | *.swp
8 | .DS_Store
9 | .atom/
10 | .buildlog/
11 | .history
12 | .svn/
13 |
14 | # IntelliJ related
15 | *.iml
16 | *.ipr
17 | *.iws
18 | .idea/
19 |
20 | # The .vscode folder contains launch configuration and tasks you configure in
21 | # VS Code which you may wish to be included in version control, so this line
22 | # is commented out by default.
23 | #.vscode/
24 |
25 | # Flutter/Dart/Pub related
26 | **/doc/api/
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Web related
36 | lib/generated_plugin_registrant.dart
37 |
38 | # Symbolication related
39 | app.*.symbols
40 |
41 | # Obfuscation related
42 | app.*.map.json
43 |
44 | # Exceptions to above rules.
45 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
46 |
--------------------------------------------------------------------------------
/example/.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: "d211f42860350d914a5ad8102f9ec32764dc6d06"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
17 | base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
18 | - platform: android
19 | create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
20 | base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
21 | - platform: ios
22 | create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
23 | base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
24 |
25 | # User provided section
26 |
27 | # List of Local paths (relative to this file) that should be
28 | # ignored by the migrate tool.
29 | #
30 | # Files that are not part of the templates will be ignored by default.
31 | unmanaged_files:
32 | - 'lib/main.dart'
33 | - 'ios/Runner.xcodeproj/project.pbxproj'
34 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # example
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
13 |
14 | For help getting started with Flutter development, view the
15 | [online documentation](https://docs.flutter.dev/), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/example/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 https://dart.dev/lints.
17 | #
18 | # Instead of disabling a lint rule for the entire project in the
19 | # section below, it can also be suppressed for a single line of code
20 | # or a specific dart file by using the `// ignore: name_of_lint` and
21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
22 | # producing the lint.
23 | rules:
24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
26 |
27 | # Additional information about this file can be found at
28 | # https://dart.dev/guides/language/analysis-options
29 |
--------------------------------------------------------------------------------
/example/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 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | id "dev.flutter.flutter-gradle-plugin"
5 | }
6 |
7 | def localProperties = new Properties()
8 | def localPropertiesFile = rootProject.file('local.properties')
9 | if (localPropertiesFile.exists()) {
10 | localPropertiesFile.withReader('UTF-8') { reader ->
11 | localProperties.load(reader)
12 | }
13 | }
14 |
15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
16 | if (flutterVersionCode == null) {
17 | flutterVersionCode = '1'
18 | }
19 |
20 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
21 | if (flutterVersionName == null) {
22 | flutterVersionName = '1.0'
23 | }
24 |
25 | android {
26 | namespace "com.example.example"
27 | compileSdkVersion flutter.compileSdkVersion
28 | ndkVersion flutter.ndkVersion
29 |
30 | compileOptions {
31 | sourceCompatibility JavaVersion.VERSION_1_8
32 | targetCompatibility JavaVersion.VERSION_1_8
33 | }
34 |
35 | kotlinOptions {
36 | jvmTarget = '1.8'
37 | }
38 |
39 | sourceSets {
40 | main.java.srcDirs += 'src/main/kotlin'
41 | }
42 |
43 | defaultConfig {
44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45 | applicationId "com.example.example"
46 | // You can update the following values to match your application needs.
47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
48 | minSdkVersion flutter.minSdkVersion
49 | targetSdkVersion flutter.targetSdkVersion
50 | versionCode flutterVersionCode.toInteger()
51 | versionName flutterVersionName
52 | }
53 |
54 | buildTypes {
55 | release {
56 | // TODO: Add your own signing config for the release build.
57 | // Signing with the debug keys for now, so `flutter run --release` works.
58 | signingConfig signingConfigs.debug
59 | }
60 | }
61 | }
62 |
63 | flutter {
64 | source '../..'
65 | }
66 |
67 | dependencies {}
68 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
14 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
29 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.7.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:7.3.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 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | tasks.register("clean", Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
6 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }
9 | settings.ext.flutterSdkPath = flutterSdkPath()
10 |
11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
12 |
13 | plugins {
14 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
15 | }
16 | }
17 |
18 | include ":app"
19 |
20 | apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle"
21 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/example/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 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, '13.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | target 'RunnerTests' do
36 | inherit! :search_paths
37 | end
38 | end
39 |
40 | post_install do |installer|
41 | installer.pods_project.targets.each do |target|
42 | flutter_additional_ios_build_settings(target)
43 | target.build_configurations.each do |config|
44 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - bonsoir_darwin (4.0.0):
3 | - Flutter
4 | - FlutterMacOS
5 | - connectivity_plus (0.0.1):
6 | - Flutter
7 | - ReachabilitySwift
8 | - Flutter (1.0.0)
9 | - ReachabilitySwift (5.0.0)
10 |
11 | DEPENDENCIES:
12 | - bonsoir_darwin (from `.symlinks/plugins/bonsoir_darwin/darwin`)
13 | - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
14 | - Flutter (from `Flutter`)
15 |
16 | SPEC REPOS:
17 | trunk:
18 | - ReachabilitySwift
19 |
20 | EXTERNAL SOURCES:
21 | bonsoir_darwin:
22 | :path: ".symlinks/plugins/bonsoir_darwin/darwin"
23 | connectivity_plus:
24 | :path: ".symlinks/plugins/connectivity_plus/ios"
25 | Flutter:
26 | :path: Flutter
27 |
28 | SPEC CHECKSUMS:
29 | bonsoir_darwin: 7da594ad87e24a387874c49496ff39ffcc9645d9
30 | connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a
31 | Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
32 | ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
33 |
34 | PODFILE CHECKSUM: 0a7d5b7d0e53420cb0284f7b2f171f93843b94d2
35 |
36 | COCOAPODS: 1.13.0
37 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 09B6BC8F2F7867700B958D2B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12958BFFDE470C0AEC5E0B1E /* Pods_Runner.framework */; };
11 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
12 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
13 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
15 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
16 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
17 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
18 | A810307DE42D40D35B78DE2E /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 708F7ADE0882B87BE0D434A4 /* Pods_RunnerTests.framework */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXContainerItemProxy section */
22 | 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
23 | isa = PBXContainerItemProxy;
24 | containerPortal = 97C146E61CF9000F007C117D /* Project object */;
25 | proxyType = 1;
26 | remoteGlobalIDString = 97C146ED1CF9000F007C117D;
27 | remoteInfo = Runner;
28 | };
29 | /* End PBXContainerItemProxy section */
30 |
31 | /* Begin PBXCopyFilesBuildPhase section */
32 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
33 | isa = PBXCopyFilesBuildPhase;
34 | buildActionMask = 2147483647;
35 | dstPath = "";
36 | dstSubfolderSpec = 10;
37 | files = (
38 | );
39 | name = "Embed Frameworks";
40 | runOnlyForDeploymentPostprocessing = 0;
41 | };
42 | /* End PBXCopyFilesBuildPhase section */
43 |
44 | /* Begin PBXFileReference section */
45 | 12958BFFDE470C0AEC5E0B1E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
47 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
48 | 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
49 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
50 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
51 | 4C86D9E5688B3273EB596676 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; };
52 | 520B5728D30A78FF10C5C581 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
53 | 708F7ADE0882B87BE0D434A4 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
54 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
55 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
56 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
57 | 7BAF53CF980267C69056A753 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
58 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
59 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
60 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
61 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
62 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
63 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
64 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
65 | A029B89B6D3A3D8C66220CFC /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; };
66 | D370CB05C2D13808BC0CF3CD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
67 | F9F67F142F6C554E58A265B5 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; };
68 | /* End PBXFileReference section */
69 |
70 | /* Begin PBXFrameworksBuildPhase section */
71 | 16F217B6AE411E6D553CE435 /* Frameworks */ = {
72 | isa = PBXFrameworksBuildPhase;
73 | buildActionMask = 2147483647;
74 | files = (
75 | A810307DE42D40D35B78DE2E /* Pods_RunnerTests.framework in Frameworks */,
76 | );
77 | runOnlyForDeploymentPostprocessing = 0;
78 | };
79 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
80 | isa = PBXFrameworksBuildPhase;
81 | buildActionMask = 2147483647;
82 | files = (
83 | 09B6BC8F2F7867700B958D2B /* Pods_Runner.framework in Frameworks */,
84 | );
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | /* End PBXFrameworksBuildPhase section */
88 |
89 | /* Begin PBXGroup section */
90 | 1A9B8FBFDA47B66D566D6F96 /* Pods */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 7BAF53CF980267C69056A753 /* Pods-Runner.debug.xcconfig */,
94 | D370CB05C2D13808BC0CF3CD /* Pods-Runner.release.xcconfig */,
95 | 520B5728D30A78FF10C5C581 /* Pods-Runner.profile.xcconfig */,
96 | A029B89B6D3A3D8C66220CFC /* Pods-RunnerTests.debug.xcconfig */,
97 | 4C86D9E5688B3273EB596676 /* Pods-RunnerTests.release.xcconfig */,
98 | F9F67F142F6C554E58A265B5 /* Pods-RunnerTests.profile.xcconfig */,
99 | );
100 | path = Pods;
101 | sourceTree = "";
102 | };
103 | 331C8082294A63A400263BE5 /* RunnerTests */ = {
104 | isa = PBXGroup;
105 | children = (
106 | 331C807B294A618700263BE5 /* RunnerTests.swift */,
107 | );
108 | path = RunnerTests;
109 | sourceTree = "";
110 | };
111 | 9740EEB11CF90186004384FC /* Flutter */ = {
112 | isa = PBXGroup;
113 | children = (
114 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
115 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
116 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
117 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
118 | );
119 | name = Flutter;
120 | sourceTree = "";
121 | };
122 | 97C146E51CF9000F007C117D = {
123 | isa = PBXGroup;
124 | children = (
125 | 9740EEB11CF90186004384FC /* Flutter */,
126 | 97C146F01CF9000F007C117D /* Runner */,
127 | 97C146EF1CF9000F007C117D /* Products */,
128 | 331C8082294A63A400263BE5 /* RunnerTests */,
129 | 1A9B8FBFDA47B66D566D6F96 /* Pods */,
130 | C8DACBEC770D48D47EB425F0 /* Frameworks */,
131 | );
132 | sourceTree = "";
133 | };
134 | 97C146EF1CF9000F007C117D /* Products */ = {
135 | isa = PBXGroup;
136 | children = (
137 | 97C146EE1CF9000F007C117D /* Runner.app */,
138 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */,
139 | );
140 | name = Products;
141 | sourceTree = "";
142 | };
143 | 97C146F01CF9000F007C117D /* Runner */ = {
144 | isa = PBXGroup;
145 | children = (
146 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
147 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
148 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
149 | 97C147021CF9000F007C117D /* Info.plist */,
150 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
151 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
152 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
153 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
154 | );
155 | path = Runner;
156 | sourceTree = "";
157 | };
158 | C8DACBEC770D48D47EB425F0 /* Frameworks */ = {
159 | isa = PBXGroup;
160 | children = (
161 | 12958BFFDE470C0AEC5E0B1E /* Pods_Runner.framework */,
162 | 708F7ADE0882B87BE0D434A4 /* Pods_RunnerTests.framework */,
163 | );
164 | name = Frameworks;
165 | sourceTree = "";
166 | };
167 | /* End PBXGroup section */
168 |
169 | /* Begin PBXNativeTarget section */
170 | 331C8080294A63A400263BE5 /* RunnerTests */ = {
171 | isa = PBXNativeTarget;
172 | buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
173 | buildPhases = (
174 | F1609B17994B047C26D5B58B /* [CP] Check Pods Manifest.lock */,
175 | 331C807D294A63A400263BE5 /* Sources */,
176 | 331C807F294A63A400263BE5 /* Resources */,
177 | 16F217B6AE411E6D553CE435 /* Frameworks */,
178 | );
179 | buildRules = (
180 | );
181 | dependencies = (
182 | 331C8086294A63A400263BE5 /* PBXTargetDependency */,
183 | );
184 | name = RunnerTests;
185 | productName = RunnerTests;
186 | productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
187 | productType = "com.apple.product-type.bundle.unit-test";
188 | };
189 | 97C146ED1CF9000F007C117D /* Runner */ = {
190 | isa = PBXNativeTarget;
191 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
192 | buildPhases = (
193 | 2D31493C31CD9CF3DDFF5C8B /* [CP] Check Pods Manifest.lock */,
194 | 9740EEB61CF901F6004384FC /* Run Script */,
195 | 97C146EA1CF9000F007C117D /* Sources */,
196 | 97C146EB1CF9000F007C117D /* Frameworks */,
197 | 97C146EC1CF9000F007C117D /* Resources */,
198 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
199 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
200 | DCEC3F3D803DB0413ACC8F94 /* [CP] Embed Pods Frameworks */,
201 | );
202 | buildRules = (
203 | );
204 | dependencies = (
205 | );
206 | name = Runner;
207 | productName = Runner;
208 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
209 | productType = "com.apple.product-type.application";
210 | };
211 | /* End PBXNativeTarget section */
212 |
213 | /* Begin PBXProject section */
214 | 97C146E61CF9000F007C117D /* Project object */ = {
215 | isa = PBXProject;
216 | attributes = {
217 | BuildIndependentTargetsInParallel = YES;
218 | LastUpgradeCheck = 1430;
219 | ORGANIZATIONNAME = "";
220 | TargetAttributes = {
221 | 331C8080294A63A400263BE5 = {
222 | CreatedOnToolsVersion = 14.0;
223 | TestTargetID = 97C146ED1CF9000F007C117D;
224 | };
225 | 97C146ED1CF9000F007C117D = {
226 | CreatedOnToolsVersion = 7.3.1;
227 | LastSwiftMigration = 1100;
228 | };
229 | };
230 | };
231 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
232 | compatibilityVersion = "Xcode 9.3";
233 | developmentRegion = en;
234 | hasScannedForEncodings = 0;
235 | knownRegions = (
236 | en,
237 | Base,
238 | );
239 | mainGroup = 97C146E51CF9000F007C117D;
240 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
241 | projectDirPath = "";
242 | projectRoot = "";
243 | targets = (
244 | 97C146ED1CF9000F007C117D /* Runner */,
245 | 331C8080294A63A400263BE5 /* RunnerTests */,
246 | );
247 | };
248 | /* End PBXProject section */
249 |
250 | /* Begin PBXResourcesBuildPhase section */
251 | 331C807F294A63A400263BE5 /* Resources */ = {
252 | isa = PBXResourcesBuildPhase;
253 | buildActionMask = 2147483647;
254 | files = (
255 | );
256 | runOnlyForDeploymentPostprocessing = 0;
257 | };
258 | 97C146EC1CF9000F007C117D /* Resources */ = {
259 | isa = PBXResourcesBuildPhase;
260 | buildActionMask = 2147483647;
261 | files = (
262 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
263 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
264 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
265 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
266 | );
267 | runOnlyForDeploymentPostprocessing = 0;
268 | };
269 | /* End PBXResourcesBuildPhase section */
270 |
271 | /* Begin PBXShellScriptBuildPhase section */
272 | 2D31493C31CD9CF3DDFF5C8B /* [CP] Check Pods Manifest.lock */ = {
273 | isa = PBXShellScriptBuildPhase;
274 | buildActionMask = 2147483647;
275 | files = (
276 | );
277 | inputFileListPaths = (
278 | );
279 | inputPaths = (
280 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
281 | "${PODS_ROOT}/Manifest.lock",
282 | );
283 | name = "[CP] Check Pods Manifest.lock";
284 | outputFileListPaths = (
285 | );
286 | outputPaths = (
287 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
288 | );
289 | runOnlyForDeploymentPostprocessing = 0;
290 | shellPath = /bin/sh;
291 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
292 | showEnvVarsInLog = 0;
293 | };
294 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
295 | isa = PBXShellScriptBuildPhase;
296 | alwaysOutOfDate = 1;
297 | buildActionMask = 2147483647;
298 | files = (
299 | );
300 | inputPaths = (
301 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
302 | );
303 | name = "Thin Binary";
304 | outputPaths = (
305 | );
306 | runOnlyForDeploymentPostprocessing = 0;
307 | shellPath = /bin/sh;
308 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
309 | };
310 | 9740EEB61CF901F6004384FC /* Run Script */ = {
311 | isa = PBXShellScriptBuildPhase;
312 | alwaysOutOfDate = 1;
313 | buildActionMask = 2147483647;
314 | files = (
315 | );
316 | inputPaths = (
317 | );
318 | name = "Run Script";
319 | outputPaths = (
320 | );
321 | runOnlyForDeploymentPostprocessing = 0;
322 | shellPath = /bin/sh;
323 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
324 | };
325 | DCEC3F3D803DB0413ACC8F94 /* [CP] Embed Pods Frameworks */ = {
326 | isa = PBXShellScriptBuildPhase;
327 | buildActionMask = 2147483647;
328 | files = (
329 | );
330 | inputFileListPaths = (
331 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
332 | );
333 | name = "[CP] Embed Pods Frameworks";
334 | outputFileListPaths = (
335 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
336 | );
337 | runOnlyForDeploymentPostprocessing = 0;
338 | shellPath = /bin/sh;
339 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
340 | showEnvVarsInLog = 0;
341 | };
342 | F1609B17994B047C26D5B58B /* [CP] Check Pods Manifest.lock */ = {
343 | isa = PBXShellScriptBuildPhase;
344 | buildActionMask = 2147483647;
345 | files = (
346 | );
347 | inputFileListPaths = (
348 | );
349 | inputPaths = (
350 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
351 | "${PODS_ROOT}/Manifest.lock",
352 | );
353 | name = "[CP] Check Pods Manifest.lock";
354 | outputFileListPaths = (
355 | );
356 | outputPaths = (
357 | "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
358 | );
359 | runOnlyForDeploymentPostprocessing = 0;
360 | shellPath = /bin/sh;
361 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
362 | showEnvVarsInLog = 0;
363 | };
364 | /* End PBXShellScriptBuildPhase section */
365 |
366 | /* Begin PBXSourcesBuildPhase section */
367 | 331C807D294A63A400263BE5 /* Sources */ = {
368 | isa = PBXSourcesBuildPhase;
369 | buildActionMask = 2147483647;
370 | files = (
371 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
372 | );
373 | runOnlyForDeploymentPostprocessing = 0;
374 | };
375 | 97C146EA1CF9000F007C117D /* Sources */ = {
376 | isa = PBXSourcesBuildPhase;
377 | buildActionMask = 2147483647;
378 | files = (
379 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
380 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
381 | );
382 | runOnlyForDeploymentPostprocessing = 0;
383 | };
384 | /* End PBXSourcesBuildPhase section */
385 |
386 | /* Begin PBXTargetDependency section */
387 | 331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
388 | isa = PBXTargetDependency;
389 | target = 97C146ED1CF9000F007C117D /* Runner */;
390 | targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
391 | };
392 | /* End PBXTargetDependency section */
393 |
394 | /* Begin PBXVariantGroup section */
395 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
396 | isa = PBXVariantGroup;
397 | children = (
398 | 97C146FB1CF9000F007C117D /* Base */,
399 | );
400 | name = Main.storyboard;
401 | sourceTree = "";
402 | };
403 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
404 | isa = PBXVariantGroup;
405 | children = (
406 | 97C147001CF9000F007C117D /* Base */,
407 | );
408 | name = LaunchScreen.storyboard;
409 | sourceTree = "";
410 | };
411 | /* End PBXVariantGroup section */
412 |
413 | /* Begin XCBuildConfiguration section */
414 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
415 | isa = XCBuildConfiguration;
416 | buildSettings = {
417 | ALWAYS_SEARCH_USER_PATHS = NO;
418 | CLANG_ANALYZER_NONNULL = YES;
419 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
420 | CLANG_CXX_LIBRARY = "libc++";
421 | CLANG_ENABLE_MODULES = YES;
422 | CLANG_ENABLE_OBJC_ARC = YES;
423 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
424 | CLANG_WARN_BOOL_CONVERSION = YES;
425 | CLANG_WARN_COMMA = YES;
426 | CLANG_WARN_CONSTANT_CONVERSION = YES;
427 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
428 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
429 | CLANG_WARN_EMPTY_BODY = YES;
430 | CLANG_WARN_ENUM_CONVERSION = YES;
431 | CLANG_WARN_INFINITE_RECURSION = YES;
432 | CLANG_WARN_INT_CONVERSION = YES;
433 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
434 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
435 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
436 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
437 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
438 | CLANG_WARN_STRICT_PROTOTYPES = YES;
439 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
440 | CLANG_WARN_UNREACHABLE_CODE = YES;
441 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
442 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
443 | COPY_PHASE_STRIP = NO;
444 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
445 | ENABLE_NS_ASSERTIONS = NO;
446 | ENABLE_STRICT_OBJC_MSGSEND = YES;
447 | GCC_C_LANGUAGE_STANDARD = gnu99;
448 | GCC_NO_COMMON_BLOCKS = YES;
449 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
450 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
451 | GCC_WARN_UNDECLARED_SELECTOR = YES;
452 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
453 | GCC_WARN_UNUSED_FUNCTION = YES;
454 | GCC_WARN_UNUSED_VARIABLE = YES;
455 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
456 | MTL_ENABLE_DEBUG_INFO = NO;
457 | SDKROOT = iphoneos;
458 | SUPPORTED_PLATFORMS = iphoneos;
459 | TARGETED_DEVICE_FAMILY = "1,2";
460 | VALIDATE_PRODUCT = YES;
461 | };
462 | name = Profile;
463 | };
464 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
465 | isa = XCBuildConfiguration;
466 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
467 | buildSettings = {
468 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
469 | CLANG_ENABLE_MODULES = YES;
470 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
471 | ENABLE_BITCODE = NO;
472 | INFOPLIST_FILE = Runner/Info.plist;
473 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
474 | LD_RUNPATH_SEARCH_PATHS = (
475 | "$(inherited)",
476 | "@executable_path/Frameworks",
477 | );
478 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
479 | PRODUCT_NAME = "$(TARGET_NAME)";
480 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
481 | SWIFT_VERSION = 5.0;
482 | VERSIONING_SYSTEM = "apple-generic";
483 | };
484 | name = Profile;
485 | };
486 | 331C8088294A63A400263BE5 /* Debug */ = {
487 | isa = XCBuildConfiguration;
488 | baseConfigurationReference = A029B89B6D3A3D8C66220CFC /* Pods-RunnerTests.debug.xcconfig */;
489 | buildSettings = {
490 | BUNDLE_LOADER = "$(TEST_HOST)";
491 | CODE_SIGN_STYLE = Automatic;
492 | CURRENT_PROJECT_VERSION = 1;
493 | GENERATE_INFOPLIST_FILE = YES;
494 | MARKETING_VERSION = 1.0;
495 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
496 | PRODUCT_NAME = "$(TARGET_NAME)";
497 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
498 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
499 | SWIFT_VERSION = 5.0;
500 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
501 | };
502 | name = Debug;
503 | };
504 | 331C8089294A63A400263BE5 /* Release */ = {
505 | isa = XCBuildConfiguration;
506 | baseConfigurationReference = 4C86D9E5688B3273EB596676 /* Pods-RunnerTests.release.xcconfig */;
507 | buildSettings = {
508 | BUNDLE_LOADER = "$(TEST_HOST)";
509 | CODE_SIGN_STYLE = Automatic;
510 | CURRENT_PROJECT_VERSION = 1;
511 | GENERATE_INFOPLIST_FILE = YES;
512 | MARKETING_VERSION = 1.0;
513 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
514 | PRODUCT_NAME = "$(TARGET_NAME)";
515 | SWIFT_VERSION = 5.0;
516 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
517 | };
518 | name = Release;
519 | };
520 | 331C808A294A63A400263BE5 /* Profile */ = {
521 | isa = XCBuildConfiguration;
522 | baseConfigurationReference = F9F67F142F6C554E58A265B5 /* Pods-RunnerTests.profile.xcconfig */;
523 | buildSettings = {
524 | BUNDLE_LOADER = "$(TEST_HOST)";
525 | CODE_SIGN_STYLE = Automatic;
526 | CURRENT_PROJECT_VERSION = 1;
527 | GENERATE_INFOPLIST_FILE = YES;
528 | MARKETING_VERSION = 1.0;
529 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
530 | PRODUCT_NAME = "$(TARGET_NAME)";
531 | SWIFT_VERSION = 5.0;
532 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
533 | };
534 | name = Profile;
535 | };
536 | 97C147031CF9000F007C117D /* Debug */ = {
537 | isa = XCBuildConfiguration;
538 | buildSettings = {
539 | ALWAYS_SEARCH_USER_PATHS = NO;
540 | CLANG_ANALYZER_NONNULL = YES;
541 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
542 | CLANG_CXX_LIBRARY = "libc++";
543 | CLANG_ENABLE_MODULES = YES;
544 | CLANG_ENABLE_OBJC_ARC = YES;
545 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
546 | CLANG_WARN_BOOL_CONVERSION = YES;
547 | CLANG_WARN_COMMA = YES;
548 | CLANG_WARN_CONSTANT_CONVERSION = YES;
549 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
550 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
551 | CLANG_WARN_EMPTY_BODY = YES;
552 | CLANG_WARN_ENUM_CONVERSION = YES;
553 | CLANG_WARN_INFINITE_RECURSION = YES;
554 | CLANG_WARN_INT_CONVERSION = YES;
555 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
556 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
557 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
558 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
559 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
560 | CLANG_WARN_STRICT_PROTOTYPES = YES;
561 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
562 | CLANG_WARN_UNREACHABLE_CODE = YES;
563 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
564 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
565 | COPY_PHASE_STRIP = NO;
566 | DEBUG_INFORMATION_FORMAT = dwarf;
567 | ENABLE_STRICT_OBJC_MSGSEND = YES;
568 | ENABLE_TESTABILITY = YES;
569 | GCC_C_LANGUAGE_STANDARD = gnu99;
570 | GCC_DYNAMIC_NO_PIC = NO;
571 | GCC_NO_COMMON_BLOCKS = YES;
572 | GCC_OPTIMIZATION_LEVEL = 0;
573 | GCC_PREPROCESSOR_DEFINITIONS = (
574 | "DEBUG=1",
575 | "$(inherited)",
576 | );
577 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
578 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
579 | GCC_WARN_UNDECLARED_SELECTOR = YES;
580 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
581 | GCC_WARN_UNUSED_FUNCTION = YES;
582 | GCC_WARN_UNUSED_VARIABLE = YES;
583 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
584 | MTL_ENABLE_DEBUG_INFO = YES;
585 | ONLY_ACTIVE_ARCH = YES;
586 | SDKROOT = iphoneos;
587 | TARGETED_DEVICE_FAMILY = "1,2";
588 | };
589 | name = Debug;
590 | };
591 | 97C147041CF9000F007C117D /* Release */ = {
592 | isa = XCBuildConfiguration;
593 | buildSettings = {
594 | ALWAYS_SEARCH_USER_PATHS = NO;
595 | CLANG_ANALYZER_NONNULL = YES;
596 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
597 | CLANG_CXX_LIBRARY = "libc++";
598 | CLANG_ENABLE_MODULES = YES;
599 | CLANG_ENABLE_OBJC_ARC = YES;
600 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
601 | CLANG_WARN_BOOL_CONVERSION = YES;
602 | CLANG_WARN_COMMA = YES;
603 | CLANG_WARN_CONSTANT_CONVERSION = YES;
604 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
605 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
606 | CLANG_WARN_EMPTY_BODY = YES;
607 | CLANG_WARN_ENUM_CONVERSION = YES;
608 | CLANG_WARN_INFINITE_RECURSION = YES;
609 | CLANG_WARN_INT_CONVERSION = YES;
610 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
611 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
612 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
613 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
614 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
615 | CLANG_WARN_STRICT_PROTOTYPES = YES;
616 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
617 | CLANG_WARN_UNREACHABLE_CODE = YES;
618 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
619 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
620 | COPY_PHASE_STRIP = NO;
621 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
622 | ENABLE_NS_ASSERTIONS = NO;
623 | ENABLE_STRICT_OBJC_MSGSEND = YES;
624 | GCC_C_LANGUAGE_STANDARD = gnu99;
625 | GCC_NO_COMMON_BLOCKS = YES;
626 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
627 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
628 | GCC_WARN_UNDECLARED_SELECTOR = YES;
629 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
630 | GCC_WARN_UNUSED_FUNCTION = YES;
631 | GCC_WARN_UNUSED_VARIABLE = YES;
632 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
633 | MTL_ENABLE_DEBUG_INFO = NO;
634 | SDKROOT = iphoneos;
635 | SUPPORTED_PLATFORMS = iphoneos;
636 | SWIFT_COMPILATION_MODE = wholemodule;
637 | SWIFT_OPTIMIZATION_LEVEL = "-O";
638 | TARGETED_DEVICE_FAMILY = "1,2";
639 | VALIDATE_PRODUCT = YES;
640 | };
641 | name = Release;
642 | };
643 | 97C147061CF9000F007C117D /* Debug */ = {
644 | isa = XCBuildConfiguration;
645 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
646 | buildSettings = {
647 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
648 | CLANG_ENABLE_MODULES = YES;
649 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
650 | ENABLE_BITCODE = NO;
651 | INFOPLIST_FILE = Runner/Info.plist;
652 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
653 | LD_RUNPATH_SEARCH_PATHS = (
654 | "$(inherited)",
655 | "@executable_path/Frameworks",
656 | );
657 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
658 | PRODUCT_NAME = "$(TARGET_NAME)";
659 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
660 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
661 | SWIFT_VERSION = 5.0;
662 | VERSIONING_SYSTEM = "apple-generic";
663 | };
664 | name = Debug;
665 | };
666 | 97C147071CF9000F007C117D /* Release */ = {
667 | isa = XCBuildConfiguration;
668 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
669 | buildSettings = {
670 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
671 | CLANG_ENABLE_MODULES = YES;
672 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
673 | ENABLE_BITCODE = NO;
674 | INFOPLIST_FILE = Runner/Info.plist;
675 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
676 | LD_RUNPATH_SEARCH_PATHS = (
677 | "$(inherited)",
678 | "@executable_path/Frameworks",
679 | );
680 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
681 | PRODUCT_NAME = "$(TARGET_NAME)";
682 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
683 | SWIFT_VERSION = 5.0;
684 | VERSIONING_SYSTEM = "apple-generic";
685 | };
686 | name = Release;
687 | };
688 | /* End XCBuildConfiguration section */
689 |
690 | /* Begin XCConfigurationList section */
691 | 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
692 | isa = XCConfigurationList;
693 | buildConfigurations = (
694 | 331C8088294A63A400263BE5 /* Debug */,
695 | 331C8089294A63A400263BE5 /* Release */,
696 | 331C808A294A63A400263BE5 /* Profile */,
697 | );
698 | defaultConfigurationIsVisible = 0;
699 | defaultConfigurationName = Release;
700 | };
701 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
702 | isa = XCConfigurationList;
703 | buildConfigurations = (
704 | 97C147031CF9000F007C117D /* Debug */,
705 | 97C147041CF9000F007C117D /* Release */,
706 | 249021D3217E4FDB00AE95B9 /* Profile */,
707 | );
708 | defaultConfigurationIsVisible = 0;
709 | defaultConfigurationName = Release;
710 | };
711 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
712 | isa = XCConfigurationList;
713 | buildConfigurations = (
714 | 97C147061CF9000F007C117D /* Debug */,
715 | 97C147071CF9000F007C117D /* Release */,
716 | 249021D4217E4FDB00AE95B9 /* Profile */,
717 | );
718 | defaultConfigurationIsVisible = 0;
719 | defaultConfigurationName = Release;
720 | };
721 | /* End XCConfigurationList section */
722 | };
723 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
724 | }
725 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/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 |
--------------------------------------------------------------------------------
/example/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/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.
--------------------------------------------------------------------------------
/example/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 |
--------------------------------------------------------------------------------
/example/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Example
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | example
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 | NSBonjourServices
49 |
50 | _googlecast._tcp
51 | _YOUR_APP_ID._googlecast._tcp
52 |
53 |
54 | NSLocalNetworkUsageDescription
55 | ${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi
56 | network.
57 |
58 |
59 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:cast/cast.dart';
3 |
4 | void main() {
5 | runApp(MyApp());
6 | }
7 |
8 | class MyApp extends StatelessWidget {
9 | @override
10 | Widget build(BuildContext context) {
11 | return MaterialApp(
12 | title: 'Cast Demo',
13 | theme: ThemeData(
14 | primarySwatch: Colors.blue,
15 | visualDensity: VisualDensity.adaptivePlatformDensity,
16 | ),
17 | home: Scaffold(
18 | appBar: AppBar(),
19 | body: MyHomePage(),
20 | ),
21 | );
22 | }
23 | }
24 |
25 | class MyHomePage extends StatefulWidget {
26 | @override
27 | _MyHomePageState createState() => _MyHomePageState();
28 | }
29 |
30 | class _MyHomePageState extends State {
31 | Future>? _future;
32 |
33 | @override
34 | void initState() {
35 | super.initState();
36 | _startSearch();
37 | }
38 |
39 | @override
40 | Widget build(BuildContext context) {
41 | return FutureBuilder>(
42 | future: _future,
43 | builder: (context, snapshot) {
44 | if (snapshot.hasError) {
45 | return Center(
46 | child: Text(
47 | 'Error: ${snapshot.error.toString()}',
48 | ),
49 | );
50 | } else if (!snapshot.hasData) {
51 | return Center(
52 | child: CircularProgressIndicator(),
53 | );
54 | }
55 |
56 | if (snapshot.data!.isEmpty) {
57 | return Column(
58 | children: [
59 | Center(
60 | child: Text(
61 | 'No Chromecast founded',
62 | ),
63 | ),
64 | ],
65 | );
66 | }
67 |
68 | return Column(
69 | children: snapshot.data!.map((device) {
70 | return ListTile(
71 | title: Text(device.name),
72 | onTap: () {
73 | // _connectToYourApp(context, device);
74 | _connectAndPlayMedia(context, device);
75 | },
76 | );
77 | }).toList(),
78 | );
79 | },
80 | );
81 | }
82 |
83 | void _startSearch() {
84 | _future = CastDiscoveryService().search();
85 | }
86 |
87 | Future _connectToYourApp(BuildContext context, CastDevice object) async {
88 | final session = await CastSessionManager().startSession(object);
89 |
90 | session.stateStream.listen((state) {
91 | if (state == CastSessionState.connected) {
92 | final snackBar = SnackBar(content: Text('Connected'));
93 | ScaffoldMessenger.of(context).showSnackBar(snackBar);
94 |
95 | _sendMessageToYourApp(session);
96 | }
97 | });
98 |
99 | session.messageStream.listen((message) {
100 | print('receive message: $message');
101 | });
102 |
103 | session.sendMessage(CastSession.kNamespaceReceiver, {
104 | 'type': 'LAUNCH',
105 | 'appId': 'Youtube', // set the appId of your app here
106 | });
107 | }
108 |
109 | void _sendMessageToYourApp(CastSession session) {
110 | print('_sendMessageToYourApp');
111 |
112 | session.sendMessage('urn:x-cast:namespace-of-the-app', {
113 | 'type': 'sample',
114 | });
115 | }
116 |
117 | Future _connectAndPlayMedia(BuildContext context, CastDevice object) async {
118 | final session = await CastSessionManager().startSession(object);
119 |
120 | session.stateStream.listen((state) {
121 | if (state == CastSessionState.connected) {
122 | final snackBar = SnackBar(content: Text('Connected'));
123 | ScaffoldMessenger.of(context).showSnackBar(snackBar);
124 | }
125 | });
126 |
127 | var index = 0;
128 |
129 | session.messageStream.listen((message) {
130 | index += 1;
131 |
132 | print('receive message: $message');
133 |
134 | if (index == 2) {
135 | Future.delayed(Duration(seconds: 5)).then((x) {
136 | _sendMessagePlayVideo(session);
137 | });
138 | }
139 | });
140 |
141 | session.sendMessage(CastSession.kNamespaceReceiver, {
142 | 'type': 'LAUNCH',
143 | 'appId': 'CC1AD845', // set the appId of your app here
144 | });
145 | }
146 |
147 | void _sendMessagePlayVideo(CastSession session) {
148 | print('_sendMessagePlayVideo');
149 |
150 | var message = {
151 | // Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
152 | 'contentId': 'http://commondatastorage.googleapis.com/gtv-videos-bucket/big_buck_bunny_1080p.mp4',
153 | 'contentType': 'video/mp4',
154 | 'streamType': 'BUFFERED', // or LIVE
155 |
156 | // Title and cover displayed while buffering
157 | 'metadata': {
158 | 'type': 0,
159 | 'metadataType': 0,
160 | 'title': "Big Buck Bunny",
161 | 'images': [
162 | {'url': 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg'}
163 | ]
164 | }
165 | };
166 |
167 | session.sendMessage(CastSession.kNamespaceMedia, {
168 | 'type': 'LOAD',
169 | 'autoPlay': true,
170 | 'currentTime': 0,
171 | 'media': message,
172 | });
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/example/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/dgph
7 | **/xcuserdata/
8 |
--------------------------------------------------------------------------------
/example/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 | import bonsoir_darwin
9 | import connectivity_plus
10 |
11 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
12 | SwiftBonsoirPlugin.register(with: registry.registrar(forPlugin: "SwiftBonsoirPlugin"))
13 | ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
14 | }
15 |
--------------------------------------------------------------------------------
/example/macos/Podfile:
--------------------------------------------------------------------------------
1 | platform :osx, '10.15'
2 |
3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
5 |
6 | project 'Runner', {
7 | 'Debug' => :debug,
8 | 'Profile' => :release,
9 | 'Release' => :release,
10 | }
11 |
12 | def flutter_root
13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
14 | unless File.exist?(generated_xcode_build_settings_path)
15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
16 | end
17 |
18 | File.foreach(generated_xcode_build_settings_path) do |line|
19 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
20 | return matches[1].strip if matches
21 | end
22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
23 | end
24 |
25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
26 |
27 | flutter_macos_podfile_setup
28 |
29 | target 'Runner' do
30 | use_frameworks!
31 | use_modular_headers!
32 |
33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
34 | target 'RunnerTests' do
35 | inherit! :search_paths
36 | end
37 | end
38 |
39 | post_install do |installer|
40 | installer.pods_project.targets.each do |target|
41 | flutter_additional_macos_build_settings(target)
42 | target.build_configurations.each do |config|
43 | config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '10.15'
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/example/macos/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - bonsoir_darwin (3.0.0):
3 | - Flutter
4 | - FlutterMacOS
5 | - connectivity_plus (0.0.1):
6 | - FlutterMacOS
7 | - ReachabilitySwift
8 | - FlutterMacOS (1.0.0)
9 | - ReachabilitySwift (5.0.0)
10 |
11 | DEPENDENCIES:
12 | - bonsoir_darwin (from `Flutter/ephemeral/.symlinks/plugins/bonsoir_darwin/darwin`)
13 | - connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
14 | - FlutterMacOS (from `Flutter/ephemeral`)
15 |
16 | SPEC REPOS:
17 | trunk:
18 | - ReachabilitySwift
19 |
20 | EXTERNAL SOURCES:
21 | bonsoir_darwin:
22 | :path: Flutter/ephemeral/.symlinks/plugins/bonsoir_darwin/darwin
23 | connectivity_plus:
24 | :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
25 | FlutterMacOS:
26 | :path: Flutter/ephemeral
27 |
28 | SPEC CHECKSUMS:
29 | bonsoir_darwin: 127bdc632fdc154ae2f277a4d5c86a6212bc75be
30 | connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
31 | FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
32 | ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
33 |
34 | PODFILE CHECKSUM: 4062a5d7621e35b4f677b9e411c2714a4f99d4c2
35 |
36 | COCOAPODS: 1.13.0
37 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @NSApplicationMain
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "app_icon_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "app_icon_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "app_icon_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "app_icon_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "app_icon_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "app_icon_256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "app_icon_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "app_icon_512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "app_icon_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "app_icon_1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/flutter_cast/69aa2fffcbcfc91bff15fab55b14502f9dbaf94c/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
--------------------------------------------------------------------------------
/example/macos/Runner/Base.lproj/MainMenu.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/AppInfo.xcconfig:
--------------------------------------------------------------------------------
1 | // Application-level settings for the Runner target.
2 | //
3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
4 | // future. If not, the values below would default to using the project name when this becomes a
5 | // 'flutter create' template.
6 |
7 | // The application's name. By default this is also the title of the Flutter window.
8 | PRODUCT_NAME = example
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2023 com.example. All rights reserved.
15 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Warnings.xcconfig:
--------------------------------------------------------------------------------
1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
2 | GCC_WARN_UNDECLARED_SELECTOR = YES
3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
6 | CLANG_WARN_PRAGMA_PACK = YES
7 | CLANG_WARN_STRICT_PROTOTYPES = YES
8 | CLANG_WARN_COMMA = YES
9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES
10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
12 | GCC_WARN_SHADOW = YES
13 | CLANG_WARN_UNREACHABLE_CODE = YES
14 |
--------------------------------------------------------------------------------
/example/macos/Runner/DebugProfile.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 | com.apple.security.network.client
10 |
11 | com.apple.security.network.server
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | $(PRODUCT_COPYRIGHT)
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 | NSBonjourServices
32 |
33 | _googlecast._tcp
34 | _YOUR_APP_ID._googlecast._tcp
35 |
36 |
37 | NSLocalNetworkUsageDescription
38 | ${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi
39 | network.
40 |
41 |
42 |
--------------------------------------------------------------------------------
/example/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController()
7 | let windowFrame = self.frame
8 | self.contentViewController = flutterViewController
9 | self.setFrame(windowFrame, display: true)
10 |
11 | RegisterGeneratedPlugins(registry: flutterViewController)
12 |
13 | super.awakeFromNib()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 | com.apple.security.network.server
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/macos/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import FlutterMacOS
2 | import Cocoa
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: cast_example
2 | description: Example projet for cast
3 | version: 1.0.0+1
4 |
5 | environment:
6 | sdk: '>=3.1.3 <4.0.0'
7 |
8 | dependencies:
9 | flutter:
10 | sdk: flutter
11 | cast:
12 | path: ../
13 |
14 | dev_dependencies:
15 | flutter_test:
16 | sdk: flutter
17 |
18 | flutter:
19 | uses-material-design: true
20 |
--------------------------------------------------------------------------------
/lib/cast.dart:
--------------------------------------------------------------------------------
1 | library cast;
2 |
3 | export 'device.dart';
4 | export 'discovery_service.dart';
5 | export 'session.dart';
6 | export 'session_manager.dart';
7 | export 'socket.dart';
8 |
--------------------------------------------------------------------------------
/lib/cast_channel/cast_channel.idl:
--------------------------------------------------------------------------------
1 | // Source https://github.com/chromium/chromium/blob/master/extensions/common/api/cast_channel.idl
2 | // Should be use to generate cast_channel.dart
3 |
4 | // Copyright 2014 The Chromium Authors. All rights reserved.
5 | // Use of this source code is governed by a BSD-style license that can be
6 | // found in the LICENSE file.
7 |
8 | // API for communicating with a Google Cast device over an authenticated
9 | // channel.
10 | namespace cast.channel {
11 | // The state of the channel.
12 | enum ReadyState {
13 | // The channel is connecting.
14 | connecting,
15 | // The channel is open and available for messaging.
16 | open,
17 | // The channel is closing.
18 | closing,
19 | // The channel is closed.
20 | closed
21 | };
22 |
23 | // Error conditions that the channel may encounter. All error conditions
24 | // are terminal. When an error condition is encountered the API will:
25 | // (1) Transition the channel to readyState == 'closed'.
26 | // (2) Set ChannelInfo.lastError to the error condition.
27 | // (3) Fire an onError event with the error condition.
28 | // (4) Fire an onClose event.
29 | enum ChannelError {
30 | // cast.channel.send() was called when ChannelInfo.readyState != 'open'.
31 | channel_not_open,
32 | // Authentication was requested and the receiver could not be
33 | // authenticated (invalid signature, invalid handhake, TLS error, etc.)
34 | authentication_error,
35 | // A new channel could not be created for reasons unrelated to
36 | // authentication (e.g., there is already an open channel to the same URL).
37 | connect_error,
38 | // There was an error writing or reading from the underlying socket.
39 | socket_error,
40 | // A transport level occurred (like an unparseable message).
41 | transport_error,
42 | // The client attempted to send an unsupported message type through the
43 | // channel.
44 | invalid_message,
45 | // An invalid channel id was passed.
46 | invalid_channel_id,
47 | // The connection could not be established before timing out.
48 | connect_timeout,
49 | // The receiving end became unresponsive.
50 | ping_timeout,
51 | // Unspecified error.
52 | unknown
53 | };
54 |
55 | // Authentication methods that may be required to connect to a Cast receiver.
56 | enum ChannelAuthType {
57 | // SSL over TCP with challenge and receiver signature verification.
58 | ssl_verified
59 | };
60 |
61 | // Describes the information needed to connect to a Cast receiver.
62 | // This replaces the prior use of cast:// and casts:// URLs.
63 | dictionary ConnectInfo {
64 | // The IPV4 address of the Cast receiver, e.g. '198.1.0.2'.
65 | // TODO(mfoltz): Investigate whether IPV6 addresses "just work."
66 | DOMString ipAddress;
67 |
68 | // The port number to connect to, 0-65535.
69 | long port;
70 |
71 | // The amount of time to wait in milliseconds before stopping the
72 | // connection process. Timeouts are disabled if the value is zero.
73 | // The default timeout is 8000ms.
74 | long? timeout;
75 |
76 | // The authentication method required for the channel.
77 | ChannelAuthType auth;
78 |
79 | // ------------------------------------------------------------------------
80 | // Both pingInterval and livenessTimeout must be set to enable keep-alive
81 | // handling.
82 |
83 | // The amount of time to wait in milliseconds before sending pings
84 | // to idle channels.
85 | long? pingInterval;
86 |
87 | // The maximum amount of idle time allowed before a channel is closed.
88 | long? livenessTimeout;
89 |
90 | // If set, CastDeviceCapability bitmask values describing capability of the
91 | // cast device.
92 | long? capabilities;
93 | };
94 |
95 | // Describes the state of a channel to a Cast receiver.
96 | dictionary ChannelInfo {
97 | // Id for the channel.
98 | long channelId;
99 |
100 | // Connection information that was used to establish the channel to the
101 | // receiver.
102 | ConnectInfo connectInfo;
103 |
104 | // The current state of the channel.
105 | ReadyState readyState;
106 |
107 | // If set, the last error condition encountered by the channel.
108 | ChannelError? errorState;
109 |
110 | // If true, keep-alive messages are handled automatically by the channel.
111 | boolean keepAlive;
112 |
113 | // Whether the channel is audio only as identified by the device
114 | // certificate during channel authentication.
115 | boolean audioOnly;
116 | };
117 |
118 | // Describes a message sent or received over the channel. Currently only
119 | // string messages are supported, although ArrayBuffer and Blob types may be
120 | // supported in the future.
121 | dictionary MessageInfo {
122 | // The message namespace. A namespace is a URN of the form
123 | // urn:cast-x: that is used to interpret and route Cast messages.
124 | DOMString namespace_;
125 |
126 | // source and destination ids identify the origin and destination of the
127 | // message. They are used to route messages between endpoints that share a
128 | // device-to-device channel.
129 | //
130 | // For messages between applications:
131 | // - The sender application id is a unique identifier generated on behalf
132 | // of the sender application.
133 | // - The receiver id is always the the session id for the application.
134 | //
135 | // For messages to or from the sender or receiver platform, the special ids
136 | // 'sender-0' and 'receiver-0' can be used.
137 | //
138 | // For messages intended for all endpoints using a given channel, the
139 | // wildcard destination_id '*' can be used.
140 | DOMString sourceId;
141 | DOMString destinationId;
142 |
143 | // The content of the message. Must be either a string or an ArrayBuffer.
144 | any data;
145 | };
146 |
147 | // Describes a terminal error encountered by the channel with details of the
148 | // error that caused the channel to be closed. One or more of the optional
149 | // fields may be set with specific error codes from the underlying
150 | // implementation.
151 | dictionary ErrorInfo {
152 | // The type of error encountered by the channel.
153 | ChannelError errorState;
154 |
155 | // The event that was occurring when the error happened. Values are defined
156 | // in the enum EventType in logging.proto.
157 | long? eventType;
158 |
159 | // An error encountered when processing the authentication handshake.
160 | // Values are defined in the enum ChallengeReplyErrorType in logging.proto.
161 | long? challengeReplyErrorType;
162 |
163 | // A return value from the underlying net:: socket libraries. Values are
164 | // defined in net/base/net_error_list.h.
165 | long? netReturnValue;
166 |
167 | // An error code returned by NSS. Values are defined in secerr.h.
168 | long? nssErrorCode;
169 | };
170 |
171 | // Callback holding the result of a channel operation.
172 | callback ChannelInfoCallback = void (ChannelInfo result);
173 |
174 | interface Functions {
175 | // Opens a new channel to the Cast receiver specified by connectInfo. Only
176 | // one channel may be connected to same receiver from the same extension at
177 | // a time. If the open request is successful, the callback will be invoked
178 | // with a ChannelInfo with readyState == 'connecting'. If unsuccessful, the
179 | // callback will be invoked with a ChannelInfo with channel.readyState ==
180 | // 'closed', channel.errorState will be set to the error condition, and
181 | // onError will be fired with error details.
182 | static void open(ConnectInfo connectInfo,
183 | ChannelInfoCallback callback);
184 |
185 | // Sends a message on the channel and invokes callback with the resulting
186 | // channel status. The channel must be in readyState == 'open'. If
187 | // unsuccessful, channel.readyState will be set to 'closed',
188 | // channel.errorState will be set to the error condition, and onError will
189 | // be fired with error details.
190 | static void send(ChannelInfo channel,
191 | MessageInfo message,
192 | ChannelInfoCallback callback);
193 |
194 | // Requests that the channel be closed and invokes callback with the
195 | // resulting channel status. The channel must be in readyState == 'open' or
196 | // 'connecting'. If successful, onClose will be fired with readyState ==
197 | // 'closed'. If unsuccessful, channel.readyState will be set to 'closed',
198 | // and channel.errorState will be set to the error condition.
199 | static void close(ChannelInfo channel,
200 | ChannelInfoCallback callback);
201 | };
202 |
203 | // Events on the channel.
204 | interface Events {
205 | // Fired when a message is received on an open channel.
206 | static void onMessage(ChannelInfo channel,
207 | MessageInfo message);
208 |
209 | // Fired when an error occurs as a result of a channel operation or a
210 | // network event. |error| contains details of the error.
211 | static void onError(ChannelInfo channel, ErrorInfo error);
212 | };
213 | };
--------------------------------------------------------------------------------
/lib/cast_channel/cast_channel.pb.dart:
--------------------------------------------------------------------------------
1 | ///
2 | // Generated code. Do not modify.
3 | // source: cast_channel.proto
4 | //
5 | // @dart = 2.12
6 | // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
7 |
8 | import 'dart:core' as $core;
9 |
10 | import 'package:protobuf/protobuf.dart' as $pb;
11 |
12 | import 'cast_channel.pbenum.dart';
13 |
14 | export 'cast_channel.pbenum.dart';
15 |
16 | class CastMessage extends $pb.GeneratedMessage {
17 | static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CastMessage', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extensions.api.cast_channel'), createEmptyInstance: create)
18 | ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'protocolVersion', $pb.PbFieldType.QE, defaultOrMaker: CastMessage_ProtocolVersion.CASTV2_1_0, valueOf: CastMessage_ProtocolVersion.valueOf, enumValues: CastMessage_ProtocolVersion.values)
19 | ..aQS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'sourceId')
20 | ..aQS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'destinationId')
21 | ..aQS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'namespace')
22 | ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'payloadType', $pb.PbFieldType.QE, defaultOrMaker: CastMessage_PayloadType.STRING, valueOf: CastMessage_PayloadType.valueOf, enumValues: CastMessage_PayloadType.values)
23 | ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'payloadUtf8')
24 | ..a<$core.List<$core.int>>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'payloadBinary', $pb.PbFieldType.OY)
25 | ;
26 |
27 | CastMessage._() : super();
28 | factory CastMessage({
29 | CastMessage_ProtocolVersion? protocolVersion,
30 | $core.String? sourceId,
31 | $core.String? destinationId,
32 | $core.String? namespace,
33 | CastMessage_PayloadType? payloadType,
34 | $core.String? payloadUtf8,
35 | $core.List<$core.int>? payloadBinary,
36 | }) {
37 | final _result = create();
38 | if (protocolVersion != null) {
39 | _result.protocolVersion = protocolVersion;
40 | }
41 | if (sourceId != null) {
42 | _result.sourceId = sourceId;
43 | }
44 | if (destinationId != null) {
45 | _result.destinationId = destinationId;
46 | }
47 | if (namespace != null) {
48 | _result.namespace = namespace;
49 | }
50 | if (payloadType != null) {
51 | _result.payloadType = payloadType;
52 | }
53 | if (payloadUtf8 != null) {
54 | _result.payloadUtf8 = payloadUtf8;
55 | }
56 | if (payloadBinary != null) {
57 | _result.payloadBinary = payloadBinary;
58 | }
59 | return _result;
60 | }
61 | factory CastMessage.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
62 | factory CastMessage.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
63 | @$core.Deprecated(
64 | 'Using this can add significant overhead to your binary. '
65 | 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
66 | 'Will be removed in next major version')
67 | CastMessage clone() => CastMessage()..mergeFromMessage(this);
68 | @$core.Deprecated(
69 | 'Using this can add significant overhead to your binary. '
70 | 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
71 | 'Will be removed in next major version')
72 | CastMessage copyWith(void Function(CastMessage) updates) => super.copyWith((message) => updates(message as CastMessage)) as CastMessage; // ignore: deprecated_member_use
73 | $pb.BuilderInfo get info_ => _i;
74 | @$core.pragma('dart2js:noInline')
75 | static CastMessage create() => CastMessage._();
76 | CastMessage createEmptyInstance() => create();
77 | static $pb.PbList createRepeated() => $pb.PbList();
78 | @$core.pragma('dart2js:noInline')
79 | static CastMessage getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create);
80 | static CastMessage? _defaultInstance;
81 |
82 | @$pb.TagNumber(1)
83 | CastMessage_ProtocolVersion get protocolVersion => $_getN(0);
84 | @$pb.TagNumber(1)
85 | set protocolVersion(CastMessage_ProtocolVersion v) { setField(1, v); }
86 | @$pb.TagNumber(1)
87 | $core.bool hasProtocolVersion() => $_has(0);
88 | @$pb.TagNumber(1)
89 | void clearProtocolVersion() => clearField(1);
90 |
91 | @$pb.TagNumber(2)
92 | $core.String get sourceId => $_getSZ(1);
93 | @$pb.TagNumber(2)
94 | set sourceId($core.String v) { $_setString(1, v); }
95 | @$pb.TagNumber(2)
96 | $core.bool hasSourceId() => $_has(1);
97 | @$pb.TagNumber(2)
98 | void clearSourceId() => clearField(2);
99 |
100 | @$pb.TagNumber(3)
101 | $core.String get destinationId => $_getSZ(2);
102 | @$pb.TagNumber(3)
103 | set destinationId($core.String v) { $_setString(2, v); }
104 | @$pb.TagNumber(3)
105 | $core.bool hasDestinationId() => $_has(2);
106 | @$pb.TagNumber(3)
107 | void clearDestinationId() => clearField(3);
108 |
109 | @$pb.TagNumber(4)
110 | $core.String get namespace => $_getSZ(3);
111 | @$pb.TagNumber(4)
112 | set namespace($core.String v) { $_setString(3, v); }
113 | @$pb.TagNumber(4)
114 | $core.bool hasNamespace() => $_has(3);
115 | @$pb.TagNumber(4)
116 | void clearNamespace() => clearField(4);
117 |
118 | @$pb.TagNumber(5)
119 | CastMessage_PayloadType get payloadType => $_getN(4);
120 | @$pb.TagNumber(5)
121 | set payloadType(CastMessage_PayloadType v) { setField(5, v); }
122 | @$pb.TagNumber(5)
123 | $core.bool hasPayloadType() => $_has(4);
124 | @$pb.TagNumber(5)
125 | void clearPayloadType() => clearField(5);
126 |
127 | @$pb.TagNumber(6)
128 | $core.String get payloadUtf8 => $_getSZ(5);
129 | @$pb.TagNumber(6)
130 | set payloadUtf8($core.String v) { $_setString(5, v); }
131 | @$pb.TagNumber(6)
132 | $core.bool hasPayloadUtf8() => $_has(5);
133 | @$pb.TagNumber(6)
134 | void clearPayloadUtf8() => clearField(6);
135 |
136 | @$pb.TagNumber(7)
137 | $core.List<$core.int> get payloadBinary => $_getN(6);
138 | @$pb.TagNumber(7)
139 | set payloadBinary($core.List<$core.int> v) { $_setBytes(6, v); }
140 | @$pb.TagNumber(7)
141 | $core.bool hasPayloadBinary() => $_has(6);
142 | @$pb.TagNumber(7)
143 | void clearPayloadBinary() => clearField(7);
144 | }
145 |
146 | class AuthChallenge extends $pb.GeneratedMessage {
147 | static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AuthChallenge', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extensions.api.cast_channel'), createEmptyInstance: create)
148 | ..hasRequiredFields = false
149 | ;
150 |
151 | AuthChallenge._() : super();
152 | factory AuthChallenge() => create();
153 | factory AuthChallenge.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
154 | factory AuthChallenge.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
155 | @$core.Deprecated(
156 | 'Using this can add significant overhead to your binary. '
157 | 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
158 | 'Will be removed in next major version')
159 | AuthChallenge clone() => AuthChallenge()..mergeFromMessage(this);
160 | @$core.Deprecated(
161 | 'Using this can add significant overhead to your binary. '
162 | 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
163 | 'Will be removed in next major version')
164 | AuthChallenge copyWith(void Function(AuthChallenge) updates) => super.copyWith((message) => updates(message as AuthChallenge)) as AuthChallenge; // ignore: deprecated_member_use
165 | $pb.BuilderInfo get info_ => _i;
166 | @$core.pragma('dart2js:noInline')
167 | static AuthChallenge create() => AuthChallenge._();
168 | AuthChallenge createEmptyInstance() => create();
169 | static $pb.PbList createRepeated() => $pb.PbList();
170 | @$core.pragma('dart2js:noInline')
171 | static AuthChallenge getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create);
172 | static AuthChallenge? _defaultInstance;
173 | }
174 |
175 | class AuthResponse extends $pb.GeneratedMessage {
176 | static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AuthResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extensions.api.cast_channel'), createEmptyInstance: create)
177 | ..a<$core.List<$core.int>>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signature', $pb.PbFieldType.QY)
178 | ..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'clientAuthCertificate', $pb.PbFieldType.QY)
179 | ..p<$core.List<$core.int>>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'clientCa', $pb.PbFieldType.PY)
180 | ;
181 |
182 | AuthResponse._() : super();
183 | factory AuthResponse({
184 | $core.List<$core.int>? signature,
185 | $core.List<$core.int>? clientAuthCertificate,
186 | $core.Iterable<$core.List<$core.int>>? clientCa,
187 | }) {
188 | final _result = create();
189 | if (signature != null) {
190 | _result.signature = signature;
191 | }
192 | if (clientAuthCertificate != null) {
193 | _result.clientAuthCertificate = clientAuthCertificate;
194 | }
195 | if (clientCa != null) {
196 | _result.clientCa.addAll(clientCa);
197 | }
198 | return _result;
199 | }
200 | factory AuthResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
201 | factory AuthResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
202 | @$core.Deprecated(
203 | 'Using this can add significant overhead to your binary. '
204 | 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
205 | 'Will be removed in next major version')
206 | AuthResponse clone() => AuthResponse()..mergeFromMessage(this);
207 | @$core.Deprecated(
208 | 'Using this can add significant overhead to your binary. '
209 | 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
210 | 'Will be removed in next major version')
211 | AuthResponse copyWith(void Function(AuthResponse) updates) => super.copyWith((message) => updates(message as AuthResponse)) as AuthResponse; // ignore: deprecated_member_use
212 | $pb.BuilderInfo get info_ => _i;
213 | @$core.pragma('dart2js:noInline')
214 | static AuthResponse create() => AuthResponse._();
215 | AuthResponse createEmptyInstance() => create();
216 | static $pb.PbList createRepeated() => $pb.PbList();
217 | @$core.pragma('dart2js:noInline')
218 | static AuthResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create);
219 | static AuthResponse? _defaultInstance;
220 |
221 | @$pb.TagNumber(1)
222 | $core.List<$core.int> get signature => $_getN(0);
223 | @$pb.TagNumber(1)
224 | set signature($core.List<$core.int> v) { $_setBytes(0, v); }
225 | @$pb.TagNumber(1)
226 | $core.bool hasSignature() => $_has(0);
227 | @$pb.TagNumber(1)
228 | void clearSignature() => clearField(1);
229 |
230 | @$pb.TagNumber(2)
231 | $core.List<$core.int> get clientAuthCertificate => $_getN(1);
232 | @$pb.TagNumber(2)
233 | set clientAuthCertificate($core.List<$core.int> v) { $_setBytes(1, v); }
234 | @$pb.TagNumber(2)
235 | $core.bool hasClientAuthCertificate() => $_has(1);
236 | @$pb.TagNumber(2)
237 | void clearClientAuthCertificate() => clearField(2);
238 |
239 | @$pb.TagNumber(3)
240 | $core.List<$core.List<$core.int>> get clientCa => $_getList(2);
241 | }
242 |
243 | class AuthError extends $pb.GeneratedMessage {
244 | static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AuthError', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extensions.api.cast_channel'), createEmptyInstance: create)
245 | ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'errorType', $pb.PbFieldType.QE, defaultOrMaker: AuthError_ErrorType.INTERNAL_ERROR, valueOf: AuthError_ErrorType.valueOf, enumValues: AuthError_ErrorType.values)
246 | ;
247 |
248 | AuthError._() : super();
249 | factory AuthError({
250 | AuthError_ErrorType? errorType,
251 | }) {
252 | final _result = create();
253 | if (errorType != null) {
254 | _result.errorType = errorType;
255 | }
256 | return _result;
257 | }
258 | factory AuthError.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
259 | factory AuthError.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
260 | @$core.Deprecated(
261 | 'Using this can add significant overhead to your binary. '
262 | 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
263 | 'Will be removed in next major version')
264 | AuthError clone() => AuthError()..mergeFromMessage(this);
265 | @$core.Deprecated(
266 | 'Using this can add significant overhead to your binary. '
267 | 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
268 | 'Will be removed in next major version')
269 | AuthError copyWith(void Function(AuthError) updates) => super.copyWith((message) => updates(message as AuthError)) as AuthError; // ignore: deprecated_member_use
270 | $pb.BuilderInfo get info_ => _i;
271 | @$core.pragma('dart2js:noInline')
272 | static AuthError create() => AuthError._();
273 | AuthError createEmptyInstance() => create();
274 | static $pb.PbList createRepeated() => $pb.PbList();
275 | @$core.pragma('dart2js:noInline')
276 | static AuthError getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create);
277 | static AuthError? _defaultInstance;
278 |
279 | @$pb.TagNumber(1)
280 | AuthError_ErrorType get errorType => $_getN(0);
281 | @$pb.TagNumber(1)
282 | set errorType(AuthError_ErrorType v) { setField(1, v); }
283 | @$pb.TagNumber(1)
284 | $core.bool hasErrorType() => $_has(0);
285 | @$pb.TagNumber(1)
286 | void clearErrorType() => clearField(1);
287 | }
288 |
289 | class DeviceAuthMessage extends $pb.GeneratedMessage {
290 | static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeviceAuthMessage', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'extensions.api.cast_channel'), createEmptyInstance: create)
291 | ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'challenge', subBuilder: AuthChallenge.create)
292 | ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'response', subBuilder: AuthResponse.create)
293 | ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'error', subBuilder: AuthError.create)
294 | ;
295 |
296 | DeviceAuthMessage._() : super();
297 | factory DeviceAuthMessage({
298 | AuthChallenge? challenge,
299 | AuthResponse? response,
300 | AuthError? error,
301 | }) {
302 | final _result = create();
303 | if (challenge != null) {
304 | _result.challenge = challenge;
305 | }
306 | if (response != null) {
307 | _result.response = response;
308 | }
309 | if (error != null) {
310 | _result.error = error;
311 | }
312 | return _result;
313 | }
314 | factory DeviceAuthMessage.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
315 | factory DeviceAuthMessage.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
316 | @$core.Deprecated(
317 | 'Using this can add significant overhead to your binary. '
318 | 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
319 | 'Will be removed in next major version')
320 | DeviceAuthMessage clone() => DeviceAuthMessage()..mergeFromMessage(this);
321 | @$core.Deprecated(
322 | 'Using this can add significant overhead to your binary. '
323 | 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
324 | 'Will be removed in next major version')
325 | DeviceAuthMessage copyWith(void Function(DeviceAuthMessage) updates) => super.copyWith((message) => updates(message as DeviceAuthMessage)) as DeviceAuthMessage; // ignore: deprecated_member_use
326 | $pb.BuilderInfo get info_ => _i;
327 | @$core.pragma('dart2js:noInline')
328 | static DeviceAuthMessage create() => DeviceAuthMessage._();
329 | DeviceAuthMessage createEmptyInstance() => create();
330 | static $pb.PbList createRepeated() => $pb.PbList();
331 | @$core.pragma('dart2js:noInline')
332 | static DeviceAuthMessage getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create);
333 | static DeviceAuthMessage? _defaultInstance;
334 |
335 | @$pb.TagNumber(1)
336 | AuthChallenge get challenge => $_getN(0);
337 | @$pb.TagNumber(1)
338 | set challenge(AuthChallenge v) { setField(1, v); }
339 | @$pb.TagNumber(1)
340 | $core.bool hasChallenge() => $_has(0);
341 | @$pb.TagNumber(1)
342 | void clearChallenge() => clearField(1);
343 | @$pb.TagNumber(1)
344 | AuthChallenge ensureChallenge() => $_ensure(0);
345 |
346 | @$pb.TagNumber(2)
347 | AuthResponse get response => $_getN(1);
348 | @$pb.TagNumber(2)
349 | set response(AuthResponse v) { setField(2, v); }
350 | @$pb.TagNumber(2)
351 | $core.bool hasResponse() => $_has(1);
352 | @$pb.TagNumber(2)
353 | void clearResponse() => clearField(2);
354 | @$pb.TagNumber(2)
355 | AuthResponse ensureResponse() => $_ensure(1);
356 |
357 | @$pb.TagNumber(3)
358 | AuthError get error => $_getN(2);
359 | @$pb.TagNumber(3)
360 | set error(AuthError v) { setField(3, v); }
361 | @$pb.TagNumber(3)
362 | $core.bool hasError() => $_has(2);
363 | @$pb.TagNumber(3)
364 | void clearError() => clearField(3);
365 | @$pb.TagNumber(3)
366 | AuthError ensureError() => $_ensure(2);
367 | }
368 |
369 |
--------------------------------------------------------------------------------
/lib/cast_channel/cast_channel.pbenum.dart:
--------------------------------------------------------------------------------
1 | ///
2 | // Generated code. Do not modify.
3 | // source: cast_channel.proto
4 | //
5 | // @dart = 2.12
6 | // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
7 |
8 | // ignore_for_file: UNDEFINED_SHOWN_NAME
9 | import 'dart:core' as $core;
10 | import 'package:protobuf/protobuf.dart' as $pb;
11 |
12 | class CastMessage_ProtocolVersion extends $pb.ProtobufEnum {
13 | static const CastMessage_ProtocolVersion CASTV2_1_0 = CastMessage_ProtocolVersion._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CASTV2_1_0');
14 |
15 | static const $core.List values = [
16 | CASTV2_1_0,
17 | ];
18 |
19 | static final $core.Map<$core.int, CastMessage_ProtocolVersion> _byValue = $pb.ProtobufEnum.initByValue(values);
20 | static CastMessage_ProtocolVersion? valueOf($core.int value) => _byValue[value];
21 |
22 | const CastMessage_ProtocolVersion._($core.int v, $core.String n) : super(v, n);
23 | }
24 |
25 | class CastMessage_PayloadType extends $pb.ProtobufEnum {
26 | static const CastMessage_PayloadType STRING = CastMessage_PayloadType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'STRING');
27 | static const CastMessage_PayloadType BINARY = CastMessage_PayloadType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BINARY');
28 |
29 | static const $core.List values = [
30 | STRING,
31 | BINARY,
32 | ];
33 |
34 | static final $core.Map<$core.int, CastMessage_PayloadType> _byValue = $pb.ProtobufEnum.initByValue(values);
35 | static CastMessage_PayloadType? valueOf($core.int value) => _byValue[value];
36 |
37 | const CastMessage_PayloadType._($core.int v, $core.String n) : super(v, n);
38 | }
39 |
40 | class AuthError_ErrorType extends $pb.ProtobufEnum {
41 | static const AuthError_ErrorType INTERNAL_ERROR = AuthError_ErrorType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'INTERNAL_ERROR');
42 | static const AuthError_ErrorType NO_TLS = AuthError_ErrorType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NO_TLS');
43 |
44 | static const $core.List values = [
45 | INTERNAL_ERROR,
46 | NO_TLS,
47 | ];
48 |
49 | static final $core.Map<$core.int, AuthError_ErrorType> _byValue = $pb.ProtobufEnum.initByValue(values);
50 | static AuthError_ErrorType? valueOf($core.int value) => _byValue[value];
51 |
52 | const AuthError_ErrorType._($core.int v, $core.String n) : super(v, n);
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/lib/cast_channel/cast_channel.pbjson.dart:
--------------------------------------------------------------------------------
1 | ///
2 | // Generated code. Do not modify.
3 | // source: cast_channel.proto
4 | //
5 | // @dart = 2.12
6 | // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
7 |
8 | import 'dart:core' as $core;
9 | import 'dart:convert' as $convert;
10 | import 'dart:typed_data' as $typed_data;
11 | @$core.Deprecated('Use castMessageDescriptor instead')
12 | const CastMessage$json = const {
13 | '1': 'CastMessage',
14 | '2': const [
15 | const {'1': 'protocol_version', '3': 1, '4': 2, '5': 14, '6': '.extensions.api.cast_channel.CastMessage.ProtocolVersion', '10': 'protocolVersion'},
16 | const {'1': 'source_id', '3': 2, '4': 2, '5': 9, '10': 'sourceId'},
17 | const {'1': 'destination_id', '3': 3, '4': 2, '5': 9, '10': 'destinationId'},
18 | const {'1': 'namespace', '3': 4, '4': 2, '5': 9, '10': 'namespace'},
19 | const {'1': 'payload_type', '3': 5, '4': 2, '5': 14, '6': '.extensions.api.cast_channel.CastMessage.PayloadType', '10': 'payloadType'},
20 | const {'1': 'payload_utf8', '3': 6, '4': 1, '5': 9, '10': 'payloadUtf8'},
21 | const {'1': 'payload_binary', '3': 7, '4': 1, '5': 12, '10': 'payloadBinary'},
22 | ],
23 | '4': const [CastMessage_ProtocolVersion$json, CastMessage_PayloadType$json],
24 | };
25 |
26 | @$core.Deprecated('Use castMessageDescriptor instead')
27 | const CastMessage_ProtocolVersion$json = const {
28 | '1': 'ProtocolVersion',
29 | '2': const [
30 | const {'1': 'CASTV2_1_0', '2': 0},
31 | ],
32 | };
33 |
34 | @$core.Deprecated('Use castMessageDescriptor instead')
35 | const CastMessage_PayloadType$json = const {
36 | '1': 'PayloadType',
37 | '2': const [
38 | const {'1': 'STRING', '2': 0},
39 | const {'1': 'BINARY', '2': 1},
40 | ],
41 | };
42 |
43 | /// Descriptor for `CastMessage`. Decode as a `google.protobuf.DescriptorProto`.
44 | final $typed_data.Uint8List castMessageDescriptor = $convert.base64Decode('CgtDYXN0TWVzc2FnZRJjChBwcm90b2NvbF92ZXJzaW9uGAEgAigOMjguZXh0ZW5zaW9ucy5hcGkuY2FzdF9jaGFubmVsLkNhc3RNZXNzYWdlLlByb3RvY29sVmVyc2lvblIPcHJvdG9jb2xWZXJzaW9uEhsKCXNvdXJjZV9pZBgCIAIoCVIIc291cmNlSWQSJQoOZGVzdGluYXRpb25faWQYAyACKAlSDWRlc3RpbmF0aW9uSWQSHAoJbmFtZXNwYWNlGAQgAigJUgluYW1lc3BhY2USVwoMcGF5bG9hZF90eXBlGAUgAigOMjQuZXh0ZW5zaW9ucy5hcGkuY2FzdF9jaGFubmVsLkNhc3RNZXNzYWdlLlBheWxvYWRUeXBlUgtwYXlsb2FkVHlwZRIhCgxwYXlsb2FkX3V0ZjgYBiABKAlSC3BheWxvYWRVdGY4EiUKDnBheWxvYWRfYmluYXJ5GAcgASgMUg1wYXlsb2FkQmluYXJ5IiEKD1Byb3RvY29sVmVyc2lvbhIOCgpDQVNUVjJfMV8wEAAiJQoLUGF5bG9hZFR5cGUSCgoGU1RSSU5HEAASCgoGQklOQVJZEAE=');
45 | @$core.Deprecated('Use authChallengeDescriptor instead')
46 | const AuthChallenge$json = const {
47 | '1': 'AuthChallenge',
48 | };
49 |
50 | /// Descriptor for `AuthChallenge`. Decode as a `google.protobuf.DescriptorProto`.
51 | final $typed_data.Uint8List authChallengeDescriptor = $convert.base64Decode('Cg1BdXRoQ2hhbGxlbmdl');
52 | @$core.Deprecated('Use authResponseDescriptor instead')
53 | const AuthResponse$json = const {
54 | '1': 'AuthResponse',
55 | '2': const [
56 | const {'1': 'signature', '3': 1, '4': 2, '5': 12, '10': 'signature'},
57 | const {'1': 'client_auth_certificate', '3': 2, '4': 2, '5': 12, '10': 'clientAuthCertificate'},
58 | const {'1': 'client_ca', '3': 3, '4': 3, '5': 12, '10': 'clientCa'},
59 | ],
60 | };
61 |
62 | /// Descriptor for `AuthResponse`. Decode as a `google.protobuf.DescriptorProto`.
63 | final $typed_data.Uint8List authResponseDescriptor = $convert.base64Decode('CgxBdXRoUmVzcG9uc2USHAoJc2lnbmF0dXJlGAEgAigMUglzaWduYXR1cmUSNgoXY2xpZW50X2F1dGhfY2VydGlmaWNhdGUYAiACKAxSFWNsaWVudEF1dGhDZXJ0aWZpY2F0ZRIbCgljbGllbnRfY2EYAyADKAxSCGNsaWVudENh');
64 | @$core.Deprecated('Use authErrorDescriptor instead')
65 | const AuthError$json = const {
66 | '1': 'AuthError',
67 | '2': const [
68 | const {'1': 'error_type', '3': 1, '4': 2, '5': 14, '6': '.extensions.api.cast_channel.AuthError.ErrorType', '10': 'errorType'},
69 | ],
70 | '4': const [AuthError_ErrorType$json],
71 | };
72 |
73 | @$core.Deprecated('Use authErrorDescriptor instead')
74 | const AuthError_ErrorType$json = const {
75 | '1': 'ErrorType',
76 | '2': const [
77 | const {'1': 'INTERNAL_ERROR', '2': 0},
78 | const {'1': 'NO_TLS', '2': 1},
79 | ],
80 | };
81 |
82 | /// Descriptor for `AuthError`. Decode as a `google.protobuf.DescriptorProto`.
83 | final $typed_data.Uint8List authErrorDescriptor = $convert.base64Decode('CglBdXRoRXJyb3ISTwoKZXJyb3JfdHlwZRgBIAIoDjIwLmV4dGVuc2lvbnMuYXBpLmNhc3RfY2hhbm5lbC5BdXRoRXJyb3IuRXJyb3JUeXBlUgllcnJvclR5cGUiKwoJRXJyb3JUeXBlEhIKDklOVEVSTkFMX0VSUk9SEAASCgoGTk9fVExTEAE=');
84 | @$core.Deprecated('Use deviceAuthMessageDescriptor instead')
85 | const DeviceAuthMessage$json = const {
86 | '1': 'DeviceAuthMessage',
87 | '2': const [
88 | const {'1': 'challenge', '3': 1, '4': 1, '5': 11, '6': '.extensions.api.cast_channel.AuthChallenge', '10': 'challenge'},
89 | const {'1': 'response', '3': 2, '4': 1, '5': 11, '6': '.extensions.api.cast_channel.AuthResponse', '10': 'response'},
90 | const {'1': 'error', '3': 3, '4': 1, '5': 11, '6': '.extensions.api.cast_channel.AuthError', '10': 'error'},
91 | ],
92 | };
93 |
94 | /// Descriptor for `DeviceAuthMessage`. Decode as a `google.protobuf.DescriptorProto`.
95 | final $typed_data.Uint8List deviceAuthMessageDescriptor = $convert.base64Decode('ChFEZXZpY2VBdXRoTWVzc2FnZRJICgljaGFsbGVuZ2UYASABKAsyKi5leHRlbnNpb25zLmFwaS5jYXN0X2NoYW5uZWwuQXV0aENoYWxsZW5nZVIJY2hhbGxlbmdlEkUKCHJlc3BvbnNlGAIgASgLMikuZXh0ZW5zaW9ucy5hcGkuY2FzdF9jaGFubmVsLkF1dGhSZXNwb25zZVIIcmVzcG9uc2USPAoFZXJyb3IYAyABKAsyJi5leHRlbnNpb25zLmFwaS5jYXN0X2NoYW5uZWwuQXV0aEVycm9yUgVlcnJvcg==');
96 |
--------------------------------------------------------------------------------
/lib/cast_channel/cast_channel.pbserver.dart:
--------------------------------------------------------------------------------
1 | ///
2 | // Generated code. Do not modify.
3 | // source: cast_channel.proto
4 | //
5 | // @dart = 2.12
6 | // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
7 |
8 | export 'cast_channel.pb.dart';
9 |
10 |
--------------------------------------------------------------------------------
/lib/cast_channel/cast_channel.proto:
--------------------------------------------------------------------------------
1 | // Source https://github.com/terrabythia/dart_chromecast/blob/master/lib/proto/cast_channel.proto
2 | // Used to generate cast_channel*.dart
3 |
4 | // Copyright 2013 The Chromium Authors. All rights reserved.
5 | // Use of this source code is governed by a BSD-style license that can be
6 | // found in the LICENSE file.
7 |
8 | syntax = "proto2";
9 |
10 | option optimize_for = LITE_RUNTIME;
11 |
12 | package extensions.api.cast_channel;
13 |
14 | message CastMessage {
15 | // Always pass a version of the protocol for future compatibility
16 | // requirements.
17 | enum ProtocolVersion {
18 | CASTV2_1_0 = 0;
19 | }
20 | required ProtocolVersion protocol_version = 1;
21 |
22 | // source and destination ids identify the origin and destination of the
23 | // message. They are used to route messages between endpoints that share a
24 | // device-to-device channel.
25 | //
26 | // For messages between applications:
27 | // - The sender application id is a unique identifier generated on behalf of
28 | // the sender application.
29 | // - The receiver id is always the the session id for the application.
30 | //
31 | // For messages to or from the sender or receiver platform, the special ids
32 | // 'sender-0' and 'receiver-0' can be used.
33 | //
34 | // For messages intended for all endpoints using a given channel, the
35 | // wildcard destination_id '*' can be used.
36 | required string source_id = 2;
37 | required string destination_id = 3;
38 |
39 | // This is the core multiplexing key. All messages are sent on a namespace
40 | // and endpoints sharing a channel listen on one or more namespaces. The
41 | // namespace defines the protocol and semantics of the message.
42 | required string namespace = 4;
43 |
44 | // Encoding and payload info follows.
45 |
46 | // What type of data do we have in this message.
47 | enum PayloadType {
48 | STRING = 0;
49 | BINARY = 1;
50 | }
51 | required PayloadType payload_type = 5;
52 |
53 | // Depending on payload_type, exactly one of the following optional fields
54 | // will always be set.
55 | optional string payload_utf8 = 6;
56 | optional bytes payload_binary = 7;
57 | }
58 |
59 | // Messages for authentication protocol between a sender and a receiver.
60 | message AuthChallenge {
61 | }
62 |
63 | message AuthResponse {
64 | required bytes signature = 1;
65 | required bytes client_auth_certificate = 2;
66 | repeated bytes client_ca = 3;
67 | }
68 |
69 | message AuthError {
70 | enum ErrorType {
71 | INTERNAL_ERROR = 0;
72 | NO_TLS = 1; // The underlying connection is not TLS
73 | }
74 | required ErrorType error_type = 1;
75 | }
76 |
77 | message DeviceAuthMessage {
78 | // Request fields
79 | optional AuthChallenge challenge = 1;
80 | // Response fields
81 | optional AuthResponse response = 2;
82 | optional AuthError error = 3;
83 | }
--------------------------------------------------------------------------------
/lib/device.dart:
--------------------------------------------------------------------------------
1 | class CastDevice {
2 | /// unique across network
3 | final String serviceName;
4 |
5 | /// friendly name
6 | final String name;
7 | final String host;
8 | final int port;
9 |
10 | final Map extras;
11 |
12 | const CastDevice({
13 | required this.serviceName,
14 | required this.name,
15 | required this.host,
16 | required this.port,
17 | this.extras = const {},
18 | });
19 |
20 | @override
21 | bool operator ==(Object other) => identical(this, other) || (other is CastDevice && runtimeType == other.runtimeType && other.serviceName == serviceName);
22 |
23 | @override
24 | int get hashCode => serviceName.hashCode;
25 | }
26 |
--------------------------------------------------------------------------------
/lib/discovery_service.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:bonsoir/bonsoir.dart';
4 |
5 | import 'device.dart';
6 |
7 | const _domain = '_googlecast._tcp';
8 |
9 | class CastDiscoveryService {
10 | static final CastDiscoveryService _instance = CastDiscoveryService._();
11 | CastDiscoveryService._();
12 |
13 | factory CastDiscoveryService() {
14 | return _instance;
15 | }
16 |
17 | Future> search({Duration timeout = const Duration(seconds: 5)}) async {
18 | final results = [];
19 |
20 | final discovery = BonsoirDiscovery(type: _domain);
21 | await discovery.ready;
22 |
23 | discovery.eventStream!.listen((event) {
24 | if (event.type == BonsoirDiscoveryEventType.discoveryServiceFound) {
25 | event.service?.resolve(discovery.serviceResolver);
26 | } else if (event.type == BonsoirDiscoveryEventType.discoveryServiceResolved) {
27 | if (event.service == null || event.service?.attributes == null) {
28 | return;
29 | }
30 |
31 | final port = event.service?.port;
32 | final host = event.service?.toJson()['service.ip'] ?? event.service?.toJson()['service.host'];
33 |
34 | String name = [
35 | event.service?.attributes?['md'],
36 | event.service?.attributes?['fn'],
37 | ].whereType().join(' - ');
38 | if (name.isEmpty) {
39 | name = event.service!.name;
40 | }
41 |
42 | if (port == null || host == null) {
43 | return;
44 | }
45 |
46 | results.add(
47 | CastDevice(
48 | serviceName: event.service!.name,
49 | name: name,
50 | port: port,
51 | host: host,
52 | extras: event.service!.attributes ?? {},
53 | ),
54 | );
55 | }
56 | }, onError: (error) {
57 | print('[CastDiscoveryService] error ${error.runtimeType} - $error');
58 | });
59 |
60 | await discovery.start();
61 | await Future.delayed(timeout);
62 | await discovery.stop();
63 |
64 | return results.toSet().toList();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/session.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'device.dart';
4 | import 'socket.dart';
5 |
6 | enum CastSessionState {
7 | connecting,
8 | connected,
9 | closed,
10 | }
11 |
12 | class CastSession {
13 | static const kNamespaceConnection = 'urn:x-cast:com.google.cast.tp.connection';
14 | static const kNamespaceHeartbeat = 'urn:x-cast:com.google.cast.tp.heartbeat';
15 | static const kNamespaceReceiver = 'urn:x-cast:com.google.cast.receiver';
16 | static const kNamespaceDeviceauth = 'urn:x-cast:com.google.cast.tp.deviceauth';
17 | static const kNamespaceMedia = 'urn:x-cast:com.google.cast.media';
18 |
19 | final String sessionId;
20 | CastSocket get socket => _socket;
21 | CastSessionState get state => _state;
22 |
23 | Stream get stateStream => _stateController.stream;
24 | Stream