devtools/madb: add "madb stop" command.
"madb stop" command stops the app specified by the application ID on
all devices. The application ID can be automatically inferred as in
other madb sub-commands.
Change-Id: I506985c61a84e7f79f5730f0154bf0b49b30f811
diff --git a/doc.go b/doc.go
index ba62f4f..581ab07 100644
--- a/doc.go
+++ b/doc.go
@@ -18,6 +18,7 @@
exec Run the provided adb command on all devices and emulators
concurrently
start Launch your app on all devices
+ stop Stop your app on all devices
uninstall Uninstall your app from all devices
name Manage device nicknames
help Display help for commands or topics
@@ -121,6 +122,51 @@
Comma-separated device serials, qualifiers, or nicknames (set by 'madb
name'). Command will be run only on specified devices.
+Madb stop - Stop your app on all devices
+
+Stops your app on all devices.
+
+Usage:
+ madb stop [flags] [<application_id>]
+
+<application_id> is usually the package name where the activities are defined.
+(See:
+http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename)
+
+If the application ID is not specified, madb automatically determines which app
+to stop, based on the build scripts found in the current working directory.
+
+1) If the working directory contains a Flutter project (i.e., has
+"flutter.yaml"), this command will run "flutter stop --android-device-id=<device
+serial>" for all the specified devices.
+
+2) If the working directory contains a Gradle Android project (i.e., has
+"build.gradle"), run a small Gradle script to extract the application ID. In
+this case, the extracted ID is cached, so that "madb stop" can be repeated
+without even running the Gradle script again. The ID can be re-extracted by
+clearing the cache by providing "-clear-cache" flag.
+
+The madb stop flags are:
+ -clear-cache=false
+ Clear the cache and re-extract the application ID and the main activity name.
+ Only takes effect when no arguments are provided.
+ -module=
+ Specify which application module to use, when the current directory is the
+ top level Gradle project containing multiple sub-modules. When not
+ specified, the first available application module is used. Only takes effect
+ when no arguments are provided.
+ -variant=
+ Specify which build variant to use. When not specified, the first available
+ build variant is used. Only takes effect when no arguments are provided.
+
+ -d=false
+ Restrict the command to only run on real devices.
+ -e=false
+ Restrict the command to only run on emulators.
+ -n=
+ Comma-separated device serials, qualifiers, or nicknames (set by 'madb
+ name'). Command will be run only on specified devices.
+
Madb uninstall - Uninstall your app from all devices
Uninstall your app from all devices.
diff --git a/madb.go b/madb.go
index c9aab4a..92c2db9 100644
--- a/madb.go
+++ b/madb.go
@@ -57,7 +57,7 @@
}
var cmdMadb = &cmdline.Command{
- Children: []*cmdline.Command{cmdMadbExec, cmdMadbStart, cmdMadbUninstall, cmdMadbName},
+ Children: []*cmdline.Command{cmdMadbExec, cmdMadbStart, cmdMadbStop, cmdMadbUninstall, cmdMadbName},
Name: "madb",
Short: "Multi-device Android Debug Bridge",
Long: `
@@ -348,6 +348,46 @@
return cmd.Shell().Err
}
+func initMadbCommand(env *cmdline.Env, args []string, flutterPassthrough bool, activityNameRequired bool) ([]string, error) {
+ var numRequiredArgs int
+ var requiredArgsStr string
+
+ if activityNameRequired {
+ numRequiredArgs = 2
+ requiredArgsStr = "two arguments"
+ } else {
+ numRequiredArgs = 1
+ requiredArgsStr = "one argument"
+ }
+
+ // Pass the arguments through if all the required arguments are provided, or if it is a flutter project.
+ if len(args) == numRequiredArgs || (flutterPassthrough && isFlutterProject(wd)) {
+ return args, nil
+ }
+
+ if len(args) != 0 {
+ return nil, fmt.Errorf("You mush provide either zero arguments or exactly %v.", requiredArgsStr)
+ }
+
+ // Try to extract the application ID and the main activity name from the Gradle scripts.
+ if isGradleProject(wd) {
+ cacheFile, err := getDefaultCacheFilePath()
+ if err != nil {
+ return nil, err
+ }
+
+ key := variantKey{wd, moduleFlag, variantFlag}
+ ids, err := getProjectIds(extractIdsFromGradle, key, clearCacheFlag, cacheFile)
+ if err != nil {
+ return nil, err
+ }
+
+ args = []string{ids.AppID, ids.Activity}[:numRequiredArgs]
+ }
+
+ return args, nil
+}
+
type idExtractorFunc func(variantKey) (projectIds, error)
// Returns the project ids for the given build variant. It returns the cached values when the
diff --git a/start.go b/start.go
index e096866..297c077 100644
--- a/start.go
+++ b/start.go
@@ -56,32 +56,7 @@
}
func initMadbStart(env *cmdline.Env, args []string) ([]string, error) {
- // If both arguments are provided, or if it is a flutter project, simply pass the arguments through.
- if len(args) == 2 || isFlutterProject(wd) {
- return args, nil
- }
-
- if len(args) != 0 {
- return nil, fmt.Errorf("You mush provide either zero or exactly two arguments.")
- }
-
- // Try to extract the application ID and the main activity name from the Gradle scripts.
- if isGradleProject(wd) {
- cacheFile, err := getDefaultCacheFilePath()
- if err != nil {
- return nil, err
- }
-
- key := variantKey{wd, moduleFlag, variantFlag}
- ids, err := getProjectIds(extractIdsFromGradle, key, clearCacheFlag, cacheFile)
- if err != nil {
- return nil, err
- }
-
- args = []string{ids.AppID, ids.Activity}
- }
-
- return args, nil
+ return initMadbCommand(env, args, true, true)
}
func runMadbStartForDevice(env *cmdline.Env, args []string, d device) error {
diff --git a/stop.go b/stop.go
new file mode 100644
index 0000000..37fa188
--- /dev/null
+++ b/stop.go
@@ -0,0 +1,73 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+
+ "v.io/x/lib/cmdline"
+ "v.io/x/lib/gosh"
+)
+
+func init() {
+ initializeIDCacheFlags(&cmdMadbStop.Flags)
+}
+
+var cmdMadbStop = &cmdline.Command{
+ Runner: subCommandRunner{initMadbStart, runMadbStartForDevice},
+ Name: "stop",
+ Short: "Stop your app on all devices",
+ Long: `
+Stops your app on all devices.
+
+`,
+ ArgsName: "[<application_id>]",
+ ArgsLong: `
+<application_id> is usually the package name where the activities are defined.
+(See: http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename)
+
+
+If the application ID is not specified, madb automatically determines which app to stop, based on
+the build scripts found in the current working directory.
+
+1) If the working directory contains a Flutter project (i.e., has "flutter.yaml"), this command will
+run "flutter stop --android-device-id=<device serial>" for all the specified devices.
+
+2) If the working directory contains a Gradle Android project (i.e., has "build.gradle"), run a
+small Gradle script to extract the application ID. In this case, the extracted ID is cached, so
+that "madb stop" can be repeated without even running the Gradle script again. The ID can be
+re-extracted by clearing the cache by providing "-clear-cache" flag.
+`,
+}
+
+func initMadbStop(env *cmdline.Env, args []string) ([]string, error) {
+ return initMadbCommand(env, args, true, false)
+}
+
+func runMadbStopForDevice(env *cmdline.Env, args []string, d device) error {
+ sh := gosh.NewShell(nil)
+ defer sh.Cleanup()
+
+ sh.ContinueOnError = true
+
+ if len(args) == 2 {
+ appID := args[0]
+
+ // More details on the "adb shell am" command can be found at: http://developer.android.com/tools/help/shell.html#am
+ cmdArgs := []string{"-s", d.Serial, "shell", "force-stop", appID}
+ cmd := sh.Cmd("adb", cmdArgs...)
+ return runGoshCommandForDevice(cmd, d)
+ }
+
+ // In case of flutter, the application ID is not even needed.
+ // Simply run "flutter stop --android-device-id <device_serial>" on all devices.
+ if isFlutterProject(wd) {
+ cmdArgs := []string{"stop", "--android-device-id", d.Serial}
+ cmd := sh.Cmd("flutter", cmdArgs...)
+ return runGoshCommandForDevice(cmd, d)
+ }
+
+ return fmt.Errorf("No arguments are provided and failed to extract the id from the build scripts.")
+}
diff --git a/uninstall.go b/uninstall.go
index 63c4958..cf2beb7 100644
--- a/uninstall.go
+++ b/uninstall.go
@@ -45,33 +45,7 @@
}
func initMadbUninstall(env *cmdline.Env, args []string) ([]string, error) {
- // If the argument is provided, simply pass it through.
- if len(args) == 1 {
- return args, nil
- }
-
- if len(args) != 0 {
- return nil, fmt.Errorf("You mush provide either zero or exactly one arguments.")
- }
-
- // Try to extract the application ID from the Gradle scripts.
- if isGradleProject(wd) {
- cacheFile, err := getDefaultCacheFilePath()
- if err != nil {
- return nil, err
- }
-
- key := variantKey{wd, moduleFlag, variantFlag}
- ids, err := getProjectIds(extractIdsFromGradle, key, clearCacheFlag, cacheFile)
- if err != nil {
- return nil, err
- }
-
- // Use only the application ID and ignore the main activity name.
- args = []string{ids.AppID}
- }
-
- return args, nil
+ return initMadbCommand(env, args, false, false)
}
func runMadbUninstallForDevice(env *cmdline.Env, args []string, d device) error {