mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 01:48:18 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f2f7d2fd4 | ||
|
|
99544b527d | ||
|
|
614fcbd2ba | ||
|
|
b04e4328a6 | ||
|
|
1a00cdb291 | ||
|
|
d1fd889433 | ||
|
|
a7e4cac6df | ||
|
|
c6df24ab95 | ||
|
|
23184ea4c2 | ||
|
|
b7ba47b811 | ||
|
|
033f5c80ab | ||
|
|
0cbb56ca9b | ||
|
|
684dd39181 | ||
|
|
52ab704acd |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,16 @@
|
||||
# Change Log
|
||||
|
||||
### version 0.7.1
|
||||
* Added the [Buy Me A Coffee](https://www.buymeacoffee.com/adelphes) link to the README
|
||||
|
||||
### version 0.7.0
|
||||
* Fix logcat not displaying
|
||||
* Fix breakpoints not triggering on Windows
|
||||
* Added kotlin folder to list of known source locations
|
||||
* Upgraded dependencies to resolve a number of security vulnerabilites
|
||||
* Updated README with info about prelaunch build task
|
||||
* Added MIT license file
|
||||
|
||||
### version 0.6.2
|
||||
* Fix broken logcat command due to missing dependency
|
||||
|
||||
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Dave Holoway
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
48
README.md
48
README.md
@@ -20,7 +20,7 @@ You must have [Android SDK Platform Tools](https://developer.android.com/studio/
|
||||
* This is a preview version so expect the unexpected. Please log any issues you find on [GitHub](https://github.com/adelphes/android-dev-ext/issues).
|
||||
* This extension **will not build your app**.
|
||||
If you use gradle (or Android Studio), you can build your app from the command-line using `./gradlew assembleDebug`.
|
||||
> You must use gradle or some other build procedure to create your APK. Once built, the extension can deploy and launch your app, allowing you to debug it in the normal way.
|
||||
> You must use gradle or some other build procedure to create your APK. Once built, the extension can deploy and launch your app, allowing you to debug it in the normal way. See the section below on how to configure a VSCode task to automatically build your app before launching a debug session.
|
||||
* Some debugger options are yet to be implemented. You cannot set conditional breakpoints and watch expressions must be simple variables.
|
||||
* If you require a must-have feature that isn't there yet, let us know on [GitHub](https://github.com/adelphes/android-dev-ext/issues).
|
||||
* This extension does not provide any additional code completion or other editing enhancements.
|
||||
@@ -54,6 +54,52 @@ The following settings are used to configure the debugger:
|
||||
]
|
||||
}
|
||||
|
||||
## Building your app automatically
|
||||
|
||||
This extension will not build your App. If you would like to run a build each time a debug session is started, you can add a `preLaunchTask` option to your `launch.json` configuration which invokes a build task.
|
||||
|
||||
#### .vscode/launch.json
|
||||
Add a `preLaunchTask` item to the launch configuration:
|
||||
```json
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "android",
|
||||
"request": "launch",
|
||||
"name": "App Build & Launch",
|
||||
"preLaunchTask": "run gradle",
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Add a new task to run the build command:
|
||||
#### .vscode/tasks.json
|
||||
```json
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "run gradle",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/gradlew",
|
||||
"args": ["assembleDebug"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Powered by coffee
|
||||
|
||||
The Android Developer Extension is a completely free, fully open-source project. If you've found the extension useful, you
|
||||
can support it by [buying me a coffee](https://www.buymeacoffee.com/adelphes).
|
||||
|
||||
If you use ApplePay or Google Pay, you can scan the code with your phone camera:
|
||||
|
||||

|
||||
|
||||
Every coffee makes a difference, so thanks for adding your support.
|
||||
|
||||
## Questions / Problems
|
||||
|
||||
If you run into any problems, tell us on [GitHub](https://github.com/adelphes/android-dev-ext/issues) or contact me on [Twitter](https://twitter.com/daveholoway).
|
||||
|
||||
BIN
images/bmac-code.png
Normal file
BIN
images/bmac-code.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
56
package-lock.json
generated
56
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "android-dev-ext",
|
||||
"version": "0.6.1",
|
||||
"version": "0.7.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -199,6 +199,11 @@
|
||||
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
|
||||
"dev": true
|
||||
},
|
||||
"async-limiter": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
@@ -389,7 +394,7 @@
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
||||
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
|
||||
"dev": true
|
||||
},
|
||||
@@ -803,9 +808,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"fstream": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
|
||||
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
|
||||
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
@@ -953,7 +958,7 @@
|
||||
},
|
||||
"through2": {
|
||||
"version": "0.6.5",
|
||||
"resolved": "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
|
||||
"integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -1348,9 +1353,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
|
||||
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
@@ -1449,9 +1454,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
|
||||
"version": "4.17.14",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
|
||||
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==",
|
||||
"dev": true
|
||||
},
|
||||
"long": {
|
||||
@@ -1693,11 +1698,6 @@
|
||||
"wordwrap": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
|
||||
"integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8="
|
||||
},
|
||||
"ordered-read-streams": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz",
|
||||
@@ -2189,13 +2189,13 @@
|
||||
}
|
||||
},
|
||||
"tar": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "http://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
|
||||
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
|
||||
"version": "2.2.2",
|
||||
"resolved": "http://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
|
||||
"integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"block-stream": "*",
|
||||
"fstream": "^1.0.2",
|
||||
"fstream": "^1.0.12",
|
||||
"inherits": "2"
|
||||
}
|
||||
},
|
||||
@@ -2313,11 +2313,6 @@
|
||||
"integrity": "sha512-jw7P2z/h6aPT4AENXDGjcfHTu5CSqzsbZc6YlUIebTyBAq8XaKp78x7VcSh30xwSCcsu5irZkYZUSFP1MrAMbg==",
|
||||
"dev": true
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
|
||||
"integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po="
|
||||
},
|
||||
"unc-path-regex": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
|
||||
@@ -2654,12 +2649,11 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz",
|
||||
"integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz",
|
||||
"integrity": "sha512-gftXq3XI81cJCgkUiAVixA0raD9IVmXqsylCrjRygw4+UOOGzPoxnQ6r/CnVL9i+mDncJo94tSkyrtuuQVBmrg==",
|
||||
"requires": {
|
||||
"options": ">=0.0.5",
|
||||
"ultron": "1.0.x"
|
||||
"async-limiter": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"xmldom": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "android-dev-ext",
|
||||
"displayName": "Android",
|
||||
"description": "Android debugging support for VS Code",
|
||||
"version": "0.6.2",
|
||||
"version": "0.7.1",
|
||||
"publisher": "adelphes",
|
||||
"preview": true,
|
||||
"license": "MIT",
|
||||
@@ -135,11 +135,11 @@
|
||||
"test": "node ./node_modules/vscode/bin/test"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-debugprotocol": "^1.32.0",
|
||||
"vscode-debugadapter": "^1.32.0",
|
||||
"long": "^4.0.0",
|
||||
"uuid": "^3.3.2",
|
||||
"ws": "^1.1.1",
|
||||
"vscode-debugadapter": "^1.32.0",
|
||||
"vscode-debugprotocol": "^1.32.0",
|
||||
"ws": "^7.1.2",
|
||||
"xmldom": "^0.1.27",
|
||||
"xpath": "^0.0.27"
|
||||
},
|
||||
|
||||
@@ -44,7 +44,7 @@ class AndroidContentProvider /*extends TextDocumentContentProvider*/ {
|
||||
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);
|
||||
var doc = this._docs[uri] = new LogcatContent(uri.query);
|
||||
return doc.content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,12 +483,12 @@ class AndroidDebugSession extends DebugSession {
|
||||
}
|
||||
catch (err) { continue }
|
||||
// ignore folders not starting with a known top-level Android folder
|
||||
if (!/^(assets|res|src|main|java)([\\/]|$)/.test(p)) continue;
|
||||
if (!/^(assets|res|src|main|java|kotlin)([\\/]|$)/.test(p)) continue;
|
||||
// is this a package folder
|
||||
var pkgmatch = p.match(/^(src|main|java)[\\/](.+)/);
|
||||
var pkgmatch = p.match(/^(src|main|java|kotlin)[\\/](.+)/);
|
||||
if (pkgmatch && /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(pkgmatch[2].split(/[\\/]/).pop())) {
|
||||
// looks good - add it to the list
|
||||
const src_folder = pkgmatch[1]; // src, main or java
|
||||
const src_folder = pkgmatch[1]; // src, main, java or kotlin
|
||||
const pkgname = pkgmatch[2].replace(/[\\/]/g,'.');
|
||||
src_packages.packages[pkgname] = {
|
||||
package: pkgname,
|
||||
@@ -614,6 +614,14 @@ class AndroidDebugSession extends DebugSession {
|
||||
if ((pkginfo = this.src_packages.packages[pkg]).package_path === srcfolder) break;
|
||||
pkginfo = null;
|
||||
}
|
||||
// if we didn't find an exact path match, look for a case-insensitive match
|
||||
if (!pkginfo) {
|
||||
for (var pkg in this.src_packages.packages) {
|
||||
if ((pkginfo = this.src_packages.packages[pkg]).package_path.localeCompare(srcfolder, undefined, { sensitivity: 'base' }) === 0) break;
|
||||
pkginfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
// if it's not in our source packages, check if it's in the Android source file cache
|
||||
if (!pkginfo && is_subpath_of(srcfpn, this._android_sources_path)) {
|
||||
// create a fake pkginfo to use to construct the bp
|
||||
|
||||
@@ -15,10 +15,8 @@ const { D } = require('./util');
|
||||
*/
|
||||
class LogcatContent {
|
||||
|
||||
constructor(provider/*: AndroidContentProvider*/, uri/*: Uri*/) {
|
||||
this._provider = provider;
|
||||
this._uri = uri;
|
||||
this._logcatid = uri.query;
|
||||
constructor(deviceid) {
|
||||
this._logcatid = deviceid;
|
||||
this._logs = [];
|
||||
this._htmllogs = [];
|
||||
this._oldhtmllogs = [];
|
||||
@@ -27,7 +25,7 @@ class LogcatContent {
|
||||
this._refreshRate = 200; // ms
|
||||
this._state = '';
|
||||
this._htmltemplate = '';
|
||||
this._adbclient = new ADBClient(uri.query);
|
||||
this._adbclient = new ADBClient(deviceid);
|
||||
this._initwait = new Promise((resolve, reject) => {
|
||||
this._state = 'connecting';
|
||||
LogcatContent.initWebSocketServer()
|
||||
@@ -79,8 +77,11 @@ class LogcatContent {
|
||||
});
|
||||
}
|
||||
sendClientMessage(msg) {
|
||||
var clients = LogcatContent._wss.clients.filter(client => client._logcatid === this._logcatid);
|
||||
clients.forEach(client => client.send(msg+'\n')); // include a newline to try and persuade a buffer write
|
||||
LogcatContent._wss.clients.forEach(client => {
|
||||
if (client._logcatid === this._logcatid) {
|
||||
client.send(msg + '\n'); // include a newline to try and persuade a buffer write
|
||||
}
|
||||
})
|
||||
}
|
||||
sendDisconnectMsg() {
|
||||
this.sendClientMessage(':disconnect');
|
||||
@@ -113,7 +114,7 @@ class LogcatContent {
|
||||
}
|
||||
updateLogs() {
|
||||
// no point in formatting the data if there are no connected clients
|
||||
var clients = LogcatContent._wss.clients.filter(client => client._logcatid === this._logcatid);
|
||||
var clients = [...LogcatContent._wss.clients].filter(client => client._logcatid === this._logcatid);
|
||||
if (clients.length) {
|
||||
var lines = '<div class="logblock">' + this._htmllogs.join('') + '</div>';
|
||||
clients.forEach(client => client.send(lines));
|
||||
@@ -189,14 +190,19 @@ LogcatContent.initWebSocketServer = function () {
|
||||
port: wssport,
|
||||
retries: 0,
|
||||
tryCreateWSS() {
|
||||
this.wss = new WebSocketServer({ host: '127.0.0.1', port: this.port }, () => {
|
||||
const wsopts = {
|
||||
host: '127.0.0.1',
|
||||
port: this.port,
|
||||
clientTracking: true,
|
||||
};
|
||||
this.wss = new WebSocketServer(wsopts, () => {
|
||||
// success - save the info and resolve the deferred
|
||||
LogcatContent._wssport = this.port;
|
||||
LogcatContent._wssstartport = this.startport;
|
||||
LogcatContent._wss = this.wss;
|
||||
this.wss.on('connection', client => {
|
||||
this.wss.on('connection', (client, req) => {
|
||||
// the client uses the url path to signify which logcat data it wants
|
||||
client._logcatid = client.upgradeReq.url.match(/^\/?(.*)$/)[1];
|
||||
client._logcatid = req.url.match(/^\/?(.*)$/)[1];
|
||||
var lc = LogcatContent.byLogcatID[client._logcatid];
|
||||
if (lc) lc.onClientConnect(client);
|
||||
else client.close();
|
||||
@@ -276,6 +282,21 @@ function openLogcatWindow(vscode) {
|
||||
.then(devices => {
|
||||
if (!Array.isArray(devices)) return; // user cancelled (or no devices connected)
|
||||
devices.forEach(device => {
|
||||
if (vscode.window.createWebviewPanel) {
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
'androidlogcat', // Identifies the type of the webview. Used internally
|
||||
`logcat-${device.serial}`, // Title of the panel displayed to the user
|
||||
vscode.ViewColumn.One, // Editor column to show the new webview panel in.
|
||||
{
|
||||
enableScripts: true,
|
||||
}
|
||||
);
|
||||
const logcat = new LogcatContent(device.serial);
|
||||
logcat.content.then(html => {
|
||||
panel.webview.html = html;
|
||||
});
|
||||
return;
|
||||
}
|
||||
var uri = AndroidContentProvider.getReadLogcatUri(device.serial);
|
||||
return vscode.commands.executeCommand("vscode.previewHtml",uri,vscode.ViewColumn.Two);
|
||||
});
|
||||
|
||||
@@ -627,9 +627,9 @@ exports.dumparr = function (arr, offset, count) {
|
||||
}
|
||||
|
||||
exports.btoa = function (arr) {
|
||||
return new Buffer(arr, 'binary').toString('base64');
|
||||
return Buffer.from(arr, 'binary').toString('base64');
|
||||
}
|
||||
|
||||
exports.atob = function (base64) {
|
||||
return new Buffer(base64, 'base64').toString('binary');
|
||||
return Buffer.from(base64, 'base64').toString('binary');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user