/**
   * Extracts the package name from an apk file.
   *
   * @param apkFile apk file to extract package name from.
   * @return the package name from inside the apk file.
   */
  protected String extractPackageNameFromApk(File apkFile) throws MojoExecutionException {
    CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
    executor.setLogger(this.getLog());
    executor.setCaptureStdOut(true);
    executor.setCaptureStdErr(true);

    AaptCommandBuilder commandBuilder =
        AaptCommandBuilder.dump(getLog())
            .xmlTree()
            .setPathToApk(apkFile.getAbsolutePath())
            .addAssetFile("AndroidManifest.xml");

    getLog().info(getAndroidSdk().getAaptPath() + " " + commandBuilder.toString());
    try {
      executor.executeCommand(getAndroidSdk().getAaptPath(), commandBuilder.build(), false);
      final String xmlTree = executor.getStandardOut();
      return extractPackageNameFromAndroidManifestXmlTree(xmlTree);
    } catch (ExecutionException e) {
      throw new MojoExecutionException(
          "Error while trying to figure out package name from inside apk file " + apkFile);
    } finally {
      String errout = executor.getStandardError();
      if ((errout != null) && (errout.trim().length() > 0)) {
        getLog().error(errout);
      }
    }
  }
  /**
   * Start the Android Emulator with the specified options.
   *
   * @throws org.apache.maven.plugin.MojoExecutionException
   * @see #emulatorAvd
   * @see #emulatorWait
   * @see #emulatorOptions
   */
  protected void startAndroidEmulator() throws MojoExecutionException {
    parseParameters();

    CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
    executor.setLogger(this.getLog());

    try {
      String filename;
      if (isWindows()) {
        filename = writeEmulatorStartScriptWindows();
      } else {
        filename = writeEmulatorStartScriptUnix();
      }

      final AndroidDebugBridge androidDebugBridge = initAndroidDebugBridge();
      if (androidDebugBridge.isConnected()) {
        List<IDevice> devices = Arrays.asList(androidDebugBridge.getDevices());
        int numberOfDevices = devices.size();
        getLog()
            .info("Found " + numberOfDevices + " devices connected with the Android Debug Bridge");

        IDevice existingEmulator = null;

        for (IDevice device : devices) {
          if (device.isEmulator()) {
            if (isExistingEmulator(device)) {
              existingEmulator = device;
              break;
            }
          }
        }

        if (existingEmulator == null) {
          getLog().info(START_EMULATOR_MSG + filename);
          executor.executeCommand(filename, null);

          getLog().info(START_EMULATOR_WAIT_MSG + parsedWait);
          // wait for the emulator to start up
          Thread.sleep(new Long(parsedWait));
        } else {
          getLog()
              .info(
                  String.format(
                      "Emulator already running [Serial No: '%s', AVD Name '%s']. Skipping start and wait.",
                      existingEmulator.getSerialNumber(), existingEmulator.getAvdName()));
        }
      }
    } catch (Exception e) {
      throw new MojoExecutionException("", e);
    }
  }
 /**
  * Extracts the package name from an apk file.
  *
  * @param apkFile apk file to extract package name from.
  * @return the package name from inside the apk file.
  */
 protected String extractPackageNameFromApk(File apkFile) throws MojoExecutionException {
   CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
   executor.setLogger(this.getLog());
   List<String> commands = new ArrayList<String>();
   commands.add("dump");
   commands.add("xmltree");
   commands.add(apkFile.getAbsolutePath());
   commands.add("AndroidManifest.xml");
   getLog().info(getAndroidSdk().getPathForTool("aapt") + " " + commands.toString());
   try {
     executor.executeCommand(getAndroidSdk().getPathForTool("aapt"), commands, true);
     final String xmlTree = executor.getStandardOut();
     return extractPackageNameFromAndroidManifestXmlTree(xmlTree);
   } catch (ExecutionException e) {
     throw new MojoExecutionException(
         "Error while trying to figure out package name from inside apk file " + apkFile);
   } finally {
     getLog().error(executor.getStandardError());
   }
 }
 /**
  * Undeploys an apk, specified by package name, from a connected emulator or usb device.
  *
  * @param packageName the package name to undeploy.
  * @param deleteDataAndCacheDirectoriesOnDevice <code>true</code> to delete the application's data
  *     and cache directories on the device, <code>false</code> to keep them.
  * @return <code>true</code> if successfully undeployed, <code>false</code> otherwise.
  */
 protected boolean undeployApk(String packageName, boolean deleteDataAndCacheDirectoriesOnDevice)
     throws MojoExecutionException {
   CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
   executor.setLogger(this.getLog());
   List<String> commands = new ArrayList<String>();
   commands.add("uninstall");
   if (!deleteDataAndCacheDirectoriesOnDevice) {
     commands.add("-k"); // ('-k' means keep the data and cache directories)
   }
   commands.add(packageName);
   getLog().info(getAndroidSdk().getPathForTool("adb") + " " + commands.toString());
   try {
     executor.executeCommand(getAndroidSdk().getPathForTool("adb"), commands, false);
     getLog().debug(executor.getStandardOut());
     getLog().debug(executor.getStandardError());
     return true;
   } catch (ExecutionException e) {
     getLog().error(executor.getStandardOut());
     getLog().error(executor.getStandardError());
     return false;
   }
 }
  /**
   * Deploys an apk file to a connected emulator or usb device.
   *
   * @param apkFile the file to deploy
   * @throws MojoExecutionException If there is a problem deploying the apk file.
   */
  protected void deployApk(File apkFile) throws MojoExecutionException {
    CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
    executor.setLogger(this.getLog());
    List<String> commands = new ArrayList<String>();

    // Check if a specific device should be used
    if (StringUtils.isNotBlank(device)) {
      if ("usb".equals(device)) {
        commands.add("-d");
      } else if ("emulator".equals(device)) {
        commands.add("-e");
      } else {
        commands.add("-s");
        commands.add(device);
      }
    }

    commands.add("install");
    commands.add("-r");
    commands.add(apkFile.getAbsolutePath());
    getLog().info(getAndroidSdk().getPathForTool("adb") + " " + commands.toString());
    try {
      executor.executeCommand(getAndroidSdk().getPathForTool("adb"), commands, false);
      final String standardOut = executor.getStandardOut();
      if (standardOut != null && standardOut.contains("Failure")) {
        throw new MojoExecutionException(
            "Error deploying "
                + apkFile
                + " to device. You might want to add command line parameter -Dandroid.undeployBeforeDeploy=true or add plugin configuration tag <undeployBeforeDeploy>true</undeployBeforeDeploy>\n"
                + standardOut);
      }
    } catch (ExecutionException e) {
      getLog().error(executor.getStandardOut());
      getLog().error(executor.getStandardError());
      throw new MojoExecutionException("Error deploying " + apkFile + " to device.", e);
    }
  }