Skip to content

Commit 52f4957

Browse files
Tiskaapoichet
andauthored
Stream Battery Eco Mode (#16)
* feat(eco mode stream): bump version 0.2, add eco mode stream --------- Co-authored-by: apoichet <a.poichet@gmail.com>
1 parent f7e0ac7 commit 52f4957

15 files changed

Lines changed: 917 additions & 244 deletions

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.2.0
2+
3+
> Add Eco Mode Stream
4+
5+
- **FEAT**: Add eco mode stream `isBatteryEcoModeStream`.
6+
17
## 0.0.1
28

39
> Initial release

README.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,22 @@ also to offer a less energy-consuming app.
2222

2323
## Features
2424

25-
| Feature | Android | iOS | Runtime | Event |
26-
|:---------------------------------------------------------------------------------------------|:---------------------------------------:|:---------------------------------------:|:-------------------------------------:|:-----:|
27-
| getPlatformInfo() | Yes | Yes | | |
28-
| getBatteryLevel() | Yes | Yes | X | |
29-
| getBatteryState() | No | Yes | X | |
30-
| isBatteryInLowPowerMode() | Yes | Yes | X | |
31-
| lowPowerModeEventStream() | Yes | Yes | X | X |
32-
| getThermalState() | Yes | Yes | X | |
33-
| getProcessorCount() | Yes | Yes | | |
34-
| getTotalMemory() | Yes | Yes | | |
35-
| getFreeMemory() | Yes | Yes | X | |
36-
| getTotalStorage() | Yes | Yes | | |
37-
| getFreeStorage() | Yes | Yes | X | |
38-
| <span style="color: #3CB371">**isBatteryEcoMode()**</span> | <span style="color: #3CB371">Yes</span> | <span style="color: #3CB371">Yes</span> | <span style="color: #3CB371">X</span> | |
39-
| <span style="color: #3CB371">**getEcoRange**()</span> | <span style="color: #3CB371">Yes</span> | <span style="color: #3CB371">Yes</span> | <span style="color: #3CB371">X</span> | |
25+
| Feature | Android | iOS | Runtime | Event |
26+
|:---------------------------------------------------------------------------------------------------|:---------------------------------------:|:---------------------------------------:|:-------------------------------------:|:-----:|
27+
| getPlatformInfo() | Yes | Yes | | |
28+
| getBatteryLevel() | Yes | Yes | X | |
29+
| getBatteryState() | No | Yes | X | |
30+
| isBatteryInLowPowerMode() | Yes | Yes | X | |
31+
| lowPowerModeEventStream() | Yes | Yes | X | X |
32+
| getThermalState() | Yes | Yes | X | |
33+
| getProcessorCount() | Yes | Yes | | |
34+
| getTotalMemory() | Yes | Yes | | |
35+
| getFreeMemory() | Yes | Yes | X | |
36+
| getTotalStorage() | Yes | Yes | | |
37+
| getFreeStorage() | Yes | Yes | X | |
38+
| isBatteryEcoModeStream | Yes | No | | X |
39+
| <span style="color: #3CB371">**isBatteryEcoMode()**</span> | <span style="color: #3CB371">Yes</span> | <span style="color: #3CB371">Yes</span> | <span style="color: #3CB371">X</span> | |
40+
| <span style="color: #3CB371">**getEcoRange**()</span> | <span style="color: #3CB371">Yes</span> | <span style="color: #3CB371">Yes</span> | <span style="color: #3CB371">X</span> | |
4041

4142

4243
## Eco Mode

android/src/main/kotlin/sncf/connect/tech/flutter_eco_mode/FlutterEcoModePlugin.kt

Lines changed: 161 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,66 @@ package sncf.connect.tech.flutter_eco_mode
33
import android.content.BroadcastReceiver
44
import android.content.Context
55
import android.content.Intent
6+
import android.content.Intent.ACTION_BATTERY_CHANGED
67
import android.content.IntentFilter
78
import android.os.BatteryManager
9+
import android.os.BatteryManager.BATTERY_STATUS_CHARGING
10+
import android.os.BatteryManager.BATTERY_STATUS_DISCHARGING
11+
import android.os.BatteryManager.BATTERY_STATUS_FULL
12+
import android.os.BatteryManager.BATTERY_STATUS_NOT_CHARGING
813
import android.os.Build
914
import android.os.Environment
1015
import android.os.PowerManager
16+
import android.os.PowerManager.THERMAL_STATUS_CRITICAL
17+
import android.os.PowerManager.THERMAL_STATUS_EMERGENCY
18+
import android.os.PowerManager.THERMAL_STATUS_LIGHT
19+
import android.os.PowerManager.THERMAL_STATUS_MODERATE
20+
import android.os.PowerManager.THERMAL_STATUS_NONE
21+
import android.os.PowerManager.THERMAL_STATUS_SEVERE
22+
import android.os.PowerManager.THERMAL_STATUS_SHUTDOWN
1123
import android.os.StatFs
1224
import androidx.annotation.RequiresApi
1325
import io.flutter.embedding.engine.plugins.FlutterPlugin
1426
import io.flutter.plugin.common.EventChannel
27+
import sncf.connect.tech.flutter_eco_mode.BatteryState.CHARGING
28+
import sncf.connect.tech.flutter_eco_mode.BatteryState.DISCHARGING
29+
import sncf.connect.tech.flutter_eco_mode.BatteryState.FULL
30+
import sncf.connect.tech.flutter_eco_mode.BatteryState.UNKNOWN
31+
import sncf.connect.tech.flutter_eco_mode.ThermalState.CRITICAL
32+
import sncf.connect.tech.flutter_eco_mode.ThermalState.FAIR
33+
import sncf.connect.tech.flutter_eco_mode.ThermalState.SAFE
34+
import sncf.connect.tech.flutter_eco_mode.ThermalState.SERIOUS
1535

16-
class FlutterEcoModePlugin : FlutterPlugin, EcoModeApi, EventChannel.StreamHandler {
36+
37+
class FlutterEcoModePlugin : FlutterPlugin, EcoModeApi {
1738
private lateinit var context: Context
1839

1940
private val lowPowerModeEventChannel = "sncf.connect.tech/battery.isLowPowerMode"
20-
private var eventSink: EventChannel.EventSink? = null
21-
22-
private var powerSavingReceiver: BroadcastReceiver? = null
41+
private val batteryStateEventChannel = "sncf.connect.tech/battery.state"
42+
private val batteryLevelEventChannel = "sncf.connect.tech/battery.level"
2343

2444
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
2545
EcoModeApi.setUp(flutterPluginBinding.binaryMessenger, this)
2646
context = flutterPluginBinding.applicationContext
2747
EventChannel(
2848
flutterPluginBinding.binaryMessenger,
29-
lowPowerModeEventChannel
30-
).setStreamHandler(this)
49+
lowPowerModeEventChannel,
50+
).setStreamHandler(PowerModeStreamHandler(context))
51+
EventChannel(
52+
flutterPluginBinding.binaryMessenger,
53+
batteryStateEventChannel,
54+
).setStreamHandler(BatteryStateStreamHandler(context))
55+
EventChannel(
56+
flutterPluginBinding.binaryMessenger,
57+
batteryLevelEventChannel,
58+
).setStreamHandler(BatteryLevelStreamHandler(context))
3159
}
3260

61+
3362
override fun onDetachedFromEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
3463
EcoModeApi.setUp(flutterPluginBinding.binaryMessenger, null)
3564
}
3665

37-
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
38-
eventSink = events
39-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
40-
setupPowerSavingReceiver()
41-
}
42-
}
43-
44-
override fun onCancel(arguments: Any?) {
45-
eventSink = null
46-
context.unregisterReceiver(powerSavingReceiver)
47-
}
48-
4966
override fun getPlatformInfo(): String {
5067
val release: String = Build.VERSION.RELEASE
5168
val device: String = Build.DEVICE
@@ -55,15 +72,12 @@ class FlutterEcoModePlugin : FlutterPlugin, EcoModeApi, EventChannel.StreamHandl
5572
return "Android - $release - $device - $hardware - $product - $type"
5673
}
5774

58-
override fun getBatteryLevel(): Double {
59-
val batteryStatus = getBatteryStatus()
60-
val batteryLevel: Double? = batteryStatus?.let { intent ->
61-
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
62-
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
63-
level * 100 / scale.toDouble()
64-
}
65-
return batteryLevel ?: 0.0
66-
}
75+
override fun getBatteryLevel(): Double = getBatteryLevel(getBatteryStatus())
76+
private fun getBatteryLevel(intent: Intent?): Double = intent?.let {
77+
val level: Int = it.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
78+
val scale: Int = it.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
79+
level * 100 / scale.toDouble()
80+
} ?: 0.0
6781

6882
override fun getBatteryState(): BatteryState {
6983
val batteryStatus = getBatteryStatus()
@@ -79,18 +93,6 @@ class FlutterEcoModePlugin : FlutterPlugin, EcoModeApi, EventChannel.StreamHandl
7993
return false // can't return null so we return false for older versions
8094
}
8195

82-
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
83-
private fun setupPowerSavingReceiver() {
84-
powerSavingReceiver = object : BroadcastReceiver() {
85-
override fun onReceive(context: Context, intent: Intent?) {
86-
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
87-
eventSink?.success(powerManager.isPowerSaveMode)
88-
}
89-
}
90-
val filter = IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)
91-
context.registerReceiver(powerSavingReceiver, filter)
92-
}
93-
9496
override fun getThermalState(): ThermalState {
9597
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
9698
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
@@ -141,27 +143,138 @@ class FlutterEcoModePlugin : FlutterPlugin, EcoModeApi, EventChannel.StreamHandl
141143
}
142144

143145
private fun getBatteryStatus(): Intent? {
144-
return IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intentFilter ->
146+
return IntentFilter(ACTION_BATTERY_CHANGED).let { intentFilter ->
145147
context.registerReceiver(null, intentFilter)
146148
}
147149
}
148150

149151
private fun convertBatteryState(state: Int): BatteryState {
150152
return when (state) {
151-
BatteryManager.BATTERY_STATUS_CHARGING -> BatteryState.CHARGING
152-
BatteryManager.BATTERY_STATUS_FULL -> BatteryState.FULL
153-
BatteryManager.BATTERY_STATUS_DISCHARGING, BatteryManager.BATTERY_STATUS_NOT_CHARGING -> BatteryState.DISCHARGING
154-
else -> BatteryState.UNKNOWN
153+
BATTERY_STATUS_CHARGING -> CHARGING
154+
BATTERY_STATUS_FULL -> FULL
155+
BATTERY_STATUS_DISCHARGING, BATTERY_STATUS_NOT_CHARGING -> DISCHARGING
156+
else -> UNKNOWN
155157
}
156158
}
157159

158160
private fun convertThermalState(state: Int): ThermalState {
159161
return when (state) {
160-
PowerManager.THERMAL_STATUS_NONE -> ThermalState.SAFE
161-
PowerManager.THERMAL_STATUS_MODERATE, PowerManager.THERMAL_STATUS_LIGHT -> ThermalState.FAIR
162-
PowerManager.THERMAL_STATUS_SEVERE -> ThermalState.SERIOUS
163-
PowerManager.THERMAL_STATUS_CRITICAL, PowerManager.THERMAL_STATUS_EMERGENCY, PowerManager.THERMAL_STATUS_SHUTDOWN -> ThermalState.CRITICAL
162+
THERMAL_STATUS_NONE -> SAFE
163+
THERMAL_STATUS_MODERATE, THERMAL_STATUS_LIGHT -> FAIR
164+
THERMAL_STATUS_SEVERE -> SERIOUS
165+
THERMAL_STATUS_CRITICAL, THERMAL_STATUS_EMERGENCY, THERMAL_STATUS_SHUTDOWN -> CRITICAL
164166
else -> ThermalState.UNKNOWN
165167
}
166168
}
167169
}
170+
171+
class PowerModeStreamHandler(private val context: Context) : EventChannel.StreamHandler {
172+
173+
private var lowPowerModeEventSink: EventChannel.EventSink? = null
174+
private var powerSavingReceiver: BroadcastReceiver? = null
175+
176+
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
177+
lowPowerModeEventSink = events
178+
179+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
180+
setupPowerSavingReceiver()
181+
}
182+
}
183+
184+
override fun onCancel(p0: Any?) {
185+
context.unregisterReceiver(powerSavingReceiver)
186+
}
187+
188+
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
189+
private fun setupPowerSavingReceiver() {
190+
powerSavingReceiver = object : BroadcastReceiver() {
191+
override fun onReceive(context: Context, intent: Intent?) {
192+
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
193+
lowPowerModeEventSink?.success(powerManager.isPowerSaveMode)
194+
}
195+
}
196+
val filter = IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)
197+
context.registerReceiver(powerSavingReceiver, filter)
198+
}
199+
200+
}
201+
202+
class BatteryStateStreamHandler(private val context: Context) : EventChannel.StreamHandler {
203+
204+
private var batteryStateEventSink: EventChannel.EventSink? = null
205+
private var batteryStateReceiver: BroadcastReceiver? = null
206+
207+
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
208+
batteryStateEventSink = events
209+
210+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
211+
setupBatteryStateReceiver()
212+
}
213+
}
214+
215+
override fun onCancel(p0: Any?) {
216+
context.unregisterReceiver(batteryStateReceiver)
217+
}
218+
219+
@RequiresApi(Build.VERSION_CODES.M)
220+
private fun setupBatteryStateReceiver() {
221+
batteryStateReceiver = object : BroadcastReceiver() {
222+
override fun onReceive(context: Context, intent: Intent?) {
223+
val event = when (intent?.action) {
224+
ACTION_BATTERY_CHANGED ->
225+
when (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)) {
226+
BATTERY_STATUS_CHARGING -> CHARGING.name
227+
BATTERY_STATUS_FULL -> FULL.name
228+
BATTERY_STATUS_DISCHARGING, BATTERY_STATUS_NOT_CHARGING -> DISCHARGING.name
229+
else -> UNKNOWN.name
230+
}
231+
else -> DISCHARGING.name
232+
}
233+
batteryStateEventSink?.success(event)
234+
}
235+
}
236+
val filterBatteryState = IntentFilter()
237+
filterBatteryState.addAction(ACTION_BATTERY_CHANGED)
238+
context.registerReceiver(batteryStateReceiver, filterBatteryState)
239+
}
240+
241+
}
242+
243+
class BatteryLevelStreamHandler(private val context: Context) : EventChannel.StreamHandler {
244+
245+
private var batteryLevelEventSink: EventChannel.EventSink? = null
246+
private var batteryLevelReceiver: BroadcastReceiver? = null
247+
248+
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
249+
batteryLevelEventSink = events
250+
251+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
252+
setupBatteryLevelReceiver()
253+
}
254+
}
255+
256+
override fun onCancel(p0: Any?) {
257+
context.unregisterReceiver(batteryLevelReceiver)
258+
}
259+
260+
261+
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
262+
private fun setupBatteryLevelReceiver() {
263+
264+
batteryLevelReceiver = object : BroadcastReceiver() {
265+
266+
override fun onReceive(context: Context, intent: Intent?) {
267+
val batteryPct = intent?.let { i ->
268+
val level: Int = i.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
269+
val scale: Int = i.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
270+
level * 100 / scale.toFloat()
271+
}
272+
batteryLevelEventSink?.success(batteryPct?.toDouble())
273+
}
274+
}
275+
val filter = IntentFilter(ACTION_BATTERY_CHANGED)
276+
context.registerReceiver(batteryLevelReceiver, filter)
277+
278+
}
279+
280+
}

0 commit comments

Comments
 (0)