diff --git a/src/main/java/io/appium/java_client/android/AndroidBatteryInfo.java b/src/main/java/io/appium/java_client/android/AndroidBatteryInfo.java new file mode 100644 index 000000000..1c3ff2872 --- /dev/null +++ b/src/main/java/io/appium/java_client/android/AndroidBatteryInfo.java @@ -0,0 +1,34 @@ +package io.appium.java_client.android; + +import io.appium.java_client.battery.BatteryInfo; + +import java.util.Map; + +public class AndroidBatteryInfo extends BatteryInfo { + + public AndroidBatteryInfo(Map input) { + super(input); + } + + @SuppressWarnings("unchecked") + @Override + public BatteryState getState() { + final int state = ((Long) getInput().get("state")).intValue(); + switch (state) { + case 2: + return BatteryState.CHARGING; + case 3: + return BatteryState.DISCHARGING; + case 4: + return BatteryState.NOT_CHARGING; + case 5: + return BatteryState.FULL; + default: + return BatteryState.UNKNOWN; + } + } + + public enum BatteryState { + UNKNOWN, CHARGING, DISCHARGING, NOT_CHARGING, FULL + } +} diff --git a/src/main/java/io/appium/java_client/android/AndroidDriver.java b/src/main/java/io/appium/java_client/android/AndroidDriver.java index 6ff2f7d54..b6988659c 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -19,6 +19,9 @@ import static io.appium.java_client.android.AndroidMobileCommandHelper.endTestCoverageCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.openNotificationsCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + +import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumDriver; import io.appium.java_client.CommandExecutionHelper; @@ -26,6 +29,7 @@ import io.appium.java_client.LocksDevice; import io.appium.java_client.PressesKeyCode; import io.appium.java_client.android.connection.HasNetworkConnection; +import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -36,6 +40,8 @@ import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; +import java.util.Collections; +import java.util.Map; /** * Android driver implementation. @@ -54,7 +60,8 @@ public class AndroidDriver FindsByAndroidUIAutomator, LocksDevice, HasAndroidSettings, HasDeviceDetails, HasSupportedPerformanceDataType, AuthenticatesByFinger, CanRecordScreen, SupportsSpecialEmulatorCommands, - SupportsNetworkStateManagement, ListensToLogcatMessages, HasAndroidClipboard { + SupportsNetworkStateManagement, ListensToLogcatMessages, HasAndroidClipboard, + HasBattery { private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID; @@ -179,4 +186,10 @@ public void toggleLocationServices() { CommandExecutionHelper.execute(this, toggleLocationServicesCommand()); } + @SuppressWarnings("unchecked") + @Override + public AndroidBatteryInfo getBatteryInfo() { + return new AndroidBatteryInfo((Map) execute(EXECUTE_SCRIPT, ImmutableMap.of( + "script", "mobile: batteryInfo", "args", Collections.emptyList()))); + } } diff --git a/src/main/java/io/appium/java_client/battery/BatteryInfo.java b/src/main/java/io/appium/java_client/battery/BatteryInfo.java new file mode 100644 index 000000000..3ad656cae --- /dev/null +++ b/src/main/java/io/appium/java_client/battery/BatteryInfo.java @@ -0,0 +1,31 @@ +package io.appium.java_client.battery; + +import java.util.Map; + +public abstract class BatteryInfo { + private final Map input; + + public BatteryInfo(Map input) { + this.input = input; + } + + /** + * @return Battery level in range [0.0, 1.0], where 1.0 means 100% charge. + */ + public double getLevel() { + final Object value = getInput().get("level"); + if (value instanceof Long) { + return ((Long) value).doubleValue(); + } + return (double) value; + } + + /** + * @return Battery state value. + */ + public abstract T getState(); + + protected Map getInput() { + return this.input; + } +} diff --git a/src/main/java/io/appium/java_client/battery/HasBattery.java b/src/main/java/io/appium/java_client/battery/HasBattery.java new file mode 100644 index 000000000..4b25cc7e4 --- /dev/null +++ b/src/main/java/io/appium/java_client/battery/HasBattery.java @@ -0,0 +1,29 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.battery; + +import io.appium.java_client.ExecutesMethod; + +public interface HasBattery extends ExecutesMethod { + + /** + * Retrieves battery info from the device under test. + * + * @return BatteryInfo instance, containing the battery information + */ + T getBatteryInfo(); +} diff --git a/src/main/java/io/appium/java_client/ios/IOSBatteryInfo.java b/src/main/java/io/appium/java_client/ios/IOSBatteryInfo.java new file mode 100644 index 000000000..3344f9903 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/IOSBatteryInfo.java @@ -0,0 +1,32 @@ +package io.appium.java_client.ios; + +import io.appium.java_client.battery.BatteryInfo; + +import java.util.Map; + +public class IOSBatteryInfo extends BatteryInfo { + + public IOSBatteryInfo(Map input) { + super(input); + } + + @SuppressWarnings("unchecked") + @Override + public BatteryState getState() { + final int state = ((Long) getInput().get("state")).intValue(); + switch (state) { + case 1: + return BatteryState.UNPLUGGED; + case 2: + return BatteryState.CHARGING; + case 3: + return BatteryState.FULL; + default: + return BatteryState.UNKNOWN; + } + } + + public enum BatteryState { + UNKNOWN, UNPLUGGED, CHARGING, FULL + } +} diff --git a/src/main/java/io/appium/java_client/ios/IOSDriver.java b/src/main/java/io/appium/java_client/ios/IOSDriver.java index 9aedde7a2..c1d111532 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -18,6 +18,9 @@ import static io.appium.java_client.MobileCommand.RUN_APP_IN_BACKGROUND; import static io.appium.java_client.MobileCommand.prepareArguments; +import static org.openqa.selenium.remote.DriverCommand.EXECUTE_SCRIPT; + +import com.google.common.collect.ImmutableMap; import io.appium.java_client.AppiumDriver; import io.appium.java_client.FindsByIosClassChain; @@ -25,6 +28,7 @@ import io.appium.java_client.FindsByIosUIAutomation; import io.appium.java_client.HidesKeyboardWithKeyName; import io.appium.java_client.LocksDevice; +import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -39,6 +43,8 @@ import java.net.URL; import java.time.Duration; +import java.util.Collections; +import java.util.Map; /** * iOS driver implementation. @@ -56,7 +62,8 @@ public class IOSDriver extends AppiumDriver implements HidesKeyboardWithKeyName, ShakesDevice, HasIOSSettings, FindsByIosUIAutomation, LocksDevice, PerformsTouchID, FindsByIosNSPredicate, - FindsByIosClassChain, PushesFiles, CanRecordScreen, HasIOSClipboard, ListensToSyslogMessages { + FindsByIosClassChain, PushesFiles, CanRecordScreen, HasIOSClipboard, ListensToSyslogMessages, + HasBattery { private static final String IOS_PLATFORM = MobilePlatform.IOS; @@ -177,6 +184,13 @@ public IOSDriver(Capabilities desiredCapabilities) { return new InnerTargetLocator(); } + @SuppressWarnings("unchecked") + @Override + public IOSBatteryInfo getBatteryInfo() { + return new IOSBatteryInfo((Map) execute(EXECUTE_SCRIPT, ImmutableMap.of( + "script", "mobile: batteryInfo", "args", Collections.emptyList()))); + } + private class InnerTargetLocator extends RemoteTargetLocator { @Override public Alert alert() { return new IOSAlert(super.alert()); diff --git a/src/test/java/io/appium/java_client/android/BatteryTest.java b/src/test/java/io/appium/java_client/android/BatteryTest.java new file mode 100644 index 000000000..a48ecc092 --- /dev/null +++ b/src/test/java/io/appium/java_client/android/BatteryTest.java @@ -0,0 +1,33 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appium.java_client.android; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + +import org.junit.Test; + +public class BatteryTest extends BaseAndroidTest { + + @Test public void veryGettingBatteryInformation() { + final AndroidBatteryInfo batteryInfo = driver.getBatteryInfo(); + assertThat(batteryInfo.getLevel(), is(greaterThan(0.0))); + assertThat(batteryInfo.getState(), is(not(AndroidBatteryInfo.BatteryState.UNKNOWN))); + } +}