diff --git a/README.md b/README.md index eeea5bd..28ce306 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,13 @@ The following settings are used to configure the debugger: "staleBuild": "warn", // Fully qualified path to the AndroidManifest.xml file compiled in the APK. Default: appSrcRoot/AndroidManifest.xml - "manifestFile": "${workspaceRoot}/app/src/main/AndroidManifest.xml" + "manifestFile": "${workspaceRoot}/app/src/main/AndroidManifest.xml", + + // APK install arguments passed to the Android package manager. Run 'adb shell pm' to show valid arguments. Default: ["-r"] + "pmInstallArgs": ["-r"], + + // Manually specify the activity to run when the app is started. + "launchActivity": ".MainActivity" } ] } diff --git a/package.json b/package.json index b3a287d..99c59da 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,11 @@ "description": "Number of entries to display in call stack views (for locations outside of the project source). 0 shows the entire call stack. Default: 1", "default": 1 }, + "launchActivity": { + "type": "string", + "description": "Manually specify the activity to run when the app is started.", + "default": "" + }, "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", @@ -89,6 +94,11 @@ "description": "Overrides the default location of AndroidManifest.xml", "default": "${workspaceRoot}/app/src/main/AndroidManifest.xml" }, + "pmInstallArgs": { + "type": "array", + "description":"APK install arguments passed to the Android package manager. Run 'adb shell pm' to show valid arguments. Default: [\"-r\"]", + "default": ["-r"] + }, "staleBuild": { "type": "string", "description": "Launch behaviour if source files have been saved after the APK was built. One of: [\"ignore\" \"warn\" \"stop\"]. Default: \"warn\"", @@ -102,7 +112,7 @@ "trace": { "type": "boolean", "description": "Set to true to output debugging logs for diagnostics", - "default": "false" + "default": false } } } diff --git a/src/debugMain.js b/src/debugMain.js index c7eca47..d123d30 100644 --- a/src/debugMain.js +++ b/src/debugMain.js @@ -245,6 +245,7 @@ class AndroidDebugSession extends DebugSession { this.app_src_root = ensure_path_end_slash(args.appSrcRoot); this.apk_fpn = args.apkFile; this.manifest_fpn = args.manifestFile; + this.pmInstallArgs = args.pmInstallArgs; if (typeof args.callStackDisplaySize === 'number' && args.callStackDisplaySize >= 0) this.callStackDisplaySize = args.callStackDisplaySize|0; @@ -397,16 +398,19 @@ class AndroidDebugSession extends DebugSession { copyAndInstallAPK() { // copy the file to the device this.LOG('Deploying current build...'); + const device_apk_fpn = '/data/local/tmp/debug.apk'; return this._device.adbclient.push_file({ - filepathname:'/data/local/tmp/debug.apk', + filepathname:device_apk_fpn, filedata:this._apk_file_data, filemtime:new Date().getTime(), }) .then(() => { // send the install command this.LOG('Installing...'); + const command = `pm install ${Array.isArray(this.pmInstallArgs) ? this.pmInstallArgs.join(' ') : '-r'} ${device_apk_fpn}`; + D(command); return this._device.adbclient.shell_cmd({ - command:'pm install -r /data/local/tmp/debug.apk', + command, untilclosed:true, }) }) @@ -418,6 +422,12 @@ class AndroidDebugSession extends DebugSession { if (m) { return $.Deferred().rejectWith(this, [new Error('Installation failed. ' + m[0])]); } + // now the 'pm install' command can have user-defined arguments, we must check that the command + // is not rejected because of bad values + m = stdout.match(/^java.lang.IllegalArgumentException:.+/m); + if (m) { + return $.Deferred().rejectWith(this, [new Error('Installation failed. ' + m[0])]); + } }) }