Integrate and use the iOS SDK for Elastic Cloud Phone.
1. Quick start
1.1 Get the SDK and demo
By downloading and using the SDK, you agree to the WUYING Workspace SDK Privacy Policy.
All documents, SDKs, and client programs on this platform are for personal or enterprise use only. Do not distribute them to any third party without the consent of Alibaba Cloud.
Integration requirements
Minimum supported iOS version: 10.0
Due to iOS API availability, peripheral mouse and keyboard features require iOS 13.4 or later.
SDK integration
Unzip the SDK and copy it into your project.
Link the SDK library.
Go to Target --> Build Phases --> Link Binary With Libraries --> + --> Add Other --> Add Files and select the required framework.
Set the embed option.
Go to Target --> General --> Frameworks, Libraries, and Embedded Content, find ASPEngineSDK.framework, and select Embed Without Signing.
SDK permissions
Add the required permissions for ASPEngineSDK to your project's Info.plist file.
1. Microphone permission
Privacy - Microphone Usage Description2. Camera permission
Privacy - Camera Usage DescriptionSDK signing
The SDK is a dynamic library and must be signed for on-device debugging or for App Store submission.
Get a signing ID
To find your signing ID, run:
security find-identity -v -p codesigningIf you don't have a local certificate, log in to your Apple Developer account and download the provisioning profile. Right-click the downloaded file, choose Get Info, and find the SHA-1 field of the target certificate. This value is the signing ID.
Signing & Capabilities
In your project target, correctly configure the certificate in the Signing & Capabilities tab.
Add a signing shell script. This script is required for physical devices but not for simulators.
Go to Target --> Build Phases --> + --> New Run Script Phase and paste the shell script content. See the sample signing shell script below.
Note: This Run Script phase must be placed after the Embed Frameworks phase.
Sample signing shell script
set -e
SHELL_PATH="${PROJECT_DIR}/ASPDemo/Lib/ASPEngineSDK/ASPEngineSDK.framework/link_and_sign.sh"
KEY_ID="Your certificate's signing ID"
echo "===> Signing using $KEY_ID"
/bin/bash -c "${SHELL_PATH}"\ "${TARGET_BUILD_DIR}"\ "${FRAMEWORKS_FOLDER_PATH}"\ "${KEY_ID}"Project configuration
Disable Bitcode.
Go to Target --> Build Settings --> Build Options --> Enable Bitcode and set the option to No.
1.2 Integration workflow
1.3 Best practices
See Best practices for quick integration with cloud phones. The following diagram outlines the integration architecture.
You can use multiple login methods to get the connection ticket required by the SDK. The following diagram illustrates these workflows.
For code examples, refer to the sample code for the lifecycle APIs.
2. Lifecycle API
2.1 Initialize instance
+ (instancetype)buildStreamView;2.2 Establish connection
- (void)startWithTicket:(ASPConnTicket*) ticketParam;ASPConnTicket parameters:
Parameter | Description |
connTicket | Connection ticket for authentication. |
caFilePath | Absolute path to the CA file for TLS encryption. |
desktopId | Application instance ID, such as |
useVpc | Whether to connect over a VPC. |
enableTls | Enables encrypted transmission. Recommended: YES. |
enableStatistics | Enables tracking. Recommended: YES. |
preferRtcTransport | Enables the RTC channel. Recommended: YES. |
2.3 Disconnect
- (int)stop;2.4 Pause
Pauses the stream from the server and rendering on the client.
- (void)pause;2.5 Resume
Resumes the stream from the server and rendering on the client.
- (void)resume;2.6 Dispose instance
- (void)dispose;2.7 Callbacks
// Callbacks for the Elastic Cloud Phone connection.
@property (nonatomic, weak) id<ASPEngineDelegate> engineDelegate;
// Callback for resolution changes.
@property (nonatomic, weak) id<ASPEngineResolutionUpdateDelegate> resolutionUpdateDelegate;
// Callbacks for the mouse cursor.
@property (nonatomic, weak) id<ASPEngineCursorDelegate> cursorDelegate;
// Callback for orientation changes of the Elastic Cloud Phone.
@property (nonatomic, weak) id<ASPEngineOrientationUpdateDelegate> orientationUpdateDelegate;
// Callbacks for tracking.
@property (nonatomic, weak) id<ASPEngineStatisticsDelegate> statisticsDelegate;
// Callbacks for the Input Method Editor (IME). Not supported by Elastic Cloud Phone.
@property (nonatomic, weak) id<ASPEngineIMEDelegate> imeDelegate;
// Callbacks for logs. We recommend using a singleton for the delegate.
+ (void)setASPEngineLogDelegate:(id<ASPEngineLogDelegate>)delegate;
+ (void)unsetASPEngineLogDelegate;ASPEngineDelegate: Callbacks for Elastic Cloud Phone connections
API | Description |
onConnectionSuccess:(int)connectId | Called when the connection to the ECP is established. Returns the connection ID. |
onConnectionFailureWithErrCode:(int)errCode errMsg:(NSString*)errMsg | Called when the connection to the ECP fails. Returns an error code and an error message. |
onEngineErrorWithErrCode:(int)errCode errMsg:(NSString*)errMsg | Called when an internal SDK error occurs. Returns an error code and an error message. |
onDisconnected:(int)reason | Called when the connection to the ECP is disconnected. Returns a code indicating the reason for the disconnection. |
onFirstFrameRendered:(long)timeCostMS | Called when the first frame from the ECP is rendered. Returns the time elapsed in milliseconds. |
onReconnect:(int)errorCode | Called when the SDK attempts to reconnect to the ECP. Returns the error code that triggered the reconnection. |
onPolicyUpdate:(NSString *)policy | Called when the ECP policy is updated. Returns the policy configuration. |
onUpdateNetworkQos:(AspNetworkQoS)qos | Called to report the network Quality of Service (QoS) status. |
onSessionSuccess | Called when the ECP session is created. |
ASPEngineResolutionUpdateDelegate: Callbacks for resolution changes
API | Description |
onResolutionUpdateWithOldWidth:(int)oldWidth oldHeight:(int)oldHeight width:(int)width height:(int)height | Called when the resolution changes. Returns the old and new resolutions. |
onMonitorsDpiConfig:(int)dpi maxSupportDpi:(int)maxSupportDpi | Provides the DPI configuration and the maximum supported DPI. Not supported by Elastic Cloud Phone. |
ASPEngineCursorDelegate: Callbacks for the mouse cursor
API | Description |
onCursorBitmapUpdateWithHotX:(int)hotX hotY:(int)hotY width:(int)width height:(int)height rgba:(char*)rgba | Called when the cursor bitmap is updated. Provides the cursor's hot spot coordinates, dimensions, and RGBA data. |
onCursorReset | Called when the mouse cursor is reset. |
onCursorHide | Called when the mouse cursor is hidden. |
onCursorMoveWithX:(int)x y:(int)y | Called when the mouse cursor moves. Provides the new coordinates. |
ASPEngineStatisticsDelegate: Callbacks for tracking
API | Description |
onStatisticsInfoUpdate:(ASPStatisticsInfo *)info | Called to report performance statistics for the ECP. The statistics are provided in an |
ASPEngineLogDelegate: Callbacks for logs. We recommend using a singleton for this delegate.
API | Description |
onLogMessage:(NSString*)msg tag:(NSString*)tag level:(AspLogLevel)level | Called for each SDK log message. Provides the log message, tag, and level for each entry. |
3. Service API
API | Description |
- (BOOL)enableStatistics:(BOOL) enabled enableGuestInfo:(BOOL)enableGuestInfo | Enables or disables statistics and guest CPU usage collection. |
- (BOOL)enableMouseMode:(BOOL)enabled | Enables or disables mouse mode. |
@property (nonatomic, assign) BOOL enableDump; | Enables or disables dumping. This feature affects performance and is for development and debugging purposes only. Do not use it in production. |
- (BOOL)sendKeyboardEvent: (ASPKeyEvent) event; | Sends a keyboard event. |
// The - (BOOL)simulateMouseClick:(BOOL)leftButton; - (BOOL)simulateMouseClick:(BOOL)leftButton x:(float)x y:(float)y; | Simulates a mouse click. |
- (void)hideCursor; - (void)showCursor; | Hides or shows the cursor. |
- (void)setVideoProfileWithWidth:(int)width height:(int)height fps:(int)fps; | Sets the resolution. The |
@property (nonatomic, assign) BOOL mute; | Mutes or unmutes the audio. |
@property (nonatomic, assign) ASPScaleType scaleType; | Scale type for the video stream. See section 5.1 |
- (void)enableDesktopMode:(BOOL)enabled; | Enables or disables desktop mode. When enabled, touch messages are converted to mouse events. For cloud phones, recommended: NO. |
- (void)enableDesktopGesture:(BOOL)enabled; | Enables or disables client-side zoom and pan gestures. For cloud phones, recommended: NO. |
@property (nonatomic, assign) BOOL enableTouchFeel; | Enables or disables haptic feedback. The default value is NO. |
LyncChannel | Channel for sending ADB commands. For an example, see |
DataChannel | Custom data channel for communication between the client and the guest. For an example, see |
LyncChannel example
// The default LyncChannel name is: static NSString *LYNC_CHANNEL_NAME = @"lync_adb_shell";
// Add the LyncChannel
self.lync = [[DemoLyncChannel alloc] initWithParameter:LYNC_CHANNEL_NAME];
[self.streamView addLyncChannel:self.lync];
// Remove the LyncChannel
[self.streamView removeLyncChannel:self.lync];
// LyncChannel implementation
@interface DemoLyncChannel : BaseLyncChannel
@property (nonatomic, strong) NSString *lslaID;
@end
@implementation DemoLyncChannel
- (void)onConnectStateChanged:(BOOL)connected {
NSLog(@"[DemoLyncChannel] onConnectStateChanged %d", connected);
if (connected) {
// Test sending a command
self.lslaID = [DemoToolBox getID];
NSString *cmdData = [DemoToolBox getJsonDataWithId:self.lslaID cmd:@"ls -la"];
NSLog(@"[DemoLyncChannel] cmdData : %@", cmdData);
LyncErrorCode code = [self sendString:cmdData];
NSLog(@"[DemoLyncChannel] cmdData code: %ld", code);
}
}
- (void)onReceiveStringData:(NSString * _Nonnull)buf {
NSLog(@"[DemoLyncChannel] onReceiveStringData %@", buf);
NSDictionary *dic = [DemoToolBox convertStringToJSON:buf];
NSString *ID = [dic objectForKey:@"id"];
if (ID != NULL && ID.length && [self.lslaID isEqualToString:ID]) {
NSLog(@"[DemoLyncChannel] onReceiveStringData: Received result for 'ls -la'.");
}
}
- (void)onReceiveRawData:(NSData * _Nonnull)buf {
NSString *string = [[NSString alloc] initWithData:buf encoding:NSUTF8StringEncoding];
NSLog(@"[DemoLyncChannel] onReceiveRawData %@", string);
}
@endDataChannel example
// The default DataChannel name is: static NSString *DATA_CHANNEL_NAME = @"wy_vdagent_default_dc";
// Add the DataChannel
self.esdAgent = [[DemoEDSAgentChannel alloc] initWithParameter:DATA_CHANNEL_NAME];
[self.streamView addDataChannel:self.esdAgent];
// Remove the DataChannel
[self.streamView removeDataChannel:self.esdAgent];
// DataChannel implementation
@interface DemoEDSAgentChannel : BaseEDSAgentChannel
@end
@implementation DemoEDSAgentChannel
- (void)onConnectStateChanged:(ASPDCConnectState)state {
NSLog(@"[DemoEDSAgentChannel] onConnectStateChanged %ld", state);
if (state == OPEN) {
// to send data
}
}
- (void)onReceiveData:(NSData * _Nonnull)buf {
NSString *string = [[NSString alloc] initWithData:buf encoding:NSUTF8StringEncoding];
NSLog(@"[DemoEDSAgentChannel] onReceiveData %@", string);
}
@endThe message channel uses the DataChannel named wy_vdagent_default_dc.
The message size is limited to 500 KB.
The basic message format is as follows:
DataChannel: Messages from client to guest
Action: insertcontact, insertsms, or sendcontactvcf
insertcontact: Inserts a contact.
The required name parameter specifies the contact name.
The required phonenumber parameter specifies the phone number.
insertsms: Inserts an SMS.
The required phonenumber parameter specifies the phone number.
The required textbody parameter specifies the SMS content.
The optional canInsertdb parameter specifies whether to insert the message into the cloud phone's SMS database. The default is 0 (do not insert); set to 1 to insert.
Example: let jsonarray = [{'action': 'insertcontact','importdata':[{ 'name': '**', 'phonenumber': '**' }, { 'name': '**', 'phonenumber': '**' }]},{'action': 'insertsms','importdata':[{'phonenumber':'**','textbody':'**,"canInsertdb":0/1}]}]
sendcontactvcf: Inserts contacts from a vcf file.
The required data parameter contains the vcf file data stream. Large files must be chunked, with a maximum chunk size of 1 MB.
The required allsize parameter is the total size of the vcf data.
The timestamp parameter is required. Use the same timestamp for all chunks of a single vcf file to ensure correct reassembly.
Example: {'action': 'sendcontactvcf', 'importdata': {'data': '', 'allsize': total_file_size, 'timestamp': current_timestamp}}.
public void processByteArrayInChunks(byte[] data) {
int chunkSize = 512 * 1024; // 512 KB
int length = data.length;
long timestamp = System.currentTimeMillis();
for (int i = 0; i < length; i += chunkSize) {
int end = Math.min(i + chunkSize, length);
byte[] chunk = Arrays.copyOfRange(data, i, end);
String str = new String(chunk, StandardCharsets.UTF_8);
/**
{'action': 'sendcontactvcf','importdata':{"data":str, "allsize":length, "timestamp":timestamp}}
*/
}
}String recvData = "";
int recvSize = 0;
long recvTimestamp = 0;
public void onMessageReceive(byte[] message) {
String action = getAction(message);
String data = getData(message);
int length = data.length;
int allSize = getAllSize(message);
long timestamp = getTimestamp(message);
if (timestamp != recvTimestamp) {
clearRecv();
}
if (action.equals("sendcontactvcf")) {
recvSize += length;
recvData = recvData + data;
if (recvSize >= allSize) {
// Write recvData to a vcf file and insert contacts.
insertContact(vcfFilePath);
sendack();
clearRecv();
}
}
}
public void clearRecv() {
recvData = "";
recvSize = 0;
recvTimestamp = 0;
}DataChannel: Messages from guest to client
Action: openeditsms, openphone, or rotation
openeditsms: Opens the SMS editor page.
The optional importdata.phonenumber parameter specifies the phone number.
The optional textbody parameter specifies the SMS content.
Example: {'action': 'openeditsms',importdata:{"phonenumber":"***", "textbody":"***"}}
openphone: Opens the phone dialer page.
The optional importdata.phonenumber parameter specifies the number to call. If provided, the dialer opens with this number; otherwise, the main dialer page opens.
Example: {'action': 'openphone','importdata':{"phonenumber":"***"}} or {'action': 'openphone'}
DataChannel ACK message
Action: ack
ack: Reports the processing status of a received message. Either the client or guest can send anackresponse if required by the application's logic.
The required source parameter is the action from the original message.
The required code parameter is the status code, with the following valid values: 0 (Unknown), 1 (Executing), 2 (Success), 3 (Failure), and 4 (Not Supported).
Example: {'action': 'ack','importdata':{"source":"***", "code": *,"id":*}}
4. Parameters
4.1 ASPConnTicket
Configuration parameters to establish a connection.
Parameter | Description |
connTicket | Connection authentication ticket. |
caFilePath | The absolute path to the CA file, used for TLS encryption. |
desktopId | Application instance ID, such as |
useVpc | Whether to connect over a VPC. |
enableTls | Enables TLS encryption. Recommended: YES. |
enableStatistics | Enables statistics. Recommended: YES. |
preferRtcTransport | Enables the RTC channel. Recommended: YES. |
4.2 ASPStatisticsInfo
Performance data.
API | Type | Description |
mReceiveFps | int | Received FPS |
mRenderFps | int | Render FPS |
mDownstreamBandwithMBPerSecond | double | Downstream bandwidth |
mUpstreamBandwithMBPerSecond | double | Upstream bandwidth |
mP2pFullLinkageLatencyMS | long | End-to-end full-link latency. Deprecated. |
mNetworkLatencyMS | long | Network RTT |
mPingGatewayRtt | long | Ping RTT |
mLostRate | double | Packet loss rate |
mServerRenderLatencyMS | long | Server-side rendering latency |
mServerEncoderLatencyMS | long | Server-side encoding latency |
mServerTotalLatencyMS | long | Server-side total latency |
accumulateBandwidth | long | Total bandwidth |
mGuestCpuUsage | long | Guest CPU usage |
mStreamType | String | Stream protocol type |
infoDic | NSDictionary | A map of performance data. |
5. Enumeration types
5.1 ASPScaleType
Specifies the content scaling type for a streamed image.
Parameter | Description |
ASPScaleTypeFill | Stretches the streamed image to fill the entire StreamView. This may cause distortion if the image's aspect ratio differs from the view's. |
ASPScaleTypeFit | Scales the streamed image to fit within the StreamView, preserving its aspect ratio. This displays the entire image without distortion, but may leave parts of the view empty. |
Error codes
Error code | Error message ( | Module | Cause |
Error codes 2–26: Network-related issues | |||
2 | Failed to connect to the %s. | ASP SDK | Invalid MAGIC. |
3 | Failed to connect to the %s. | ASP SDK | Incorrect data. |
4 | The client version does not match the server version. | ASP SDK | Version mismatch. |
5 | The connection requires TLS. | ASP SDK | TLS is required. |
6 | The connection does not require TLS. | ASP SDK | TLS was used when not required. |
7 | You do not have permission to connect to the %s. | ASP SDK | Permission denied. |
8 | ASP SDK | Invalid client ID during migration. | |
9 | Failed to connect to the %s. | ASP SDK | The specified channel does not exist. |
20 | Failed to connect to the ASP server. | ASP SDK | Channel connection error. |
21 | TLS authentication failed. | ASP SDK | TLS authentication failed. |
22 | Failed to connect to the %s. | ASP SDK | Channel link error. |
23 | Failed to connect to the %s. | ASP SDK | Connection authentication error. |
24 | Failed to connect to the %s. | ASP SDK | Connection I/O error. |
25 | Failed to connect to the %s. | ASP SDK | Ticket validation failed. This error also occurs if you use the same ticket for a new connection after the previous session disconnects. |
26 | ASP SDK | XQUIC handshake failure. | |
1206 | A ticket supports only one active connection at a time. This error occurs if you attempt to use it for a new connection while a session is already active. | ASP SDK | |
1207 | Restarting the instance invalidated the ticket. | ASP SDK | |
SDK stream collaboration error codes | |||
1000 | token empty | ASP SDK | These stream collaboration errors occur when secondary validation between the client and server fails. |
1001 | user empty | ASP SDK | |
1200 | token invalid | ASP SDK | |
1201 | vm invalid | ASP SDK | |
1202 | ADMIN internal error | ASP SDK | |
1203 | user invalid | ASP SDK | |
1204 | token expired | ASP SDK | |
1500 | server internal error | ASP SDK | |
1501 | server network error | ASP SDK | |
Disconnections and connection errors | |||
2000 | The connection to the server timed out while retrieving data from the %s. | ASP SDK | Normal disconnection. |
2001 | The %s was disconnected from the server. This may happen if the %s process was forcibly terminated. | ASP SDK | This typically occurs when the client-side app process is terminated, for example, when a user closes the application. |
2002 | Another user has connected to the %s from a different client. Please try again later. | ASP SDK | The session was taken over by another user in preemptive mode. |
2003 | The %s is shutting down or restarting. This operation is usually initiated by an administrator. Please try again later. | ASP SDK | The cloud phone was shut down or restarted, typically by an administrator. |
2004 | The current user connection was terminated. | ASP SDK | The client initiated the disconnection, or the server terminated the session. |
2005 | The %s disconnected because the session reached the usage limit set by an administrator. | ASP SDK | The session was terminated because it reached the usage limit set by an administrator. |
2006 | An administrator revoked your permission to use this cloud phone. Your session will be disconnected. | ASP SDK | An administrator revoked the user's permission. |
2010 | Failed to connect to the %s. | ASP SDK | Vdagent connection failure. |
2011 | Invalid connection parameters. | ASP SDK | The client attempted to connect with invalid parameters. |
2027 | The stream pull mode has been switched. | ASP SDK | The stream pull mode was switched from preemptive mode to collaborative mode, or vice versa. |
2100 | Clipboard permission denied: copying from the %s to the local client is not permitted. | ASP SDK | Clipboard permission denied: copying from the VM to the local client is not permitted. |
2101 | Clipboard permission denied: copying from the local client to the %s is not permitted. | ASP SDK | Clipboard permission denied: copying from the local client to the VM is not permitted. |
2200 | The %s is attempting to reconnect... | ASP SDK | A network issue caused a connection loss. The ASP SDK is attempting to reconnect. |
2201 | The %s was disconnected due to a network issue on your device. | ASP SDK | A network issue caused a connection loss. The ASP SDK does not support automatic reconnection for the current image, so the app-side must initiate it. |
2202 | Reconnection to the %s timed out. Check your device's network and try again. | ASP SDK | ASP SDK reconnection timeout. |
2210 | The cloud phone disconnected because the client device entered sleep mode, causing a network loss. | ASP SDK | |
2212 | The cloud phone was disconnected due to a local network issue. | ASP SDK | |
2220 | The cloud phone was disconnected due to a local network issue. | ASP SDK | |
2240 | Reconnection failed because the token within the ticket is invalid. | ||
2300 | Connection failed due to invalid parameters passed from the app-side. | ||
2501 | The client failed to connect to the stream gateway. The network is unreachable. | ||
2502 | The client failed to connect to the stream gateway. The TCP connection to the stream gateway IP timed out after three attempts (15 seconds total). | ||
2503 | The client failed to connect to the stream gateway due to an unknown network error. | ||
2504 | The client connection to the stream gateway was interrupted by software. | ||
2505 | The client connection to the stream gateway was refused. | ||
2506 | Invalid ticket. The stream gateway failed to parse the token. | ||
2507 | Invalid ticket. The ticket has expired. | ||
2508 | Invalid ticket. The UUID does not match. | ||
2509 | The stream gateway failed to probe the ASP server. | ||
2510 | The server refused the probe. | ||
2511 | The server probe failed for a reason other than a timeout or refusal. | ||
2512 | Stream gateway token validation failed. The vpcId in the management token does not match the vpcId of the stream gateway. | ||
2513 | The TCP connection was unexpectedly reset during the "hello" exchange between the client and the stream gateway. | ||
2520 | Connection failed. The client's self-diagnosis indicates a network issue. | ||
2521 | The connection was abnormally terminated three times during the TLS handshake phase between the client and the stream gateway. | ||
2522 | A connection error occurred in a VPN environment. | ||
2523 | The client is attempting to connect using a national cryptographic protocol. Verify the server settings or select a compatible connection method. | ||
2701 | Client-side network issue. As a test, try connecting by using a 5G mobile hotspot to see if the issue persists. | ||
2702 | The SSL handshake between the client and the stream gateway timed out. | ||
2703 | The "hello" exchange between the client and the stream gateway timed out. | ||
2704 | The ASP server timed out while responding to the connection establishment request. Possible causes include a frozen ASP server, network issues, an unresponsive image, or high CPU/memory usage. | ||
2705 | The ASP client timed out while waiting for the first frame. Possible causes include a frozen ASP server, frame generation failure (due to screen capture or GPU driver issues), network issues, or high CPU/memory usage. | ||
2706 | Connection failed due to high CPU or memory usage on the client device. | ||
2707 | The ASP server timed out while retrieving the first screen capture frame from the guest OS. | ||
2708 | Connection failed because an SDK thread is stuck. | ||
Client-side logic errors | |||
5100 | Connection to the ASP server timed out. Please try again later. | App-side | The client-side did not receive a "connected" event within the expected time frame. |
5102 | Timed out while waiting for data from %s. Please try again later. | App-side | The client-side received a "connected" event but not a "display" event within the expected time frame. |
5004 | The client encountered an error. Please restart the client. | App-side | The client-side received invalid startup parameters. This typically occurs during development. |
5200 | Client reconnection timed out. Please try again later. | App-side | |
FAQ
Restart Elastic Cloud Phone
To restart an instance, call the Restart Instance API. This disconnects the ECP from the client. After the instance restarts, reconnect to it.
Common ADB commands
Function | Command |
Back button | input keyevent KEYCODE_BACK |
Home button | input keyevent KEYCODE_HOME |
App switch button | input keyevent KEYCODE_APP_SWITCH |
Mute | input keyevent 164 |
Volume up | input keyevent KEYCODE_VOLUME_UP |
Volume down | input keyevent KEYCODE_VOLUME_DOWN |
Hide navigation bar | setprop persist.wy.hasnavibar false; killall com.android.systemui |
Show navigation bar | setprop persist.wy.hasnavibar true; killall com.android.systemui |
Screenshot | screencap -p /sdcard/Download/abc.png |