本章介绍如何使用Python来操作Android App。

禁止转载,侵权必究!

前言

为了搭建Python的手机游戏强化学习环境,我们需要具备从python端下发指令到Android手机的能力,这样action才可以被执行并影响目标游戏state。因此,我们需要了解一些python操作Android的基础知识。

Android知识

1.aapt

我们想要用Python操纵App,我们首先要知道目标App的信息。既然Android系统本身可以解析App,那么我们应该可以通过系统工具得到我们想要的信息。这个工具叫aapt。

打开某build-tools子目录

cd /Users/ouyang/Library/Android/sdk/build-tools/26.0.2

执行命令,解析游戏《明日方舟》App内部信息:

./aapt dump badging /Users/ouyang/Downloads/arknights-hg-1201.apk 
package: name='com.hypergryph.arknights' versionCode='20' versionName='1.2.01' platformBuildVersionName='6.0-2438415'
install-location:'preferExternal'
sdkVersion:'16'
targetSdkVersion:'28'
uses-permission: name='android.permission.READ_LOGS'
uses-permission: name='android.permission.GET_TASKS'
application-label:'arknights'
...

获取到了package名字叫com.hypergryph.arknights

执行命令,解析launch的activity:

(base) ouyangMBP:26.0.2 ouyang$ ./aapt dump badging /Users/ouyang/Downloads/arknights-hg-1201.apk | grep "activity"
launchable-activity: name='com.u8.sdk.U8UnityContext'  label='arknights' icon=''
leanback-launchable-activity: name='com.u8.sdk.U8UnityContext'  label='arknights' icon='' banner=''

获取到了activity的名字叫com.u8.sdk.U8UnityContext

2.adb shell

命令行启动游戏《明日方舟》:

# 参数为:package/activity
adb shell am start com.hypergryph.arknights/com.u8.sdk.U8UnityContext

命令行关闭游戏《明日方舟》:

# 参数为:package
adb shell am force-stop com.hypergryph.arknights

Python编程

引入依赖

import os
import subprocess
import time
# adb命令的目录
ADBPATH = '/Users/ouyang/Library/Android/sdk/platform-tools'

定义启动/停止App的函数

def startArKnights():
    return subprocess.Popen('adb shell am start com.hypergryph.arknights/com.u8.sdk.U8UnityContext', shell=True).wait()

def stopArKnights():
    return subprocess.Popen('adb shell am force-stop com.hypergryph.arknights', shell=True).wait()

定义点击动作

def tap(x,y):
    return subprocess.Popen('adb shell input tap ' + str(x) + ' ' + str(y), shell=True).wait()

def taptap(x, y, n=10, frequency=1):
    for i in range(0,n):
        tap(x,y)
        time.sleep(frequency)

定义滑动

def swipe(x1, y1, x2, y2):
    # return subprocess.Popen('adb shell input swipe 100 500 1000 500', shell=True).wait()
    return subprocess.Popen('adb shell input swipe ' + str(x1) + ' ' + str(y1) + ' ' + str(x2) + ' ' + str(y2), shell=True).wait()

def swipeswipe(x1, y1, x2, y2, n=10, frequency=1):
    for i in range(0,n):
        swipe(x1,y1,x2,y2)
        time.sleep(frequency)
# 横屏x++=右滑
def rightswipeswipe(n=10, frequency=1):
    swipeswipe(100,500,1000,500,n,frequency)

测试:

if __name__ == '__main__':
    os.environ["PATH"] += os.pathsep + ADBPATH
    start = startArKnights()
    print("start ", start)
    time.sleep(10)

    taptap(950,750)
    time.sleep(20)

    print('tap')
    tap(1485,300)
    time.sleep(1)
    
    print("swipe start")
    rightswipeswipe(3,1)

    time.sleep(30)
    stop = stopArKnights()
    print("stop ", stop)

查看效果

视频太大,不上传了。