Unverified Commit 674ff157 authored by Chris Bracken's avatar Chris Bracken Committed by GitHub

[macOS] Add platform_channel sample/test (#123141)

Adds a macOS implementation of the platform_channel example,
demonstrating method channels and event channels with a battery power
plugin.

Adds platform_channel_sample_test_macos macOS host test to verify the
sample works.

Issue: https://github.com/flutter/flutter/issues/79204
parent 28d40a4d
...@@ -2972,6 +2972,20 @@ targets: ...@@ -2972,6 +2972,20 @@ targets:
] ]
task_name: platform_view_macos__start_up task_name: platform_view_macos__start_up
- name: Mac platform_channel_sample_test_macos
bringup: true
recipe: devicelab/devicelab_drone
presubmit: false
timeout: 60
properties:
dependencies: >-
[
{"dependency": "xcode", "version": "14a5294e"}
]
tags: >
["devicelab", "hostonly", "mac"]
task_name: platform_channel_sample_test_macos
- name: Mac plugin_dependencies_test - name: Mac plugin_dependencies_test
recipe: devicelab/devicelab_drone recipe: devicelab/devicelab_drone
timeout: 60 timeout: 60
......
...@@ -250,6 +250,7 @@ ...@@ -250,6 +250,7 @@
/dev/devicelab/bin/tasks/module_test.dart @zanderso @flutter/tool /dev/devicelab/bin/tasks/module_test.dart @zanderso @flutter/tool
/dev/devicelab/bin/tasks/module_test_ios.dart @jmagman @flutter/tool /dev/devicelab/bin/tasks/module_test_ios.dart @jmagman @flutter/tool
/dev/devicelab/bin/tasks/native_ui_tests_macos.dart @cbracken @flutter/desktop /dev/devicelab/bin/tasks/native_ui_tests_macos.dart @cbracken @flutter/desktop
/dev/devicelab/bin/tasks/platform_channel_sample_test_macos.dart @cbracken @flutter/desktop
/dev/devicelab/bin/tasks/platform_channel_sample_test_windows.dart @cbracken @flutter/desktop /dev/devicelab/bin/tasks/platform_channel_sample_test_windows.dart @cbracken @flutter/desktop
/dev/devicelab/bin/tasks/platform_view_macos__start_up.dart @a-wallen @flutter/desktop /dev/devicelab/bin/tasks/platform_view_macos__start_up.dart @a-wallen @flutter/desktop
/dev/devicelab/bin/tasks/platform_view_win_desktop__start_up.dart @yaakovschectman @flutter/desktop /dev/devicelab/bin/tasks/platform_view_win_desktop__start_up.dart @yaakovschectman @flutter/desktop
......
// Copyright 2014 The Flutter Authors. 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_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/tasks/integration_tests.dart';
Future<void> main() async {
await task(createPlatformChannelSampleTest(deviceIdOverride: 'macos'));
}
# Flutter-related
**/Flutter/ephemeral/
**/Pods/
# Xcode-related
**/dgph
**/xcuserdata/
#include "ephemeral/Flutter-Generated.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"
<?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>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "platform_channel.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 = "33CC10EC2044A3C60003C045"
BuildableName = "platform_channel.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C80D4294CF70F00263BE5"
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 = "33CC10EC2044A3C60003C045"
BuildableName = "platform_channel.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 = "33CC10EC2044A3C60003C045"
BuildableName = "platform_channel.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?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>
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import Cocoa
import FlutterMacOS
@NSApplicationMain
class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
This diff is collapsed.
// Application-level settings for the Runner target.
//
// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
// future. If not, the values below would default to using the project name when this becomes a
// 'flutter create' template.
// The application's name. By default this is also the title of the Flutter window.
PRODUCT_NAME = platform_channel
// The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = com.example.platformChannel
// The copyright displayed in application information
PRODUCT_COPYRIGHT = Copyright © 2023 com.example. All rights reserved.
#include "../../Flutter/Flutter-Debug.xcconfig"
#include "Warnings.xcconfig"
#include "../../Flutter/Flutter-Release.xcconfig"
#include "Warnings.xcconfig"
WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
GCC_WARN_UNDECLARED_SELECTOR = YES
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
CLANG_WARN_PRAGMA_PACK = YES
CLANG_WARN_STRICT_PROTOTYPES = YES
CLANG_WARN_COMMA = YES
GCC_WARN_STRICT_SELECTOR_MATCH = YES
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
GCC_WARN_SHADOW = YES
CLANG_WARN_UNREACHABLE_CODE = YES
<?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>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>
<?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>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>$(PRODUCT_COPYRIGHT)</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>FlutterApplication</string>
</dict>
</plist>
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import Cocoa
import FlutterMacOS
class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeDelegate {
private let powerSource = PowerSource()
private let stateChangeSource = PowerSourceStateChangeHandler()
private var eventSink: FlutterEventSink?
override func awakeFromNib() {
let flutterViewController = FlutterViewController.init()
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
// Register battery method channel.
let registrar = flutterViewController.registrar(forPlugin: "BatteryLevel")
let batteryChannel = FlutterMethodChannel(
name: "samples.flutter.io/battery",
binaryMessenger: registrar.messenger)
batteryChannel.setMethodCallHandler({ [weak self] (call, result) in
switch call.method {
case "getBatteryLevel":
let level = self?.powerSource.getCurrentCapacity()
if level == -1 {
result(
FlutterError(
code: "UNAVAILABLE",
message: "Battery info unavailable",
details: nil))
}
result(level)
default:
result(FlutterMethodNotImplemented)
}
})
// Register charging event channel.
let chargingChannel = FlutterEventChannel(
name: "samples.flutter.io/charging",
binaryMessenger: registrar.messenger)
chargingChannel.setStreamHandler(self)
RegisterGeneratedPlugins(registry: flutterViewController)
super.awakeFromNib()
}
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink)
-> FlutterError?
{
self.eventSink = events
self.emitPowerStatusEvent()
self.stateChangeSource.delegate = self
return nil
}
func onCancel(withArguments arguments: Any?) -> FlutterError? {
self.stateChangeSource.delegate = nil
self.eventSink = nil
return nil
}
func onPowerSourceStateChanged() {
self.emitPowerStatusEvent()
}
func emitPowerStatusEvent() {
if let sink = self.eventSink {
switch self.powerSource.getPowerState() {
case .ac:
sink("charging")
case .battery:
sink("discharging")
case .unknown:
sink("UNAVAILABLE")
}
}
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import Foundation
import IOKit.ps
enum PowerState {
case ac
case battery
case unknown
}
/// A convenience wrapper for an IOKit power source.
class PowerSource {
let info = IOPSCopyPowerSourcesInfo().takeRetainedValue()
lazy var sources = IOPSCopyPowerSourcesList(info).takeRetainedValue() as Array
/// Returns the current power source capacity. Apple-defined power sources will return this value
/// as a percentage.
func getCurrentCapacity() -> Int {
if let source = sources.first {
let description =
IOPSGetPowerSourceDescription(info, source).takeUnretainedValue() as! [String: AnyObject]
if let level = description[kIOPSCurrentCapacityKey] as? Int {
return level
}
}
return -1
}
/// Returns whether the device is drawing battery power or connected to an external power source.
func getPowerState() -> PowerState {
if !sources.isEmpty {
let source = sources[0]
let description =
IOPSGetPowerSourceDescription(info, source).takeUnretainedValue() as! [String: AnyObject]
if let state = description[kIOPSPowerSourceStateKey] as? String {
switch state {
case kIOPSACPowerValue:
return .ac
case kIOPSBatteryPowerValue:
return .battery
default:
return .unknown
}
}
}
return .unknown
}
}
protocol PowerSourceStateChangeDelegate: AnyObject {
func onPowerSourceStateChanged()
}
/// A listener for system power source state change events. Notifies the delegate on each event.
class PowerSourceStateChangeHandler {
private var runLoopSource: CFRunLoopSource?
weak var delegate: PowerSourceStateChangeDelegate?
init() {
let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
self.runLoopSource = IOPSNotificationCreateRunLoopSource(
{ (context: UnsafeMutableRawPointer?) in
let weakSelf = Unmanaged<PowerSourceStateChangeHandler>.fromOpaque(
UnsafeRawPointer(context!)
).takeUnretainedValue()
weakSelf.delegate?.onPowerSourceStateChanged()
}, context
).takeRetainedValue()
CFRunLoopAddSource(CFRunLoopGetCurrent(), self.runLoopSource, .defaultMode)
}
deinit {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), self.runLoopSource, .defaultMode)
}
}
<?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>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import FlutterMacOS
import Cocoa
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.
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment