mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-22 17:39:19 +00:00
More configuration settings
Added autoStartADB and logcatPort launch config settings Moved AndroidContentProvider into it's own file.
This commit is contained in:
19
extension.js
19
extension.js
@@ -1,20 +1,15 @@
|
|||||||
// The module 'vscode' contains the VS Code extensibility API
|
// The module 'vscode' contains the VS Code extensibility API
|
||||||
// Import the module and reference it with the alias vscode in your code below
|
// Import the module and reference it with the alias vscode in your code below
|
||||||
const vscode = require('vscode');
|
const vscode = require('vscode');
|
||||||
const { AndroidContentProvider, openLogcatWindow } = require('./src/logcat');
|
const { AndroidContentProvider } = require('./src/contentprovider');
|
||||||
|
const { openLogcatWindow } = require('./src/logcat');
|
||||||
|
|
||||||
function getADBPort() {
|
function getADBPort() {
|
||||||
var adbPort = 5037;
|
var defaultPort = 5037;
|
||||||
// there's surely got to be a better way than this...
|
var adbPort = AndroidContentProvider.getLaunchConfigSetting('adbPort', defaultPort);
|
||||||
var configs = vscode.workspace.getConfiguration('launch.configurations');
|
if (typeof adbPort === 'number' && adbPort === (adbPort|0))
|
||||||
for (var i=0,config; config=configs.get(''+i); i++) {
|
return adbPort;
|
||||||
if (config.type!=='android') continue;
|
return defaultPort;
|
||||||
if (config.request!=='launch') continue;
|
|
||||||
if (typeof config.adbPort === 'number' && config.adbPort === (config.adbPort|0))
|
|
||||||
adbPort = config.adbPort;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return adbPort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method is called when your extension is activated
|
// this method is called when your extension is activated
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -66,6 +66,16 @@
|
|||||||
"description": "Port number to connect to the local ADB (Android Debug Bridge) instance. Default: 5037",
|
"description": "Port number to connect to the local ADB (Android Debug Bridge) instance. Default: 5037",
|
||||||
"default": 5037
|
"default": 5037
|
||||||
},
|
},
|
||||||
|
"autoStartADB": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Automatically launch 'adb start-server' if not already started. Default: true",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"logcatPort": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Port number to use for the internal logcat websocket link. Changes to this value only apply when the extension is restarted. Default: 7038",
|
||||||
|
"default": 7038
|
||||||
|
},
|
||||||
"staleBuild": {
|
"staleBuild": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Launch behaviour if source files have been saved after the APK was built. One of: [\"ignore\" \"warn\" \"stop\"]. Default: \"warn\"",
|
"description": "Launch behaviour if source files have been saved after the APK was built. One of: [\"ignore\" \"warn\" \"stop\"]. Default: \"warn\"",
|
||||||
|
|||||||
78
src/contentprovider.js
Normal file
78
src/contentprovider.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
'use strict'
|
||||||
|
// vscode stuff
|
||||||
|
const { workspace, EventEmitter, Uri } = require('vscode');
|
||||||
|
|
||||||
|
class AndroidContentProvider /*extends TextDocumentContentProvider*/ {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._docs = {}; // hashmap<url, LogcatContent>
|
||||||
|
this._onDidChange = new EventEmitter();
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this._onDidChange.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event to signal a resource has changed.
|
||||||
|
*/
|
||||||
|
get onDidChange() {
|
||||||
|
return this._onDidChange.event;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide textual content for a given uri.
|
||||||
|
*
|
||||||
|
* The editor will use the returned string-content to create a readonly
|
||||||
|
* [document](TextDocument). Resources allocated should be released when
|
||||||
|
* the corresponding document has been [closed](#workspace.onDidCloseTextDocument).
|
||||||
|
*
|
||||||
|
* @param uri An uri which scheme matches the scheme this provider was [registered](#workspace.registerTextDocumentContentProvider) for.
|
||||||
|
* @param token A cancellation token.
|
||||||
|
* @return A string or a thenable that resolves to such.
|
||||||
|
*/
|
||||||
|
provideTextDocumentContent(uri/*: Uri*/, token/*: CancellationToken*/)/*: string | Thenable<string>;*/ {
|
||||||
|
var doc = this._docs[uri];
|
||||||
|
if (doc) return this._docs[uri].content;
|
||||||
|
switch (uri.authority) {
|
||||||
|
// android-dev-ext://logcat/read?<deviceid>
|
||||||
|
case 'logcat': return this.provideLogcatDocumentContent(uri);
|
||||||
|
}
|
||||||
|
throw new Error('Document Uri not recognised');
|
||||||
|
}
|
||||||
|
|
||||||
|
provideLogcatDocumentContent(uri) {
|
||||||
|
// LogcatContent depends upon AndroidContentProvider, so we must delay-load this
|
||||||
|
const { LogcatContent } = require('./logcat');
|
||||||
|
var doc = this._docs[uri] = new LogcatContent(this, uri);
|
||||||
|
return doc.content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the statics
|
||||||
|
AndroidContentProvider.SCHEME = 'android-dev-ext';
|
||||||
|
AndroidContentProvider.register = (ctx, workspace) => {
|
||||||
|
var provider = new AndroidContentProvider();
|
||||||
|
var registration = workspace.registerTextDocumentContentProvider(AndroidContentProvider.SCHEME, provider);
|
||||||
|
ctx.subscriptions.push(registration);
|
||||||
|
ctx.subscriptions.push(provider);
|
||||||
|
}
|
||||||
|
AndroidContentProvider.getReadLogcatUri = (deviceId) => {
|
||||||
|
var uri = Uri.parse(`${AndroidContentProvider.SCHEME}://logcat/logcat-${deviceId}.txt`);
|
||||||
|
return uri.with({
|
||||||
|
query: deviceId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
AndroidContentProvider.getLaunchConfigSetting = (name, defvalue) => {
|
||||||
|
// there's surely got to be a better way than this...
|
||||||
|
var configs = workspace.getConfiguration('launch.configurations');
|
||||||
|
for (var i=0,config; config=configs.get(''+i); i++) {
|
||||||
|
if (config.type!=='android') continue;
|
||||||
|
if (config.request!=='launch') continue;
|
||||||
|
if (config[name]) return config[name];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return defvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.AndroidContentProvider = AndroidContentProvider;
|
||||||
@@ -312,7 +312,7 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
.then(err => {
|
.then(err => {
|
||||||
// if adb is not running, see if we can start it ourselves using ANDROID_HOME (and a sensible port number)
|
// if adb is not running, see if we can start it ourselves using ANDROID_HOME (and a sensible port number)
|
||||||
var adbport = ws_proxy.adbport;
|
var adbport = ws_proxy.adbport;
|
||||||
if (err && process.env.ANDROID_HOME && typeof adbport === 'number' && adbport > 0 && adbport < 65536) {
|
if (err && args.autoStartADB!==false && process.env.ANDROID_HOME && typeof adbport === 'number' && adbport > 0 && adbport < 65536) {
|
||||||
var adbpath = path.join(process.env.ANDROID_HOME, 'platform-tools', /^win/.test(process.platform)?'adb.exe':'adb');
|
var adbpath = path.join(process.env.ANDROID_HOME, 'platform-tools', /^win/.test(process.platform)?'adb.exe':'adb');
|
||||||
var adbargs = ['-P',''+adbport,'start-server'];
|
var adbargs = ['-P',''+adbport,'start-server'];
|
||||||
try {
|
try {
|
||||||
@@ -396,7 +396,7 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
this.LOG('Launch failed: '+(e.message||e.msg||'No additional information is available'));
|
this.LOG('Launch failed: '+(e.message||e.msg||'No additional information is available'));
|
||||||
// more info for adb connect errors
|
// more info for adb connect errors
|
||||||
if (/^ADB server is not running/.test(e.msg)) {
|
if (/^ADB server is not running/.test(e.msg)) {
|
||||||
this.LOG('Make sure the Android SDK tools are installed and run:');
|
this.LOG('Make sure the Android SDK Platform Tools are installed and run:');
|
||||||
this.LOG(' adb start-server');
|
this.LOG(' adb start-server');
|
||||||
this.LOG('If you are running ADB on a non-default port, also make sure the adbPort value in your launch.json is correct.');
|
this.LOG('If you are running ADB on a non-default port, also make sure the adbPort value in your launch.json is correct.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const path = require('path');
|
|||||||
const WebSocketServer = require('ws').Server;
|
const WebSocketServer = require('ws').Server;
|
||||||
// our stuff
|
// our stuff
|
||||||
const { ADBClient } = require('./adbclient');
|
const { ADBClient } = require('./adbclient');
|
||||||
|
const { AndroidContentProvider } = require('./contentprovider');
|
||||||
const $ = require('./jq-promise');
|
const $ = require('./jq-promise');
|
||||||
const { D } = require('./util');
|
const { D } = require('./util');
|
||||||
|
|
||||||
@@ -171,19 +172,29 @@ class LogcatContent {
|
|||||||
LogcatContent.byLogcatID = {};
|
LogcatContent.byLogcatID = {};
|
||||||
|
|
||||||
LogcatContent.initWebSocketServer = function () {
|
LogcatContent.initWebSocketServer = function () {
|
||||||
|
|
||||||
if (LogcatContent._wssdone) {
|
if (LogcatContent._wssdone) {
|
||||||
// already inited
|
// already inited
|
||||||
return LogcatContent._wssdone;
|
return LogcatContent._wssdone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// retrieve the logcat websocket port
|
||||||
|
var default_wssport = 7038;
|
||||||
|
var wssport = AndroidContentProvider.getLaunchConfigSetting('logcatPort', default_wssport);
|
||||||
|
if (typeof wssport !== 'number' || wssport <= 0 || wssport >= 65536 || wssport !== (wssport|0))
|
||||||
|
wssport = default_wssport;
|
||||||
|
|
||||||
LogcatContent._wssdone = $.Deferred();
|
LogcatContent._wssdone = $.Deferred();
|
||||||
({
|
({
|
||||||
wss: null,
|
wss: null,
|
||||||
port: 31100,
|
startport: wssport,
|
||||||
|
port: wssport,
|
||||||
retries: 0,
|
retries: 0,
|
||||||
tryCreateWSS() {
|
tryCreateWSS() {
|
||||||
this.wss = new WebSocketServer({ host: '127.0.0.1', port: this.port }, () => {
|
this.wss = new WebSocketServer({ host: '127.0.0.1', port: this.port }, () => {
|
||||||
// success - save the info and resolve the deferred
|
// success - save the info and resolve the deferred
|
||||||
LogcatContent._wssport = this.port;
|
LogcatContent._wssport = this.port;
|
||||||
|
LogcatContent._wssstartport = this.startport;
|
||||||
LogcatContent._wss = this.wss;
|
LogcatContent._wss = this.wss;
|
||||||
this.wss.on('connection', client => {
|
this.wss.on('connection', client => {
|
||||||
// the client uses the url path to signify which logcat data it wants
|
// the client uses the url path to signify which logcat data it wants
|
||||||
@@ -216,66 +227,6 @@ LogcatContent.initWebSocketServer = function () {
|
|||||||
return LogcatContent._wssdone;
|
return LogcatContent._wssdone;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AndroidContentProvider /*extends TextDocumentContentProvider*/ {
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this._logs = {}; // hashmap<url, LogcatContent>
|
|
||||||
this._onDidChange = new EventEmitter();
|
|
||||||
}
|
|
||||||
|
|
||||||
dispose() {
|
|
||||||
this._onDidChange.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An event to signal a resource has changed.
|
|
||||||
*/
|
|
||||||
get onDidChange() {
|
|
||||||
return this._onDidChange.event;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide textual content for a given uri.
|
|
||||||
*
|
|
||||||
* The editor will use the returned string-content to create a readonly
|
|
||||||
* [document](TextDocument). Resources allocated should be released when
|
|
||||||
* the corresponding document has been [closed](#workspace.onDidCloseTextDocument).
|
|
||||||
*
|
|
||||||
* @param uri An uri which scheme matches the scheme this provider was [registered](#workspace.registerTextDocumentContentProvider) for.
|
|
||||||
* @param token A cancellation token.
|
|
||||||
* @return A string or a thenable that resolves to such.
|
|
||||||
*/
|
|
||||||
provideTextDocumentContent(uri/*: Uri*/, token/*: CancellationToken*/)/*: string | Thenable<string>;*/ {
|
|
||||||
var doc = this._logs[uri];
|
|
||||||
if (doc) return this._logs[uri].content;
|
|
||||||
switch (uri.authority) {
|
|
||||||
// android-dev-ext://logcat/read?<deviceid>
|
|
||||||
case 'logcat': return this.provideLogcatDocumentContent(uri);
|
|
||||||
}
|
|
||||||
throw new Error('Document Uri not recognised');
|
|
||||||
}
|
|
||||||
|
|
||||||
provideLogcatDocumentContent(uri) {
|
|
||||||
var doc = this._logs[uri] = new LogcatContent(this, uri);
|
|
||||||
return doc.content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the statics
|
|
||||||
AndroidContentProvider.SCHEME = 'android-dev-ext';
|
|
||||||
AndroidContentProvider.register = (ctx, workspace) => {
|
|
||||||
var provider = new AndroidContentProvider();
|
|
||||||
var registration = workspace.registerTextDocumentContentProvider(AndroidContentProvider.SCHEME, provider);
|
|
||||||
ctx.subscriptions.push(registration);
|
|
||||||
ctx.subscriptions.push(provider);
|
|
||||||
}
|
|
||||||
AndroidContentProvider.getReadLogcatUri = (deviceId) => {
|
|
||||||
var uri = Uri.parse(`${AndroidContentProvider.SCHEME}://logcat/logcat-${deviceId}.txt`);
|
|
||||||
return uri.with({
|
|
||||||
query: deviceId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function openLogcatWindow(vscode) {
|
function openLogcatWindow(vscode) {
|
||||||
new ADBClient().list_devices().then(devices => {
|
new ADBClient().list_devices().then(devices => {
|
||||||
switch(devices.length) {
|
switch(devices.length) {
|
||||||
@@ -314,5 +265,5 @@ function openLogcatWindow(vscode) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.AndroidContentProvider = AndroidContentProvider;
|
exports.LogcatContent = LogcatContent;
|
||||||
exports.openLogcatWindow = openLogcatWindow;
|
exports.openLogcatWindow = openLogcatWindow;
|
||||||
|
|||||||
Reference in New Issue
Block a user