Python脚本解析Android APK信息
2015-10-15
Python 已有2730人围观

    工作上的需求需要解析用户上传的APK文件,获取APK的包名,版本号等信息;于是用aapt和python实现了一段脚本,写出来供大家参考。


    一、依赖


    为了能够在Ubuntu上运行aapt(Android Asset Packaging Tool),你需要安装ia32-libs,如果没有可以按照下面的方式安装依赖:

sudo apt-get install ia32-libs
# 如果上面的命令没有成功,可以执行:
sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0 lib32stdc++6

    如果还有问题,可以参考StackOverflow上的一个回答:install aapt

    另外,你还需要安装Java依赖,安装命令如下:

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer


    二、代码


    脚本代码如下:

# -*- coding: utf-8 -*-
import os
import re
import sys
import zipfile
import datetime
from subprocess import Popen, PIPE
from os.path import dirname, realpath, join

# tools path
AAPT_PATH = join(dirname(realpath(__file__)), 'aapt')
GET_SIGN_PATH = join(dirname(realpath(__file__)), 'getSign.jar')

# package name
CMD_PACKAGE_INFO = AAPT_PATH + ' dump badging "%s" | head -n 1'
PACKAGE_INFO_REGEX = re.compile(r"package: name='(.*)' versionCode='(.*)' versionName='(.*)'", re.I)

# min sdk version
MIN_SDK_VERSION_INFO_REGEX = re.compile(r"sdkVersion:'(\d+)'", re.I)
CMD_MIN_SDK_VERSION_INFO = AAPT_PATH + ' dump badging "%s" | grep sdkVersion:'

# app name and icon
CMD_APP_INFO = AAPT_PATH + ' dump badging "%s" | grep application: '
APP_INFO_REGEX = re.compile(r"application: label='(.+)' icon='(.+)'", re.I)

# app sign
CMD_GET_SIGN = 'java -jar ' + GET_SIGN_PATH + ' "%s"'

CMD_UNZIP_FILE = 'unzip "%s" -d %s'


def extract_apk_infos(file_path):
    apk_infos = {}

    # get package name and version_name & version_code
    try:
        info = Popen(CMD_PACKAGE_INFO % file_path, stdout=PIPE, shell=True).communicate()[0].replace('\n', '')
        m = PACKAGE_INFO_REGEX.search(info)
        if m:
            apk_infos['package_name'] = m.group(1)
            apk_infos['version_code'] = int(m.group(2) or 0)
            apk_infos['version_name'] = m.group(3)
    except Exception, e:
        'get package info failed, cmd: %s, error: %s' % (CMD_PACKAGE_INFO % file_path, e)

    try:
        min_sdk_info = Popen(CMD_MIN_SDK_VERSION_INFO % file_path, stdout=PIPE, shell=True).communicate()[0].replace('\n', '')
        m2 = MIN_SDK_VERSION_INFO_REGEX.search(min_sdk_info)
        if m2:
            apk_infos['min_sdk_version'] = int(m2.group(1) or 0)
    except Exception, e:
        print 'get min_sdk_version info failed, cmd: %s, error: %s' % (CMD_MIN_SDK_VERSION_INFO % file_path, e)

    # get apk name and icon file
    try:
        info = Popen(CMD_APP_INFO % file_path, stdout=PIPE, shell=True).communicate()[0].replace('\n', '')
        m = APP_INFO_REGEX.search(info)
        if m:
            apk_infos['name'] = m.group(1)
            icon_path = m.group(2)
            icon_content = None
            try:
                apk_zipfile = zipfile.ZipFile(file_path)
                if icon_path in apk_zipfile.namelist():
                    icon_content = apk_zipfile.read(icon_path)
                apk_zipfile.close()
            except Exception, e:
                print 'extract apk with zipfile failed, error: %s' % e
                extract_dir = '/tmp/tmp_unpack_dir'
                os.popen(CMD_UNZIP_FILE % (file_path, extract_dir))
                icon_content = open(os.path.join(extract_dir, icon_path)).read()
                os.popen('rm -rf %s' % extract_dir)

            if icon_content:
                icon_name = '%s_%s.%s' % (apk_infos['name'], datetime.datetime.now().strftime('%Y%m%d%H%M%S'), icon_path.split('.')[-1])
                with open('/tmp/%s' % icon_name, 'w') as fp:
                    fp.write(icon_content)
    except Exception, e:
        print 'get app info failed, cmd: %s, error: %s' % (CMD_APP_INFO % file_path, e)

    # get apk sign
    try:
        sign = Popen(CMD_GET_SIGN % file_path, stdout=PIPE, shell=True).communicate()[0].replace('\n', '')
        apk_infos['package_sign'] = sign
    except Exception, e:
        print 'get app sign failed, cmd: %s, error: %s' % (CMD_GET_SIGN % file_path, e)

    return apk_infos


if __name__ == '__main__':
    if not len(sys.argv):
        print 'USAGE: python apk.py APK_FILE_PATH'
    else:
        print extract_apk_infos(sys.argv[-1])


    运行方法:

python apk.py free.apk

    用到的工具:aapt 和 getSign.jar


Over!

本文地址:http://xianglong.me/article/get-android-apk-infos-using-aapt-and-python/

特别声明:本站文章,如非注明,皆为降龙原创。转载需注明本文链接并保证链接可用。