mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
utils/android: Add support for using aapt2
aapt is now depreciated in favour of aapt2 therefore prefer using the newer binary if it is found on the system. If not present fallback to the old implementation. Currently all invocations of aapt within devlib are compatible with aapt2 however expose the `aapt_version` attribute to indicate which version has been selected to allow for allow maintaining future compatibility.
This commit is contained in:
parent
b52462440c
commit
45ee68fdd4
@ -46,6 +46,7 @@ logger = logging.getLogger('android')
|
|||||||
|
|
||||||
MAX_ATTEMPTS = 5
|
MAX_ATTEMPTS = 5
|
||||||
AM_START_ERROR = re.compile(r"Error: Activity.*")
|
AM_START_ERROR = re.compile(r"Error: Activity.*")
|
||||||
|
AAPT_BADGING_OUTPUT = re.compile(r"no dump ((file)|(apk)) specified", re.IGNORECASE)
|
||||||
|
|
||||||
# See:
|
# See:
|
||||||
# http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
|
# http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
|
||||||
@ -93,6 +94,7 @@ android_home = None
|
|||||||
platform_tools = None
|
platform_tools = None
|
||||||
adb = None
|
adb = None
|
||||||
aapt = None
|
aapt = None
|
||||||
|
aapt_version = None
|
||||||
fastboot = None
|
fastboot = None
|
||||||
|
|
||||||
|
|
||||||
@ -201,7 +203,9 @@ class ApkInfo(object):
|
|||||||
@property
|
@property
|
||||||
def activities(self):
|
def activities(self):
|
||||||
if self._activities is None:
|
if self._activities is None:
|
||||||
cmd = [aapt, 'dump', 'xmltree', self._apk_path,
|
file_flag = '--file' if aapt_version == 2 else ''
|
||||||
|
cmd = [aapt, 'dump', 'xmltree',
|
||||||
|
self._apk_path, '{}'.format(file_flag),
|
||||||
'AndroidManifest.xml']
|
'AndroidManifest.xml']
|
||||||
matched_activities = self.activity_regex.finditer(self._run(cmd))
|
matched_activities = self.activity_regex.finditer(self._run(cmd))
|
||||||
self._activities = [m.group('name') for m in matched_activities]
|
self._activities = [m.group('name') for m in matched_activities]
|
||||||
@ -644,6 +648,7 @@ class _AndroidEnvironment(object):
|
|||||||
self.build_tools = None
|
self.build_tools = None
|
||||||
self.adb = None
|
self.adb = None
|
||||||
self.aapt = None
|
self.aapt = None
|
||||||
|
self.aapt_version = None
|
||||||
self.fastboot = None
|
self.fastboot = None
|
||||||
|
|
||||||
|
|
||||||
@ -676,31 +681,66 @@ def _init_common(env):
|
|||||||
def _discover_build_tools(env):
|
def _discover_build_tools(env):
|
||||||
logger.debug('ANDROID_HOME: {}'.format(env.android_home))
|
logger.debug('ANDROID_HOME: {}'.format(env.android_home))
|
||||||
build_tools_directory = os.path.join(env.android_home, 'build-tools')
|
build_tools_directory = os.path.join(env.android_home, 'build-tools')
|
||||||
if not os.path.isdir(build_tools_directory):
|
if os.path.isdir(build_tools_directory):
|
||||||
msg = '''ANDROID_HOME ({}) does not appear to have valid Android SDK install
|
env.build_tools = build_tools_directory
|
||||||
(cannot find build-tools)'''
|
|
||||||
raise HostError(msg.format(env.android_home))
|
def _check_supported_aapt2(binary):
|
||||||
env.build_tools = build_tools_directory
|
# At time of writing the version argument of aapt2 is not helpful as
|
||||||
|
# the output is only a placeholder that does not distinguish between versions
|
||||||
|
# with and without support for badging. Unfortunately aapt has been
|
||||||
|
# deprecated and fails to parse some valid apks so we will try to favour
|
||||||
|
# aapt2 if possible else will fall back to aapt.
|
||||||
|
# Try to execute the badging command and check if we get an expected error
|
||||||
|
# message as opposed to an unknown command error to determine if we have a
|
||||||
|
# suitable version.
|
||||||
|
cmd = '{} dump badging'.format(binary)
|
||||||
|
result = subprocess.run(cmd.encode('utf-8'), shell=True, stderr=subprocess.PIPE)
|
||||||
|
supported = bool(AAPT_BADGING_OUTPUT.search(result.stderr.decode('utf-8')))
|
||||||
|
msg = 'Found a {} aapt2 binary at: {}'
|
||||||
|
logger.debug(msg.format('supported' if supported else 'unsupported', binary))
|
||||||
|
return supported
|
||||||
|
|
||||||
def _discover_aapt(env):
|
def _discover_aapt(env):
|
||||||
if env.build_tools:
|
if env.build_tools:
|
||||||
|
aapt_path = ''
|
||||||
|
aapt2_path = ''
|
||||||
versions = os.listdir(env.build_tools)
|
versions = os.listdir(env.build_tools)
|
||||||
for version in reversed(sorted(versions)):
|
for version in reversed(sorted(versions)):
|
||||||
aapt_path = os.path.join(env.build_tools, version, 'aapt')
|
if not aapt2_path and not os.path.isfile(aapt2_path):
|
||||||
if os.path.isfile(aapt_path):
|
aapt2_path = os.path.join(env.build_tools, version, 'aapt2')
|
||||||
logger.debug('Using aapt for version {}'.format(version))
|
if not aapt_path and not os.path.isfile(aapt_path):
|
||||||
env.aapt = aapt_path
|
aapt_path = os.path.join(env.build_tools, version, 'aapt')
|
||||||
|
aapt_version = 1
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Use aapt2 only if present and we have a suitable version
|
||||||
|
if aapt2_path and _check_supported_aapt2(aapt2_path):
|
||||||
|
aapt_path = aapt2_path
|
||||||
|
aapt_version = 2
|
||||||
|
|
||||||
|
# Use the aapt version discoverted from build tools.
|
||||||
|
if aapt_path:
|
||||||
|
logger.debug('Using {} for version {}'.format(aapt_path, version))
|
||||||
|
env.aapt = aapt_path
|
||||||
|
env.aapt_version = aapt_version
|
||||||
|
return
|
||||||
|
|
||||||
|
# Try detecting aapt2 and aapt from PATH
|
||||||
if not env.aapt:
|
if not env.aapt:
|
||||||
env.aapt = which(aapt)
|
aapt2_path = which('aapt2')
|
||||||
|
if _check_supported_aapt2(aapt2_path):
|
||||||
|
env.aapt = aapt2_path
|
||||||
|
env.aapt_version = 2
|
||||||
|
else:
|
||||||
|
env.aapt = which('aapt')
|
||||||
|
env.aapt_version = 1
|
||||||
|
|
||||||
if not env.aapt:
|
if not env.aapt:
|
||||||
raise HostError('aapt not found. Please make sure it is avaliable in PATH'
|
raise HostError('aapt/aapt2 not found. Please make sure it is avaliable in PATH'
|
||||||
' or at least one Android platform is installed')
|
' or at least one Android platform is installed')
|
||||||
|
|
||||||
def _check_env():
|
def _check_env():
|
||||||
global android_home, platform_tools, adb, aapt # pylint: disable=W0603
|
global android_home, platform_tools, adb, aapt, aapt_version # pylint: disable=W0603
|
||||||
if not android_home:
|
if not android_home:
|
||||||
android_home = os.getenv('ANDROID_HOME')
|
android_home = os.getenv('ANDROID_HOME')
|
||||||
if android_home:
|
if android_home:
|
||||||
@ -711,6 +751,7 @@ def _check_env():
|
|||||||
platform_tools = _env.platform_tools
|
platform_tools = _env.platform_tools
|
||||||
adb = _env.adb
|
adb = _env.adb
|
||||||
aapt = _env.aapt
|
aapt = _env.aapt
|
||||||
|
aapt_version = _env.aapt_version
|
||||||
|
|
||||||
class LogcatMonitor(object):
|
class LogcatMonitor(object):
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user