Skip to content

Commit 0f374c9

Browse files
author
Mykola Mokhnach
committed
Update applications management endpoints
1 parent 7da2d6c commit 0f374c9

11 files changed

+583
-16
lines changed

src/main/java/io/appium/java_client/InteractsWithApps.java

Lines changed: 116 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,34 @@
1616

1717
package io.appium.java_client;
1818

19+
import static io.appium.java_client.MobileCommand.ACTIVATE_APP;
1920
import static io.appium.java_client.MobileCommand.CLOSE_APP;
2021
import static io.appium.java_client.MobileCommand.INSTALL_APP;
2122
import static io.appium.java_client.MobileCommand.IS_APP_INSTALLED;
2223
import static io.appium.java_client.MobileCommand.LAUNCH_APP;
24+
import static io.appium.java_client.MobileCommand.QUERY_APP_STATE;
2325
import static io.appium.java_client.MobileCommand.REMOVE_APP;
2426
import static io.appium.java_client.MobileCommand.RESET;
2527
import static io.appium.java_client.MobileCommand.RUN_APP_IN_BACKGROUND;
28+
import static io.appium.java_client.MobileCommand.TERMINATE_APP;
2629
import static io.appium.java_client.MobileCommand.prepareArguments;
2730

2831
import com.google.common.collect.ImmutableMap;
32+
import io.appium.java_client.appmanagement.ApplicationState;
33+
import io.appium.java_client.appmanagement.BaseActivateApplicationOptions;
34+
import io.appium.java_client.appmanagement.BaseInstallApplicationOptions;
35+
import io.appium.java_client.appmanagement.BaseRemoveApplicationOptions;
36+
import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions;
2937

38+
import javax.annotation.Nullable;
3039
import java.time.Duration;
3140
import java.util.AbstractMap;
3241

3342
public interface InteractsWithApps extends ExecutesMethod {
43+
3444
/**
35-
* Launch the app which was provided in the capabilities at session creation.
45+
* Launches the app, which was provided in the capabilities at session creation,
46+
* and (re)starts the session.
3647
*/
3748
default void launchApp() {
3849
execute(LAUNCH_APP);
@@ -44,7 +55,23 @@ default void launchApp() {
4455
* @param appPath path to app to install.
4556
*/
4657
default void installApp(String appPath) {
47-
execute(INSTALL_APP, ImmutableMap.of("appPath", appPath));
58+
installApp(appPath, null);
59+
}
60+
61+
/**
62+
* Install an app on the mobile device.
63+
*
64+
* @param appPath path to app to install or a remote URL.
65+
* @param options Set of the corresponding instllation options for
66+
* the particular platform.
67+
*/
68+
default void installApp(String appPath, @Nullable BaseInstallApplicationOptions options) {
69+
String[] parameters = options == null ? new String[]{"appPath"} :
70+
new String[]{"appPath", "options"};
71+
Object[] values = options == null ? new Object[]{appPath} :
72+
new Object[]{appPath, options.build()};
73+
CommandExecutionHelper.execute(this,
74+
new AbstractMap.SimpleEntry<>(INSTALL_APP, prepareArguments(parameters, values)));
4875
}
4976

5077
/**
@@ -59,7 +86,7 @@ default boolean isAppInstalled(String bundleId) {
5986
}
6087

6188
/**
62-
* Reset the currently running app for this session.
89+
* Resets the currently running app together with the session.
6390
*/
6491
default void resetApp() {
6592
execute(RESET);
@@ -79,17 +106,99 @@ default void runAppInBackground(Duration duration) {
79106
/**
80107
* Remove the specified app from the device (uninstall).
81108
*
82-
* @param bundleId the bunble identifier (or app id) of the app to remove.
109+
* @param bundleId the bundle identifier (or app id) of the app to remove.
110+
*/
111+
default boolean removeApp(String bundleId) {
112+
return removeApp(bundleId, null);
113+
}
114+
115+
/**
116+
* Remove the specified app from the device (uninstall).
117+
*
118+
* @param bundleId the bundle identifier (or app id) of the app to remove.
119+
* @param options the set of uninstall options supported by the
120+
* particular platform.
121+
* @return true if the uninstall was successful.
83122
*/
84-
default void removeApp(String bundleId) {
85-
execute(REMOVE_APP, ImmutableMap.of("bundleId", bundleId));
123+
default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOptions options) {
124+
String[] parameters = options == null ? new String[]{"bundleId"} :
125+
new String[]{"bundleId", "options"};
126+
Object[] values = options == null ? new Object[]{bundleId} :
127+
new Object[]{bundleId, options.build()};
128+
return CommandExecutionHelper.execute(this,
129+
new AbstractMap.SimpleEntry<>(REMOVE_APP, prepareArguments(parameters, values)));
86130
}
87131

88132
/**
89-
* Close the app which was provided in the capabilities at session creation.
133+
* Close the app which was provided in the capabilities at session creation
134+
* and quits the session.
90135
*/
91136
default void closeApp() {
92137
execute(CLOSE_APP);
93138
}
94139

140+
/**
141+
* Activates the given app if it installed, but not running or if it is running in the
142+
* background.
143+
*
144+
* @param bundleId the bundle identifier (or app id) of the app to activate.
145+
*/
146+
default void activateApp(String bundleId) {
147+
activateApp(bundleId, null);
148+
}
149+
150+
/**
151+
* Activates the given app if it installed, but not running or if it is running in the
152+
* background.
153+
*
154+
* @param bundleId the bundle identifier (or app id) of the app to activate.
155+
* @param options the set of activation options supported by the
156+
* particular platform.
157+
*/
158+
default void activateApp(String bundleId, @Nullable BaseActivateApplicationOptions options) {
159+
String[] parameters = options == null ? new String[]{"bundleId"} :
160+
new String[]{"bundleId", "options"};
161+
Object[] values = options == null ? new Object[]{bundleId} :
162+
new Object[]{bundleId, options.build()};
163+
CommandExecutionHelper.execute(this,
164+
new AbstractMap.SimpleEntry<>(ACTIVATE_APP, prepareArguments(parameters, values)));
165+
}
166+
167+
/**
168+
* Queries the state of an application.
169+
*
170+
* @param bundleId the bundle identifier (or app id) of the app to query the state of.
171+
* @return one of possible {@link ApplicationState} values,
172+
*/
173+
default ApplicationState queryAppState(String bundleId) {
174+
return ApplicationState.ofCode(CommandExecutionHelper.execute(this,
175+
new AbstractMap.SimpleEntry<>(QUERY_APP_STATE, ImmutableMap.of("bundleId", bundleId))));
176+
}
177+
178+
/**
179+
* Terminate the particular application if it is running.
180+
*
181+
* @param bundleId the bundle identifier (or app id) of the app to be terminated.
182+
* @return true if the app was running before and has been successfully stopped.
183+
*/
184+
default boolean terminateApp(String bundleId) {
185+
return terminateApp(bundleId, null);
186+
}
187+
188+
/**
189+
* Terminate the particular application if it is running.
190+
*
191+
* @param bundleId the bundle identifier (or app id) of the app to be terminated.
192+
* @param options the set of termination options supported by the
193+
* particular platform.
194+
* @return true if the app was running before and has been successfully stopped.
195+
*/
196+
default boolean terminateApp(String bundleId, @Nullable BaseTerminateApplicationOptions options) {
197+
String[] parameters = options == null ? new String[]{"bundleId"} :
198+
new String[]{"bundleId", "options"};
199+
Object[] values = options == null ? new Object[]{bundleId} :
200+
new Object[]{bundleId, options.build()};
201+
return CommandExecutionHelper.execute(this,
202+
new AbstractMap.SimpleEntry<>(TERMINATE_APP, prepareArguments(parameters, values)));
203+
}
95204
}

src/main/java/io/appium/java_client/MobileCommand.java

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,20 @@ public class MobileCommand {
4444
public static final String RUN_APP_IN_BACKGROUND;
4545
protected static final String PERFORM_TOUCH_ACTION;
4646
protected static final String PERFORM_MULTI_TOUCH;
47-
protected static final String IS_APP_INSTALLED;
48-
protected static final String INSTALL_APP;
49-
protected static final String REMOVE_APP;
5047
protected static final String LAUNCH_APP;
5148
protected static final String CLOSE_APP;
5249
protected static final String GET_DEVICE_TIME;
5350
protected static final String GET_SESSION;
5451

52+
//region Applications Management
53+
protected static final String IS_APP_INSTALLED;
54+
protected static final String INSTALL_APP;
55+
protected static final String ACTIVATE_APP;
56+
protected static final String QUERY_APP_STATE;
57+
protected static final String TERMINATE_APP;
58+
protected static final String REMOVE_APP;
59+
//endregion
60+
5561
protected static final String GET_PERFORMANCE_DATA;
5662
protected static final String GET_SUPPORTED_PERFORMANCE_DATA_TYPES;
5763

@@ -97,14 +103,20 @@ public class MobileCommand {
97103
RUN_APP_IN_BACKGROUND = "runAppInBackground";
98104
PERFORM_TOUCH_ACTION = "performTouchAction";
99105
PERFORM_MULTI_TOUCH = "performMultiTouch";
100-
IS_APP_INSTALLED = "isAppInstalled";
101-
INSTALL_APP = "installApp";
102-
REMOVE_APP = "removeApp";
103106
LAUNCH_APP = "launchApp";
104107
CLOSE_APP = "closeApp";
105108
GET_DEVICE_TIME = "getDeviceTime";
106109
GET_SESSION = "getSession";
107110

111+
//region Applications Management
112+
IS_APP_INSTALLED = "isAppInstalled";
113+
QUERY_APP_STATE = "queryAppState";
114+
TERMINATE_APP = "terminateApp";
115+
ACTIVATE_APP = "activateApp";
116+
REMOVE_APP = "removeApp";
117+
INSTALL_APP = "installApp";
118+
//endregion
119+
108120
GET_PERFORMANCE_DATA = "getPerformanceData";
109121
GET_SUPPORTED_PERFORMANCE_DATA_TYPES = "getSuppportedPerformanceDataTypes";
110122

@@ -148,9 +160,6 @@ public class MobileCommand {
148160
commandRepository.put(RUN_APP_IN_BACKGROUND, postC("/session/:sessionId/appium/app/background"));
149161
commandRepository.put(PERFORM_TOUCH_ACTION, postC("/session/:sessionId/touch/perform"));
150162
commandRepository.put(PERFORM_MULTI_TOUCH, postC("/session/:sessionId/touch/multi/perform"));
151-
commandRepository.put(IS_APP_INSTALLED, postC("/session/:sessionId/appium/device/app_installed"));
152-
commandRepository.put(INSTALL_APP, postC("/session/:sessionId/appium/device/install_app"));
153-
commandRepository.put(REMOVE_APP, postC("/session/:sessionId/appium/device/remove_app"));
154163
commandRepository.put(LAUNCH_APP, postC("/session/:sessionId/appium/app/launch"));
155164
commandRepository.put(CLOSE_APP, postC("/session/:sessionId/appium/app/close"));
156165
commandRepository.put(LOCK, postC("/session/:sessionId/appium/device/lock"));
@@ -166,6 +175,16 @@ public class MobileCommand {
166175
postC("/session/:sessionId/appium/start_recording_screen"));
167176
commandRepository.put(STOP_RECORDING_SCREEN,
168177
postC("/session/:sessionId/appium/stop_recording_screen"));
178+
179+
//region Applications Management
180+
commandRepository.put(IS_APP_INSTALLED, postC("/session/:sessionId/appium/device/app_installed"));
181+
commandRepository.put(INSTALL_APP, postC("/session/:sessionId/appium/device/install_app"));
182+
commandRepository.put(ACTIVATE_APP, postC("/session/:sessionId/appium/device/activate_app"));
183+
commandRepository.put(REMOVE_APP, postC("/session/:sessionId/appium/device/remove_app"));
184+
commandRepository.put(TERMINATE_APP, postC("/session/:sessionId/appium/device/terminate_app"));
185+
commandRepository.put(QUERY_APP_STATE, getC("/session/:sessionId/appium/device/app_state"));
186+
//endregion
187+
169188
//iOS
170189
commandRepository.put(SHAKE, postC("/session/:sessionId/appium/device/shake"));
171190
commandRepository.put(TOUCH_ID, postC("/session/:sessionId/appium/simulator/touch_id"));
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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.appmanagement;
18+
19+
import com.google.common.collect.ImmutableMap;
20+
21+
import java.time.Duration;
22+
import java.util.Map;
23+
24+
import static com.google.common.base.Preconditions.checkArgument;
25+
import static com.google.common.base.Preconditions.checkNotNull;
26+
import static java.util.Optional.ofNullable;
27+
28+
public class AndroidInstallApplicationOptions extends
29+
BaseInstallApplicationOptions<AndroidInstallApplicationOptions> {
30+
private Boolean replace;
31+
private Duration timeout;
32+
private Boolean allowTestPackages;
33+
private Boolean useSdcard;
34+
private Boolean grantPermissions;
35+
36+
/**
37+
* Enables the possibility to upgrade/reinstall the application
38+
* if it is already present on the device (the default behavior).
39+
*
40+
* @return self instance for chaining.
41+
*/
42+
public AndroidInstallApplicationOptions withReplaceEnabled() {
43+
this.replace = true;
44+
return this;
45+
}
46+
47+
/**
48+
* Disables the possibility to upgrade/reinstall the application
49+
* if it is already present on the device.
50+
*
51+
* @return self instance for chaining.
52+
*/
53+
public AndroidInstallApplicationOptions withReplaceDisabled() {
54+
this.replace = false;
55+
return this;
56+
}
57+
58+
/**
59+
* The time to wait until the app is installed (60000ms by default).
60+
*
61+
* @param timeout the actual timeout value. The minimum time resolution
62+
* unit is one millisecond.
63+
* @return self instance for chaining.
64+
*/
65+
public AndroidInstallApplicationOptions withTimeout(Duration timeout) {
66+
checkArgument(!checkNotNull(timeout).isNegative(), "The timeout value cannot be negative");
67+
this.timeout = timeout;
68+
return this;
69+
}
70+
71+
/**
72+
* Allows to install packages marked as test in the manifest.
73+
*
74+
* @return self instance for chaining.
75+
*/
76+
public AndroidInstallApplicationOptions withAllowTestPackagesEnabled() {
77+
this.allowTestPackages = true;
78+
return this;
79+
}
80+
81+
/**
82+
* Disables a possibility to install packages marked as test in
83+
* the manifest (the default setting).
84+
*
85+
* @return self instance for chaining.
86+
*/
87+
public AndroidInstallApplicationOptions withAllowTestPackagesDisabled() {
88+
this.allowTestPackages = false;
89+
return this;
90+
}
91+
92+
/**
93+
* Forces the application to be installed of SD card
94+
* instead of the internal memory.
95+
*
96+
* @return self instance for chaining.
97+
*/
98+
public AndroidInstallApplicationOptions withUseSdcardEnabled() {
99+
this.useSdcard = true;
100+
return this;
101+
}
102+
103+
/**
104+
* Forces the application to be installed to the internal memory
105+
* (the default behavior).
106+
*
107+
* @return self instance for chaining.
108+
*/
109+
public AndroidInstallApplicationOptions withUseSdcardDisabled() {
110+
this.useSdcard = false;
111+
return this;
112+
}
113+
114+
/**
115+
* Grants all the permissions requested in the
116+
* application's manifest automatically after the installation
117+
* is completed under Android 6+.
118+
*
119+
* @return self instance for chaining.
120+
*/
121+
public AndroidInstallApplicationOptions withGrantPermissionsEnabled() {
122+
this.grantPermissions = true;
123+
return this;
124+
}
125+
126+
/**
127+
* Does not grant all the permissions requested in the
128+
* application's manifest automatically after the installation
129+
* is completed (the default behavior).
130+
*
131+
* @return self instance for chaining.
132+
*/
133+
public AndroidInstallApplicationOptions withGrantPermissionsDisabled() {
134+
this.grantPermissions = false;
135+
return this;
136+
}
137+
138+
@SuppressWarnings("unchecked")
139+
@Override
140+
public Map<String, Object> build() {
141+
final ImmutableMap.Builder builder = new ImmutableMap.Builder<String, Object>();
142+
ofNullable(replace).map(x -> builder.put("replace", x));
143+
ofNullable(timeout).map(x -> builder.put("timeout", x.toMillis()));
144+
ofNullable(allowTestPackages).map(x -> builder.put("allowTestPackages", x));
145+
ofNullable(useSdcard).map(x -> builder.put("useSdcard", x));
146+
ofNullable(grantPermissions).map(x -> builder.put("grantPermissions", x));
147+
return builder.build();
148+
}
149+
}

0 commit comments

Comments
 (0)