Skip to content

Commit 827acb6

Browse files
committed
add app_version && optimize list_apps(Lazy loading, default: third-party apps)
1 parent 5b72e3f commit 827acb6

3 files changed

Lines changed: 92 additions & 10 deletions

File tree

hmdriver2/driver.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,11 @@ def install_app(self, apk_path: str):
117117
def uninstall_app(self, package_name: str):
118118
self.hdc.uninstall(package_name)
119119

120-
def list_apps(self) -> List:
121-
return self.hdc.list_apps()
120+
def list_apps(self, include_system_apps: bool = False) -> List:
121+
return self.hdc.list_apps(include_system_apps)
122+
123+
def app_version(self, bundle_name) -> Dict:
124+
return self.hdc.app_version(bundle_name)
122125

123126
def has_app(self, package_name: str) -> bool:
124127
return self.hdc.has_app(package_name)
@@ -484,3 +487,4 @@ def xpath(self):
484487
"""
485488
from ._xpath import _XPath
486489
return _XPath(self)
490+

hmdriver2/hdc.py

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import re
77
import os
88
import subprocess
9-
from typing import Union, List, Dict, Tuple
9+
from typing import Union, List, Dict, Tuple, Optional
1010

1111
from . import logger
1212
from .utils import FreePort
@@ -139,13 +139,65 @@ def install(self, apkpath: str):
139139
raise HdcError("HDC install error", result.error)
140140
return result
141141

142-
def list_apps(self) -> List[str]:
143-
result = self.shell("bm dump -a")
142+
def list_apps(self, include_system_apps: bool = False) -> List[str]:
143+
"""
144+
List installed applications on the device. (Lazy loading, default: third-party apps)
145+
146+
Args:
147+
include_system_apps (bool): If True, include system apps in the list.
148+
If False, only list third-party apps.
149+
150+
Returns:
151+
List[str]: A list of application package names.
152+
153+
Note:
154+
- When include_system_apps is False, the list typically contains around 50 third-party apps.
155+
- When include_system_apps is True, the list typically contains around 200 apps in total.
156+
"""
157+
# Construct the shell command based on the include_system_apps flag
158+
if include_system_apps:
159+
command = "bm dump -a"
160+
else:
161+
command = "bm dump -a | grep -v 'com.huawei'"
162+
163+
# Execute the shell command
164+
result = self.shell(command)
144165
raw = result.output.split('\n')
145-
# Use regular expressions to filter out strings starting with 'ID:' and empty strings
146-
# raw origin data: ['ID: 100:', 'cn.wps.mobileoffice.hap', '']
166+
167+
# Filter out strings starting with 'ID:' and empty strings
147168
return [item.strip() for item in raw if item.strip() and not re.match(r'^ID:', item.strip())]
148169

170+
def app_version(self, bundlename: str) -> Dict[str, Optional[str]]:
171+
"""
172+
Get the version information of an app installed on the device.
173+
174+
Args:
175+
bundlename (str): The bundle name of the app.
176+
177+
Returns:
178+
dict: A dictionary containing the version information:
179+
- "versionName": The version name of the app.
180+
- "versionCode": The version code of the app.
181+
"""
182+
result = _execute_command(f"{self.hdc_prefix} -t {self.serial} shell bm dump -n {bundlename} | grep '\"versionCode\":\\|versionName\"'")
183+
184+
matches = re.findall(r'"versionCode":\s*(\d+),\s*"versionName":\s*"([^"]*)"', result.output)
185+
if not matches:
186+
return dict(
187+
version_name='',
188+
version_code=''
189+
)
190+
191+
# Select the last match
192+
version_code, version_name = matches[-1]
193+
version_code = int(version_code) if version_code.isdigit() else None
194+
version_name = version_name if version_name != "" else None
195+
196+
return dict(
197+
version_name=version_name,
198+
version_code=version_code
199+
)
200+
149201
def has_app(self, package_name: str) -> bool:
150202
data = self.shell("bm dump -a").output
151203
return True if package_name in data else False

tests/test_driver.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,40 @@ def test_uninstall_app(d):
5151

5252

5353
def test_list_apps(d):
54+
apps = d.list_apps()
5455
# Assert that no item in the list starts with "ID:"
55-
assert not any(item.startswith("ID:") for item in d.list_apps())
56+
assert not any(item.startswith("ID:") for item in apps)
5657

5758
# Assert that no empty strings are in the list
58-
assert "" not in d.list_apps()
59+
assert "" not in apps
5960

6061
# Assert that "com.samples.test.uitest" is in the list
61-
assert "com.samples.test.uitest" in d.list_apps()
62+
assert "com.sogou.input" in apps
63+
# assert "com.samples.test.uitest" in apps
64+
65+
# Test all apps (include system apps)
66+
all_apps = d.list_apps(include_system_apps=True)
67+
68+
# Assert that "com.huawei.systemmanager" is in the list (system app)
69+
assert "com.huawei.hmos.settings" in all_apps, "'com.huawei.hmos.settings' is not in the full apps list."
70+
71+
# Assert that "com.sogou.input" is also in the list
72+
assert "com.sogou.input" in all_apps, "'com.sogou.input' is not in the full apps list."
73+
74+
# Assert that the total number of apps is greater than the number of third-party apps
75+
assert len(all_apps) > len(apps), "Full apps list is not larger than third-party apps list."
76+
77+
78+
def test_app_version(d):
79+
version_info = d.app_version('com.sogou.input')
80+
81+
# Assert that version_name and version_code exist in the returned dictionary
82+
assert 'version_name' in version_info, "version_name is missing in the returned dictionary."
83+
assert 'version_code' in version_info, "version_code is missing in the returned dictionary."
84+
85+
# Assert specific values
86+
assert version_info['version_name'] == "1.0.4", "version_name does not match expected value."
87+
assert version_info['version_code'] == 5, "version_code does not match expected value."
6288

6389

6490
def test_has_app(d):

0 commit comments

Comments
 (0)