# How the UAD-NG Update Checker Fetches New Package Lists from GitHub

> Discover how the UAD-NG update checker fetches new package lists from GitHub for the universal android debloater. Learn about its GitHub API integration and JSON parsing process.

- Repository: [Universal-Debloater-Alliance/universal-android-debloater-next-generation](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation)
- Tags: internals
- Published: 2026-06-20

---

**The UAD-NG update checker retrieves fresh package lists by querying the GitHub Releases API to detect new versions, then downloading the raw JSON content from the repository's main branch and deserializing it into a `PackageHashMap` using `serde_json`.**

The Universal Android Debloater Next Generation (UAD-NG) automates package list synchronization through a two-stage update mechanism that interfaces directly with GitHub's public API and raw content endpoints. This architecture ensures users always have the latest debloating definitions without manual intervention. The implementation spans the `uad-core` and `uad-cli` crates, utilizing the `ureq` HTTP client for lightweight, authentication-free requests.

## Release Discovery via the GitHub API

The update process begins in [`crates/uad-core/src/update.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/update.rs) with the `get_latest_release()` function (lines 75–88). This method sends a `GET` request to the GitHub Releases endpoint:

```rust
const GITHUB_API_URL: &str = "https://api.github.com/repos/Universal-Debloater-Alliance/universal-android-debloater/releases/latest";

let release: Release = ureq::get(GITHUB_API_URL)
    .call()?
    .into_json()?;

```

The response deserializes into a `Release` struct containing `tag_name` and `assets` fields. The checker compares this remote `tag_name` against the current binary version defined by `env!("CARGO_PKG_VERSION")`. If the remote version is newer, the `Release` object propagates to the download stage, triggering the package list update workflow.

## Fetching Raw Package List Content

Rather than bundling package definitions with releases, the system pulls the authoritative JSON directly from the repository’s main branch. In [`crates/uad-cli/src/commands.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-cli/src/commands.rs), the `update_package_lists()` function (lines 453–462) constructs a raw content URL:

```rust
let url = format!(
    "https://raw.githubusercontent.com/Universal-Debloater-Alliance/universal-android-debloater/main/package_lists/uad_lists.json"
);

```

This approach guarantees that every client receives the exact same curated data maintained in version control. The `ureq` client downloads the file via `download_file(url, dest_path)`, streaming the response into a temporary location before validation.

## Deserialization and Cache Persistence

Once downloaded, the JSON string deserializes using `serde_json::from_str()` into the internal `PackageHashMap` structure defined in [`crates/uad-lists/src/lib.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-lists/src/lib.rs):

```rust
let content = std::fs::read_to_string(&temp_path)?;
let package_map: PackageHashMap = serde_json::from_str(&content)?;

```

The newly populated `PackageHashMap` replaces the on-disk cache at `$XDG_DATA_HOME/uad/package_lists/`. The GUI layer in [`crates/uad-gui/src/views/about.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/views/about.rs) subsequently reads this cached data to display the current package list version (e.g., **"UAD-NG package list: v20241012"**) in the About screen.

## Retry Logic and Network Resilience

Both the release check and package list download wrap in a **`retry::Fibonacci`** backoff strategy. If temporary network glitches or OS-level file-lock issues occur, the operation retries automatically for up to approximately **30 seconds**. This same retry mechanism handles file system operations like `rename()` and `remove_file()` during the atomic update process, ensuring the cache never corrupts due to incomplete writes.

## Summary

- **`get_latest_release()`** in [`crates/uad-core/src/update.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/update.rs) queries the GitHub API to compare `tag_name` against `CARGO_PKG_VERSION`.
- Raw content URLs pointing to [`package_lists/uad_lists.json`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/package_lists/uad_lists.json) on the main branch provide the authoritative package definitions.
- **`serde_json::from_str()`** deserializes the downloaded JSON into `PackageHashMap`.
- **`retry::Fibonacci`** provides approximately 30 seconds of automatic retry logic for network and file system operations.
- Cached lists persist to **`$XDG_DATA_HOME/uad/package_lists/`** and refresh the UI via [`crates/uad-gui/src/views/about.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/views/about.rs).

## Frequently Asked Questions

### Does the update checker require GitHub authentication?

No. The update checker uses public GitHub API endpoints and raw content URLs that require no authentication. The `ureq` client handles both requests without API tokens, making the update process accessible to all users regardless of GitHub account status.

### Where does UAD-NG store the downloaded package lists?

The application stores cached package lists in the user’s data directory at **`$XDG_DATA_HOME/uad/package_lists/`** (or the platform equivalent). This location persists across application restarts and updates atomically only after successful download and validation.

### How does the update checker handle network failures?

The system implements a **`retry::Fibonacci`** backoff strategy that retries failed requests for up to approximately 30 seconds. This handles temporary network interruptions, DNS resolution delays, and transient HTTP errors without user intervention.

### What triggers the package list update process?

The update triggers when `get_latest_release()` detects that the remote `tag_name` is newer than the current binary version (`env!("CARGO_PKG_VERSION")`). This version comparison occurs automatically during the application’s update check cycle, prompting the CLI to execute `update_package_lists()` and refresh the local cache.