Re: PSA: How to archive your EXACT homescreen(s) apps to Windows for perfect cross-platform backup/restore sans the net

Maria Sophia <[email protected]>
Newsgroups comp.mobile.android,alt.comp.microsoft.windows,alt.comp.os.windows-10
Organization BWH Usenet Archive (https://usenet.blueworldhosting.com)
Message-ID <[email protected]>
Here is the first working script, with a debug feature added.
It looks at the nova sql database and builds a duplicate hierarchy.
Then it populates that hierarchy with the APK files from the phone.

  # -------------------------------------------------------------------
  # apkhome.py 
  #   Parse nova.db, build homescreen folder/app skeleton and pull APKs 
  #    python apkhome.py
  # -------------------------------------------------------------------
  # v1p2 20260819 Added interactive debug mode toggle for dry runs
  # v1p1 20260819 Added automated ADB split/monolithic APK pulling
  # v1p0 20260819 Combined SQL parsing and direct directory tree generation
  # -------------------------------------------------------------------
  # Reads nova.db, re-creates the homescreen folder and package hierarchy,
  # checks for a connected ADB device, runs adb shell pm path <package> 
  # to dynamically locate and pull component files (base.apk plus splits) 
  # feeding results into the newly created matching homescreen hierarchy.
  # -------------------------------------------------------------------
  import os
  import re
  import sqlite3
  import subprocess
  
  db_file = "nova.db"
  base_dir = "./apkhome"
  
  if not os.path.exists(db_file):
      print(f"Error: {db_file} not found. Please place it in the working directory.")
      exit(1)
  
  # --- DEBUG / LIVE MODE PROMPT ---
  print("--- Setup Mode ---")
  mode_choice = input("Run in [D]ebug mode (mock files, no phone needed) or [L]ive mode (real ADB pull)? [d/l]: ").strip().lower()
  DEBUG_MODE = mode_choice.startswith('d')
  
  adb_active = False
  if DEBUG_MODE:
      print("\n[!] Running in DEBUG mode. ADB will be bypassed, and dummy APKs will be created.")
  else:
      print("\n[i] Running in LIVE mode. Checking ADB...")
      # Check if ADB is accessible and a device is connected
      try:
          adb_check = subprocess.run(["adb", "devices"], capture_output=True, text=True, check=True)
          devices = [line for line in adb_check.stdout.splitlines() if "\tdevice" in line]
          if not devices:
              print("Warning: No active ADB devices found. Directory skeleton will be built, but APK pulling will be skipped.")
              adb_active = False
          else:
              print(f"ADB device detected: {devices[0].split()[0]}")
              adb_active = True
      except (subprocess.SubprocessError, FileNotFoundError):
          print("Warning: 'adb' command not found in PATH. Skipping APK pulling.")
          adb_active = False
  
  print(f"\nConnecting to {db_file} and processing layout...")
  
  conn = sqlite3.connect(db_file)
  cursor = conn.cursor()
  
  # 1. Fetch distinct screen indices associated with desktop items
  cursor.execute(
      "SELECT DISTINCT screen FROM favorites WHERE container = -100 ORDER BY screen ASC;"
  )
  screens = cursor.fetchall()
  
  for (screen_num,) in screens:
      current_panel = f"panel_{screen_num}"
      print(f"\n--- Processing: {current_panel} ---")
  
      # 2. Find folders located directly on this specific screen (ignoring blank titles)
      cursor.execute(
          "SELECT _id, title FROM favorites WHERE container = -100 AND screen = ?"
          " AND intent IS NULL AND title IS NOT NULL AND TRIM(title) != '';",
          (screen_num,),
      )
      folders = cursor.fetchall()
  
      for folder_id, folder_name in folders:
          clean_folder_name = re.sub(r'[\\/*?:"<>|]', "", folder_name).strip()
          if not clean_folder_name:
              clean_folder_name = "unnamed_folder"
  
          cursor.execute(
              "SELECT title, intent FROM favorites WHERE container = ?;",
              (folder_id,),
          )
          items = cursor.fetchall()
  
          if items:
              for app_title, intent in items:
                  pkg = "Unknown"
                  if intent and "component=" in intent:
                      try:
                          part = intent.split("component=")[1]
                          pkg = part.split("/")[0]
                      except IndexError:
                          pkg = intent
  
                  target_path = os.path.join(
                      base_dir, current_panel, clean_folder_name, pkg
                  )
                  os.makedirs(target_path, exist_ok=True)
                  print(f"  [Folder] {clean_folder_name} -> App: {pkg}")
  
                  # Pull APK or generate mock file depending on mode
                  if DEBUG_MODE and pkg != "Unknown":
                      dummy_apk_path = os.path.join(target_path, "base.apk")
                      with open(dummy_apk_path, "w") as f:
                          f.write("mock apk content")
                      print(f"    [Mock ADB] Created test file at {dummy_apk_path}")
                  elif adb_active and pkg != "Unknown":
                      path_cmd = subprocess.run(
                          ["adb", "shell", "pm", "path", pkg],
                          capture_output=True, text=True
                      )
                      for line in path_cmd.stdout.splitlines():
                          if line.startswith("package:"):
                              remote_path = line.replace("package:", "").strip()
                              if remote_path:
                                  subprocess.run(
                                      ["adb", "pull", remote_path, target_path],
                                      stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
                                  )
          else:
              target_path = os.path.join(base_dir, current_panel, clean_folder_name)
              os.makedirs(target_path, exist_ok=True)
  
      # 3. Find loose/top-level apps sitting directly on this screen
      cursor.execute(
          "SELECT title, intent FROM favorites WHERE container = -100 AND screen = ?"
          " AND intent IS NOT NULL;",
          (screen_num,),
      )
      loose_apps = cursor.fetchall()
  
      if loose_apps:
          for app_title, intent in loose_apps:
              pkg = "Unknown"
              if intent and "component=" in intent:
                  try:
                      part = intent.split("component=")[1]
                      pkg = part.split("/")[0]
                  except IndexError:
                      pkg = intent
  
              target_path = os.path.join(
                  base_dir, current_panel, "loose_apps", pkg
              )
              os.makedirs(target_path, exist_ok=True)
              print(f"  [Loose App] {pkg}")
  
              if DEBUG_MODE and pkg != "Unknown":
                  dummy_apk_path = os.path.join(target_path, "base.apk")
                  with open(dummy_apk_path, "w") as f:
                      f.write("mock apk content")
                  print(f"    [Mock ADB] Created test file at {dummy_apk_path}")
              elif adb_active and pkg != "Unknown":
                  path_cmd = subprocess.run(
                      ["adb", "shell", "pm", "path", pkg],
                      capture_output=True, text=True
                  )
                  for line in path_cmd.stdout.splitlines():
                      if line.startswith("package:"):
                          remote_path = line.replace("package:", "").strip()
                          if remote_path:
                              subprocess.run(
                                  ["adb", "pull", remote_path, target_path],
                                  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
                              )
  
  conn.close()
  print("\nArchive layout processing complete!")
  
  # end of apkhome.py
--
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.