12306-specific knowledge for booking train tickets. Covers app UI structure, station search behavior, booking flow, and common pitfalls. Uses the appium-andr...
---
name: 12306-android-adb
description: 12306-specific knowledge for booking train tickets. Covers app UI structure, station search behavior, booking flow, and common pitfalls. Uses the appium-android-adb bridge for all screen interaction ā NEVER use raw ADB commands on 12306.
---
# 12306 Train Booking
12306-specific knowledge, workflows, and pitfalls. For screen interaction, use the `appium-android-adb` skill (`bridge_daemon.py`).
## šØ Before Any 12306 Action
Start the Appium bridge (once per session):
```bash
bash ~/.openclaw/workspace/skills/appium-android-adb/start_bridge.sh
```
All screen interactions use `python3 ~/.openclaw/workspace/skills/appium-android-adb/bridge_daemon.py <command>`.
## ā Never Use Raw ADB on 12306
The 12306 app uses UC WebView for the train list and booking pages. **ADB `input tap` is IGNORED.** Always use `bridge_daemon.py` from `appium-android-adb`.
## 12306 App Structure
| Page | Package/Activity | How to Detect |
|------|-----------------|---------------|
| Home | `com.MobileTicket` / `MainActivity` | `ticket_home_btn_search` button exists |
| Train list | `com.MobileTicket` / `H5Activity` | `title` contains `<>` (e.g. "äøęµ· <> čå·") |
| Booking | same H5Activity | "é¢č®¢" buttons exist |
| Confirmation | same H5Activity | "ę交订å" button exists |
| Payment | same H5Activity | "ē«å³ęÆä»" or "å»ęÆä»" button |
### Key Element IDs (Home Page)
| Element | Resource ID |
|---------|------------|
| Search button | `ticket_home_btn_search` |
| Departure station | `home_page_train_dep1` |
| Arrival station | `home_page_train_arr1` |
| Date container | `home_page_depart_date_view_container` |
## ā Station Search Behavior
**Any station in a city searches ALL stations in that city.** Example:
- "äøęµ·č¹ę”„āčå·" also shows trains from äøęµ·ē«, äøęµ·åē«, äøęµ·ę¾ę± etc.
- "äøęµ·āčå·å" also shows trains to čå·ē«, čå·ååŗ, čå·ę°åŗ etc.
**Once you have ANY valid city-to-city search result, NEVER go back to change stations.** If the target train isn't immediately visible, just scroll ā it's in the list.
## Booking Flow
### Step 1: Home page ā ensure valid city pair + date
```
dump ā check current stations and date
If stations show any valid city pair (e.g. "äøęµ·č¹ę”„āčå·" or "äøęµ·āčå·å"):
ā SKIP station changes. All trains from both cities will appear.
If stations are completely wrong:
ā tap departure, pick ANY station in correct city
ā tap arrival, pick ANY station in correct city
tap date container ā pick target date
tap "ę„询车焨"
```
### Step 2: Find and select train
```
dump ā check trains[] for target train number
scroll down ā dump ā repeat until target appears
tap train by text (e.g. '{"text": "G7004"}')
ā train detail / booking page appears
```
### Step 3: Book seat
```
dump ā see seat options, look for "é¢č®¢" buttons
tap '{"text": "é¢č®¢", "index": 0}' ā first is usually äŗēåŗ§
```
### Step 4: Fingerprint (manual ā tell user)
```
If alert with "ęēŗ¹" appears: tell user to authenticate on phone. Wait, then dump to verify.
```
### Step 5: Confirm and submit
```
dump ā verify train, passenger, seat, price
If passenger not selected: tap "éę©ä¹č½¦äŗŗ" ā tap passenger name
tap "ę交订å"
```
### Step 6: Payment (user handles Alipay/WeChat)
```
dump ā tap "ē«å³ęÆä»" or "å»ęÆä»"
ā User handles Alipay/WeChat login manually
```
## Decision Tree
```
dump the screen:
āā package != "com.MobileTicket" ā app not in foreground, tap app icon or adb shell monkey
āā "ticket_home_btn_search" in buttons ā HOME PAGE
ā ā ensure valid city pair (any station!) + date ā tap ę„询车焨
āā title contains "<>" ā TRAIN LIST
ā ā scroll + dump to find target train ā tap it
ā ā NEVER go back to change stations ā scroll instead
āā "é¢č®¢" in buttons ā BOOKING PAGE
ā ā tap é¢č®¢ for seat type
āā "ę交订å" in buttons ā CONFIRMATION
ā ā verify details ā select passenger ā submit
āā "ē«å³ęÆä»" in buttons ā PAYMENT
ā ā tap to pay, user handles auth
āā alerts not empty ā dismiss first, re-dump
```
## Common Pitfalls
- **Going back to change stations**: Don't. Any station in a city shows all trains. Just scroll.
- **Train at viewport edge (h=6)**: Scroll slightly to bring it into view, then tap.
- **Fingerprint dialog**: Cannot automate. Tell user to authenticate.
- **Session timeout**: The bridge daemon holds a persistent session ā no timeout issues.
- **Wrong date on train list**: The results page has date tabs at the top. Tap the correct date there directly.
## Files
- `adb_helper.py` ā Low-level ADB helper (native element dump/find/tap/swipe). Use for pre-Appium checks or native-only pages.
- `SKILL.md` ā This file. 12306-specific knowledge.
- `README.md` ā Reference docs.
don't have the plugin yet? install it then click "run inline in claude" again.