Skip to content

Commit 8cf79ea

Browse files
author
Mykola Mokhnach
authored
Refactor network connection setting on Android (#865)
* Refactor network connection setting on Android * Add a comment about airplane mode * Change bit mask type to long * Update constant types * Use operation shortcuts * Remove the redundant verification * Update tests * Tune assertions
1 parent 3bfe707 commit 8cf79ea

File tree

7 files changed

+243
-37
lines changed

7 files changed

+243
-37
lines changed

src/main/java/io/appium/java_client/android/AndroidDriver.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.appium.java_client.FindsByAndroidUIAutomator;
2626
import io.appium.java_client.LocksDevice;
2727
import io.appium.java_client.PressesKeyCode;
28+
import io.appium.java_client.android.connection.HasNetworkConnection;
2829
import io.appium.java_client.remote.MobilePlatform;
2930
import io.appium.java_client.screenrecording.CanRecordScreen;
3031
import io.appium.java_client.service.local.AppiumDriverLocalService;

src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,12 @@ public class AndroidMobileCommandHelper extends MobileCommand {
197197
/**
198198
* This method forms a {@link Map} of parameters for the setting of device network connection.
199199
*
200-
* @param connection The bitmask of the desired connection
200+
* @param bitMask The bitmask of the desired connection
201201
* @return a key-value pair. The key is the command name. The value is a {@link Map} command arguments.
202202
*/
203-
public static Map.Entry<String, Map<String, ?>> setConnectionCommand(Connection connection) {
203+
public static Map.Entry<String, Map<String, ?>> setConnectionCommand(long bitMask) {
204204
String[] parameters = new String[] {"name", "parameters"};
205-
Object[] values =
206-
new Object[] {"network_connection", ImmutableMap.of("type", connection.bitMask)};
205+
Object[] values = new Object[] {"network_connection", ImmutableMap.of("type", bitMask)};
207206
return new AbstractMap.SimpleEntry<>(
208207
SET_NETWORK_CONNECTION, prepareArguments(parameters, values));
209208
}

src/main/java/io/appium/java_client/android/Connection.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
/**
2020
* for use with setting Network Connections on a mobile device.
21+
* @deprecated Use {@link io.appium.java_client.android.connection.ConnectionState} instead
2122
*/
23+
@Deprecated
2224
public enum Connection {
2325
NONE(0),
2426
AIRPLANE(1),
@@ -31,4 +33,8 @@ public enum Connection {
3133
Connection(int bitMask) {
3234
this.bitMask = bitMask;
3335
}
36+
37+
public int getBitMask() {
38+
return bitMask;
39+
}
3440
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.android.connection;
18+
19+
public class ConnectionState {
20+
public static final long AIRPLANE_MODE_MASK = 0b001;
21+
public static final long WIFI_MASK = 0b010;
22+
public static final long DATA_MASK = 0b100;
23+
24+
private final long bitMask;
25+
26+
public long getBitMask() {
27+
return bitMask;
28+
}
29+
30+
public ConnectionState(long bitMask) {
31+
this.bitMask = bitMask;
32+
}
33+
34+
/**
35+
* @return true if airplane mode is enabled.
36+
*/
37+
public boolean isAirplaneModeEnabled() {
38+
return (bitMask & AIRPLANE_MODE_MASK) != 0;
39+
}
40+
41+
/**
42+
* @return true if Wi-Fi connection is enabled.
43+
*/
44+
public boolean isWiFiEnabled() {
45+
return (bitMask & WIFI_MASK) != 0;
46+
}
47+
48+
/**
49+
* @return true if data connection is enabled.
50+
*/
51+
public boolean isDataEnabled() {
52+
return (bitMask & DATA_MASK) != 0;
53+
}
54+
}
55+
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.android.connection;
18+
19+
import static io.appium.java_client.android.connection.ConnectionState.AIRPLANE_MODE_MASK;
20+
import static io.appium.java_client.android.connection.ConnectionState.DATA_MASK;
21+
import static io.appium.java_client.android.connection.ConnectionState.WIFI_MASK;
22+
23+
public class ConnectionStateBuilder {
24+
private long bitMask;
25+
26+
/**
27+
* Initializes connection state builder with the default value (all off).
28+
*/
29+
public ConnectionStateBuilder() {
30+
this.bitMask = 0;
31+
}
32+
33+
/**
34+
* Initializes connection state builder with the the predefined bit mask.
35+
* This constructor might be handy to change an existing connection state.
36+
*
37+
* @param bitMask the actual initial state bit mask to set
38+
*/
39+
public ConnectionStateBuilder(long bitMask) {
40+
this.bitMask = bitMask;
41+
}
42+
43+
/**
44+
* Initializes connection state builder with the the predefined bit mask.
45+
* This constructor might be handy to change an existing connection state.
46+
*
47+
* @param state the actual initial state to set
48+
*/
49+
public ConnectionStateBuilder(ConnectionState state) {
50+
this(state.getBitMask());
51+
}
52+
53+
/**
54+
* Sets airplane mode to enabled state if it was disabled.
55+
* This option only works up to Android 6.
56+
* Enabling the airplane mode on the device will automatically
57+
* disable Wi-Fi and data connections.
58+
*
59+
* @return self instance for chaining
60+
*/
61+
public ConnectionStateBuilder withAirplaneModeEnabled() {
62+
bitMask |= AIRPLANE_MODE_MASK;
63+
return this;
64+
}
65+
66+
/**
67+
* Sets airplane mode to disabled state if it was enabled.
68+
* This option only works up to Android 6.
69+
*
70+
* @return self instance for chaining
71+
*/
72+
public ConnectionStateBuilder withAirplaneModeDisabled() {
73+
bitMask &= ~AIRPLANE_MODE_MASK;
74+
return this;
75+
}
76+
77+
/**
78+
* Sets Wi-Fi connection mode to enabled state if it was disabled.
79+
*
80+
* @return self instance for chaining
81+
*/
82+
public ConnectionStateBuilder withWiFiEnabled() {
83+
bitMask |= WIFI_MASK;
84+
return this;
85+
}
86+
87+
/**
88+
* Sets Wi-Fi connection mode to disabled state if it was enabled.
89+
*
90+
* @return self instance for chaining
91+
*/
92+
public ConnectionStateBuilder withWiFiDisabled() {
93+
bitMask &= ~WIFI_MASK;
94+
return this;
95+
}
96+
97+
/**
98+
* Sets data connection mode to enabled state if it was disabled.
99+
* This option only works on rooted devices or on emulators.
100+
*
101+
* @return self instance for chaining
102+
*/
103+
public ConnectionStateBuilder withDataEnabled() {
104+
bitMask |= DATA_MASK;
105+
return this;
106+
}
107+
108+
/**
109+
* Sets data connection mode to disabled state if it was enabled.
110+
* This option only works on rooted devices or on emulators.
111+
*
112+
* @return self instance for chaining
113+
*/
114+
public ConnectionStateBuilder withDataDisabled() {
115+
bitMask &= ~DATA_MASK;
116+
return this;
117+
}
118+
119+
/**
120+
* Builds connection state instance, which is ready to be passed as Appium server parameter.
121+
*
122+
* @return ConnectionState instance
123+
*/
124+
public ConnectionState build() {
125+
return new ConnectionState(bitMask);
126+
}
127+
}

src/main/java/io/appium/java_client/android/HasNetworkConnection.java renamed to src/main/java/io/appium/java_client/android/connection/HasNetworkConnection.java

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,43 +14,44 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.appium.java_client.android;
17+
package io.appium.java_client.android.connection;
1818

1919
import static io.appium.java_client.android.AndroidMobileCommandHelper.getNetworkConnectionCommand;
2020
import static io.appium.java_client.android.AndroidMobileCommandHelper.setConnectionCommand;
2121

2222
import io.appium.java_client.CommandExecutionHelper;
2323
import io.appium.java_client.ExecutesMethod;
24-
import org.openqa.selenium.WebDriverException;
24+
import io.appium.java_client.android.Connection;
2525

2626
public interface HasNetworkConnection extends ExecutesMethod {
27-
2827
/**
2928
* Set the network connection of the device.
3029
*
3130
* @param connection The bitmask of the desired connection
31+
* @deprecated use {@link #setConnection(ConnectionState)} instead
3232
*/
33+
@Deprecated
3334
default void setConnection(Connection connection) {
34-
CommandExecutionHelper.execute(this, setConnectionCommand(connection));
35+
CommandExecutionHelper.execute(this, setConnectionCommand(connection.getBitMask()));
3536
}
3637

38+
/**
39+
* Set the network connection of the device.
40+
*
41+
* @param connection The bitmask of the desired connection
42+
* @return Connection object, which represents the resulting state
43+
*/
44+
default ConnectionState setConnection(ConnectionState connection) {
45+
return new ConnectionState(CommandExecutionHelper.execute(this,
46+
setConnectionCommand(connection.getBitMask())));
47+
}
3748

3849
/**
3950
* Get the current network settings of the device.
4051
*
41-
* @return Connection object will let you inspect the status
42-
* of None, AirplaneMode, Wifi, Data and All connections
52+
* @return Connection object, which lets you to inspect the current status
4353
*/
44-
default Connection getConnection() {
45-
long bitMask = CommandExecutionHelper.execute(this, getNetworkConnectionCommand());
46-
Connection[] types = Connection.values();
47-
48-
for (Connection connection: types) {
49-
if (connection.bitMask == bitMask) {
50-
return connection;
51-
}
52-
}
53-
throw new WebDriverException("The unknown network connection "
54-
+ "type has been returned. The bitmask is " + bitMask);
54+
default ConnectionState getConnection() {
55+
return new ConnectionState(CommandExecutionHelper.execute(this, getNetworkConnectionCommand()));
5556
}
5657
}

src/test/java/io/appium/java_client/android/AndroidConnectionTest.java

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,50 @@
1616

1717
package io.appium.java_client.android;
1818

19-
import static org.junit.Assert.assertEquals;
19+
import static org.junit.Assert.assertFalse;
20+
import static org.junit.Assert.assertTrue;
2021

22+
import io.appium.java_client.android.connection.ConnectionState;
23+
import io.appium.java_client.android.connection.ConnectionStateBuilder;
2124
import org.junit.FixMethodOrder;
2225
import org.junit.Test;
2326
import org.junit.runners.MethodSorters;
2427

2528
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
2629
public class AndroidConnectionTest extends BaseAndroidTest {
2730

28-
@Test public void test1() {
29-
driver.setConnection(Connection.WIFI);
30-
assertEquals(Connection.WIFI,
31-
driver.getConnection());
31+
@Test
32+
public void test1() {
33+
ConnectionState state = driver.setConnection(new ConnectionStateBuilder()
34+
.withWiFiEnabled()
35+
.build());
36+
assertTrue(state.isWiFiEnabled());
3237
}
3338

34-
@Test public void test2() {
35-
driver.setConnection(Connection.NONE);
36-
assertEquals(Connection.NONE,
37-
driver.getConnection());
38-
driver.setConnection(Connection.AIRPLANE);
39-
assertEquals(Connection.AIRPLANE,
40-
driver.getConnection());
39+
@Test
40+
public void test2() {
41+
ConnectionState state = driver.setConnection(new ConnectionStateBuilder()
42+
.withAirplaneModeDisabled()
43+
.build());
44+
assertFalse(state.isAirplaneModeEnabled());
45+
assertFalse(state.isWiFiEnabled());
46+
assertFalse(state.isDataEnabled());
47+
state = driver.setConnection(new ConnectionStateBuilder(state)
48+
.withAirplaneModeEnabled()
49+
.build());
50+
assertTrue(state.isAirplaneModeEnabled());
4151
}
4252

43-
@Test public void test3() {
44-
driver.setConnection(Connection.ALL);
45-
assertEquals(Connection.ALL,
46-
driver.getConnection());
53+
@Test
54+
public void test3() {
55+
ConnectionState state = driver.setConnection(
56+
new ConnectionStateBuilder(driver.getConnection())
57+
.withAirplaneModeDisabled()
58+
.withWiFiEnabled()
59+
.withDataEnabled()
60+
.build());
61+
assertFalse(state.isAirplaneModeEnabled());
62+
assertTrue(state.isWiFiEnabled());
63+
assertTrue(state.isDataEnabled());
4764
}
4865
}

0 commit comments

Comments
 (0)