fix(android): expose stable native selectors with exact pixel bounds

This commit is contained in:
chenmingxuan committed 2026-11-03 00:02:35 +08:00
1 parent 4ea7939d9c
commit dc3a48f6b2
13 files changed
+313 -43

No files matched your search

+34
View File
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from collections import Counter
import io
import json
import os
@@ -351,6 +352,12 @@ def format_minimal_list_with_elements(
idx = 1
added_items = [] # list of tuples: (text, cx, cy)
items_bounds = [] # list of tuples: (idx, (left, top, right, bottom))
resource_counts = Counter(
resource_id
for node in fused_xml
if isinstance(resource_id := node.get("resource-id") or node.get("resource_id"), str)
and resource_id
)
def normalize_bounds(left: int, top: int, right: int, bottom: int) -> str:
n_left = int(max(0, min(1000, left * 1000 / width)))
@@ -450,6 +457,31 @@ def format_minimal_list_with_elements(
line += f" | range: {json.dumps(native_state['range'], ensure_ascii=False)}"
if native_state.get("actions"):
line += f" | actions: {','.join(native_state['actions'])}"
# Displayed Bounds are normalized and lossy. Native matching needs
# exact pixels; changing readouts are values, not identity filters.
native_selector: dict[str, Any] = {
key: value
for key, value in (
("resource_id", node.get("resource-id") or node.get("resource_id")),
("class_name", node.get("class") or node.get("class_name")),
("package_name", node.get("package") or node.get("package_name")),
)
if isinstance(value, str) and 0 < len(value) <= 512
}
if (
native_selector.get("resource_id") or native_selector.get("class_name")
) and "[OCR]" not in str(node.get("class", "")):
resource_id = native_selector.get("resource_id")
if not resource_id or resource_counts[resource_id] > 1:
native_selector["bounds"] = node.get("native_bounds_px") or [
left,
top,
right,
bottom,
]
line += f" | native_selector: {json.dumps(native_selector, ensure_ascii=False)}"
else:
native_selector = {}
if error:
line += f" | Error: '{error}'"
if value_evidence:
@@ -474,6 +506,8 @@ def format_minimal_list_with_elements(
element["error"] = error
element.update(value_evidence)
element.update(native_state)
if native_selector:
element["native_selector"] = native_selector
if native_control:
element["content_desc"] = node.get("content-desc") or ""
element["native_text"] = node.get("text") or ""