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]>
Maria Sophia wrote:
> The goal is a perfect archive on sdcard or on the desktop of our
> Android homescreen(s) and all the folders & app APKs inside them.

This makes a skeleton on the desktop of the homescreen hierarchy.
But, there are two python scripts which need to be merged into one.

1. First, novasql.py creates a file containing panels, folders & apps
2. Then, novadir.py creates a physical folder hierarchy for each panel

  # -------------------------------------------------------------------
  # novasql.py 
  #   Parse nova.db binary SQL database using "python novasql.py"
  #    python novasql.py > result.txt
  # -------------------------------------------------------------------
  # The "favorites" table stores app shortcuts and folder containers.
  # -------------------------------------------------------------------
  # v1p4 20260819 Ignore homescreen folders that don't have a valid title
  # v1p3 20260819 Separates output by homescreen panels (0,1,2,etc.)
  # v1p2 20260819 Cleaned up the output a bit to make it more readable
  # v1p1 20260819 Try to map which app packages live inside each folder
  # v1p0 20260819 Spits out the nova.db into a human-readable text file
  # -------------------------------------------------------------------
  # This creates an automated inventory of Android homescreen folders, 
  # loose desktop shortcuts and underlying Android application packages 
  # extracted from Nova Launcher  internal databases (nova.db). 
  # 
  # Nova Launcher is a third-party customization interface for Android 
  # devices that replaces the default home screen. It organizes apps 
  # into custom desktop grids, user-defined folders and dedicated dock 
  # panels. This archive maps out that exact physical layout and group 
  # structure for long-term preservation and system migration reference.
  # 
  # Last known good version of TeslaCoil Nova free/adfree launcher 7.0.57 
  # <https://mobile.softpedia.com/apk/nova-launcher/7.0.57/>
  # -------------------------------------------------------------------
  # Each folder on the homescreen gets a row in the favorites table 
  # with a unique ID and intent IS NULL. For any named folder, 
  # the title column stores that name. But if we never named the folder,
  # then Nova stores it with a blank, null, or whitespace-only title. 
  # -------------------------------------------------------------------
  import sys
  import sqlite3
  
  sys.stdout.reconfigure(encoding="utf-8")
  
  conn = sqlite3.connect("nova.db")
  cursor = conn.cursor()
  
  print("=== NOVA LAUNCHER ARCHIVE: HOME SCREENS & FOLDERS ===\n")
  
  # 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:
      print(f"--- HOME SCREEN PANEL: {screen_num} ---")
  
      # Find folders located directly on this specific screen, 
      # but ignore folders with 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:
          print(f"  Folder: [ {folder_name} ] (ID: {folder_id})")
  
          # Get apps inside this 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
                  print(f"      - App: {app_title} ({pkg})")
          else:
              print("      - (Empty folder)")
  
      # Find loose/top-level apps sitting directly on this screen (not in folders)
      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:
          print("  Loose Home Screen 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
              print(f"      - {app_title} ({pkg})")
  
      print()
  
  conn.close()
  # end of novasql.py

  # -------------------------------------------------------------------
  # novadir.py 
  #  Create hierarchical-folder skeleton for Android homescreen APKs
  #   python novadir.py 
  # -------------------------------------------------------------------
  # v1p3 20260819 Improved bad-data handling
  # v1p2 20260819 Removed non-ASCII text
  # v1p1 20260819 Solved unknown header bug
  # v1p0 20260819 Creates a folder hierarchy based on nova.db output
  # -------------------------------------------------------------------
  # This creates a ./folder/app/ hierarchy for Android homescreen folders.
  # -------------------------------------------------------------------
  import os
  import re
  
  input_file = "screens_archive.txt"
  base_dir = "./android_archive"
  
  print(f"Reading archive from {input_file}...")
  
  if not os.path.exists(input_file):
    print(
        f"Error: {input_file} not found. Please make sure it's in the same"
        " directory."
    )
    exit(1)
  
  current_panel = "panel_0"
  current_folder = "loose_apps"
  
  with open(input_file, "r", encoding="utf-8") as f:
    for line in f:
      line_stripped = line.replace("\xa0", " ").strip()
  
      # Match Home Screen Panel headers accurately
      panel_match = re.search(r"HOME\s+SCREEN\s+PANEL:\s*(-?\d+)", line_stripped)
      if panel_match:
        panel_id = panel_match.group(1)
        current_panel = f"panel_{panel_id}"
        current_folder = "loose_apps"
        print(f"\n--- Switched to: {current_panel} ---")
        continue
  
      # Match Folder headers, e.g., "Folder: [ stuff ] (ID: 585)"
      folder_match = re.search(r"Folder:\s*\[\s*(.*?)\s*\]", line_stripped)
      if folder_match:
        folder_name = folder_match.group(1).strip()
        if not folder_name:
          folder_name = "unnamed_folder"
        current_folder = re.sub(r'[\\/*?:"<>|]', "", folder_name).strip()
        continue
  
      # Match App entries containing package names in parentheses at the end
      app_match = re.search(r"\(([\w\.]+)\)\s*$", line_stripped)
      if app_match and ("App:" in line_stripped or line_stripped.startswith("-")):
        pkg_name = app_match.group(1)
  
        target_path = os.path.join(
            base_dir, current_panel, current_folder, pkg_name
        )
        os.makedirs(target_path, exist_ok=True)
        print(f"Created: {target_path}")
  
  print("\nSkeleton folder hierarchy successfully created!")
  # end of novadir.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.