44import shutil
55import zipfile
66import subprocess
7+ import traceback
78from pathlib import Path
89import httpx
10+ from Framework .install_handler .install_log_config import get_logger
911from Framework .install_handler .utils import send_response
1012from settings import ZEUZ_NODE_DOWNLOADS_DIR
1113
14+ logger = get_logger ()
15+
1216
1317async def check_status () -> bool :
1418 """Check if Android SDK is installed in isolated directory (following Node.js installer pattern)."""
15- print ("[installer][android-sdk] Checking status..." )
19+ logger . info ("[installer][android-sdk] Checking status..." )
1620
1721 # Simple file existence check in isolated directory (like Node.js installer)
1822 adb_path = get_adb_path ()
1923
2024 if adb_path .exists ():
2125 sdk_root = _get_sdk_root ()
22- print ( f "[installer][android-sdk] Already installed at { sdk_root } " )
26+ logger . info ( "[installer][android-sdk] Already installed at %s" , sdk_root )
2327
2428
2529 await send_response ({
@@ -34,7 +38,7 @@ async def check_status() -> bool:
3438 return True
3539
3640 # Not installed
37- print ("[installer][android-sdk] Not installed" )
41+ logger . info ("[installer][android-sdk] Not installed" )
3842 await send_response ({
3943 "action" : "status" ,
4044 "data" : {
@@ -73,13 +77,13 @@ def update_android_sdk_path():
7377 # Check if SDK exists
7478 adb_path = get_adb_path ()
7579 if not adb_path .exists ():
76- print ("[installer][android-sdk] Warning: Android SDK not found for PATH update." )
80+ logger . warning ("[installer][android-sdk] Warning: Android SDK not found for PATH update." )
7781 return
7882
7983 # Set ANDROID_HOME and ANDROID_SDK_ROOT for current process
8084 os .environ ['ANDROID_HOME' ] = str (sdk_root )
8185 os .environ ['ANDROID_SDK_ROOT' ] = str (sdk_root )
82- print ( f "[installer][android-sdk] ANDROID_HOME set for current process: { sdk_root } " )
86+ logger . info ( "[installer][android-sdk] ANDROID_HOME set for current process: %s" , sdk_root )
8387
8488 # Add SDK paths to PATH for current process (prepend so they take precedence)
8589 sdk_paths = [
@@ -93,7 +97,7 @@ def update_android_sdk_path():
9397 # Always prepend to ensure isolated SDK takes precedence (even if path already exists)
9498 os .environ ['PATH' ] = f"{ sdk_path } { os .pathsep } { current_path } "
9599 current_path = os .environ ['PATH' ]
96- print ( f "[installer][android-sdk] Prepended to current process PATH: { sdk_path } " )
100+ logger . info ( "[installer][android-sdk] Prepended to current process PATH: %s" , sdk_path )
97101
98102
99103def _get_cmdline_tools_url () -> str :
@@ -117,7 +121,7 @@ async def _download_cmdline_tools(archive_path: Path) -> bool:
117121 archive_path .parent .mkdir (parents = True , exist_ok = True )
118122
119123
120- print ( f "[installer][android-sdk] Downloading Android Command Line Tools to { archive_path } ..." )
124+ logger . info ( "[installer][android-sdk] Downloading Android Command Line Tools to %s ..." , archive_path )
121125 await send_response ({
122126 "action" : "status" ,
123127 "data" : {
@@ -136,19 +140,19 @@ async def _download_cmdline_tools(archive_path: Path) -> bool:
136140 total_size = int (response .headers .get ("content-length" , 0 ))
137141 downloaded = 0
138142 chunk = 8192
139- counts = []
143+ last_pct = [- 1 ]
140144 with open (archive_path , "wb" ) as f :
141145 async for data in response .aiter_bytes (chunk ):
142146 f .write (data )
143147 downloaded += len (data )
144148 if total_size > 0 :
145149 progress = (downloaded / total_size ) * 100
146- mb_d = downloaded / ( 1024 * 1024 )
147- mb_t = total_size / ( 1024 * 1024 )
148- print ( f" \r [installer][android-sdk] Download { progress :.1f } % ( { mb_d :.1f } / { mb_t :.1f } MB)" , end = '' , flush = True )
149- p = round ( mb_d / mb_t , 1 )
150- if p not in counts :
151- counts . append ( p )
150+ pct = int ( progress )
151+ if pct != last_pct [ 0 ]:
152+ last_pct [ 0 ] = pct
153+ mb_d = downloaded / ( 1024 * 1024 )
154+ mb_t = total_size / ( 1024 * 1024 )
155+ logger . info ( "[installer][android-sdk] Download %d%% (%.1f/%.1f MB)" , pct , mb_d , mb_t )
152156 await send_response ({
153157 "action" : "status" ,
154158 "data" : {
@@ -158,11 +162,10 @@ async def _download_cmdline_tools(archive_path: Path) -> bool:
158162 "comment" : f"Downloading Android Command Line Tools... { progress :.1f} % ({ mb_d :.1f} /{ mb_t :.1f} MB)" ,
159163 }
160164 })
161- print ()
162- print (f"[installer][android-sdk] Download complete: { archive_path } " )
165+ logger .info ("[installer][android-sdk] Download complete: %s" , archive_path )
163166 return True
164167 except Exception as e :
165- print ( f" \n [installer][android-sdk] Download failed: { e } " )
168+ logger . error ( " [installer][android-sdk] Download failed: %s" , e )
166169 await send_response ({
167170 "action" : "status" ,
168171 "data" : {
@@ -206,7 +209,7 @@ async def _extract_cmdline_tools(archive_path: Path, sdk_root: Path) -> bool:
206209 # If already extracted, clean stale zip and exit success
207210 sdkmanager = _find_executable (latest_dir / "bin" , "sdkmanager" )
208211 if sdkmanager :
209- print ("[installer][android-sdk] Command Line Tools already extracted" )
212+ logger . info ("[installer][android-sdk] Command Line Tools already extracted" )
210213 try :
211214 if archive_path .exists ():
212215 archive_path .unlink ()
@@ -215,7 +218,7 @@ async def _extract_cmdline_tools(archive_path: Path, sdk_root: Path) -> bool:
215218 return True
216219
217220
218- print ("[installer][android-sdk] Extracting Android Command Line Tools..." )
221+ logger . info ("[installer][android-sdk] Extracting Android Command Line Tools..." )
219222 await send_response ({
220223 "action" : "status" ,
221224 "data" : {
@@ -265,10 +268,10 @@ async def _extract_cmdline_tools(archive_path: Path, sdk_root: Path) -> bool:
265268 pass
266269
267270
268- print ("[installer][android-sdk] Extraction complete" )
271+ logger . info ("[installer][android-sdk] Extraction complete" )
269272 return True
270273 except Exception as e :
271- print ( f "[installer][android-sdk] Extraction failed: { e } " )
274+ logger . error ( "[installer][android-sdk] Extraction failed: %s" , e )
272275 await send_response ({
273276 "action" : "status" ,
274277 "data" : {
@@ -293,7 +296,7 @@ async def _run_sdkmanager(sdk_root: Path, args: list[str]) -> bool:
293296 try :
294297 sdkmanager = _find_sdkmanager (sdk_root )
295298 if not sdkmanager :
296- print ("[installer][android-sdk] sdkmanager not found" )
299+ logger . info ("[installer][android-sdk] sdkmanager not found" )
297300 return False
298301
299302 import asyncio
@@ -309,8 +312,8 @@ async def _run_sdkmanager(sdk_root: Path, args: list[str]) -> bool:
309312 # Wrap each arg in single quotes to preserve semicolons in package names like "platforms;android-36"
310313 quoted_args = " " .join ([f"'{ arg } '" for arg in args ])
311314 shell_cmd = f'powershell -Command "{ yes_responses } | &\\ "{ str (sdkmanager )} \\ " --sdk_root={ sdk_root } { quoted_args } "'
312- print ( f "[installer][android-sdk] Running: sdkmanager { ' ' .join (args )} " )
313- print ( f "[installer][android-sdk] This may take 5-15 minutes to download ~450MB of components..." )
315+ logger . info ( "[installer][android-sdk] Running: sdkmanager %s" , " " .join (args ))
316+ logger . info ( "[installer][android-sdk] This may take 5-15 minutes to download ~450MB of components..." )
314317
315318 loop = asyncio .get_event_loop ()
316319
@@ -333,10 +336,10 @@ def run_sdkmanager():
333336 try :
334337 for line in iter (process .stdout .readline , '' ):
335338 if line :
336- print ( line .rstrip ()) # Print immediately
339+ logger . info ( "%s" , line .rstrip ())
337340 output_lines .append (line .strip ())
338341 except Exception as e :
339- print ( f "[installer][android-sdk] Output reading error: { e } " )
342+ logger . error ( "[installer][android-sdk] Output reading error: %s" , e )
340343
341344 process .stdout .close ()
342345 returncode = process .wait (timeout = 1800 )
@@ -353,7 +356,7 @@ class Result:
353356 elif system == "Linux" :
354357 # Linux can execute directly
355358 cmd = [str (sdkmanager ), f"--sdk_root={ sdk_root } " ] + args
356- print ( f "[installer][android-sdk] Running: { ' ' .join (cmd )} " )
359+ logger . info ( "[installer][android-sdk] Running: %s" , " " .join (cmd ))
357360
358361 loop = asyncio .get_event_loop ()
359362 result = await loop .run_in_executor (
@@ -369,7 +372,7 @@ class Result:
369372 elif system == "Darwin" :
370373 # macOS can execute directly
371374 cmd = [str (sdkmanager ), f"--sdk_root={ sdk_root } " ] + args
372- print ( f "[installer][android-sdk] Running: { ' ' .join (cmd )} " )
375+ logger . info ( "[installer][android-sdk] Running: %s" , " " .join (cmd ))
373376
374377 loop = asyncio .get_event_loop ()
375378 result = await loop .run_in_executor (
@@ -383,25 +386,24 @@ class Result:
383386 )
384387 output = (result .stdout or "" ) + (result .stderr or "" )
385388 else :
386- print ( f "[installer][android-sdk] Unsupported platform: { system } " )
389+ logger . warning ( "[installer][android-sdk] Unsupported platform: %s" , system )
387390 return False
388391
389392 if result .returncode != 0 :
390- print ( f "[installer][android-sdk] sdkmanager failed (returncode={ result .returncode } )" )
393+ logger . error ( "[installer][android-sdk] sdkmanager failed (returncode=%s)" , result .returncode )
391394 if output :
392- print ( f "[installer][android-sdk] Last output:\n { output } " )
395+ logger . error ( "[installer][android-sdk] Last output:\n %s" , output )
393396 return False
394397
395- print ( f "[installer][android-sdk] sdkmanager completed successfully" )
398+ logger . info ( "[installer][android-sdk] sdkmanager completed successfully" )
396399 if output :
397- print ( f "[installer][android-sdk] Final output:\n { output [- 500 :]} " ) # Last 500 chars
400+ logger . info ( "[installer][android-sdk] Final output:\n %s" , output [- 500 :])
398401 return True
399402 except subprocess .TimeoutExpired :
400- print ("[installer][android-sdk] sdkmanager timed out after 30 minutes" )
403+ logger . warning ("[installer][android-sdk] sdkmanager timed out after 30 minutes" )
401404 return False
402405 except Exception as e :
403- print (f"[installer][android-sdk] sdkmanager error: { e } " )
404- import traceback
406+ logger .exception ("[installer][android-sdk] sdkmanager error: %s" , e )
405407 traceback .print_exc ()
406408 return False
407409
@@ -411,14 +413,14 @@ async def _accept_licenses(sdk_root: Path) -> bool:
411413 try :
412414 sdkmanager = _find_sdkmanager (sdk_root )
413415 if not sdkmanager :
414- print ("[installer][android-sdk] sdkmanager not found" )
416+ logger . info ("[installer][android-sdk] sdkmanager not found" )
415417 return False
416418
417419 import asyncio
418420 import subprocess
419421
420422 cmd = [str (sdkmanager ), f"--sdk_root={ sdk_root } " , "--licenses" ]
421- print ( f "[installer][android-sdk] Accepting licenses: { ' ' .join (cmd )} " )
423+ logger . info ( "[installer][android-sdk] Accepting licenses: %s" , " " .join (cmd ))
422424
423425 if platform .system () == "Windows" :
424426 # On Windows, use PowerShell to pipe 'y' responses
@@ -470,25 +472,24 @@ async def _accept_licenses(sdk_root: Path) -> bool:
470472 returncode = result .returncode
471473
472474 if returncode != 0 :
473- print ( f "[installer][android-sdk] License acceptance failed: { output } " )
475+ logger . error ( "[installer][android-sdk] License acceptance failed: %s" , output )
474476 return False
475- print ("[installer][android-sdk] Licenses accepted successfully" )
477+ logger . info ("[installer][android-sdk] Licenses accepted successfully" )
476478 return True
477479 except Exception as e :
478- print (f"[installer][android-sdk] License acceptance error: { e } " )
479- import traceback
480+ logger .exception ("[installer][android-sdk] License acceptance error: %s" , e )
480481 traceback .print_exc ()
481482 return False
482483
483484
484485
485486
486487async def install () -> bool :
487- print ("[installer][android-sdk] Installing..." )
488+ logger . info ("[installer][android-sdk] Installing..." )
488489
489490 # Check if Android SDK is already installed
490491 if await check_status ():
491- print ("[installer][android-sdk] Android SDK is already installed" )
492+ logger . info ("[installer][android-sdk] Android SDK is already installed" )
492493 return True
493494
494495 sdk_root = _get_sdk_root ()
@@ -520,7 +521,7 @@ async def install() -> bool:
520521 }
521522 })
522523 if not await _accept_licenses (sdk_root ):
523- print ("[installer][android-sdk] License acceptance failed" )
524+ logger . warning ("[installer][android-sdk] License acceptance failed" )
524525 # Continue; some environments prompt-less acceptance may not be required
525526
526527
@@ -542,15 +543,15 @@ async def install() -> bool:
542543 }
543544 })
544545 if not await _run_sdkmanager (sdk_root , core_components ):
545- print ("[installer][android-sdk] Failed installing one or more SDK components" )
546+ logger . error ("[installer][android-sdk] Failed installing one or more SDK components" )
546547 return False
547548
548549
549550 # Update PATH after successful installation
550551 update_android_sdk_path ()
551552
552553
553- print ( f "[installer][android-sdk] Installation successful at { sdk_root } " )
554+ logger . info ( "[installer][android-sdk] Installation successful at %s" , sdk_root )
554555 await send_response ({
555556 "action" : "status" ,
556557 "data" : {
0 commit comments