Skip to content

Conversation

@Dor-bl
Copy link
Collaborator

@Dor-bl Dor-bl commented Nov 15, 2025

List of changes

This pull request introduces a new capability to the AndroidDriver class for handling Android logcat message broadcasts via WebSocket. It adds a dedicated interface for listening to logcat messages and implements a set of methods for starting/stopping broadcasts and managing event handlers. Additionally, supporting interfaces for handling WebSocket messages, connections, disconnections, and errors are introduced.

Logcat broadcast and listener functionality

  • Added the IListensToLogcatMessages interface (src/Appium.Net/Appium/Android/Interfaces/IListensToLogcatMessages.cs) to define methods for starting/stopping logcat broadcasts and managing listeners for messages, errors, connections, and disconnections.
  • Implemented logcat broadcast management methods in AndroidDriver, including starting/stopping broadcasts and adding/removing listeners for different WebSocket events. The driver now uses a StringWebSocketClient instance for handling logcat events. [1] [2]

WebSocket event handler interfaces

  • Added ICanHandleMessages<T>, ICanHandleConnects, ICanHandleDisconnects, and ICanHandleErrors interfaces in the WebSocket namespace to provide standardized APIs for registering and removing event handlers for messages, connections, disconnections, and errors, respectively. [1] [2] [3] [4]

Dependency updates

  • Updated AndroidDriver to import the new OpenQA.Selenium.Appium.WebSocket namespace for WebSocket support.

These changes enable real-time logcat monitoring and event-driven handling in Android automation tests using Appium.

Related to: #255

Types of changes

What types of changes are you proposing/introducing to the .NET client?
Put an x in the boxes that apply

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change that adds functionality or value)
  • Breaking change (fix or feature that would cause existing functionality not to work as expected)
  • Test fix (non-breaking change that improves test stability or correctness)

Documentation

  • Have you proposed a file change/ PR with Appium to update documentation?

This can be done by navigating to the documentation section on http://appium.io selecting the appropriate command/endpoint, and clicking the 'Edit this doc' link to update the C# example

Integration tests

  • Have you provided integration tests for your changes? (required for Bugfix, New feature, or Test fix)

Details

Please provide more details about changes if necessary. You can provide code samples showing how they work and possible use cases if there are new features. Also, you can create gists with pasted C# code samples or put them here using markdown.
About markdown please read Mastering markdown and Writing on GitHub

Tests Results

image

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces WebSocket-based log broadcast support for Android (and interface for iOS), enabling real-time logcat monitoring through event-driven handlers. The implementation adds a StringWebSocketClient for handling WebSocket connections, new interfaces for managing WebSocket events, and extends AndroidDriver with logcat broadcast capabilities.

Key Changes:

  • New StringWebSocketClient class for WebSocket communication with message, error, connection, and disconnection handlers
  • IListensToLogcatMessages interface and implementation in AndroidDriver for logcat streaming
  • Four generic WebSocket handler interfaces (ICanHandleMessages, ICanHandleErrors, ICanHandleConnects, ICanHandleDisconnects)

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 26 comments.

Show a summary per file
File Description
src/Appium.Net/Appium/Android/AndroidDriver.cs Adds IListensToLogcatMessages implementation with methods to start/stop broadcasts and manage listeners
src/Appium.Net/Appium/Android/Interfaces/IListensToLogcatMessages.cs Defines interface for Android logcat message broadcasting
src/Appium.Net/Appium/iOS/Interfaces/IListensToSyslogMessages.cs Defines parallel interface for iOS syslog message broadcasting
src/Appium.Net/Appium/WebSocket/StringWebSocketClient.cs Core WebSocket client implementation for string message handling
src/Appium.Net/Appium/WebSocket/ICanHandleMessages.cs Generic interface for message handler registration
src/Appium.Net/Appium/WebSocket/ICanHandleErrors.cs Interface for error handler registration
src/Appium.Net/Appium/WebSocket/ICanHandleConnects.cs Interface for connection handler registration
src/Appium.Net/Appium/WebSocket/ICanHandleDisconnects.cs Interface for disconnection handler registration
test/integration/Android/Session/Logs/LogcatBroadcastTests.cs Integration tests covering listener assignment, broadcast lifecycle, and error handling

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

/// <param name="port">The port of the host where Appium server is running.</param>
public void StartLogcatBroadcast(string host, int port)
{
ExecuteScript("mobile: startLogsBroadcast", new Dictionary<string, object>());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KazuCocoa, I attempted several different methods using BiDI, but unfortunately, none of them worked for me.
I'm also experiencing a problem with the BiDi test that you added recently (this might be connected to my issue).
When I attempt to establish a connection, I encounter this error:

❌ FAILED: RunBiDiScript (1358ms)
   System.Net.WebSockets.WebSocketException : Unable to connect to the remote server
                                                                                     ----> System.Net.Http.HttpRequestException : IPv4 address 0.0.0.0 and IPv6 address ::0 are unspecified addresses that cannot be used as a target address. (Parameter 'hostName') (0.0.0.0:4723)
                          ----> System.ArgumentException : IPv4 address 0.0.0.0 and IPv6 address ::0 are unspecified addresses that cannot be used as a target address. (Parameter 'hostName')

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you share the appium server-side log as well?

I'm also experiencing a problem with the BiDi test that you added recently (this might be connected to my issue).

When i ran dotnet test test/integration/Appium.Net.Integration.Tests.csproj -f net8.0 --filter "FullyQualifiedName~Appium.Net.Integration.Tests.Android.BiDiTests" on my local:

[f6166589][AndroidUiautomator2Driver@63b2] Responding to client with driver.createSession() result: {"capabilities":{"platformName":"Android","webSocketUrl":"ws://192.168.5.20:4723/bidi/f6166589-401f-45e0-854a-073385995062","automationName":"UIAutomator2","deviceName":"emulator-5554","platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"Android","webSocketUrl":true,"automationName":"UIAutomator2","deviceName":"Android Emulator"},"deviceUDID":"emulator-5554","pixelRatio":"2.625","statBarHeight":63,"viewportRect":{"left":0,"top":63,"width":1080,"height":2337},"deviceApiLevel":32,"platformVersion":"12","deviceManufacturer":"Google","deviceModel":"sdk_gphone64_arm64","deviceScreenSize":"1080x2400","deviceScreenDensity":420}}
[f6166589][HTTP] <-- POST /session 200 20100 ms - 858
[AppiumDriver@12ee] Bidi websocket connection made for session f6166589-401f-45e0-854a-073385995062
[AndroidUiautomator2Driver@63b2] --> BIDI message #1
[AndroidUiautomator2Driver@63b2] Executing bidi command 'session.status' with params {} by passing to driver method 'bidiStatus'
[AndroidUiautomator2Driver@63b2] Responding to bidi command 'session.status' with {"ready":true,"message":"AndroidUiautomator2Driver is ready to accept commands"}
[AndroidUiautomator2Driver@63b2] <-- BIDI message #1
[HTTP] <-- GET /bidi/f6166589-401f-45e0-854a-073385995062 - - ms - -
[AndroidUiautomator2Driver@63b2] BiDi socket connection closed (code 1006, reason: '')
[f6166589][HTTP] --> DELETE /session/f6166589-401f-45e0-854a-073385995062
[f6166589][AndroidUiautomator2Driver@63b2] Calling AppiumDriver.deleteSession() with args: ["f6166589-401f-45e0-854a-073385995062"]
[f6166589][AppiumDriver@12ee] Event 'quitSessionRequested' logged at 1763333223903 (14:47:03 GMT-0800 (Pacific Standard Time))
[f6166589][AppiumDriver@12ee] Removing session f6166589-401f-45e0-854a-073385995062 from our master session list
[f6166589][AppiumDriver@12ee] Closing bidi socket(s) associated with session f6166589-401f-45e0-854a-073385995062

appium was 3.1.1, uia2 driver was 6.1.0

Copy link
Collaborator Author

@Dor-bl Dor-bl Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KazuCocoa, does BiDi require a specific minimum version of Appium/UIAutomator2 to function?

EDIT: Looks like I'm a bit behind with the versions:

https://gist.github.com/Dor-bl/95d17ca78974d6883da682fba6e49d10

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minimal could be appium 2 and uia2 3.7.10. Old ones might have issues though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look at the log.entryAdded hanlding in each driver implementation tonight

cc @mykola-mokhnach

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened an issue on the Appium server:
appium/appium#21741

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in appium/appium-android-driver#1031, the context property in the source object is optional and should not be relied on. While I agree with @KazuCocoa in that there's no harm in adding it on the driver side, if Selenium is expecting this property, then this issue should be primarily fixed on the Selenium side.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nvborisenko, can we apply a fix on the Selenium side, following the above comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I can accept it. But why:

In this case NATIVE_APP is magic string. Is it even required when we want to subscribe?

We subscribe like:

await bidi.Log.OnEntryAddedAsync(Console.WriteLine, new() { Contexts = ["NATIVE_APP"] });

According spec contexts property is not required: https://w3c.github.io/webdriver-bidi/#cddl-type-sessionsubscribeparameters. But appium server-side implementation requires it.

Copy link
Member

@KazuCocoa KazuCocoa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left minor comments, otherwise lgtm in best knowledge

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 21, 2025

@KazuCocoa, I've encountered an issue. The tests have suddenly started failing. Perhaps you can identify the problem from the logs? I haven't made any recent code changes that would explain this.

.NET Error:

  ----> System.Net.WebSockets.WebSocketException : The server returned status code '404' when status code '101' was expected.
[DEBUG] Connecting to WebSocket: ws://127.0.0.1:4723/ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[CanStartAndStopLogcatBroadcast] [DEBUG] Connecting to WebSocket: ws://127.0.0.1:4723/ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat

Appium logs:

[c9d0ae1a][AppiumDriver@4b02] Event 'newSessionStarted' logged at 1763764773530 (23:39:33 GMT+0100 (Central European Standard Time))
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Cached the protocol value 'W3C' for the new session c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.createSession() result: {"capabilities":{"platformName":"Android","app":"/var/folders/v1/jsmj5_w55cx0xk4js5ywgfzm0000gn/T/ApiDemos-debug.apk","automationName":"UIAutomator2","deviceName":"emulator-5554","newCommandTimeout":300,"platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"Android","app":"/var/folders/v1/jsmj5_w55cx0xk4js5ywgfzm0000gn/T/ApiDemos-debug.apk","automationName":"UIAutomator2","deviceName":"Android Emulator","newCommandTimeout":300},"deviceUDID":"emulator-5554","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","pixelRatio":"2.625","statBarHeight":63,"viewportRect":{"left":0,"top":63,"width":1080,"height":2337},"deviceApiLevel":35,"platformVersion":"15","deviceManufacturer":"Google","deviceModel":"sdk_gphone64_arm64","deviceScreenSize":"1080x2400","deviceScreenDensity":420}}
[c9d0ae1a][HTTP] <-- POST /session 200 2195 ms - 1042 
[c9d0ae1a][HTTP] Request idempotency key: 18269e7e-ef1a-4d00-8410-f5b35c0a6588
[c9d0ae1a][HTTP] --> POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync {"script":"mobile: startLogsBroadcast","args":[{}]}
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.execute() with args: ["mobile: startLogsBroadcast",[{}],"c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Starting logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.execute() result: null
[c9d0ae1a][HTTP] <-- POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync 200 1 ms - 14 
[c9d0ae1a][HTTP] Request idempotency key: c9117e98-d654-40aa-b7e3-c8076ec9fd65
[c9d0ae1a][HTTP] --> POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync {"script":"mobile: stopLogsBroadcast","args":[{}]}
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.execute() with args: ["mobile: stopLogsBroadcast",[{}],"c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Stopping logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.execute() result: null
[c9d0ae1a][HTTP] <-- POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync 200 2 ms - 14 
[c9d0ae1a][HTTP] Request idempotency key: 44ef9318-eebc-4a96-8971-5d7f4c9c4549
[c9d0ae1a][HTTP] --> POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync {"script":"mobile: startLogsBroadcast","args":[{}]}
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.execute() with args: ["mobile: startLogsBroadcast",[{}],"c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Starting logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.execute() result: null
[c9d0ae1a][HTTP] <-- POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync 200 1 ms - 14 
[c9d0ae1a][HTTP] Request idempotency key: 7b80c547-ebd8-481a-aa39-db8160a9b3bf
[c9d0ae1a][HTTP] --> POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync {"script":"mobile: stopLogsBroadcast","args":[{}]}
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.execute() with args: ["mobile: stopLogsBroadcast",[{}],"c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Stopping logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.execute() result: null
[c9d0ae1a][HTTP] <-- POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync 200 4 ms - 14 
[c9d0ae1a][HTTP] Request idempotency key: bd2e07d4-15ee-4fc2-b193-8b6ac1141836
[c9d0ae1a][HTTP] --> POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync {"script":"mobile: startLogsBroadcast","args":[{}]}
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.execute() with args: ["mobile: startLogsBroadcast",[{}],"c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Starting logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.execute() result: null
[c9d0ae1a][HTTP] <-- POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync 200 2 ms - 14 
[c9d0ae1a][HTTP] Request idempotency key: 4afef766-c93a-42ae-ae46-3e13582d7df0
[c9d0ae1a][HTTP] --> POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync {"script":"mobile: startLogsBroadcast","args":[{}]}
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.execute() with args: ["mobile: startLogsBroadcast",[{}],"c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] The logcat broadcasting web socket server is already listening at /ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.execute() result: null
[c9d0ae1a][HTTP] <-- POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync 200 2 ms - 14 
[c9d0ae1a][HTTP] Request idempotency key: 6b4e80b5-28e0-40f3-bd6e-7f0b3fe80caf
[c9d0ae1a][HTTP] --> POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync {"script":"mobile: startLogsBroadcast","args":[{}]}
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.execute() with args: ["mobile: startLogsBroadcast",[{}],"c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] The logcat broadcasting web socket server is already listening at /ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.execute() result: null
[c9d0ae1a][HTTP] <-- POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync 200 2 ms - 14 
[c9d0ae1a][HTTP] Request idempotency key: 5ca4f1f2-4f77-4ce8-93bd-ea636ff37f86
[c9d0ae1a][HTTP] --> POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync {"script":"mobile: stopLogsBroadcast","args":[{}]}
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.execute() with args: ["mobile: stopLogsBroadcast",[{}],"c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Stopping logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/appium/device/logcat
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Responding to client with driver.execute() result: null
[c9d0ae1a][HTTP] <-- POST /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47/execute/sync 200 2 ms - 14 
[c9d0ae1a][HTTP] --> DELETE /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47 
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.deleteSession() with args: ["c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AppiumDriver@4b02] Event 'quitSessionRequested' logged at 1763764783674 (23:39:43 GMT+0100 (Central European Standard Time))
[c9d0ae1a][AppiumDriver@4b02] Removing session c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47 from our master session list
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Deleting UiAutomator2 session
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Deleting UiAutomator2 server session
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Proxying [DELETE /] to [DELETE http://127.0.0.1:8200/session/c252f06e-a4e2-4d54-88da-fda0e3a6e87b] with no body
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Got response with status 200: {"sessionId":"c252f06e-a4e2-4d54-88da-fda0e3a6e87b","value":null}
[c9d0ae1a][ADB] Getting IDs of all 'io.appium.uiautomator2.server' processes

@KazuCocoa
Copy link
Member

I guess that occurred after deleting the session c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47, so after:

[c9d0ae1a][HTTP] --> DELETE /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47 
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.deleteSession() with args: ["c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AppiumDriver@4b02] Event 'quitSessionRequested' logged at 1763764783674 (23:39:43 GMT+0100 (Central European Standard Time))
[c9d0ae1a][AppiumDriver@4b02] Removing session c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47 from our master session list
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Deleting UiAutomator2 session

?

@KazuCocoa
Copy link
Member

UIA2 6.3.0 returns context in source, btw

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 22, 2025

I guess that occurred after deleting the session c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47, so after:

[c9d0ae1a][HTTP] --> DELETE /session/c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47 
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Calling AppiumDriver.deleteSession() with args: ["c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47"]
[c9d0ae1a][AppiumDriver@4b02] Event 'quitSessionRequested' logged at 1763764783674 (23:39:43 GMT+0100 (Central European Standard Time))
[c9d0ae1a][AppiumDriver@4b02] Removing session c9d0ae1a-bb10-40ce-a71d-a446bc1a0e47 from our master session list
[c9d0ae1a][AndroidUiautomator2Driver@fb2b] Deleting UiAutomator2 session

?

It also occurs when I only run one test at a time..
So it shouldn't be related to the fact that the following sessions were deleted. I'll keep digging.


[6f42d675][HTTP] Request idempotency key: 962bbb50-3248-479b-9011-60dfcc763beb
[6f42d675][HTTP] --> POST /session/6f42d675-28a8-46ee-90db-9def84a72654/execute/sync {"script":"mobile: startLogsBroadcast","args":[{}]}
[6f42d675][AndroidUiautomator2Driver@472d] Calling AppiumDriver.execute() with args: ["mobile: startLogsBroadcast",[{}],"6f42d675-28a8-46ee-90db-9def84a72654"]
[6f42d675][AndroidUiautomator2Driver@472d] Starting logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/6f42d675-28a8-46ee-90db-9def84a72654/appium/device/logcat
[6f42d675][AndroidUiautomator2Driver@472d] Responding to client with driver.execute() result: null
[6f42d675][HTTP] <-- POST /session/6f42d675-28a8-46ee-90db-9def84a72654/execute/sync 200 3 ms - 14 

@KazuCocoa
Copy link
Member

Hm, interesting. I haven't seen the error case in several log via bidi tests like testing with Ruby, Python and our test cases in driver repos. Do you have test script snippet for it? I can take a look later

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 22, 2025

Hm, interesting. I haven't seen the error case in several log via bidi tests like testing with Ruby, Python and our test cases in driver repos. Do you have test script snippet for it? I can take a look later

Just the tests from this PR

@KazuCocoa
Copy link
Member

Ah, I see.

I ran this test with dotnet test test/integration/Appium.Net.Integration.Tests.csproj -f net8.0 --filter "FullyQualifiedName~LogcatBroadcastTests" --logger "console;verbosity=detailed" on my local 10 times. All tests passed 👀

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 23, 2025

Ah, I see.

I ran this test with dotnet test test/integration/Appium.Net.Integration.Tests.csproj -f net8.0 --filter "FullyQualifiedName~LogcatBroadcastTests" --logger "console;verbosity=detailed" on my local 10 times. All tests passed 👀

Could it be some network issues on my end?
Bad appium server config?

@KazuCocoa
Copy link
Member

Hm. appium 3.1.1 and uia2 6.1.1 in running env.

2025-11-23 20:00:56:264 [AppiumDriver@1d98] Appium v3.1.1 creating new AndroidUiautomator2Driver (v6.1.1) session
2025-11-23 20:00:56:264 [AppiumDriver@1d98] Checking BaseDriver versions for Appium and AndroidUiautomator2Driver
2025-11-23 20:00:56:264 [AppiumDriver@1d98] Appium's BaseDriver version is 10.1.1
2025-11-23 20:00:56:264 [AppiumDriver@1d98] AndroidUiautomator2Driver's BaseDriver version is 10.1.1

(from appium log)

The server returned status code '404' when status code '101' was expected. probably meant the endpoint returned 404 - no active session existed instead of an upgrade for the ws connection request. Then, for me, it might be timing if the URL is valid or not, rather than a network issue

@KazuCocoa
Copy link
Member

If you could see timestamp info as well, we might be able to guess when such a 404 returned

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 23, 2025

[AppiumDriver@dec7] Appium v3.1.1 creating new AndroidUiautomator2Driver (v6.3.0) session
[AppiumDriver@dec7] Checking BaseDriver versions for Appium and AndroidUiautomator2Driver
[AppiumDriver@dec7] Appium's BaseDriver version is 10.1.1
[AppiumDriver@dec7] AndroidUiautomator2Driver's BaseDriver version is 10.1.1

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 23, 2025

❌ FAILED: CanStartLogcatBroadcastWithCustomHost (47ms)
OpenQA.Selenium.WebDriverException : Failed to connect to WebSocket at 2025-11-23 20:56:17.327 UTC
----> System.Net.WebSockets.WebSocketException : The server returned status code '404' when status code '101' was expected.

2025-11-23 20:56:17:266 - [58e6df27][AppiumDriver@79ef] Event 'newSessionStarted' logged at 1763931377266 (21:56:17 GMT+0100 (Central European Standard Time))
2025-11-23 20:56:17:267 - [58e6df27][AndroidUiautomator2Driver@d423] Cached the protocol value 'W3C' for the new session 58e6df27-83fb-4101-81c1-d64f6c3dfca6
2025-11-23 20:56:17:268 - [58e6df27][AndroidUiautomator2Driver@d423] Responding to client with driver.createSession() result: {"capabilities":{"platformName":"Android","app":"/var/folders/v1/jsmj5_w55cx0xk4js5ywgfzm0000gn/T/ApiDemos-debug.apk","automationName":"UIAutomator2","deviceName":"emulator-5554","platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"Android","app":"/var/folders/v1/jsmj5_w55cx0xk4js5ywgfzm0000gn/T/ApiDemos-debug.apk","automationName":"UIAutomator2","deviceName":"Android Emulator"},"deviceUDID":"emulator-5554","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","pixelRatio":"2.625","statBarHeight":63,"viewportRect":{"left":0,"top":63,"width":1080,"height":2337},"deviceApiLevel":35,"platformVersion":"15","deviceManufacturer":"Google","deviceModel":"sdk_gphone64_arm64","deviceScreenSize":"1080x2400","deviceScreenDensity":420}}
2025-11-23 20:56:17:270 - [58e6df27][HTTP] <-- POST /session 200 12994 ms - 994
2025-11-23 20:56:17:290 - [58e6df27][HTTP] Request idempotency key: 1c590bcb-78e4-4a1b-bf88-d3c5986e271f
2025-11-23 20:56:17:291 - [58e6df27][HTTP] --> POST /session/58e6df27-83fb-4101-81c1-d64f6c3dfca6/execute/sync {"script":"mobile: startLogsBroadcast","args":[{}]}
2025-11-23 20:56:17:294 - [58e6df27][AndroidUiautomator2Driver@d423] Calling AppiumDriver.execute() with args: ["mobile: startLogsBroadcast",[{}],"58e6df27-83fb-4101-81c1-d64f6c3dfca6"]
2025-11-23 20:56:17:295 - [58e6df27][AndroidUiautomator2Driver@d423] Starting logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/58e6df27-83fb-4101-81c1-d64f6c3dfca6/appium/device/logcat
2025-11-23 20:56:17:296 - [58e6df27][AndroidUiautomator2Driver@d423] Responding to client with driver.execute() result: null
2025-11-23 20:56:17:296 - [58e6df27][HTTP] <-- POST /session/58e6df27-83fb-4101-81c1-d64f6c3dfca6/execute/sync 200 5 ms - 14
2025-11-23 20:56:17:337 - [58e6df27][HTTP] --> DELETE /session/58e6df27-83fb-4101-81c1-d64f6c3dfca6
2025-11-23 20:56:17:337 - [58e6df27][AndroidUiautomator2Driver@d423] Calling AppiumDriver.deleteSession() with args: ["58e6df27-83fb-4101-81c1-d64f6c3dfca6"]
2025-11-23 20:56:17:337 - [58e6df27][AppiumDriver@79ef] Event 'quitSessionRequested' logged at 1763931377337 (21:56:17 GMT+0100 (Central European Standard Time))
2025-11-23 20:56:17:338 - [58e6df27][AppiumDriver@79ef] Removing session 58e6df27-83fb-4101-81c1-d64f6c3dfca6 from our master session list
2025-11-23 20:56:17:338 - [58e6df27][AndroidUiautomator2Driver@d423] Deleting UiAutomator2 session
2025-11-23 20:56:17:338 - [58e6df27][AndroidUiautomator2Driver@d423] Deleting UiAutomator2 server session
2025-11-23 20:56:17:338 - [58e6df27][AndroidUiautomator2Driver@d423] Proxying [DELETE /] to [DELETE http://127.0.0.1:8201/session/6277ea58-2327-4858-8ac2-ca40846b0cb6] with no body
2025-11-23 20:56:17:457 - [58e6df27][AndroidUiautomator2Driver@d423] Got response with status 200: {"sessionId":"6277ea58-2327-4858-8ac2-ca40846b0cb6","value":null}
2025-11-23 20:56:17:458 - [58e6df27][ADB] Getting IDs of all 'io.appium.uiautomator2.server' processes
2025-11-23 20:56:17:458 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell ps --help'
2025-11-23 20:56:17:542 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell ps -A'
2025-11-23 20:56:17:807 - [58e6df27][AndroidUiautomator2Driver@d423] [Instrumentation] io.appium.uiautomator2.server.test.AppiumUiAutomator2Server:.
2025-11-23 20:56:17:807 - [58e6df27][AndroidUiautomator2Driver@d423] [Instrumentation]
2025-11-23 20:56:17:807 - [58e6df27][AndroidUiautomator2Driver@d423] [Instrumentation] Time: 6.468
2025-11-23 20:56:17:807 - [58e6df27][AndroidUiautomator2Driver@d423] [Instrumentation]
2025-11-23 20:56:17:807 - [58e6df27][AndroidUiautomator2Driver@d423] [Instrumentation] OK (1 test)
2025-11-23 20:56:17:807 - [58e6df27][AndroidUiautomator2Driver@d423] [Instrumentation]
2025-11-23 20:56:17:807 - [58e6df27][AndroidUiautomator2Driver@d423] [Instrumentation]
2025-11-23 20:56:18:077 - [58e6df27][ADB] Getting IDs of all 'io.appium.uiautomator2.server' processes
2025-11-23 20:56:18:078 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell ps -A'
2025-11-23 20:56:18:309 - [58e6df27][AndroidUiautomator2Driver@d423] [Instrumentation] The process has exited with code null, signal SIGTERM
2025-11-23 20:56:18:310 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell am force-stop io.appium.uiautomator2.server'
2025-11-23 20:56:18:312 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell am force-stop io.appium.uiautomator2.server.test'
2025-11-23 20:56:18:595 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys activity services io.appium.settings/.recorder.RecorderService'
2025-11-23 20:56:18:597 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell am force-stop io.appium.android.apis'
2025-11-23 20:56:18:993 - [58e6df27][ADB] Removing forwarded port socket connection: 8201
2025-11-23 20:56:18:993 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 forward --remove tcp:8201'
2025-11-23 20:56:19:023 - [58e6df27][AndroidUiautomator2Driver@d423] Restoring hidden api policy to the device default configuration
2025-11-23 20:56:19:023 - [58e6df27][ADB] Running '/Users/dor.blayzer/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell 'settings delete global hidden_api_policy_pre_p_apps;settings delete global hidden_api_policy_p_apps;settings delete global hidden_api_policy''
2025-11-23 20:56:19:574 - [58e6df27][Logcat] Stopping logcat capture
2025-11-23 20:56:19:578 - [58e6df27][AppiumDriver@79ef] Event 'quitSessionFinished' logged at 1763931379578 (21:56:19 GMT+0100 (Central European Standard Time))
2025-11-23 20:56:19:578 - [58e6df27][AppiumDriver@79ef] Received response: null
2025-11-23 20:56:19:579 - [58e6df27][AppiumDriver@79ef] But deleting session, so not returning
2025-11-23 20:56:19:579 - [58e6df27][AppiumDriver@79ef] Responding to client with driver.deleteSession() result: null
2025-11-23 20:56:19:580 - [58e6df27][HTTP] <-- DELETE /session/58e6df27-83fb-4101-81c1-d64f6c3dfca6 200 2242 ms - 14

@KazuCocoa
Copy link
Member

What happens if you change localhost to 127.0.0.1 as my review comments

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 23, 2025

What happens if you change localhost to 127.0.0.1 as my review comments

Same issue 😔

@KazuCocoa
Copy link
Member

Hm, then I have no idea.
Maybe it makes sense to print the url target also as part of the error message.

@KazuCocoa
Copy link
Member

One potential related thing is 0.0.0.0 below. My local had 127.0.0.1. This might be related to early conversation(?)

2025-11-23 20:56:17:295 - [58e6df27][AndroidUiautomator2Driver@d423] Starting logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/58e6df27-83fb-4101-81c1-d64f6c3dfca6/appium/device/logcat
2025-11-23 20:56:17:296 - [58e6df27][AndroidUiautomator2Driver@d423] Responding to client with driver.execute() result: null

Also, it makes sense to double check with another library, such as https://www.npmjs.com/package/wscat if the same url got the same result

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 24, 2025

One potential related thing is 0.0.0.0 below. My local had 127.0.0.1. This might be related to early conversation(?)

2025-11-23 20:56:17:295 - [58e6df27][AndroidUiautomator2Driver@d423] Starting logcat broadcasting on web socket server {"address":"0.0.0.0","family":"IPv4","port":4723} to /ws/session/58e6df27-83fb-4101-81c1-d64f6c3dfca6/appium/device/logcat
2025-11-23 20:56:17:296 - [58e6df27][AndroidUiautomator2Driver@d423] Responding to client with driver.execute() result: null

Also, it makes sense to double check with another library, such as https://www.npmjs.com/package/wscat if the same url got the same result

Yea. I also found this address odd.
How can we change it? Who provide it?

@KazuCocoa
Copy link
Member

It might be --address passed to the appium server.

argList.Add("--address");
argList.Add($"\"{IpAddress}\"");

The appium server log kicked by this test had below address: '127.0.0.1'.

2025-11-25 07:08:56:464 [Appium] Welcome to Appium v3.1.1 (REV bab86d5de571015b63fd8fc30b47bbe072a1290e)
2025-11-25 07:08:56:466 [Appium] Non-default server args:
2025-11-25 07:08:56:467 [Appium] { address: '127.0.0.1' }
2025-11-25 07:08:56:467 [Appium] The autodetected Appium home path: /Users/kazu/.appium
2025-11-25 07:08:56:468 [Appium] Attempting to load driver uiautomator2...

It looks like this test case doesn't kill the running appium server process, so it probably makese sense to make sure the host doesn't have appium process

@Dor-bl
Copy link
Collaborator Author

Dor-bl commented Nov 25, 2025

It might be --address passed to the appium server.

argList.Add("--address");
argList.Add($"\"{IpAddress}\"");

The appium server log kicked by this test had below address: '127.0.0.1'.

2025-11-25 07:08:56:464 [Appium] Welcome to Appium v3.1.1 (REV bab86d5de571015b63fd8fc30b47bbe072a1290e)
2025-11-25 07:08:56:466 [Appium] Non-default server args:
2025-11-25 07:08:56:467 [Appium] { address: '127.0.0.1' }
2025-11-25 07:08:56:467 [Appium] The autodetected Appium home path: /Users/kazu/.appium
2025-11-25 07:08:56:468 [Appium] Attempting to load driver uiautomator2...

It looks like this test case doesn't kill the running appium server process, so it probably makese sense to make sure the host doesn't have appium process

Great catch @KazuCocoa .
Apparently, it's due to my running a server in the background.
When I ran the tests with no server instance, it passed.

image

@Dor-bl Dor-bl merged commit 6f16c47 into appium:main Nov 25, 2025
3 checks passed
@Dor-bl Dor-bl deleted the log-broadcast-android branch November 25, 2025 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants