Script tùy chỉnh
Các script tích hợp đã bao quát những luồng thông dụng. Khi bạn cần thứ chúng không có — một bước theo thứ tự khác, một màn hình chúng không bao giờ chạm tới, hoặc một ứng dụng không phải TikTok hay Instagram — bạn có thể tự viết bằng bất kỳ ngôn ngữ nào và để TikMatrix giao chiếc điện thoại cho bạn.
Yêu cầu
Script tùy chỉnh cần gói Pro, Team hoặc Business. Gói Starter không có quyền truy cập.
Số thiết bị trong gói của bạn cũng chính là giới hạn chạy đồng thời: gói Pro (20 thiết bị) có thể điều khiển 20 điện thoại cùng lúc, dù qua tác vụ tích hợp, script tùy chỉnh, hay kết hợp cả hai.
Hai cách chạy một script
Độc lập
Bạn tự chạy chương trình. TikMatrix chỉ cho mượn thiết bị.
from tikmatrix import TikMatrix
client = TikMatrix()
for device in client.devices():
if device["busy"]:
continue
with client.device(device["serial"], label="my crawler") as d:
d.press("home")
print(d.info())
Phù hợp cho việc chạy một lần, thu thập dữ liệu, và mọi thứ bạn muốn khởi động từ bộ lập lịch của riêng mình.
Được quản lý
Bạn đăng ký chương trình trong TikMatrix và nó trở thành một tác vụ như mọi tác vụ khác. Nó có hàng đợi tác vụ, giới hạn đồng thời theo gói, tự động thử lại, nhật ký tác vụ và mẫu lịch chạy. TikMatrix thuê thiết bị trước khi khởi động chương trình của bạn và truyền id thuê qua biến môi trường.
from tikmatrix import TikMatrix
with TikMatrix.from_env() as d: # thi ết bị đã được thuê sẵn
d.click(text="Log in")
print("done") # dòng này sẽ nằm trong nhật ký tác vụ
Phù hợp cho mọi thứ bạn muốn chạy lặp lại, theo lịch, hoặc trên nhiều thiết bị.
Chọn cái nào
| Độc lập | Được quản lý | |
|---|---|---|
| Ai khởi động | Bạn | Hàng đợi tác vụ của TikMatrix |
| Thuê thiết bị | Bạn tự lấy | Đã có sẵn khi khởi động |
| Thử lại, lịch chạy, nhật ký | Bạn tự xây | Có sẵn |
| Chạy trên nhiều thiết bị | Bạn tự viết vòng lặp | Mỗi thiết bị một tác vụ, chạy song song |
| Tốt nhất cho | Khám phá, trình thu thập, việc chạy một lần | Mọi thứ bạn muốn lặp lại |
Bạn có thể bắt đầu ở chế độ độc lập trong lúc hoàn thiện luồng, rồi đăng ký chính tệp đó thành script được quản lý — dòng duy nhất thay đổi là TikMatrix.from_env().
Bắt đầu
1. Cài thư viện client
pip install requests
Rồi sao chép tikmatrix.py từ thư mục SDK đặt cạnh script của bạn. Thư viện chỉ là một tệp duy nhất, không có phụ thuộc nào khác.
Bạn không bắt buộc phải dùng nó — API chỉ là JSON thuần qua HTTP, và các endpoint thô được ghi rõ bên dưới.
2. Viết script của bạn
from tikmatrix import TikMatrix
client = TikMatrix()
with client.device("192.168.1.5:5555") as d:
d.press("home")
d.adb("shell", "am", "start", "-a", "android.settings.SETTINGS")
d.wait_for(text="Settings", timeout=15)
d.screenshot("settings.png")
Chạy nó khi TikMatrix đang mở và điện thoại đã kết nối. Nếu nó in ra một từ điển thông tin thiết bị thì mọi thứ đã thông suốt.
3. Đăng ký nó (chỉ chế độ được quản lý)
Vào Thiết bị → Script tùy chỉnh → Thêm script:
| Trường | Ý nghĩa |
|---|---|
| Tên | Hiển thị trong danh sách script và nhật ký tác vụ |
| Lệnh | Dòng lệnh chương trình cần chạy, ví dụ python C:/scripts/my_flow.py |
| Thư mục làm việc | Tùy chọn. Nơi chương trình khởi động |
| Nền tảng | Xem chế độ nền tảng bên dưới |
| Thời gian chờ | Số giây trước khi script bị buộc dừng và tác vụ bị đánh dấu thất bại. Mặc định 1800 |
| Biến môi trường bổ sung | Đối tượng JSON tùy chọn, được hợp nhất vào môi trường của chương trình |
| Bật | Tắt một script mà không xóa. Script bị tắt không thể được điều phối |
Sau đó nhấn ▶ trên dòng của script và chọn thiết bị, hệt như với script tích hợp.
Trợ lý AI có thể soạn một script tùy chỉnh từ mô tả bằng ngôn ngữ thường và đăng ký nó chỉ trong một bước. Nó cho bạn xem toàn bộ tệp trước khi ghi bất cứ thứ gì lên đĩa.
Thuê thiết bị
Một điện thoại chỉ có thể được điều khiển bởi một thứ tại một thời điểm. Thuê nó là báo cho TikMatrix biết thiết bị đang bận, nhờ đó:
- hàng đợi tác vụ sẽ không đẩy tác vụ lên cùng màn hình đó, và
- các lệnh gọi JSON-RPC của bạn báo cáo tình trạng agent y như script tích hợp, nên bộ giám sát thấy một agent đang bận thay vì một agent im lặng.
Việc thuê cũng chiếm một suất thiết bị trong gói của bạn.
Lượt thuê sẽ hết hạn — mặc định 120 giây, tối đa 600. Thư viện Python gia hạn lượt thuê của bạn trong một luồng nền và giải phóng khi khối with kết thúc, nên một script bị sập sẽ trả thiết bị trong vài giây thay vì giữ đến khi bạn khởi động lại ứng dụng. Nếu bạn gọi API trực tiếp, bạn phải tự gửi nhịp tim.
Bạn có thể xem mọi lượt thuê đang sống — và giải phóng cưỡng bức — tại Cài đặt → Developer API → Phiên thiết bị đang hoạt động.
Chế độ nền tảng
Script đã đăng ký khai báo mục tiêu của nó:
Generic — thiết bị được giao nguyên trạng. Không mở ứng dụng nào, không chuyển tài khoản, không kiểm tra bộ gõ, và không đóng gì sau khi xong. Dùng chế độ này để tự động hóa bất cứ thứ gì không phải TikTok hay Instagram.
TikTok / Instagram — ứng dụng được mở và tài khoản được chuyển trước khi ch ương trình của bạn bắt đầu, rồi ứng dụng được đóng khi kết thúc, hệt như với script tích hợp. TIKMATRIX_PACKAGE cho biết gói ứng dụng nào đã được xác định. Dùng chế độ này để thêm một bước mà script tích hợp không có.
Biến môi trường
Script được quản lý nhận:
| Biến | Ý nghĩa |
|---|---|
TIKMATRIX_API_BASE | URL máy chủ, ví dụ http://127.0.0.1:50809 |
TIKMATRIX_SESSION_ID | Lượt thuê đã được giữ sẵn cho bạn |
TIKMATRIX_SERIAL | Thiết bị mà tác vụ này được gửi tới |
TIKMATRIX_PACKAGE | Gói ứng dụng đã xác định |
TIKMATRIX_PLATFORM | tiktok, instagram hoặc generic |
TikMatrix.from_env() đọc toàn bộ những thứ này giúp bạn.
Script độc lập không nhận biến nào trong số đó — hãy thuê thiết bị một cách tường minh.
Mọi thứ bạn đặt trong Biến môi trường bổ sung sẽ được hợp nhất đè lên trên, đây là cách thông dụng để truyền thiết lập riêng cho từng lần chạy vào cùng một script đã đăng ký mà không phải sửa tệp.
Tham chiếu thư viện Python
TikMatrix — kết nối
| Lời gọi | Làm gì |
|---|---|
TikMatrix(base_url=None, timeout=30.0) | Kết nối. Lùi về TIKMATRIX_API_BASE, rồi http://127.0.0.1:50809 |
client.devices() | Thiết bị trực tuyến, mỗi thiết bị có serial, real_serial và busy |
client.sessions() | Mọi lượt thuê đang sống, kể cả của tiến trình khác |
client.device(serial, label=..., ttl_secs=120) | Thuê một thiết bị và trả về Device |
TikMatrix.from_env() | Tiếp nhận thiết bị mà script được quản lý đã khởi động cùng |
Device — chiếc điện thoại
| Lời gọi | Làm gì |
|---|---|
d.info() | Thông tin thiết bị từ UIAutomator2 |
d.window_size() | (rộng, cao) |
d.screenshot(path=None) | Byte PNG, tùy chọn ghi ra path |
d.hierarchy() | Cây giao diện hiện tại dưới dạng XML |
d.find(text=, resource_id=, description=, class_name=) | Các nút khớp, mỗi nút có bounds và center |
d.exists(**criteria) | Có gì khớp hay không |
d.wait_for(timeout=10.0, interval=1.0, **criteria) | Chờ đến khi xuất hiện rồi trả về |
d.click(timeout=10.0, **criteria) | Chờ phần tử rồi chạm vào tâm của nó |
d.click_xy(x, y) | Chạm vào tọa độ |
d.swipe(sx, sy, ex, ey, steps=20) | Vuốt |
d.press(key) | back, home, recent, enter, … |
d.input_text(text) | Gõ vào ô đang được chọn qua bộ gõ nhanh đi kèm |
d.jsonrpc(method, params=None, timeout=10) | Bất kỳ phương thức UIAutomator2 nào |
d.adb(*args, timeout_ms=None) | Chạy một lệnh ADB |
d.release() | Giải phóng lượt thuê. with làm điều này giúp bạn |
find so khớp trên cây giao diện đã kết xuất, nên khi một selector trượt bạn có thể print(d.hierarchy()) và xem chính xác nó đã tìm trong gì. Trình kiểm tra phần tử ở khung thiết bị hiển thị cùng cây đó dưới dạng trực quan, thường là cách nhanh nhất để tìm resource-id.
input_text cần ADBNó gửi broadcast tới bộ gõ đi kèm, đi qua adb shell. Hãy bật quyền ADB trước khi dùng, nếu không nó sẽ thất bại với mã 403.
Lỗi
Thư viện ném ra hai ngoại lệ, cả hai đều là lớp con của RuntimeError:
| Ngoại lệ | Khi nào |
|---|---|
DeviceBusyError | HTTP 409 — thiết bị đã được thuê, hoặc gói của bạn hết suất thiết bị |
TikMatrixError | Mọi trường hợp còn lại: gói quá thấp, lượt thuê hết hạn, ADB bị tắt, selector không bao giờ khớp |
from tikmatrix import TikMatrix, TikMatrixError, DeviceBusyError
client = TikMatrix()
try:
with client.device("192.168.1.5:5555") as d:
d.click(text="Log in", timeout=20)
except DeviceBusyError:
print("máy đó đang có người dùng — thử máy khác")
except TikMatrixError as exc:
print("thất bại:", exc)
Trong một script được quản lý, để ngoại lệ thoát ra ngoài thường là điều đúng đắn: mã thoát khác 0 đánh dấu tác vụ thất bại và vết lỗi sẽ nằm trong nhật ký tác vụ.
Endpoint HTTP
Các thao tác trên thiết bị cần header x-session-id trỏ tới một lượt thuê đang sống. Không có khóa API: giống như phần còn lại của API cục bộ, các endpoint này không xác thực — việc tiếp cận được máy này trên mạng chính là kiểm soát truy cập. Chúng không gửi header CORS nào, nên hãy gọi từ một chương trình (curl, Python, bất kỳ mã phía máy chủ nào) chứ đừng gọi từ một trang trong trình duyệt.
| Phương thức | Đường dẫn | Mục đích |
|---|---|---|
GET | /api/v1/rpc/devices | Liệt kê thiết bị trực tuyến và tình trạng bận |
POST | /api/v1/rpc/session | Thuê một thiết bị → session_id |
POST | /api/v1/rpc/session/{id}/heartbeat | Gia hạn lượt thuê |
DELETE | /api/v1/rpc/session/{id} | Giải phóng lượt thuê |
GET | /api/v1/rpc/session | Liệt kê các lượt thuê đang sống |
POST | /api/v1/rpc/jsonrpc | Gọi một phương thức UIAutomator2 |
POST | /api/v1/rpc/adb | Ch ạy một lệnh ADB |
GET | /api/v1/rpc/hierarchy?serial= | Cây giao diện hiện tại dạng XML |
GET | /api/v1/rpc/screenshot?serial= | Màn hình hiện tại dạng PNG |
Phản hồi JSON dùng cùng lớp bao như phần còn lại của API cục bộ — {"code": 0, "message": "success", "data": ...}, với code khác 0 khi thất bại. hierarchy và screenshot trả về nội dung thô.
Ví dụ
# Thuê một thiết bị
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","label":"curl test","ttl_secs":120}'
# {"code":0,"message":"success","data":{"session_id":"ff3ae079-...","serial":"192.168.1.5:5555", ...}}
# Điều khiển nó
curl -X POST http://127.0.0.1:50809/api/v1/rpc/jsonrpc \
-H "x-session-id: ff3ae079-..." \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","method":"deviceInfo","params":[]}'
# Giữ lượt thuê sống trong khi làm việc
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-.../heartbeat \
-H "Content-Type: application/json" \
-d '{"ttl_secs":120}'
# Trả lại
curl -X DELETE http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-...
Lỗi
| Trạng thái | Ý nghĩa |
|---|---|
| 403 | Gói thấp hơn Pro, không có lượt thuê, lượt thuê hết hạn, hoặc quyền ADB bị tắt |
| 409 | Thiết bị đã được thuê, hoặc gói của bạn hết suất thiết bị |
Viết bằng ngôn ngữ khác
Không có gì ở đây gắn riêng với Python. Bất kỳ môi trường chạy nào gửi được yêu cầu HTTP đều dùng được — hợp đồng của chế độ được quản lý chỉ là "đọc ba biến môi trường, thoát với mã 0 khi thành công".
// my_flow.js — đăng ký bằng: node C:/scripts/my_flow.js
const base = process.env.TIKMATRIX_API_BASE || "http://127.0.0.1:50809";
const serial = process.env.TIKMATRIX_SERIAL;
const session = process.env.TIKMATRIX_SESSION_ID;
async function jsonrpc(method, params = []) {
const res = await fetch(`${base}/api/v1/rpc/jsonrpc`, {
method: "POST",
headers: { "content-type": "application/json", "x-session-id": session },
body: JSON.stringify({ serial, method, params }),
});
const body = await res.json();
if (!res.ok || body.code !== 0) throw new Error(body.message || res.statusText);
return body.data;
}
console.log(await jsonrpc("deviceInfo"));
Nếu trình thông dịch không nằm trong PATH, hãy ghi đường dẫn đầy đủ ở ô Lệnh, ví dụ C:/Program Files/nodejs/node.exe C:/scripts/my_flow.js.
Kích hoạt script tùy chỉnh từ API
Script đã đăng ký cũng có thể được khởi động qua API quản lý tác vụ, nhờ đó một script có thể xếp hàng công việc tiếp theo:
curl -X POST http://127.0.0.1:50809/api/v1/task \
-H "Content-Type: application/json" \
-d '{
"serials": ["192.168.1.5:5555"],
"script_name": "custom_script",
"script_config": {
"custom_script_id": 1,
"custom_script_platform": "generic"
}
}'
custom_script_id là id của script bạn đã đăng ký.
Quyền ADB
/api/v1/rpc/adb cho script của bạn một shell trên thiết bị — bạn cần nó để đẩy media, cài APK và đổi cài đặt hệ thống. Vì đó là một shell đầy đủ trên một endpoint không có khóa API, nó được xuất xưởng ở trạng thái tắt. Hãy bật ở Cài đặt → Developer API → Cho phép lệnh ADB khi bạn có script cần đến; tự động hóa giao diện qua /rpc/jsonrpc vẫn chạy được mà không cần nó.
Khi đang tắt, /api/v1/rpc/adb trả về 403 và phần còn lại của API vẫn hoạt động bình thường. Mọi lệnh ADB mà script chạy đều được ghi vào tệp nhật ký của bạn.
Viết script để nó tiếp tục chạy được
- Hãy chờ màn hình, đừng ngủ thay cho nó.
d.wait_for(...)trả về ngay khi phần tử xuất hiện; một lệnh ngủ cố định thì hoặc chậm hơn mức cần thiết, hoặc quá ngắn vào một ngày xui. - Kiểm tra trước khi chạm. Một lần
d.exists(...)trên hộp thoại đồng ý hay lời nhắc "để sau" chỉ tốn một lần kết xuất cây, nhưng cứu được một lần chạy lẽ ra đã chạm vào chỗ trống. - In ra những gì bạn đã làm. Ở chế độ được quản lý, stdout chính là nhật ký tác vụ, và đó là dấu vết duy nhất của một lần chạy không ai theo dõi.
- Làm cho việc chạy lại an toàn. Thử lại sẽ chạy lại toàn bộ chương trình, nên script đăng bài nên kiểm tra xem nó đã đăng chưa thay vì mặc định rằng nó bắt đầu từ đầu.
- Một script một việc. Mức đồng thời tính theo thiết bị, nên mười tác vụ nhỏ trên mười điện thoại xong sớm hơn nhiều so với một script lặp qua mười điện thoại.
Ghi chú và giới hạn
- Lệnh được thực thi trực tiếp, không qua shell, nên
&&và|bị coi là tham số chứ không phải toán tử. Hãy đăng kýcmd /c "..."(Windows) hoặcsh -c "..."(macOS) nếu bạn muốn hành vi của shell. - Đặt dấu nháy quanh đường dẫn có khoảng trắng:
"C:/Program Files/Python/python.exe" my_script.py. - Script vượt quá thời gian chờ sẽ bị chấm dứt và tác vụ bị đánh dấu thất bại.
- Mã thoát khác 0 đánh dấu tác vụ thất bại; mọi thứ script ghi ra stdout và stderr đều vào nhật ký tác vụ.
- Script chạy với cùng quyền hạn như chính TikMatrix. Chỉ đăng ký những chương trình bạn tự viết hoặc tin tưởng.