microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.3.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/android/adb.ts

273lines · modeblame

52f3873ddigeff10 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
db6fd42aRuslan Bikkinin7 years ago4import { ChildProcess, ISpawnResult } from "../../common/node/childProcess";
5import { CommandExecutor } from "../../common/commandExecutor";
6import * as path from "path";
7import * as fs from "fs";
8import { ILogger } from "../log/LogHelper";
8b383051Ruslan Bikkinin7 years ago9import * as os from "os";
d7d405aeYuri Skorokhodov7 years ago10import * as nls from "vscode-nls";
34472878RedMickey5 years ago11nls.config({
12messageFormat: nls.MessageFormat.bundle,
13bundleFormat: nls.BundleFormat.standalone,
14})();
d7d405aeYuri Skorokhodov7 years ago15const localize = nls.loadMessageBundle();
52f3873ddigeff10 years ago16
ce7fd946digeff10 years ago17// See android versions usage at: http://developer.android.com/about/dashboards/index.html
52f3873ddigeff10 years ago18export enum AndroidAPILevel {
ce7fd946digeff10 years ago19Marshmallow = 23,
52f3873ddigeff10 years ago20LOLLIPOP_MR1 = 22,
34472878RedMickey5 years ago21LOLLIPOP = 21 /* Supports adb reverse */,
52f3873ddigeff10 years ago22KITKAT = 19,
23JELLY_BEAN_MR2 = 18,
24JELLY_BEAN_MR1 = 17,
25JELLY_BEAN = 16,
26ICE_CREAM_SANDWICH_MR1 = 15,
27GINGERBREAD_MR1 = 10,
28}
29
7daed3fcArtem Egorov8 years ago30enum KeyEvents {
31KEYCODE_BACK = 4,
32KEYCODE_DPAD_UP = 19,
33KEYCODE_DPAD_DOWN = 20,
34KEYCODE_DPAD_CENTER = 23,
35KEYCODE_MENU = 82,
36}
37
52f3873ddigeff10 years ago38export enum DeviceType {
39AndroidSdkEmulator, // These seem to have emulator-<port> ids
27710197Vladimir Kotikov8 years ago40Other,
52f3873ddigeff10 years ago41}
42
43export interface IDevice {
44id: string;
45isOnline: boolean;
46type: DeviceType;
47}
48
7daed3fcArtem Egorov8 years ago49const AndroidSDKEmulatorPattern = /^emulator-\d{1,5}$/;
52f3873ddigeff10 years ago50
7daed3fcArtem Egorov8 years ago51export class AdbHelper {
db6fd42aRuslan Bikkinin7 years ago52private childProcess: ChildProcess = new ChildProcess();
53private commandExecutor: CommandExecutor = new CommandExecutor();
54private adbExecutable: string = "";
78c2b4deRedMickey6 years ago55private launchActivity: string;
db6fd42aRuslan Bikkinin7 years ago56
78c2b4deRedMickey6 years ago57constructor(projectRoot: string, logger?: ILogger, launchActivity: string = "MainActivity") {
8152571aYuri Skorokhodov6 years ago58this.adbExecutable = this.getAdbPath(projectRoot, logger);
78c2b4deRedMickey6 years ago59this.launchActivity = launchActivity;
db6fd42aRuslan Bikkinin7 years ago60}
52f3873ddigeff10 years ago61
62/**
63* Gets the list of Android connected devices and emulators.
64*/
ce5e88eeYuri Skorokhodov5 years ago65public getConnectedDevices(): Promise<IDevice[]> {
34472878RedMickey5 years ago66return this.childProcess.execToString(`${this.adbExecutable} devices`).then(output => {
67return this.parseConnectedDevices(output);
68});
52f3873ddigeff10 years ago69}
70
78c2b4deRedMickey6 years ago71public setLaunchActivity(launchActivity: string): void {
72this.launchActivity = launchActivity;
73}
74
52f3873ddigeff10 years ago75/**
76* Broadcasts an intent to reload the application in debug mode.
77*/
34472878RedMickey5 years ago78public switchDebugMode(
79projectRoot: string,
80packageName: string,
81enable: boolean,
82debugTarget?: string,
83): Promise<void> {
84let enableDebugCommand = `${this.adbExecutable} ${
85debugTarget ? "-s " + debugTarget : ""
86} shell am broadcast -a "${packageName}.RELOAD_APP_ACTION" --ez jsproxy ${enable}`;
87return new CommandExecutor(projectRoot)
88.execute(enableDebugCommand)
89.then(() => {
90// We should stop and start application again after RELOAD_APP_ACTION, otherwise app going to hangs up
91return new Promise(resolve => {
ce5e88eeYuri Skorokhodov5 years ago92setTimeout(() => {
34472878RedMickey5 years ago93this.stopApp(projectRoot, packageName, debugTarget).then(() => {
94return resolve();
95});
ce5e88eeYuri Skorokhodov5 years ago96}, 200); // We need a little delay after broadcast command
97});
b57ea017Artem Egorov8 years ago98})
99.then(() => {
100return this.launchApp(projectRoot, packageName, debugTarget);
101});
52f3873ddigeff10 years ago102}
103
104/**
105* Sends an intent which launches the main activity of the application.
106*/
34472878RedMickey5 years ago107public launchApp(
108projectRoot: string,
109packageName: string,
110debugTarget?: string,
111): Promise<void> {
112let launchAppCommand = `${this.adbExecutable} ${
113debugTarget ? "-s " + debugTarget : ""
114} shell am start -n ${packageName}/.${this.launchActivity}`;
52f3873ddigeff10 years ago115return new CommandExecutor(projectRoot).execute(launchAppCommand);
116}
117
ce5e88eeYuri Skorokhodov5 years ago118public stopApp(projectRoot: string, packageName: string, debugTarget?: string): Promise<void> {
34472878RedMickey5 years ago119let stopAppCommand = `${this.adbExecutable} ${
120debugTarget ? "-s " + debugTarget : ""
121} shell am force-stop ${packageName}`;
b57ea017Artem Egorov8 years ago122return new CommandExecutor(projectRoot).execute(stopAppCommand);
123}
124
ce5e88eeYuri Skorokhodov5 years ago125public apiVersion(deviceId: string): Promise<AndroidAPILevel> {
52f3873ddigeff10 years ago126return this.executeQuery(deviceId, "shell getprop ro.build.version.sdk").then(output =>
34472878RedMickey5 years ago127parseInt(output, 10),
128);
52f3873ddigeff10 years ago129}
130
ce5e88eeYuri Skorokhodov5 years ago131public reverseAdb(deviceId: string, packagerPort: number): Promise<void> {
b57ea017Artem Egorov8 years ago132return this.execute(deviceId, `reverse tcp:${packagerPort} tcp:${packagerPort}`);
52f3873ddigeff10 years ago133}
134
ce5e88eeYuri Skorokhodov5 years ago135public showDevMenu(deviceId?: string): Promise<void> {
34472878RedMickey5 years ago136let command = `${this.adbExecutable} ${
137deviceId ? "-s " + deviceId : ""
138} shell input keyevent ${KeyEvents.KEYCODE_MENU}`;
7daed3fcArtem Egorov8 years ago139return this.commandExecutor.execute(command);
140}
141
ce5e88eeYuri Skorokhodov5 years ago142public reloadApp(deviceId?: string): Promise<void> {
34472878RedMickey5 years ago143let command = `${this.adbExecutable} ${
144deviceId ? "-s " + deviceId : ""
145} shell input text "RR"`;
e23ea82cAlter Code7 years ago146return this.commandExecutor.execute(command);
7daed3fcArtem Egorov8 years ago147}
148
ce5e88eeYuri Skorokhodov5 years ago149public getOnlineDevices(): Promise<IDevice[]> {
7daed3fcArtem Egorov8 years ago150return this.getConnectedDevices().then(devices => {
34472878RedMickey5 years ago151return devices.filter(device => device.isOnline);
7daed3fcArtem Egorov8 years ago152});
153}
154
db6fd42aRuslan Bikkinin7 years ago155public startLogCat(adbParameters: string[]): ISpawnResult {
b78a1aaeYuri Skorokhodov5 years ago156return this.childProcess.spawn(this.adbExecutable.replace(/\"/g, ""), adbParameters);
db6fd42aRuslan Bikkinin7 years ago157}
158
8df5011eYuri Skorokhodov5 years ago159public parseSdkLocation(fileContent: string, logger?: ILogger): string | null {
8b383051Ruslan Bikkinin7 years ago160const matches = fileContent.match(/^sdk\.dir=(.+)$/m);
161if (!matches || !matches[1]) {
162if (logger) {
34472878RedMickey5 years ago163logger.info(
164localize(
165"NoSdkDirFoundInLocalPropertiesFile",
166"No sdk.dir value found in local.properties file. Using Android SDK location from PATH.",
167),
168);
8b383051Ruslan Bikkinin7 years ago169}
170return null;
171}
172
173let sdkLocation = matches[1].trim();
174if (os.platform() === "win32") {
175// For Windows we need to unescape files separators and drive letter separators
176sdkLocation = sdkLocation.replace(/\\\\/g, "\\").replace("\\:", ":");
177}
178if (logger) {
34472878RedMickey5 years ago179logger.info(
180localize(
181"UsindAndroidSDKLocationDefinedInLocalPropertiesFile",
182"Using Android SDK location defined in android/local.properties file: {0}.",
183sdkLocation,
184),
185);
8b383051Ruslan Bikkinin7 years ago186}
187
188return sdkLocation;
189}
190
8152571aYuri Skorokhodov6 years ago191public getAdbPath(projectRoot: string, logger?: ILogger): string {
192// Trying to read sdk location from local.properties file and if we succueded then
193// we would run adb from inside it, otherwise we would rely to PATH
194const sdkLocation = this.getSdkLocationFromLocalPropertiesFile(projectRoot, logger);
195return sdkLocation ? `"${path.join(sdkLocation, "platform-tools", "adb")}"` : "adb";
196}
197
db6fd42aRuslan Bikkinin7 years ago198private parseConnectedDevices(input: string): IDevice[] {
52f3873ddigeff10 years ago199let result: IDevice[] = [];
200let regex = new RegExp("^(\\S+)\\t(\\S+)$", "mg");
201let match = regex.exec(input);
202while (match != null) {
34472878RedMickey5 years ago203result.push({
204id: match[1],
205isOnline: match[2] === "device",
206type: this.extractDeviceType(match[1]),
207});
52f3873ddigeff10 years ago208match = regex.exec(input);
209}
210return result;
211}
212
db6fd42aRuslan Bikkinin7 years ago213private extractDeviceType(id: string): DeviceType {
52f3873ddigeff10 years ago214return id.match(AndroidSDKEmulatorPattern)
215? DeviceType.AndroidSdkEmulator
216: DeviceType.Other;
217}
218
ce5e88eeYuri Skorokhodov5 years ago219private executeQuery(deviceId: string, command: string): Promise<string> {
52f3873ddigeff10 years ago220return this.childProcess.execToString(this.generateCommandForDevice(deviceId, command));
221}
222
ce5e88eeYuri Skorokhodov5 years ago223private execute(deviceId: string, command: string): Promise<void> {
52f3873ddigeff10 years ago224return this.commandExecutor.execute(this.generateCommandForDevice(deviceId, command));
225}
226
db6fd42aRuslan Bikkinin7 years ago227private generateCommandForDevice(deviceId: string, adbCommand: string): string {
228return `${this.adbExecutable} -s "${deviceId}" ${adbCommand}`;
229}
230
34472878RedMickey5 years ago231private getSdkLocationFromLocalPropertiesFile(
232projectRoot: string,
233logger?: ILogger,
234): string | null {
db6fd42aRuslan Bikkinin7 years ago235const localPropertiesFilePath = path.join(projectRoot, "android", "local.properties");
236if (!fs.existsSync(localPropertiesFilePath)) {
237if (logger) {
34472878RedMickey5 years ago238logger.info(
239localize(
240"LocalPropertiesFileDoesNotExist",
241"local.properties file doesn't exist. Using Android SDK location from PATH.",
242),
243);
db6fd42aRuslan Bikkinin7 years ago244}
245return null;
246}
247
8b383051Ruslan Bikkinin7 years ago248let fileContent: string;
db6fd42aRuslan Bikkinin7 years ago249try {
250fileContent = fs.readFileSync(localPropertiesFilePath).toString();
251} catch (e) {
252if (logger) {
34472878RedMickey5 years ago253logger.error(
254localize(
255"CouldNotReadFrom",
256"Couldn't read from {0}.",
257localPropertiesFilePath,
258),
259e,
260e.stack,
261);
262logger.info(
263localize(
264"UsingAndroidSDKLocationFromPATH",
265"Using Android SDK location from PATH.",
266),
267);
db6fd42aRuslan Bikkinin7 years ago268}
269return null;
270}
8b383051Ruslan Bikkinin7 years ago271return this.parseSdkLocation(fileContent, logger);
52f3873ddigeff10 years ago272}
273}