跳转到内容
Last updated

云手机示例

使用开放 API 进行云手机管理的完整工作示例。

基本网址https://api.morelogin.com


完整工作流程:身份验证→创建→安装应用程序→ADB

curl

# 1. Get access token
TOKEN=$(curl -s -X POST https://api.morelogin.com/oauth2/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "YOUR_API_ID",
    "client_secret": "YOUR_API_KEY",
    "grant_type": "client_credentials"
  }' | jq -r '.data.access_token')

echo "Token: $TOKEN"

# 2. Create a cloud phone
curl -X POST https://api.morelogin.com/cloudphone/create \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "skuId": "10002",
    "quantity": 1,
    "envRemark": "my-cloud-phone"
  }'

# Save data[0] from the response as CLOUD_PHONE_ID.

# 3. Power on the cloud phone
curl -X POST https://api.morelogin.com/cloudphone/powerOn \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"id": "CLOUD_PHONE_ID"}'

# 4. Install an app
curl -X POST https://api.morelogin.com/cloudphone/app/install \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "id": "CLOUD_PHONE_ID",
    "packageName": "com.example.app",
    "versionCode": 1
  }'

# 5. Enable ADB
curl -X POST https://api.morelogin.com/cloudphone/updateAdb \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"enableAdb": true, "ids": ["CLOUD_PHONE_ID"]}'

# 6. Query ADB connection details
curl -X POST https://api.morelogin.com/cloudphone/batchAdbInfo \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"envIds": ["CLOUD_PHONE_ID"]}'

# 7. Power off when finished
curl -X POST https://api.morelogin.com/cloudphone/powerOff \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"id": "CLOUD_PHONE_ID"}'

Python(请求)

import requests

BASE = "https://api.morelogin.com"
API_ID = "YOUR_API_ID"
API_KEY = "YOUR_API_KEY"

# 1. Get access token
resp = requests.post(f"{BASE}/oauth2/token", json={
    "client_id": API_ID,
    "client_secret": API_KEY,
    "grant_type": "client_credentials"
})
token = resp.json()["data"]["access_token"]
headers = {"Authorization": f"Bearer {token}"}
print(f"Token acquired (expires in {resp.json()['data']['expires_in']}s)")

# 2. Create a cloud phone
resp = requests.post(f"{BASE}/cloudphone/create", headers=headers, json={
    "skuId": "10002",
    "quantity": 1,
    "envRemark": "automation-phone"
})
body = resp.json()
if body["code"] != 0:
    raise RuntimeError(f"Create failed: {body['msg']} ({body['requestId']})")
phone_id = body["data"][0]
print(f"Created cloud phone: {phone_id}")

# 3. Power on the cloud phone
resp = requests.post(f"{BASE}/cloudphone/powerOn", headers=headers, json={
    "id": phone_id
})
print(f"Power-on accepted: {resp.json()['code'] == 0}")

# 4. Install app
resp = requests.post(f"{BASE}/cloudphone/app/install", headers=headers, json={
    "id": phone_id,
    "packageName": "com.example.app",
    "versionCode": 1
})
print(f"App install: {resp.json()['code']}")

# 5. Enable ADB
resp = requests.post(f"{BASE}/cloudphone/updateAdb", headers=headers, json={
    "enableAdb": True,
    "ids": [phone_id]
})
if resp.json()["code"] != 0:
    raise RuntimeError(f"Enable ADB failed: {resp.json()}")

resp = requests.post(f"{BASE}/cloudphone/batchAdbInfo", headers=headers, json={
    "envIds": [phone_id]
})
adb_info = resp.json()["data"][0]
print(f"ADB command: {adb_info.get('command')}")

# 6. Power off when done
resp = requests.post(f"{BASE}/cloudphone/powerOff", headers=headers, json={
    "id": phone_id
})
print("Cloud phone power-off accepted.")

Node.js(axios)

const axios = require('axios');

const BASE = 'https://api.morelogin.com';
const API_ID = 'YOUR_API_ID';
const API_KEY = 'YOUR_API_KEY';

async function main() {
  // 1. Get access token
  const authResp = await axios.post(`${BASE}/oauth2/token`, {
    client_id: API_ID,
    client_secret: API_KEY,
    grant_type: 'client_credentials'
  });
  const token = authResp.data.data.access_token;
  const headers = { Authorization: `Bearer ${token}` };
  console.log('Token acquired');

  // 2. Create a cloud phone
  const createResp = await axios.post(`${BASE}/cloudphone/create`,
    { skuId: '10002', quantity: 1, envRemark: 'automation-phone' },
    { headers }
  );
  if (createResp.data.code !== 0) {
    throw new Error(`Create failed: ${createResp.data.msg} (${createResp.data.requestId})`);
  }
  const phoneId = createResp.data.data[0];
  console.log(`Created cloud phone: ${phoneId}`);

  // 3. Start cloud phone
  await axios.post(`${BASE}/cloudphone/powerOn`,
    { id: phoneId },
    { headers }
  );
  console.log('Cloud phone started');

  // 4. Install app
  await axios.post(`${BASE}/cloudphone/app/install`,
    { id: phoneId, packageName: 'com.example.app', versionCode: 1 },
    { headers }
  );
  console.log('App installation initiated');

  // 5. Enable ADB
  await axios.post(`${BASE}/cloudphone/updateAdb`,
    { enableAdb: true, ids: [phoneId] },
    { headers }
  );
  const adbResp = await axios.post(`${BASE}/cloudphone/batchAdbInfo`,
    { envIds: [phoneId] },
    { headers }
  );
  console.log('ADB info:', adbResp.data.data[0]);

  // 6. Stop when done
  await axios.post(`${BASE}/cloudphone/powerOff`,
    { id: phoneId },
    { headers }
  );
  console.log('Cloud phone stopped');
}

main().catch(console.error);

文件上传示例(Python)

import requests

BASE = "https://api.morelogin.com"
headers = {"Authorization": "Bearer YOUR_TOKEN"}

phone_id = "1234567890"

# 1. Get presigned upload URL
resp = requests.post(f"{BASE}/cloudphone/uploadUrl", headers=headers, json={
    "id": phone_id,
    "fileName": "config.json"
})
upload_url = resp.json()["data"]["presignedUrl"]

# 2. Upload file to presigned URL
with open("config.json", "rb") as f:
    requests.put(upload_url, data=f)

# 3. Trigger file upload to cloud phone
resp = requests.post(f"{BASE}/cloudphone/uploadFile", headers=headers, json={
    "id": phone_id,
    "url": upload_url,
    "uploadDest": "/Download"
})
file_id = resp.json()["data"]["fileId"]

# 4. Check upload result
resp = requests.post(f"{BASE}/cloudphone/uploadFileResult", headers=headers, json={
    "id": phone_id,
    "fileId": file_id
})
print(f"Upload status: {resp.json()['data']['status']}")  # 1 = success

完整 Python SDK 示例

上面的代码片段演示了单个 API 调用。如需包含自动 Token 管理、连接池和完整设备生命周期操作的生产就绪 Python 客户端类,请参阅 GitHub 上的完整示例:

📦 GitHub — cloud_phone_open_api_demo.py

功能概览:

功能描述
自动 Token 刷新在过期前 60 秒自动获取和刷新访问令牌
连接池使用 requests.Session 并支持可配置的连接池大小,适用于高吞吐量场景
设备管理列表查询、设备详情、通过 Android ID 查询
电源管理开关机,支持开机时指定代理
应用管理安装、启动、停止、重启、卸载应用
文件管理上传和下载云手机文件
代理与分组通过开放 API 管理代理和分组

快速使用:

from cloud_phone_open_api_demo import MoreLoginCloudPhone

client = MoreLoginCloudPhone(app_id="YOUR_APP_ID", api_key="YOUR_API_KEY")

# List all cloud phones
devices = client.list_devices()
print(devices)

# Get device info
info = client.get_device_info(phone_id="1234567890")
print(info)

# Power on a cloud phone
client.power_on(phone_id="1234567890")