snapshot of https://github.com/flutter/samples.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Main Branch CI / Test Flutter beta on ubuntu-latest (push) Has been skipped
Main Branch CI / Test Flutter stable on ubuntu-latest (push) Has been skipped
Main Branch CI / Test Flutter beta on macos-latest (push) Has been cancelled
Main Branch CI / Test Flutter stable on macos-latest (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-16 01:43:26 +05:00
commit 9ed6a80afa
2886 changed files with 140184 additions and 0 deletions

43
platform_channels/.gitignore vendored Normal file
View File

@@ -0,0 +1,43 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

View File

@@ -0,0 +1,33 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "db7ef5bf9f59442b0e200a90587e8fa5e0c6336a"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
- platform: android
create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
- platform: ios
create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View File

@@ -0,0 +1,42 @@
# Platform Channel Samples
A sample app which demonstrates how to use `MethodChannel`, `EventChannel`, `BasicMessageChannel` and `MessageCodec` in Flutter.
## Goals
* Demonstrate how to use `MethodChannel` to invoke platform methods.
* Demonstrate how to use `EventChannel` to listen continuous value changes from the platform.
* Demonstrate how to use `BasicMessageChannel` and `MessageCodec` to send messages of different types across the platform.
## The important bits
### [Method Channel demo](./lib/src/method_channel_demo.dart)
Demonstrates how to implement a `MethodChannel` to increment and decrement a
counter.
### [Event Channel demo](./lib/src/event_channel_demo.dart)
Demonstrates how to implement an `EventChannel` to listen to value changes from
the Accelerometer sensor from native side.
### [Platform Image demo](./lib/src/platform_image_demo.dart)
Demonstrates how to implement a `BasicMessageChannel` using
`StandardMessageCodec` to load an image from native asset.
### [Basic Message Channel demo](./lib/src/pet_list_screen.dart)
Demonstrates how to implement `BasicMessageChannel` using `JSONMessageCodec`,
`BinaryCodec` and `StringCodec` to send and receive data about pets.
## Questions/issues
If you have a general question about Platform Channels in Flutter, the
best places to go are:
* [The FlutterDev Google Group](https://groups.google.com/forum/#!forum/flutter-dev)
* [The Flutter Gitter channel](https://gitter.im/flutter/flutter)
* [StackOverflow](https://stackoverflow.com/questions/tagged/flutter)
If you run into an issue with the sample itself, please file an issue [here](https://github.com/flutter/samples/issues).

View File

@@ -0,0 +1 @@
include: ../analysis_options.yaml

13
platform_channels/android/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

View File

@@ -0,0 +1,69 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
android {
namespace "dev.flutter.platform_channels"
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "dev.flutter.platform_channels"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation 'com.google.code.gson:gson:2.8.6'
}

View File

@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@@ -0,0 +1,33 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="platform_channels"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -0,0 +1,39 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package dev.flutter.platform_channels
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import io.flutter.plugin.common.EventChannel
class AccelerometerStreamHandler(sManager: SensorManager, s: Sensor) : EventChannel.StreamHandler, SensorEventListener {
private val sensorManager: SensorManager = sManager
private val accelerometerSensor: Sensor = s
private lateinit var eventSink: EventChannel.EventSink
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
if (events != null) {
eventSink = events
sensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_UI)
}
}
override fun onCancel(arguments: Any?) {
sensorManager.unregisterListener(this)
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
override fun onSensorChanged(sensorEvent: SensorEvent?) {
if (sensorEvent != null) {
val axisValues = listOf(sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2])
eventSink.success(axisValues)
} else {
eventSink.error("DATA_UNAVAILABLE", "Cannot get accelerometer data", null)
}
}
}

View File

@@ -0,0 +1,88 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package dev.flutter.platform_channels
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.*
import java.io.InputStream
import java.nio.ByteBuffer
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
// Creates a MethodChannel as soon as the FlutterEngine is attached to
// the Activity, and registers a MethodCallHandler. The Method.setMethodCallHandler
// is responsible to register a MethodCallHandler to handle the incoming calls.
// The call parameter of MethodCallHandler has information about the incoming call,
// like method name, and arguments. The result parameter of MethodCallHandler is
// responsible to send the results of the call.
MethodChannel(flutterEngine.dartExecutor, "methodChannelDemo")
.setMethodCallHandler { call, result ->
val count: Int? = call.argument<Int>("count")
if (count == null) {
result.error("INVALID ARGUMENT", "Value of count cannot be null", null)
} else {
when (call.method) {
"increment" -> result.success(count + 1)
"decrement" -> result.success(count - 1)
else -> result.notImplemented()
}
}
}
val sensorManger: SensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val accelerometerSensor: Sensor = sensorManger.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
EventChannel(flutterEngine.dartExecutor, "eventChannelDemo")
.setStreamHandler(AccelerometerStreamHandler(sensorManger, accelerometerSensor))
// Registers a MessageHandler for BasicMessageChannel to receive a message from Dart and send
// image data in reply.
BasicMessageChannel(flutterEngine.dartExecutor, "platformImageDemo", StandardMessageCodec())
.setMessageHandler { message, reply ->
if (message == "getImage") {
val inputStream: InputStream = assets.open("eat_new_orleans.jpg")
reply.reply(inputStream.readBytes())
}
}
val petList = mutableListOf<Map<String, String>>()
val gson = Gson()
// A BasicMessageChannel for sending petList to Dart.
val stringCodecChannel = BasicMessageChannel(flutterEngine.dartExecutor, "stringCodecDemo", StringCodec.INSTANCE)
// Registers a MessageHandler for BasicMessageChannel to receive pet details to be
// added in petList and send the it back to Dart using stringCodecChannel.
BasicMessageChannel(flutterEngine.dartExecutor, "jsonMessageCodecDemo", JSONMessageCodec.INSTANCE)
.setMessageHandler { message, reply ->
petList.add(0, gson.fromJson(message.toString(), object : TypeToken<Map<String, String>>() {}.type))
stringCodecChannel.send(gson.toJson(mapOf("petList" to petList)))
}
// Registers a MessageHandler for BasicMessageChannel to receive the index of pet
// details to be removed from the petList and send the petList back to Dart using
// stringCodecChannel. If the index is not in the range of petList, we send null
// back to Dart.
BasicMessageChannel(flutterEngine.dartExecutor, "binaryCodecDemo", BinaryCodec.INSTANCE)
.setMessageHandler { message, reply ->
val index = String(message!!.array()).toInt()
if (index >= 0 && index < petList.size) {
petList.removeAt(index)
val replyMessage = "Removed Successfully"
reply.reply(ByteBuffer.allocateDirect(replyMessage.toByteArray().size).put(replyMessage.toByteArray()))
stringCodecChannel.send(gson.toJson(mapOf("petList" to petList)))
} else {
reply.reply(null)
}
}
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@@ -0,0 +1,30 @@
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

View File

@@ -0,0 +1,29 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
plugins {
id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
}
include ":app"

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

34
platform_channels/ios/.gitignore vendored Normal file
View File

@@ -0,0 +1,34 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
</dict>
</plist>

View File

@@ -0,0 +1 @@
#include "Generated.xcconfig"

View File

@@ -0,0 +1 @@
#include "Generated.xcconfig"

View File

@@ -0,0 +1,614 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
F1246E9A9D19DC437CB1F19C /* AccelerometerStreamHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 875C3ADF5E4877B6D6ECA77F /* AccelerometerStreamHandler.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
875C3ADF5E4877B6D6ECA77F /* AccelerometerStreamHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccelerometerStreamHandler.swift; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
875C3ADF5E4877B6D6ECA77F /* AccelerometerStreamHandler.swift */,
);
path = Runner;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
F1246E9A9D19DC437CB1F19C /* AccelerometerStreamHandler.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.platformChannels;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.platformChannels.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.platformChannels.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.platformChannels.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.platformChannels;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.platformChannels;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,38 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import CoreMotion
class AccelerometerStreamHandler: NSObject, FlutterStreamHandler {
var motionManager: CMMotionManager;
override init() {
motionManager = CMMotionManager()
}
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
if !motionManager.isAccelerometerAvailable {
events(FlutterError(code: "SENSOR_UNAVAILABLE", message: "Accelerometer is not available", details: nil))
}
motionManager.accelerometerUpdateInterval = 0.1
motionManager.startAccelerometerUpdates(to: OperationQueue.main) {(data, error) in
guard let accelerationData = data?.acceleration else {
events(FlutterError(code: "DATA_UNAVAILABLE", message: "Cannot get accelerometer data", details: nil ))
return
}
events([accelerationData.x, accelerationData.y, accelerationData.z])
}
return nil
}
func onCancel(withArguments arguments: Any?) -> FlutterError? {
return nil
}
}

View File

@@ -0,0 +1,89 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let flutterViewController = window.rootViewController as! FlutterViewController
FlutterMethodChannel(name: "methodChannelDemo", binaryMessenger: flutterViewController.binaryMessenger).setMethodCallHandler({
(call: FlutterMethodCall, result: FlutterResult) -> Void in
guard let count = (call.arguments as? NSDictionary)?["count"] as? Int else {
result(FlutterError(code: "INVALID_ARGUMENT", message: "Value of count cannot be null", details: nil))
return
}
switch call.method {
case "increment":
result(count + 1)
case "decrement":
result(count - 1)
default:
result(FlutterMethodNotImplemented)
}
})
FlutterBasicMessageChannel(name: "platformImageDemo", binaryMessenger: flutterViewController.binaryMessenger, codec: FlutterStandardMessageCodec.sharedInstance()).setMessageHandler{
(message: Any?, reply: FlutterReply) -> Void in
if(message as! String == "getImage") {
guard let image = UIImage(named: "eat_new_orleans.jpg") else {
reply(nil)
return
}
reply(FlutterStandardTypedData(bytes: image.jpegData(compressionQuality: 1)!))
}
}
FlutterEventChannel(name: "eventChannelDemo", binaryMessenger: flutterViewController.binaryMessenger).setStreamHandler(AccelerometerStreamHandler())
var petList : [[String:String]] = []
// A FlutterBasicMessageChannel for sending petList to Dart.
let stringCodecChannel = FlutterBasicMessageChannel(name: "stringCodecDemo", binaryMessenger: flutterViewController.binaryMessenger, codec: FlutterStringCodec.sharedInstance())
// Registers a MessageHandler for FlutterBasicMessageChannel to receive pet details.
FlutterBasicMessageChannel(name: "jsonMessageCodecDemo", binaryMessenger: flutterViewController.binaryMessenger, codec: FlutterJSONMessageCodec.sharedInstance())
.setMessageHandler{(message: Any?, reply: FlutterReply) -> Void in
petList.insert(message! as! [String: String], at: 0)
stringCodecChannel.sendMessage(self.convertPetListToJson(petList: petList))
}
// Registers a MessageHandler for FlutterBasicMessageHandler to receive indices of detail records to remove from the petList.
FlutterBasicMessageChannel(name: "binaryCodecDemo", binaryMessenger: flutterViewController.binaryMessenger, codec: FlutterBinaryCodec.sharedInstance()).setMessageHandler{
(message: Any?, reply: FlutterReply) -> Void in
guard let index = Int.init(String.init(data: message! as! Data, encoding: String.Encoding.utf8)!) else {
reply(nil)
return
}
if (index >= 0 && index < petList.count) {
petList.remove(at: index)
reply("Removed Successfully".data(using: .utf8)!)
stringCodecChannel.sendMessage(self.convertPetListToJson(petList: petList))
} else {
reply(nil)
}
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// Function to convert petList to json string.
func convertPetListToJson(petList: [[String: String]]) -> String? {
guard let data = try? JSONSerialization.data(withJSONObject: ["petList": petList], options: .prettyPrinted) else {
return nil
}
return String(data: data, encoding: String.Encoding.utf8)
}
}

View File

@@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View File

@@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
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.

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "eat_new_orleans.jpg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Platform Channels</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>platform_channels</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"

View File

@@ -0,0 +1,12 @@
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}

View File

@@ -0,0 +1,113 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:platform_channels/src/add_pet_details.dart';
import 'package:platform_channels/src/event_channel_demo.dart';
import 'package:platform_channels/src/method_channel_demo.dart';
import 'package:platform_channels/src/pet_list_screen.dart';
import 'package:platform_channels/src/platform_image_demo.dart';
void main() {
runApp(const PlatformChannelSample());
}
class PlatformChannelSample extends StatelessWidget {
const PlatformChannelSample({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Platform Channel Sample',
theme: ThemeData(
snackBarTheme: SnackBarThemeData(
backgroundColor: Colors.blue[500],
),
),
routerConfig: router(),
);
}
}
GoRouter router([String? initialLocation]) {
return GoRouter(
initialLocation: initialLocation ?? '/',
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
path: 'methodChannelDemo',
builder: (context, state) => const MethodChannelDemo(),
),
GoRoute(
path: 'eventChannelDemo',
builder: (context, state) => const EventChannelDemo(),
),
GoRoute(
path: 'platformImageDemo',
builder: (context, state) => const PlatformImageDemo(),
),
GoRoute(
path: 'petListScreen',
builder: (context, state) => const PetListScreen(),
routes: [
GoRoute(
path: 'addPetDetails',
builder: (context, state) => const AddPetDetails(),
),
],
),
],
),
],
);
}
class DemoInfo {
final String demoTitle;
final String demoRoute;
DemoInfo(this.demoTitle, this.demoRoute);
}
List<DemoInfo> demoList = [
DemoInfo('MethodChannel Demo', '/methodChannelDemo'),
DemoInfo('EventChannel Demo', '/eventChannelDemo'),
DemoInfo('Platform Image Demo', '/platformImageDemo'),
DemoInfo('BasicMessageChannel Demo', '/petListScreen'),
];
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Platform Channel Sample')),
body: ListView(
children: demoList.map((demoInfo) => DemoTile(demoInfo)).toList(),
),
);
}
}
/// This widget is responsible for displaying the [ListTile] on [HomePage].
class DemoTile extends StatelessWidget {
final DemoInfo demoInfo;
const DemoTile(this.demoInfo, {super.key});
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(demoInfo.demoTitle),
onTap: () {
context.go(demoInfo.demoRoute);
},
);
}
}

View File

@@ -0,0 +1,37 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/services.dart';
/// This class includes the implementation for [EventChannel] to listen to value
/// changes from the Accelerometer sensor from native side. It has a [readings]
/// getter to provide a stream of [AccelerometerReadings].
class Accelerometer {
static const _eventChannel = EventChannel('eventChannelDemo');
/// Method responsible for providing a stream of [AccelerometerReadings] to listen
/// to value changes from the Accelerometer sensor.
static Stream<AccelerometerReadings> get readings {
return _eventChannel.receiveBroadcastStream().map(
(dynamic event) => AccelerometerReadings(
event[0] as double,
event[1] as double,
event[2] as double,
),
);
}
}
class AccelerometerReadings {
/// Acceleration force along the x-axis.
final double x;
/// Acceleration force along the y-axis.
final double y;
/// Acceleration force along the z-axis.
final double z;
AccelerometerReadings(this.x, this.y, this.z);
}

View File

@@ -0,0 +1,81 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:platform_channels/src/pet_list_message_channel.dart';
/// Demonstrates how to use [BasicMessageChannel] to send a message to platform.
///
/// The widget uses [TextField] and [RadioListTile] to take the [PetDetails.breed] and
/// [PetDetails.petType] from the user respectively.
class AddPetDetails extends StatefulWidget {
const AddPetDetails({super.key});
@override
State<AddPetDetails> createState() => _AddPetDetailsState();
}
class _AddPetDetailsState extends State<AddPetDetails> {
final breedTextController = TextEditingController();
String petType = 'Dog';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Add Pet Details'),
actions: [
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
PetListMessageChannel.addPetDetails(
PetDetails(
petType: petType,
breed: breedTextController.text,
),
);
context.pop();
},
),
],
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: RadioGroup(
groupValue: petType,
onChanged: (value) {
setState(() {
petType = value!;
});
},
child: Column(
children: [
const SizedBox(height: 8),
TextField(
controller: breedTextController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
filled: true,
hintText: 'Breed of pet',
labelText: 'Breed',
),
),
const SizedBox(height: 8),
RadioListTile<String>(
title: const Text('Dog'),
value: 'Dog',
),
RadioListTile<String>(
title: const Text('Cat'),
value: 'Cat',
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,33 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/services.dart';
/// This class includes implementation of two platform methods [increment],
/// and [decrement] which are used to increment and decrement value
/// of count respectively.
class Counter {
/// Creates a [MethodChannel] with the specified name to invoke platform method.
/// In order to communicate across platforms, the name of MethodChannel
/// should be same on native and dart side.
static MethodChannel methodChannel = const MethodChannel(
'methodChannelDemo',
);
/// This method is responsible to increment and return the value of count.
static Future<int> increment({required int counterValue}) async {
final result = await methodChannel.invokeMethod<int>('increment', {
'count': counterValue,
});
return result!;
}
/// This method is responsible to decrement and return the value of count.
static Future<int> decrement({required int counterValue}) async {
final result = await methodChannel.invokeMethod<int>('decrement', {
'count': counterValue,
});
return result!;
}
}

View File

@@ -0,0 +1,56 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:platform_channels/src/accelerometer_event_channel.dart';
/// Demonstrates how to use [EventChannel] to listen continuous values
/// of Accelerometer Sensor from platform.
///
/// The widget uses a [StreamBuilder] to rebuild it's descendant whenever it
/// listens a new value from the [Accelerometer.readings] stream. It has three
/// [Text] widgets to display the value of [AccelerometerReadings.x],
/// [AccelerometerReadings.y], and [AccelerometerReadings.z] respectively.
class EventChannelDemo extends StatelessWidget {
const EventChannelDemo({super.key});
@override
Widget build(BuildContext context) {
final textStyle = Theme.of(context).textTheme.headlineSmall;
return Scaffold(
appBar: AppBar(title: const Text('EventChannel Demo')),
body: Center(
child: StreamBuilder<AccelerometerReadings>(
stream: Accelerometer.readings,
builder: (context, snapshot) {
return switch (snapshot) {
AsyncSnapshot(hasError: true) => Text(
(snapshot.error as PlatformException).message!,
),
AsyncSnapshot(hasData: true) => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'x axis: ${snapshot.data!.x.toStringAsFixed(3)}',
style: textStyle,
),
Text(
'y axis: ${snapshot.data!.y.toStringAsFixed(3)}',
style: textStyle,
),
Text(
'z axis: ${snapshot.data!.z.toStringAsFixed(3)}',
style: textStyle,
),
],
),
_ => Text('No Data Available', style: textStyle),
};
},
),
),
);
}
}

View File

@@ -0,0 +1,28 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/services.dart';
/// This class manages a [BasicMessageChannel] that can return an image loaded
/// from a native asset. The [BasicMessageChannel] uses [StandardMessageCodec]
/// since it supports [Uint8List], which is used to transport the image data.
class PlatformImageFetcher {
static const _basicMessageChannel = BasicMessageChannel<dynamic>(
'platformImageDemo',
StandardMessageCodec(),
);
/// Method responsible for providing the platform image.
static Future<Uint8List> getImage() async {
final reply = await _basicMessageChannel.send('getImage') as Uint8List?;
if (reply == null) {
throw PlatformException(
code: 'Error',
message: 'Failed to load Platform Image',
details: null,
);
}
return reply;
}
}

View File

@@ -0,0 +1,90 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:platform_channels/src/counter_method_channel.dart';
/// The widget demonstrates how to use [MethodChannel] to invoke platform methods.
/// It has two [FilledButton]s to increment and decrement the value of
/// [count], and a [Text] widget to display its value.
class MethodChannelDemo extends StatefulWidget {
const MethodChannelDemo({super.key});
@override
State<MethodChannelDemo> createState() => _MethodChannelDemoState();
}
class _MethodChannelDemoState extends State<MethodChannelDemo> {
int count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('MethodChannel Demo')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Value of count is $count',
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// Whenever users press the FilledButton, it invokes
// Counter.increment method to increment the value of count.
FilledButton.icon(
onPressed: () async {
try {
final value = await Counter.increment(
counterValue: count,
);
setState(() => count = value);
} catch (error) {
if (!context.mounted) return;
showErrorMessage(
context,
(error as PlatformException).message!,
);
}
},
icon: const Icon(Icons.add),
label: const Text('Increment'),
),
// Whenever users press the FilledButton, it invokes
// Counter.decrement method to decrement the value of count.
FilledButton.icon(
onPressed: () async {
try {
final value = await Counter.decrement(
counterValue: count,
);
setState(() => count = value);
} catch (error) {
if (!context.mounted) return;
showErrorMessage(
context,
(error as PlatformException).message!,
);
}
},
icon: const Icon(Icons.remove),
label: const Text('Decrement'),
),
],
),
],
),
);
}
void showErrorMessage(BuildContext context, String errorMessage) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(errorMessage)));
}
}

View File

@@ -0,0 +1,86 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'package:flutter/services.dart';
/// This class includes two methods [addPetDetails] and [removePet] which are used
/// to add a new pet and remove a pet from the the list respectively.
class PetListMessageChannel {
static const _jsonMessageCodecChannel = BasicMessageChannel<dynamic>(
'jsonMessageCodecDemo',
JSONMessageCodec(),
);
static const _binaryCodecChannel = BasicMessageChannel(
'binaryCodecDemo',
BinaryCodec(),
);
/// Method to add a new pet to the list.
///
/// Demonstrates how to use [BasicMessageChannel] and [JSONMessageCodec] to
/// send more structured data to platform like a [Map] in this case.
static void addPetDetails(PetDetails petDetails) {
_jsonMessageCodecChannel.send(petDetails.toJson());
}
/// Method to remove a pet from the list.
///
/// Demonstrates how to use [BasicMessageChannel] and [BinaryCodec] to
/// send [ByteData] to platform. If the reply received is null, then
/// we will throw a [PlatformException].
static Future<void> removePet(int index) async {
final uInt8List = utf8.encoder.convert(index.toString());
final reply = await _binaryCodecChannel.send(
uInt8List.buffer.asByteData(),
);
if (reply == null) {
throw PlatformException(
code: 'INVALID INDEX',
message: 'Failed to delete pet details',
details: null,
);
}
}
}
/// A model class that provides [petList] which is received from platform.
class PetListModel {
PetListModel({required this.petList});
final List<PetDetails> petList;
/// Method that maps the incoming string of json object to List of [PetDetails].
factory PetListModel.fromJson(String jsonString) {
final jsonData = json.decode(jsonString) as Map<String, dynamic>;
return PetListModel(
petList: List.from(
(jsonData['petList'] as List).map<PetDetails>(
(dynamic petDetailsMap) =>
PetDetails.fromMap(petDetailsMap as Map<String, dynamic>),
),
),
);
}
}
/// A simple model that provides pet details like [petType] and [breed] of pet.
class PetDetails {
PetDetails({required this.petType, required this.breed});
final String petType;
final String breed;
factory PetDetails.fromMap(Map<String, dynamic> map) => PetDetails(
petType: map['petType'] as String,
breed: map['breed'] as String,
);
Map<String, String> toJson() => <String, String>{
'petType': petType,
'breed': breed,
};
}

View File

@@ -0,0 +1,103 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:go_router/go_router.dart';
import 'package:platform_channels/src/pet_list_message_channel.dart';
/// Demonstrates how to use [BasicMessageChannel] to send & receive the platform
/// Message.
class PetListScreen extends StatefulWidget {
const PetListScreen({super.key});
@override
State<PetListScreen> createState() => _PetListScreenState();
}
class _PetListScreenState extends State<PetListScreen> {
PetListModel petListModel = PetListModel(petList: []);
final scaffoldKey = GlobalKey<ScaffoldState>();
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Receives a string of json object from the platform and converts it
// to PetModel.
final scaffoldMessenger = ScaffoldMessenger.of(context);
const BasicMessageChannel<String?>(
'stringCodecDemo',
StringCodec(),
).setMessageHandler((message) async {
if (message == null) {
scaffoldMessenger.showSnackBar(
const SnackBar(
content: Text('An error occurred while adding pet details.'),
),
);
} else {
setState(() {
petListModel = PetListModel.fromJson(message);
});
}
return null;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(title: const Text('Pet List')),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
context.go('/petListScreen/addPetDetails');
},
),
body: petListModel.petList.isEmpty
? const Center(child: Text('Enter Pet Details'))
: BuildPetList(petListModel.petList),
);
}
}
/// Shows list of [PetDetails].
class BuildPetList extends StatelessWidget {
final List<PetDetails> petList;
const BuildPetList(this.petList, {super.key});
@override
Widget build(BuildContext context) {
return ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: petList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('Pet breed: ${petList[index].breed}'),
subtitle: Text('Pet type: ${petList[index].petType}'),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
final scaffoldMessenger = ScaffoldMessenger.of(context);
try {
await PetListMessageChannel.removePet(index);
scaffoldMessenger.showSnackBar(
const SnackBar(content: Text('Removed successfully!')),
);
} catch (error) {
scaffoldMessenger.showSnackBar(
SnackBar(
content: Text((error as PlatformException).message!),
),
);
}
},
),
);
},
);
}
}

View File

@@ -0,0 +1,74 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:platform_channels/src/image_basic_message_channel.dart';
/// Demonstrates how to use [BasicMessageChannel] to get an image from platform.
///
/// The widget uses [Image.memory] to display the image obtained from the
/// platform.
class PlatformImageDemo extends StatefulWidget {
const PlatformImageDemo({super.key});
@override
State<PlatformImageDemo> createState() => _PlatformImageDemoState();
}
class _PlatformImageDemoState extends State<PlatformImageDemo> {
Future<Uint8List>? imageData;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Platform Image Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: FractionallySizedBox(
widthFactor: 1,
heightFactor: 0.6,
child: FutureBuilder<Uint8List>(
future: imageData,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.none) {
return const Placeholder();
} else if (snapshot.hasError) {
return Center(
child: Text(
(snapshot.error as PlatformException).message!,
),
);
} else if (snapshot.connectionState ==
ConnectionState.done) {
return Image.memory(
snapshot.data!,
fit: BoxFit.fill,
);
}
return const CircularProgressIndicator();
},
),
),
),
const SizedBox(height: 16),
FilledButton(
onPressed: imageData != null
? null
: () {
setState(() {
imageData = PlatformImageFetcher.getImage();
});
},
child: const Text('Get Image'),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,23 @@
name: platform_channels
description: A new Flutter project.
version: 1.0.0+1
resolution: workspace
environment:
sdk: ^3.9.0-0
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.3
go_router: ^16.0.0
dev_dependencies:
analysis_defaults:
path: ../analysis_defaults
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- assets/

View File

@@ -0,0 +1,17 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform_channels/main.dart';
void main() {
group('HomePage tests', () {
testWidgets('HomePage has multiple Text widgets', (tester) async {
await tester.pumpWidget(const MaterialApp(home: HomePage()));
expect(find.byType(Text), findsWidgets);
});
});
}

View File

@@ -0,0 +1,47 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform_channels/main.dart' as app;
void main() {
group('AddPetDetails tests', () {
var petList = <Map>[];
testWidgets('Enter pet details', (tester) async {
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(
const BasicMessageChannel<dynamic>(
'jsonMessageCodecDemo',
JSONMessageCodec(),
),
(dynamic message) async {
petList.add(message as Map);
},
);
var router = app.router('/petListScreen/addPetDetails');
await tester.pumpWidget(MaterialApp.router(routerConfig: router));
// Enter the breed of cat.
await tester.enterText(find.byType(TextField), 'Persian');
// Select cat from the pet type.
await tester.tap(find.text('Cat'));
// Initially the list will be empty.
expect(petList, isEmpty);
await tester.tap(find.byIcon(Icons.add));
expect(petList, isNotEmpty);
expect(petList.last['breed'], 'Persian');
// Navigate back to /petListScreen
await tester.pumpAndSettle();
expect(
router.routeInformationProvider.value.uri.path,
'/petListScreen',
);
});
});
}

View File

@@ -0,0 +1,72 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform_channels/src/event_channel_demo.dart';
void main() {
group('EventChannel Demo tests', () {
final sensorValues = [1.3556, 2.3, -0.12];
setUpAll(() {
// By default EventChannel uses StandardMethodCodec to communicate with
// platform.
const standardMethod = StandardMethodCodec();
// This function handles the incoming messages from the platform. It
// calls the BinaryMessenger.setMessageHandler registered for the EventChannel
// and add the incoming message to the StreamController used by the EventChannel
// after decoding the message with codec used by the EventChannel.
void emitValues(ByteData? event) {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.handlePlatformMessage('eventChannelDemo', event, (reply) {});
}
// Register a mock for EventChannel. EventChannel under the hood uses
// MethodChannel to listen and cancel the created stream.
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMessageHandler('eventChannelDemo', (message) async {
// Decode the message into MethodCallHandler.
final methodCall = standardMethod.decodeMethodCall(message);
if (methodCall.method == 'listen') {
// Emit new sensor values.
emitValues(
standardMethod.encodeSuccessEnvelope(sensorValues),
);
emitValues(null);
return standardMethod.encodeSuccessEnvelope(null);
} else if (methodCall.method == 'cancel') {
return standardMethod.encodeSuccessEnvelope(null);
} else {
fail('Expected listen or cancel');
}
});
});
testWidgets('EventChannel AccelerometerReadings Stream test', (
tester,
) async {
await tester.pumpWidget(const MaterialApp(home: EventChannelDemo()));
await tester.pumpAndSettle();
// Check the values of axis. The value is rounded to 3 decimal places.
expect(
find.text('x axis: ${sensorValues[0].toStringAsFixed(3)}'),
findsOneWidget,
);
expect(
find.text('y axis: ${sensorValues[1].toStringAsFixed(3)}'),
findsOneWidget,
);
expect(
find.text('z axis: ${sensorValues[2].toStringAsFixed(3)}'),
findsOneWidget,
);
});
});
}

View File

@@ -0,0 +1,46 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform_channels/src/method_channel_demo.dart';
void main() {
group('MethodChannelDemo tests', () {
testWidgets('MethodChannelDemo count test', (tester) async {
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
const MethodChannel('methodChannelDemo'),
(call) async {
var count = call.arguments['count'] as int;
if (call.method == 'increment') {
return ++count;
} else if (call.method == 'decrement') {
return --count;
}
return MissingPluginException();
},
);
await tester.pumpWidget(
const MaterialApp(home: MethodChannelDemo()),
);
// Initially the value of count should be 0.
expect(find.text('Value of count is 0'), findsOneWidget);
// Tap the ElevatedButton with Icons.add to increment the value of count.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
expect(find.text('Value of count is 1'), findsOneWidget);
// Tap the ElevatedButton with Icons.remove to decrement the value of count.
await tester.tap(find.byIcon(Icons.remove));
await tester.pump();
expect(find.text('Value of count is 0'), findsOneWidget);
});
});
}

View File

@@ -0,0 +1,96 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform_channels/src/pet_list_message_channel.dart';
import 'package:platform_channels/src/pet_list_screen.dart';
void main() {
group('PetListScreen tests', () {
const basicMessageChannel = BasicMessageChannel<String?>(
'stringCodecDemo',
StringCodec(),
);
var petList = [
{'petType': 'Dog', 'breed': 'Pug'},
];
PetListModel? petListModel;
setUpAll(() {
// Mock for the pet list received from the platform.
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockDecodedMessageHandler(basicMessageChannel, (
message,
) async {
petListModel = PetListModel.fromJson(message!);
return null;
});
// Mock for the index received from the Dart to delete the pet details,
// and send the updated pet list back to Dart.
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockDecodedMessageHandler(
const BasicMessageChannel<ByteData?>(
'binaryCodecDemo',
BinaryCodec(),
),
(message) async {
// Convert the ByteData to String.
final index = utf8.decoder.convert(
message!.buffer.asUint8List(
message.offsetInBytes,
message.lengthInBytes,
),
);
// Remove the pet details at the given index.
petList.removeAt(int.parse(index));
// Send the updated petList back.
final map = {'petList': petList};
await basicMessageChannel.send(json.encode(map));
return null;
},
);
});
test('convert json message to PetListModel', () {
TestWidgetsFlutterBinding.ensureInitialized();
// Initially petListModel will be null.
expect(petListModel, isNull);
// Send the pet list using BasicMessageChannel.
final map = {'petList': petList};
basicMessageChannel.send(json.encode(map));
// Get the details of first pet.
final petDetails = petListModel!.petList.first;
expect(petDetails.petType, 'Dog');
expect(petDetails.breed, 'Pug');
});
testWidgets('BuildPetList test', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(body: BuildPetList(petListModel!.petList)),
),
);
expect(find.text('Pet type: Dog'), findsOneWidget);
expect(find.text('Pet breed: Pug'), findsOneWidget);
// Delete the pet details.
await tester.tap(find.byIcon(Icons.delete).first);
expect(petListModel!.petList, isEmpty);
});
});
}

View File

@@ -0,0 +1,41 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform_channels/src/platform_image_demo.dart';
void main() {
group('Platform Image Demo tests', () {
testWidgets('Platform Image test', (tester) async {
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler(
const BasicMessageChannel<dynamic>(
'platformImageDemo',
StandardMessageCodec(),
),
(dynamic message) async {
var byteData = await rootBundle.load(
'assets/eat_new_orleans.jpg',
);
return byteData.buffer.asUint8List();
},
);
await tester.pumpWidget(
const MaterialApp(home: PlatformImageDemo()),
);
// Initially a PlaceHolder is displayed when imageData is null.
expect(find.byType(Placeholder), findsOneWidget);
expect(find.byType(Image), findsNothing);
// Tap on ElevatedButton to get Image.
await tester.tap(find.byType(FilledButton));
await tester.pumpAndSettle();
expect(find.byType(Placeholder), findsNothing);
expect(find.byType(Image), findsOneWidget);
});
});
}