From 4a4d100b91fb9fed3b1a260c06dcfa1ae8a359e8 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Wed, 5 Apr 2017 09:40:35 +0200 Subject: [PATCH] Add battery charging status to Platform Channel example (#9147) --- .../example/platformchannel/MainActivity.java | 45 ++++++++++++- .../platform_channel/ios/Runner/AppDelegate.h | 2 +- .../platform_channel/ios/Runner/AppDelegate.m | 49 +++++++++++++- examples/platform_channel/lib/main.dart | 67 ++++++++++++++----- .../test_driver/button_tap_test.dart | 27 ++++---- .../.idea/workspace.xml | 29 -------- 6 files changed, 155 insertions(+), 64 deletions(-) delete mode 100644 examples/platform_channel_swift/.idea/workspace.xml diff --git a/examples/platform_channel/android/app/src/main/java/com/example/platformchannel/MainActivity.java b/examples/platform_channel/android/app/src/main/java/com/example/platformchannel/MainActivity.java index af0825c077..6f10be30e0 100644 --- a/examples/platform_channel/android/app/src/main/java/com/example/platformchannel/MainActivity.java +++ b/examples/platform_channel/android/app/src/main/java/com/example/platformchannel/MainActivity.java @@ -4,6 +4,8 @@ package com.example.platformchannel; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; @@ -13,19 +15,41 @@ import android.os.Build.VERSION_CODES; import android.os.Bundle; import io.flutter.app.FlutterActivity; +import io.flutter.plugin.common.FlutterEventChannel; +import io.flutter.plugin.common.FlutterEventChannel.EventSink; +import io.flutter.plugin.common.FlutterEventChannel.StreamHandler; import io.flutter.plugin.common.FlutterMethodChannel; import io.flutter.plugin.common.FlutterMethodChannel.MethodCallHandler; import io.flutter.plugin.common.FlutterMethodChannel.Response; import io.flutter.plugin.common.MethodCall; public class MainActivity extends FlutterActivity { - private static final String CHANNEL = "samples.flutter.io/battery"; + private static final String BATTERY_CHANNEL = "samples.flutter.io/battery"; + private static final String CHARGING_CHANNEL = "samples.flutter.io/charging"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - new FlutterMethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler( + new FlutterEventChannel(getFlutterView(), CHARGING_CHANNEL).setStreamHandler( + new StreamHandler() { + private BroadcastReceiver chargingStateChangeReceiver; + @Override + public void onListen(Object arguments, EventSink events) { + chargingStateChangeReceiver = createChargingStateChangeReceiver(events); + registerReceiver( + chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + } + + @Override + public void onCancel(Object arguments) { + unregisterReceiver(chargingStateChangeReceiver); + chargingStateChangeReceiver = null; + } + } + ); + + new FlutterMethodChannel(getFlutterView(), BATTERY_CHANNEL).setMethodCallHandler( new MethodCallHandler() { @Override public void onMethodCall(MethodCall call, Response response) { @@ -45,6 +69,23 @@ public class MainActivity extends FlutterActivity { ); } + private BroadcastReceiver createChargingStateChangeReceiver(final EventSink events) { + return new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); + + if (status == BatteryManager.BATTERY_STATUS_UNKNOWN) { + events.error("UNAVAILABLE", "Charging status unavailable", null); + } else { + boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || + status == BatteryManager.BATTERY_STATUS_FULL; + events.success(isCharging ? "charging" : "discharging"); + } + } + }; + } + private int getBatteryLevel() { int batteryLevel = -1; if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { diff --git a/examples/platform_channel/ios/Runner/AppDelegate.h b/examples/platform_channel/ios/Runner/AppDelegate.h index d81813b700..c3197e9418 100644 --- a/examples/platform_channel/ios/Runner/AppDelegate.h +++ b/examples/platform_channel/ios/Runner/AppDelegate.h @@ -5,6 +5,6 @@ #import #import -@interface AppDelegate : FlutterAppDelegate +@interface AppDelegate : FlutterAppDelegate @end diff --git a/examples/platform_channel/ios/Runner/AppDelegate.m b/examples/platform_channel/ios/Runner/AppDelegate.m index c74eb73515..75f1172523 100644 --- a/examples/platform_channel/ios/Runner/AppDelegate.m +++ b/examples/platform_channel/ios/Runner/AppDelegate.m @@ -5,11 +5,16 @@ #import "AppDelegate.h" #import -@implementation AppDelegate + +@implementation AppDelegate { + FlutterEventReceiver _eventReceiver; +} + - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; + FlutterMethodChannel* batteryChannel = [FlutterMethodChannel methodChannelWithName:@"samples.flutter.io/battery" binaryMessenger:controller]; @@ -28,6 +33,11 @@ result(FlutterMethodNotImplemented); } }]; + + FlutterEventChannel* chargingChannel = [FlutterEventChannel + eventChannelWithName:@"samples.flutter.io/charging" + binaryMessenger:controller]; + [chargingChannel setStreamHandler:self]; return YES; } @@ -41,4 +51,41 @@ } } +- (FlutterError*)onListenWithArguments:(id)arguments + eventReceiver:(FlutterEventReceiver)eventReceiver { + _eventReceiver = eventReceiver; + [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onBatteryStateDidChange:) + name:UIDeviceBatteryStateDidChangeNotification + object:nil]; + return nil; +} + +- (void)onBatteryStateDidChange:(NSNotification*)notification { + if (!_eventReceiver) return; + UIDeviceBatteryState state = [[UIDevice currentDevice] batteryState]; + switch (state) { + case UIDeviceBatteryStateFull: + case UIDeviceBatteryStateCharging: + _eventReceiver(@"charging"); + break; + case UIDeviceBatteryStateUnplugged: + _eventReceiver(@"discharging"); + break; + default: + _eventReceiver([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Charging status unavailable" + details:nil]); + break; + } +} + +- (FlutterError*)onCancelWithArguments:(id)arguments { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + _eventReceiver = nil; + return nil; +} + @end diff --git a/examples/platform_channel/lib/main.dart b/examples/platform_channel/lib/main.dart index 6c8c1615e1..19f6738f7a 100644 --- a/examples/platform_channel/lib/main.dart +++ b/examples/platform_channel/lib/main.dart @@ -1,4 +1,4 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -13,36 +13,67 @@ class PlatformChannel extends StatefulWidget { } class _PlatformChannelState extends State { - static const PlatformMethodChannel platform = const PlatformMethodChannel('samples.flutter.io/battery'); - String _batteryLevel = ''; + static const PlatformMethodChannel methodChannel = + const PlatformMethodChannel('samples.flutter.io/battery'); + static const PlatformEventChannel eventChannel = + const PlatformEventChannel('samples.flutter.io/charging'); + + String _batteryLevel = 'Battery level: unknown.'; + String _chargingStatus = 'Battery status: unknown.'; Future _getBatteryLevel() async { String batteryLevel; try { - final int result = await platform.invokeMethod('getBatteryLevel'); - batteryLevel = 'Battery level at $result % .'; - } on PlatformException catch (e) { - batteryLevel = "Failed to get battery level: '${e.message}'."; + final int result = await methodChannel.invokeMethod('getBatteryLevel'); + batteryLevel = 'Battery level: $result%.'; + } on PlatformException { + batteryLevel = "Failed to get battery level."; } setState(() { _batteryLevel = batteryLevel; }); } + @override + void initState() { + super.initState(); + eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError); + } + + void _onEvent(String event) { + setState(() { + _chargingStatus = + "Battery status: ${event == 'charging' ? '' : 'dis'}charging."; + }); + } + + void _onError(PlatformException error) { + setState(() { + _chargingStatus = "Battery status: unknown."; + }); + } + @override Widget build(BuildContext context) { return new Material( - child: new Center( - child: new Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - new RaisedButton( - child: new Text('Get Battery Level'), - onPressed: _getBatteryLevel, - ), - new Text(_batteryLevel, key: new Key('Battery level label')), - ], - ), + child: new Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + new Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + new Text(_batteryLevel, key: new Key('Battery level label')), + new Padding( + padding: new EdgeInsets.all(16.0), + child: new RaisedButton( + child: new Text('Refresh'), + onPressed: _getBatteryLevel, + ), + ), + ], + ), + new Text(_chargingStatus), + ], ), ); } diff --git a/examples/platform_channel/test_driver/button_tap_test.dart b/examples/platform_channel/test_driver/button_tap_test.dart index cf6601ead1..67ea6b86f9 100644 --- a/examples/platform_channel/test_driver/button_tap_test.dart +++ b/examples/platform_channel/test_driver/button_tap_test.dart @@ -14,23 +14,24 @@ void main() { }); tearDownAll(() async { - if (driver != null) - driver.close(); + if (driver != null) driver.close(); }); test('tap on the button, verify result', () async { - final SerializableFinder batteryLevelLabel = find.byValueKey('Battery level label'); - expect(batteryLevelLabel, isNotNull); + final SerializableFinder batteryLevelLabel = + find.byValueKey('Battery level label'); + expect(batteryLevelLabel, isNotNull); - final SerializableFinder button = find.text('Get Battery Level'); - await driver.waitFor(button); - await driver.tap(button); + final SerializableFinder button = find.text('Refresh'); + await driver.waitFor(button); + await driver.tap(button); - String batteryLevel; - while(batteryLevel == null || batteryLevel.isEmpty) { - batteryLevel = await driver.getText(batteryLevelLabel); - } - expect(batteryLevel, isNotEmpty); + String batteryLevel; + while (batteryLevel == null || batteryLevel.contains('unknown')) { + batteryLevel = await driver.getText(batteryLevelLabel); + } + + expect(batteryLevel.contains('%'), isTrue); }); }); -} \ No newline at end of file +} diff --git a/examples/platform_channel_swift/.idea/workspace.xml b/examples/platform_channel_swift/.idea/workspace.xml deleted file mode 100644 index 1e7e0cd929..0000000000 --- a/examples/platform_channel_swift/.idea/workspace.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - -