La distribution et le support d'UWSC étant terminés, j'ai réécrit la macro que j'avais écrite dans UWSC auparavant en Python. Ainsi, du contenu réécrit, j'ai décidé de résumer le contenu important pour exécuter NoxPlayer avec des macros.
Le contenu comprend comment envoyer les commandes ADB requises pour le fonctionnement Nox, le fonctionnement bidirectionnel entre le programme et Nox et la méthode de reconnaissance d'image floue. J'ai mis le code source, mais c'est peut-être faux car je l'ai écrit en le modifiant
NoxPlayer 6.6.0.0 Python 3.6 opencv-python 4.1.2.30
Lors de l'automatisation du fonctionnement d'Android avec NoxPlayer, il est difficile d'utiliser la souris une par une Par conséquent, il est nécessaire d'opérer en arrière-plan, mais pour cela, il est nécessaire d'utiliser la commande ADB. → Nox est livré avec nox_adb.exe en standard, utilisez donc ceci
Premièrement, en Python, la fonction correspondant au DOSCMD de UWSC peut être écrite comme suit
code
from subprocess import run, PIPE
def doscmd(directory, command):
completed_process = run(command, stdout=PIPE, shell=True, cwd=directory, universal_newlines=True, timeout=10)
return completed_process.stdout
Lors de l'envoi de commandes ADB à l'aide de ce doscmd, par exemple, dans le cas d'une opération tap
code
def send_cmd_to_adb(cmd):
_dir = "D:/Program Files/Nox/bin"
return doscmd(_dir, cmd)
def tap(x, y):
_cmd = "nox_adb shell input touchscreen tap " + str(x) + " " + str(y)
send_cmd_to_adb(_cmd)
Peut être décrit de manière concise D'autres commandes ADB sortiront si vous les vérifiez (bien que vous puissiez les mettre plus tard)
Lors de l'automatisation, ce sera mieux si vous pouvez voir dynamiquement le comportement de l'application et d'Android avec logcat, mais à ce moment-là
code
def show_log():
_cmd = "nox_adb logcat -d"
_pipe = send_cmd_to_adb(_cmd)
return _pipe
Sortira logcat Par exemple, pour ouvrir le gestionnaire de fichiers standard Nox avec la commande ADB et confirmer qu'il a été ouvert
code
def start_app():
_cmd = "nox_adb shell am start -n com.cyanogenmod.filemanager/.activities.NavigationActivity"
_pipe = send_cmd_to_adb(_cmd)
print(_pipe)
start_app()
Terminal
Starting: Intent { cmp=com.cyanogenmod.filemanager/.activities.NavigationActivity }
Mais en utilisant logcat
code
def clear_log():
_cmd = "nox_adb logcat -c"
send_cmd_to_adb(_cmd)
def get_log():
_cmd = "nox_adb logcat -v raw -d -s ActivityManager:I | find \"com.cyanogenmod.filemanager/.activities.NavigationActivity\""
_pipe = send_cmd_to_adb(_cmd)
print(_pipe)
clear_log()
start_app()
get_log()
Terminal
START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.cyanogenmod.filemanager/.activities.NavigationActivity bnds=[334,174][538,301](has extras)} from pid 681
Start proc com.cyanogenmod.filemanager for activity com.cyanogenmod.filemanager/.activities.NavigationActivity: pid=14454 uid=10018 gids={50018, 1028, 1015, 1023}
Displayed com.cyanogenmod.filemanager/.activities.NavigationActivity: +691ms
START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.cyanogenmod.filemanager/.activities.NavigationActivity bnds=[334,174][538,301](has extras)} from pid 681
Start proc com.cyanogenmod.filemanager for activity com.cyanogenmod.filemanager/.activities.NavigationActivity: pid=14562 uid=10018 gids={50018, 1028, 1015, 1023}
Displayed com.cyanogenmod.filemanager/.activities.NavigationActivity: +604ms
START u0 {flg=0x10000000 cmp=com.cyanogenmod.filemanager/.activities.NavigationActivity} from pid 14665
Start proc com.cyanogenmod.filemanager for activity com.cyanogenmod.filemanager/.activities.NavigationActivity: pid=14675 uid=10018 gids={50018, 1028, 1015, 1023}
Displayed com.cyanogenmod.filemanager/.activities.NavigationActivity: +584ms
START u0 {flg=0x10000000 cmp=com.cyanogenmod.filemanager/.activities.NavigationActivity} from pid 14771
START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.cyanogenmod.filemanager/.activities.NavigationActivity bnds=[334,174][538,301](has extras)} from pid 681
Start proc com.cyanogenmod.filemanager for activity com.cyanogenmod.filemanager/.activities.NavigationActivity: pid=14792 uid=10018 gids={50018, 1028, 1015, 1023}
Displayed com.cyanogenmod.filemanager/.activities.NavigationActivity: +589ms
Vous pouvez voir le comportement comme celui-ci
Lors de l'automatisation des opérations d'application, vous pouvez effectuer diverses opérations en examinant le moment de la transition d'activité et du fonctionnement du GC (libération de la mémoire). clear_log → Opération spécifique → get_log → Discrimination, vous pouvez déterminer l'état de l'écran sans reconnaissance d'image </ font>
Lors de l'automatisation d'une application, l'objet se déplace dynamiquement dans ~~ jeux, etc., donc l'objet doit être reconnu par programme. Par conséquent, en reconnaissant l'objet comme une image, il peut être traité sur le programme. Comme méthode concrète
C'était la méthode la plus simple
Comme un avantage
Si vous souhaitez prendre une capture d'écran dans l'image avec la commande ADB et l'enregistrer dans le PC
code
_DIR_ANDROID_CAPTURE = "/sdcard/_capture.png "
_NAME_INTERNAL_CAPTURE_FOLDER = "pics"
def capture_screen(dir_android, folder_name):
_cmd = "nox_adb shell screencap -p " + dir_android
_pipe = send_cmd_to_adb(_cmd)
_cmd = "nox_adb pull " + dir_android+ " " + folder_name
send_cmd_to_adb(_cmd)
capture_screen(_DIR_ANDROID_CAPTURE, _NAME_INTERNAL_CAPTURE_FOLDER)
Générera D: / Program Files / Nox / bin / pics / _capture.png De plus, lors de la création d'un modèle, si vous le créez à partir de cette image, vous pouvez le créer quelle que soit la taille de la fenêtre de Nox.
Plus précisément, comme indiqué ci-dessous, une méthode de renvoi des coordonnées du centre de la pièce qui correspond au modèle dans l'image peut être envisagée. Quand il y a un modèle de img / temp.png dans le même répertoire que main.py
code
import cv2
import numpy as np
_DIR_INTERNAL_CAPTURE = "D:/Program Files/Nox/bin/pics/_capture.png "
_DIR_TEMP = "img/temp.png "
_THRESHOLD = 0.9 #Degré de similitude
def get_center_position_from_tmp(dir_input, dir_tmp):
_input = cv2.imread(dir_input)
_temp = cv2.imread(dir_tmp)
gray = cv2.cvtColor(_input, cv2.COLOR_RGB2GRAY)
temp = cv2.cvtColor(_temp, cv2.COLOR_RGB2GRAY)
_h, _w = _temp.shape
_match = cv2.matchTemplate(_input, _temp, cv2.TM_CCOEFF_NORMED)
_loc = np.where(_match >= _THRESHOLD)
try:
_x = _loc[1][0]
_y = _loc[0][0]
return _x + _w / 2, _y + _h / 2
except IndexError as e:
return -1, -1
get_center_position_from_tmp(_DIR_INTERNAL_CAPTURE , _DIR_TEMP)
Peut être écrit
Si vous souhaitez appuyer sur les coordonnées obtenues à l'étape 2, utilisez la méthode tap et la méthode get_center_position_from_tmp ci-dessus.
code
_DIR_INTERNAL_CAPTURE = "D:/Program Files/Nox/bin/pics/_capture.png "
_DIR_TEMP = "img/temp.png "
x,y = get_center_position_from_tmp(_DIR_INTERNAL_CAPTURE, _DIR_TEMP)
tap(x, y)
Peut être décrit comme
A titre d'exemple concret, l'écran suivant modèle Si vous souhaitez appuyer avec, Appuyez sur l'image, découpez la partie appropriée avec GIMP et placez-la dans img / tmp.png </ font> Après cela, exécutez la méthode capture_screen → méthode get_center_position_from_tmp → appuyez sur la méthode dans cet ordre sur le programme </ font> En d'autres termes, pour résumer le passé
code
from subprocess import run, PIPE
import cv2
import numpy as np
_DIR_NOX = "D:/Program Files/Nox/bin"
_DIR_ANDROID_CAPTURE = "/sdcard/_capture.png "
_NAME_INTERNAL_CAPTURE_FOLDER = "pics"
_DIR_INTERNAL_CAPTURE = "D:/Program Files/Nox/bin/pics/_capture.png "
_DIR_TEMP = "img/temp.png " #J'ai mis l'image du signet ici
_THRESHOLD = 0.9 #Degré de similitude
def main():
capture_screen(_DIR_ANDROID_CAPTURE, _NAME_INTERNAL_CAPTURE_FOLDER)
x, y = get_center_position_from_tmp(_DIR_INTERNAL_CAPTURE, _DIR_TEMP)
tap(x, y)
def capture_screen(dir_android, folder_name):
_cmd = "nox_adb shell screencap -p " + dir_android
_pipe = send_cmd_to_adb(_cmd)
_cmd = "nox_adb pull " + dir_android+ " " + folder_name
send_cmd_to_adb(_cmd)
get_center_position_from_tmp(_DIR_INTERNAL_CAPTURE , _DIR_TEMP)
def get_center_position_from_tmp(dir_input, dir_tmp):
_input = cv2.imread(dir_input)
_temp = cv2.imread(dir_tmp)
gray = cv2.cvtColor(_input, cv2.COLOR_RGB2GRAY)
temp = cv2.cvtColor(_temp, cv2.COLOR_RGB2GRAY)
_h, _w = _temp.shape
_match = cv2.matchTemplate(_input, _temp, cv2.TM_CCOEFF_NORMED)
_loc = np.where(_match >= _THRESHOLD)
try:
_x = _loc[1][0]
_y = _loc[0][0]
return _x + _w / 2, _y + _h / 2
except IndexError as e:
return -1, -1
def doscmd(directory, command):
completed_process = run(command, stdout=PIPE, shell=True, cwd=directory, universal_newlines=True, timeout=10)
return completed_process.stdout
def send_cmd_to_adb(cmd):
return doscmd(_DIR_NOX, cmd)
def tap(x, y):
_cmd = "nox_adb shell input touchscreen tap " + str(x) + " " + str(y)
send_cmd_to_adb(_cmd)
if __name__ == '__main__':
main()
Et le comportement réel est Devrait être
Si le journal disparaît immédiatement après l'exécution, vous ne pourrez pas voir ce que vous avez imprimé, vous devez donc vous assurer que le journal reste. Pour ce faire, écrivez a = input () à la fin de la macro
code
def main():
print("Start")
#Unité de traitement
print("Finish")
_a = input()
if __name__ == "__main__":
main()
code
##Robinet
def tap(x, y):
_cmd = "nox_adb shell input touchscreen tap " + str(x) + " " + str(y)
send_cmd_to_adb(_cmd)
##Glisser
def swipe(x1, y1, x2, y2, seconds):
_millis = seconds * 1000
_cmd = "nox_adb shell input touchscreen swipe " + str(x1) + " " + str(y1) + " " \
+ str(x2) + " " + str(y2) + " " + str(_millis)
send_cmd_to_adb(_cmd)
##Longue pression
def long_tap(x, y, seconds):
swipe(x, y, x, y, seconds)
##Démarrage de l'application (activité)
def start_app():
_cmd = "nox_adb shell am start -n com.hoge.fuga/.MyActivity"
send_cmd_to_adb(_cmd)
##Arrêt de l'application
def start_app():
_cmd = "nox_adb shell am force-stop com.hoge.fuga"
send_cmd_to_adb(_cmd)
##Retourner à la maison
def return_home():
_cmd = "nox_adb shell input keyevent KEYCODE_HOME"
send_cmd_to_adb(_cmd)
##Changer la date du terminal (je l'ai écrit car les informations n'ont pas été collectées uniquement par cette méthode)
import datetime
def set_date(delta_days):
_ANDROID_DATE_FORMAT = "%Y%m%d.%H%M%S"
_day = datetime.datetime.today() - datetime.timedelta(days=delta_days)
_days_ago = _day.strftime(_ANDROID_DATE_FORMAT)
_cmd = "nox_adb shell date -s " + date_2days_ago
send_cmd_to_adb(_cmd)
Faire un exe en utilisant Pyinstaller progressera
Veuillez vous référer au site suivant (il est difficile d'écrire) ・ Créer un fichier exe avec PyInstaller --Qiita
Voir également ci-dessous lors de l'utilisation avec Pycharm, la bonne réponse est d'utiliser les outils externes d'aerobiomat
Le répertoire de Nox lui-même peut changer en fonction de l'environnement, mais s'il est converti en fichier exe, il ne sera pas possible de changer le programme. Par conséquent, il est nécessaire de créer un fichier config.ini à l'avance. Dans cet exemple, en supposant que le fichier exe et config.ini se trouvent dans le même répertoire
main.py
import configparser
def main():
config_ini = configparser.ConfigParser()
config_ini.read('config.ini', encoding='utf-8')
_ADB_DIR = config_ini['DEFAULT']['NoxDirectory']
print("start macro")
#Unité de traitement
print("finish macro")
_a = input()
if __name__ == "__main__":
main()
config.ini
[DEFAULT]
NoxDirectory = D:/Program Files/Nox/bin
Peut être écrit comme
Recommended Posts