microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.5.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/android/adb.ts

157lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as Q from "q";
5
6import {ChildProcess} from "../../common/node/childProcess";
7import {CommandExecutor} from "../../common/commandExecutor";
8
9// See android versions usage at: http://developer.android.com/about/dashboards/index.html
10export enum AndroidAPILevel {
11 Marshmallow = 23,
12 LOLLIPOP_MR1 = 22,
13 LOLLIPOP = 21, /* Supports adb reverse */
14 KITKAT = 19,
15 JELLY_BEAN_MR2 = 18,
16 JELLY_BEAN_MR1 = 17,
17 JELLY_BEAN = 16,
18 ICE_CREAM_SANDWICH_MR1 = 15,
19 GINGERBREAD_MR1 = 10,
20}
21
22enum KeyEvents {
23 KEYCODE_BACK = 4,
24 KEYCODE_DPAD_UP = 19,
25 KEYCODE_DPAD_DOWN = 20,
26 KEYCODE_DPAD_CENTER = 23,
27 KEYCODE_MENU = 82,
28}
29
30export enum DeviceType {
31 AndroidSdkEmulator, // These seem to have emulator-<port> ids
32 Other,
33}
34
35export interface IDevice {
36 id: string;
37 isOnline: boolean;
38 type: DeviceType;
39}
40
41const AndroidSDKEmulatorPattern = /^emulator-\d{1,5}$/;
42
43export class AdbHelper {
44 private static childProcess: ChildProcess = new ChildProcess();
45 private static commandExecutor: CommandExecutor = new CommandExecutor();
46
47 /**
48 * Gets the list of Android connected devices and emulators.
49 */
50 public static getConnectedDevices(): Q.Promise<IDevice[]> {
51 return this.childProcess.execToString("adb devices")
52 .then(output => {
53 return this.parseConnectedDevices(output);
54 });
55 }
56
57 /**
58 * Broadcasts an intent to reload the application in debug mode.
59 */
60 public static switchDebugMode(projectRoot: string, packageName: string, enable: boolean, debugTarget?: string): Q.Promise<void> {
61 let enableDebugCommand = `adb ${debugTarget ? "-s " + debugTarget : ""} shell am broadcast -a "${packageName}.RELOAD_APP_ACTION" --ez jsproxy ${enable}`;
62 return new CommandExecutor(projectRoot).execute(enableDebugCommand)
63 .then(() => { // We should stop and start application again after RELOAD_APP_ACTION, otherwise app going to hangs up
64 let deferred = Q.defer();
65 setTimeout(() => {
66 this.stopApp(projectRoot, packageName, debugTarget)
67 .then(() => {
68 return deferred.resolve({});
69 });
70 }, 200); // We need a little delay after broadcast command
71
72 return deferred.promise;
73 })
74 .then(() => {
75 return this.launchApp(projectRoot, packageName, debugTarget);
76 });
77 }
78
79 /**
80 * Sends an intent which launches the main activity of the application.
81 */
82 public static launchApp(projectRoot: string, packageName: string, debugTarget?: string): Q.Promise<void> {
83 let launchAppCommand = `adb ${debugTarget ? "-s " + debugTarget : ""} shell am start -n ${packageName}/.MainActivity`;
84 return new CommandExecutor(projectRoot).execute(launchAppCommand);
85 }
86
87 public static stopApp(projectRoot: string, packageName: string, debugTarget?: string): Q.Promise<void> {
88 let stopAppCommand = `adb ${debugTarget ? "-s " + debugTarget : ""} shell am force-stop ${packageName}`;
89 return new CommandExecutor(projectRoot).execute(stopAppCommand);
90 }
91
92 public static apiVersion(deviceId: string): Q.Promise<AndroidAPILevel> {
93 return this.executeQuery(deviceId, "shell getprop ro.build.version.sdk").then(output =>
94 parseInt(output, 10));
95 }
96
97 public static reverseAdb(deviceId: string, packagerPort: number): Q.Promise<void> {
98 return this.execute(deviceId, `reverse tcp:${packagerPort} tcp:${packagerPort}`);
99 }
100
101 public static showDevMenu(deviceId?: string): Q.Promise<void> {
102 let command = `adb ${deviceId ? "-s " + deviceId : ""} shell input keyevent ${KeyEvents.KEYCODE_MENU}`;
103 return this.commandExecutor.execute(command);
104 }
105
106 public static reloadApp(deviceId?: string): Q.Promise<void> {
107 let commands = [
108 `adb ${deviceId ? "-s " + deviceId : ""} shell input keyevent ${KeyEvents.KEYCODE_MENU}`,
109 `adb ${deviceId ? "-s " + deviceId : ""} shell input keyevent ${KeyEvents.KEYCODE_DPAD_UP}`,
110 `adb ${deviceId ? "-s " + deviceId : ""} shell input keyevent ${KeyEvents.KEYCODE_DPAD_CENTER}`,
111 ];
112
113 return this.executeChain(commands);
114 }
115
116 public static getOnlineDevices(): Q.Promise<IDevice[]> {
117 return this.getConnectedDevices().then(devices => {
118 return devices.filter(device =>
119 device.isOnline);
120 });
121 }
122
123 private static parseConnectedDevices(input: string): IDevice[] {
124 let result: IDevice[] = [];
125 let regex = new RegExp("^(\\S+)\\t(\\S+)$", "mg");
126 let match = regex.exec(input);
127 while (match != null) {
128 result.push({ id: match[1], isOnline: match[2] === "device", type: this.extractDeviceType(match[1]) });
129 match = regex.exec(input);
130 }
131 return result;
132 }
133
134 private static extractDeviceType(id: string): DeviceType {
135 return id.match(AndroidSDKEmulatorPattern)
136 ? DeviceType.AndroidSdkEmulator
137 : DeviceType.Other;
138 }
139
140 private static executeQuery(deviceId: string, command: string): Q.Promise<string> {
141 return this.childProcess.execToString(this.generateCommandForDevice(deviceId, command));
142 }
143
144 private static execute(deviceId: string, command: string): Q.Promise<void> {
145 return this.commandExecutor.execute(this.generateCommandForDevice(deviceId, command));
146 }
147
148 private static executeChain(commands: string[]): Q.Promise<any> {
149 return commands.reduce((promise, command) => {
150 return promise.then(() => this.commandExecutor.execute(command));
151 }, Q(void 0));
152 }
153
154 private static generateCommandForDevice(deviceId: string, adbCommand: string): string {
155 return `adb -s "${deviceId}" ${adbCommand}`;
156 }
157}
158