Skip to content

Commit 2f60e64

Browse files
Mykola MokhnachSrinivasanTarget
Mykola Mokhnach
authored andcommitted
Add clipboard handlers (#855)
* Add clipboard handlers * Fix checkstyle * Make Codacy happy
1 parent 7dd64d3 commit 2f60e64

File tree

9 files changed

+326
-2
lines changed

9 files changed

+326
-2
lines changed

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ public class MobileCommand {
5858
protected static final String REMOVE_APP;
5959
//endregion
6060

61+
//region Clipboard
62+
public static final String GET_CLIPBOARD;
63+
public static final String SET_CLIPBOARD;
64+
//endregion
65+
6166
protected static final String GET_PERFORMANCE_DATA;
6267
protected static final String GET_SUPPORTED_PERFORMANCE_DATA_TYPES;
6368

@@ -127,6 +132,11 @@ public class MobileCommand {
127132
INSTALL_APP = "installApp";
128133
//endregion
129134

135+
//region Clipboard
136+
SET_CLIPBOARD = "setClipboard";
137+
GET_CLIPBOARD = "getClipboard";
138+
//endregion
139+
130140
GET_PERFORMANCE_DATA = "getPerformanceData";
131141
GET_SUPPORTED_PERFORMANCE_DATA_TYPES = "getSuppportedPerformanceDataTypes";
132142

@@ -205,6 +215,11 @@ public class MobileCommand {
205215
commandRepository.put(QUERY_APP_STATE, postC("/session/:sessionId/appium/device/app_state"));
206216
//endregion
207217

218+
//region Clipboard
219+
commandRepository.put(GET_CLIPBOARD, postC("/session/:sessionId/appium/device/get_clipboard"));
220+
commandRepository.put(SET_CLIPBOARD, postC("/session/:sessionId/appium/device/set_clipboard"));
221+
//endregion
222+
208223
//iOS
209224
commandRepository.put(SHAKE, postC("/session/:sessionId/appium/device/shake"));
210225
commandRepository.put(TOUCH_ID, postC("/session/:sessionId/appium/simulator/touch_id"));

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public class AndroidDriver<T extends WebElement>
5353
FindsByAndroidUIAutomator<T>, LocksDevice, HasAndroidSettings, HasDeviceDetails,
5454
HasSupportedPerformanceDataType, AuthenticatesByFinger,
5555
CanRecordScreen, SupportsSpecialEmulatorCommands,
56-
SupportsNetworkStateManagement {
56+
SupportsNetworkStateManagement, HasAndroidClipboard {
5757

5858
private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID;
5959

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
import static io.appium.java_client.MobileCommand.SET_CLIPBOARD;
21+
import static io.appium.java_client.MobileCommand.prepareArguments;
22+
23+
import io.appium.java_client.CommandExecutionHelper;
24+
import io.appium.java_client.clipboard.ClipboardContentType;
25+
import io.appium.java_client.clipboard.HasClipboard;
26+
27+
import java.nio.charset.StandardCharsets;
28+
import java.util.AbstractMap;
29+
import java.util.Base64;
30+
31+
public interface HasAndroidClipboard extends HasClipboard {
32+
/**
33+
* Set the content of device's clipboard.
34+
*
35+
* @param label clipboard data label.
36+
* @param contentType one of supported content types.
37+
* @param base64Content base64-encoded content to be set.
38+
*/
39+
default void setClipboard(String label, ClipboardContentType contentType, byte[] base64Content) {
40+
String[] parameters = new String[]{"content", "contentType", "label"};
41+
Object[] values = new Object[]{new String(checkNotNull(base64Content), StandardCharsets.UTF_8),
42+
contentType.name().toLowerCase(), checkNotNull(label)};
43+
CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(SET_CLIPBOARD,
44+
prepareArguments(parameters, values)));
45+
}
46+
47+
/**
48+
* Set the clipboard text.
49+
*
50+
* @param label clipboard data label.
51+
* @param text The actual text to be set.
52+
*/
53+
default void setClipboardText(String label, String text) {
54+
setClipboard(label, ClipboardContentType.PLAINTEXT, Base64
55+
.getEncoder()
56+
.encode(text.getBytes(StandardCharsets.UTF_8)));
57+
}
58+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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.clipboard;
18+
19+
public enum ClipboardContentType {
20+
PLAINTEXT, IMAGE, URL
21+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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.clipboard;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
import static io.appium.java_client.MobileCommand.GET_CLIPBOARD;
21+
import static io.appium.java_client.MobileCommand.SET_CLIPBOARD;
22+
import static io.appium.java_client.MobileCommand.prepareArguments;
23+
24+
import io.appium.java_client.CommandExecutionHelper;
25+
import io.appium.java_client.ExecutesMethod;
26+
27+
import java.nio.charset.StandardCharsets;
28+
import java.util.AbstractMap;
29+
import java.util.Base64;
30+
31+
public interface HasClipboard extends ExecutesMethod {
32+
/**
33+
* Set the content of device's clipboard.
34+
*
35+
* @param contentType one of supported content types.
36+
* @param base64Content base64-encoded content to be set.
37+
*/
38+
default void setClipboard(ClipboardContentType contentType, byte[] base64Content) {
39+
String[] parameters = new String[]{"content", "contentType"};
40+
Object[] values = new Object[]{new String(checkNotNull(base64Content), StandardCharsets.UTF_8),
41+
contentType.name().toLowerCase()};
42+
CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(SET_CLIPBOARD,
43+
prepareArguments(parameters, values)));
44+
}
45+
46+
/**
47+
* Get the content of the clipboard.
48+
*
49+
* @param contentType one of supported content types.
50+
* @return the actual content of the clipboard as base64-encoded string or an empty string if the clipboard is empty
51+
*/
52+
default String getClipboard(ClipboardContentType contentType) {
53+
return CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(GET_CLIPBOARD,
54+
prepareArguments("contentType", contentType.name().toLowerCase())));
55+
}
56+
57+
/**
58+
* Set the clipboard text.
59+
*
60+
* @param text The actual text to be set.
61+
*/
62+
default void setClipboardText(String text) {
63+
setClipboard(ClipboardContentType.PLAINTEXT, Base64
64+
.getEncoder()
65+
.encode(text.getBytes(StandardCharsets.UTF_8)));
66+
}
67+
68+
/**
69+
* Get the clipboard text.
70+
*
71+
* @return Either the text, which is stored in the clipboard or an empty string if the clipboard is empty
72+
*/
73+
default String getClipboardText() {
74+
byte[] base64decodedBytes = Base64
75+
.getDecoder()
76+
.decode(getClipboard(ClipboardContentType.PLAINTEXT));
77+
return new String(base64decodedBytes, StandardCharsets.UTF_8);
78+
}
79+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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.ios;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
21+
import io.appium.java_client.clipboard.ClipboardContentType;
22+
import io.appium.java_client.clipboard.HasClipboard;
23+
24+
import java.awt.image.BufferedImage;
25+
import java.io.ByteArrayInputStream;
26+
import java.io.ByteArrayOutputStream;
27+
import java.io.IOException;
28+
import java.net.MalformedURLException;
29+
import java.net.URL;
30+
import java.nio.charset.StandardCharsets;
31+
import java.util.Base64;
32+
import javax.imageio.ImageIO;
33+
34+
public interface HasIOSClipboard extends HasClipboard {
35+
/**
36+
* Set an image to the clipboard.
37+
*
38+
* @param img the actual image to be set.
39+
* @throws IOException if the image cannot be decoded in PNG representation
40+
*/
41+
default void setClipboardImage(BufferedImage img) throws IOException {
42+
try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) {
43+
ImageIO.write(checkNotNull(img), "png", os);
44+
setClipboard(ClipboardContentType.IMAGE, Base64
45+
.getEncoder()
46+
.encode(os.toByteArray()));
47+
}
48+
}
49+
50+
/**
51+
* Get an image from the clipboard
52+
*
53+
* @return the actual image instance.
54+
* @throws IOException If the returned image cannot be decoded or if the clipboard is empty.
55+
*/
56+
default BufferedImage getClipboardImage() throws IOException {
57+
final byte[] base64decodedBytes = Base64
58+
.getDecoder()
59+
.decode(getClipboard(ClipboardContentType.IMAGE));
60+
return ImageIO.read(new ByteArrayInputStream(base64decodedBytes));
61+
}
62+
63+
/**
64+
* Set an URL to the clipboard.
65+
*
66+
* @param url the actual URL to set.
67+
*/
68+
default void setClipboardUrl(URL url) {
69+
setClipboard(ClipboardContentType.URL, Base64
70+
.getEncoder()
71+
.encode(checkNotNull(url).toString().getBytes(StandardCharsets.UTF_8)));
72+
}
73+
74+
/**
75+
* Get an URL from the clipboard
76+
*
77+
* @return the actual URL instance.
78+
* @throws MalformedURLException if the URL in the clipboard is not valid or if the clipboard is empty.
79+
*/
80+
default URL getClipboardUrl() throws MalformedURLException {
81+
final byte[] base64decodedBytes = Base64
82+
.getDecoder()
83+
.decode(getClipboard(ClipboardContentType.URL));
84+
return new URL(new String(base64decodedBytes, StandardCharsets.UTF_8));
85+
}
86+
}

src/main/java/io/appium/java_client/ios/IOSDriver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public class IOSDriver<T extends WebElement>
5656
extends AppiumDriver<T>
5757
implements HidesKeyboardWithKeyName, ShakesDevice, HasIOSSettings,
5858
FindsByIosUIAutomation<T>, LocksDevice, PerformsTouchID, FindsByIosNSPredicate<T>,
59-
FindsByIosClassChain<T>, PushesFiles, CanRecordScreen {
59+
FindsByIosClassChain<T>, PushesFiles, CanRecordScreen, HasIOSClipboard {
6060

6161
private static final String IOS_PLATFORM = MobilePlatform.IOS;
6262

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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;
18+
19+
import static org.junit.Assert.assertEquals;
20+
21+
import org.junit.Before;
22+
import org.junit.Test;
23+
24+
public class ClipboardTest extends BaseAndroidTest {
25+
26+
@Before public void setUp() {
27+
driver.resetApp();
28+
}
29+
30+
@Test public void verifySetAndGetClipboardText() {
31+
final String text = "Happy testing";
32+
driver.setClipboardText(text);
33+
assertEquals(driver.getClipboardText(), text);
34+
}
35+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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.ios;
18+
19+
import static org.junit.Assert.assertEquals;
20+
21+
import org.junit.Test;
22+
23+
public class ClipboardTest extends AppIOSTest {
24+
25+
@Test public void verifySetAndGetClipboardText() {
26+
final String text = "Happy testing";
27+
driver.setClipboardText(text);
28+
assertEquals(driver.getClipboardText(), text);
29+
}
30+
}

0 commit comments

Comments
 (0)