Удаленка для jenkins+selenide+selenoid+allure+docker спецов на 2-3 часа в день. 100% remote! Присоединиться к проекту

Как получить package name перед установкой Android приложения? java

java
appium
android
Теги: #<Tag:0x00007fedc4162ee8> #<Tag:0x00007fedc4162da8> #<Tag:0x00007fedc4162c68>

(Hulk) #1

Привет всем. Планируется автотест для нескольких приложений.
Перед выполнением теста на этапе подготовке драйвера нужно сначала в capabilities получить package приложения.
Так как приложений будет несколько, вопрос такой - как на этом этапе в коде получать package и вставлять его в capabilities ?


(Evgenii) #2

Кажется package не является обязательной capabilities. Обычно достаточно указать app и значение /path/to/apk.apk чтобы работало.


(Taras) #3

Appium Inspector умеет ето делать, либо используйте monitor - инструмент с Android SDK - он тоже показивает ето


(Hulk) #4
  1. У меня без package не запускается тесты)
  2. Мне нужно методом на java получить package из apk и затем использвовать этот package далее

(Dmitri Korobtsov) #5

Appium сам это делать умеет… (собственно говоря, аппиум это делает в обязательном порядке, если в капабилитиз пакадж и активити не указаны - он их сам из заданного апк достает). Так что достаточно при запуске драйвера разные апк файлы подсовывать.

Но если хочется это делать вручную, можете посмотреть appium adb модуль, там есть реализация (правда на js).
Вкратце, работае так:

  1. Аппиум выкусывает path к Android SDK.
  2. Находит бинарники build-tools (если несколько версий, работать будет с первой попавшейся)
  3. Для данной задачи работает с aapt. Выполняет команду типа:
    PS ~Android\sdk\build-tools\25.0.3> .\aapt.exe dumb badging ~\apk\app.apk
    Команда выкусывает из apk всю необходимую информацию - активити на старте, пакадж нейм, версию приложения, локали, версию сдк, и тп…

Можно то же самое сделать из ява - запустить команду, отпарсить аутпут, достать все необходимое, переиспользовать (но по-моему и без этого все должно прекрасно взлететь). :).


(Алексей Берлин) #6

Они и не запустятся, есть два варианта:

  1. либо указывается путь к app файлу и не указываете пекедж неймы и активити
  2. либо указываете пекедж нейм + активити, но не указываете путь к app файлу

Также нужно помнить о том, что у вас может быть для аппиума задан ключ full-reset, который будет сносить приложение в конце каждого теста.

Также нужно помнить, что получить в рантайме пекедж нейм - это из разряда фантастики


(Hulk) #7

у меня сейчас указывается путь к app файлу и не указывается пекедж неймы и активити
и задан ключ full-reset. И как раз таки ошибка при запуске. Приложение запускается, показывается стартовый экран и тест валится(


(Алексей Берлин) #8
  1. Аттачь логи креша
  2. Определись как ты будешь запускать приложение (чере путь к файлу или прописав пекедж неймы) и придерживайся этого пути да и все

(Dmitri Korobtsov) #9

А в чем сложность?) Аппиум это делает при каждом запуске драйвера.


(Алексей Берлин) #10

нет, к сожалению


(Dmitri Korobtsov) #11

Пфф)

Родная реализация в Аппиуме:

manifestMethods.packageAndLaunchActivityFromManifest = async function (localApk) {
  try {
    await this.initAapt();
    log.info("Extracting package and launch activity from manifest");
    let args = ['dump', 'badging', localApk];
    let {stdout} = await exec(this.binaries.aapt, args);
    let apkPackage = new RegExp(/package: name='([^']+)'/g).exec(stdout);
    if (apkPackage && apkPackage.length >= 2) {
      apkPackage = apkPackage[1];
    } else {
      log.errorAndThrow(`Cannot parse package name from ` +
        `'${_.join([this.binaries.aapt, 'dump', 'badging', '"' + localApk + '"'], ' ')}' command  output`);
    }
    let apkActivity = new RegExp(/launchable-activity: name='([^']+)'/g).exec(stdout);
    if (apkActivity && apkActivity.length >= 2) {
      apkActivity = apkActivity[1];
    } else {
      let outputPath = path.resolve(this.tmpDir, apkPackage);
      let getLaunchActivity = ['-jar', this.jars['appium_apk_tools.jar'],
                               'printLaunchActivity', localApk,
                               outputPath];
      let {stdout, stderr} = await exec('java', getLaunchActivity);
      if (stderr) {
        log.errorAndThrow(`Cannot parse launchActivity from manifest: ${stderr}`);
      }
      let act = new RegExp(/Launch activity parsed:([^']+)/g).exec(stdout);
      if (act && act.length >= 2) {
        apkActivity = act[1];
      }
    }
    log.debug(`badging package: ${apkPackage}`);
    log.debug(`badging act: ${apkActivity}`);
    return {apkPackage, apkActivity};
  } catch (e) {
    log.errorAndThrow(`packageAndLaunchActivityFromManifest failed. Original error: ${e.message}`);
  }
};

Ну или вот на яве (звиняйте, если кривая реализация, только что накатал) :slight_smile:

      String output = new CommandPrompt().runCommand("PATH_TO_ANDROID_SDK/sdk/build-tools/25.0.3/aapt.exe dumb badging " + PATH_TO_TARGET_APP_APK);
       log.info(output);
       Pattern p = Pattern.compile("package: name='([^']+)'", Pattern.MULTILINE);
       Matcher m = p.matcher(output);
       String packageName = "";
       while (m.find()) packageName = (m.group().replaceFirst("('$)","").replaceAll(".*'",""));
       System.out.println(packageName);

Дальше - еще проще - packageName скармливаете в capabilities и запускаете драйвер, в чем фантастика?)
CommandPrompt - запускает шелл команду и возврает аутпут как стринг…


(Алексей Берлин) #12

Хм, признаю, был не прав. Попробую)