UNPKG

@u4/adbkit

Version:

A Typescript client for the Android Debug Bridge.

132 lines 5.49 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const xpath_1 = __importDefault(require("xpath")); const xmldom_1 = require("@xmldom/xmldom"); const keycode_1 = require("./keycode"); const index_1 = require("../index"); class DeviceClientExtra { constructor(deviceClient) { this.deviceClient = deviceClient; } /** * rootless version of enable usb tethering * Depends of phone language will fail with non latin language. * @param enable */ async usbTethering(enable) { await this.keyCode(keycode_1.KeyCodes.KEYCODE_WAKEUP); await this.deviceClient.startActivity({ component: 'com.android.settings/.TetherSettings', wait: true }); const xml = await this.deviceClient.execOut('uiautomator dump /dev/tty', 'utf8'); const doc = new xmldom_1.DOMParser().parseFromString(xml); // https://gist.github.com/LeCoupa/8c305ec8c713aad07b14 const nodes = xpath_1.default.select('//*[contains(@text,"USB")]/../..', doc); if (!nodes.length) throw Error('can not find USB labeled node'); const switch_widget = xpath_1.default.select('./*/node[@class="android.widget.Switch"]', nodes[0]); if (!switch_widget.length) throw Error('can not find android.widget.Switch linked to USB label'); const [checkBox] = switch_widget; // console.log(checkBox.toString()); const checked = checkBox.getAttribute('checked') === 'true'; const bounds = checkBox.getAttribute('bounds'); if (!bounds) throw Error('missing bounds attribut to checkbox'); if (checked === enable) { return false; } const m = bounds.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/); if (!m) throw Error('failed to parse Switch bounds'); const [, x1, y1] = m; // , x2, y2 await this.deviceClient.exec('input tap ' + x1 + ' ' + y1); return true; } /** * rootless version of enable air plain mode * Depends of phone language will fail with non latin language. * @param enable expected final stat for airplain mode * @param twiceMs if > 0 will switch airplan mode 2 time to match expected state */ async airPlainMode(enable, twiceMs) { // wake screen await this.keyCode(keycode_1.KeyCodes.KEYCODE_WAKEUP); await this.deviceClient.startActivity({ action: 'android.settings.AIRPLANE_MODE_SETTINGS', wait: true }); // await Utils.delay(100); let xml = await this.deviceClient.execOut('uiautomator dump /dev/tty', 'utf8'); xml = xml.replace('UI hierchary dumped to: /dev/tty', ''); // xml = xml.replace(/ ([a-z-]+)=""/g, ''); // xml = xml.replace(/ (checkable|clickable|content-desc|enabled|focused|focusable|index|long-clickable|package|password|resource-id|scrollable|selected)="[^"]*"/g, ''); const textFilter = (text) => text.toLowerCase(); const doc = new xmldom_1.DOMParser().parseFromString(textFilter(xml)); const all_switch_widget = xpath_1.default.select(textFilter('//*/node[@class="android.widget.Switch"]'), doc); let theSwitch = null; if (!all_switch_widget.length) { throw Error('no switch on screen.'); } for (let i = 0; i < all_switch_widget.length; i++) { const nodes = xpath_1.default.select('../../*/node[contains(@text,"mode")]', all_switch_widget[i]); if (nodes.length) { theSwitch = all_switch_widget[i]; } } if (!theSwitch) { throw Error('can not find mode labeled node "mode avion" airPlainMode switch failed'); } // https://gist.github.com/LeCoupa/8c305ec8c713aad07b14 // "Airplane mode" const checked = theSwitch.getAttribute('checked') === 'true'; const bounds = theSwitch.getAttribute('bounds'); if (!bounds) throw Error('missing bounds attribut in switch'); if (!twiceMs && checked === enable) { return false; } const m = bounds.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/); if (!m) throw Error('failed to parse Switch bounds airPlainMode switch failed'); const [, x1, y1] = m; // , x2, y2 await this.tap(x1, y1); if (twiceMs && checked === enable) { await index_1.Utils.delay(twiceMs); await this.tap(x1, y1); } return true; } /** * enable / disable * type: bluetooth / data/ wifi */ async setSvc(type, enable) { const action = enable ? 'enable' : 'disable'; return this.deviceClient.execOut(`svc ${type} ${action}`, 'utf8'); } /** * Tap on screen * @param x1 * @param y1 * @returns */ async tap(x1, y1) { return this.deviceClient.execOut(`input tap ${x1} ${y1}`, 'utf8'); } /** * Tap a keyCode * @param key * @returns */ async keyCode(key) { return this.deviceClient.execOut(`input keyevent ${key}`, 'utf8'); } /** * press the back button * @returns */ async back() { return this.keyCode(keycode_1.KeyCodes.KEYCODE_BACK); } } exports.default = DeviceClientExtra; //# sourceMappingURL=DeviceClientExtra.js.map