Metadata-Version: 2.1
Name: apkpy
Version: 0.9.7.1
Summary: Build native Android apps in pure Python — no Java, no Android Studio required.
Home-page: https://github.com/apkpy-project/repo-apkpy
Author: Martim
Project-URL: Source, https://github.com/apkpy-project/repo-apkpy
Project-URL: Changelog, https://github.com/apkpy-project/repo-apkpy/blob/main/CHANGELOG.md
Project-URL: Bug Tracker, https://github.com/apkpy-project/repo-apkpy/issues
Keywords: android,apk,python,mobile,app,framework,android-development,no-java,python-to-android,native-android,mobile-development,gui,sqlite,http,rest-api,hot-reload,compiler,build-tool
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Software Development :: Compilers
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Multimedia :: Graphics
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Requires-Dist: click

# 🚀 ApkPy — Build Native Android Apps in Pure Python

Welcome to **ApkPy**, the revolutionary transpiler framework that empowers you to build lightning-fast, native Android applications using **only Python and CSS-style definitions**. We don't use heavy WebViews or slow runtime rendering engines. ApkPy parses your Python logic and directly generates pure **Android Java and XML components**, ready to be compiled into a `.apk`.

---

## 1. The Vision & Philosophy 🌟

Forget the steep learning curves of Java or Kotlin, and avoid the massive footprint of cross-platform engines. Why choose ApkPy over interpreted frameworks like Kivy or Flet?

- **Zero Bloat, Smaller APKs**: Because we transpile to pure Android projects, you avoid bundling heavy Python interpreters into your deployment.
- **Flawless Performance**: By generating true native `Activity`, `Button`, `ImageView`, and `EditText` elements under the hood, your app runs at the maximum possible speed the OS allows.
- **100% Native Look & Feel**: Because your components interact directly with the Android SDK, OS-level features like haptics, text-selection, and system animations are preserved automatically.

---

## 2. How it Works (The Technical Secret) 🛠️

**How it works:** ApkPy parses your Python code into an Abstract Syntax Tree (AST) and maps UI calls to their corresponding Android XML Layouts and Java Activity classes. It's not a simulation; it's code generation.

Here's what happens under the hood every time you run `apkpy build`:

1. **Parsing** — ApkPy reads your `writehere.py` file and builds a full AST.
2. **Component Mapping** — Each `label()`, `button()`, `inputs()`, `image()` call is translated to its native Android equivalent (`TextView`, `Button`, `EditText`, `ImageView`).
3. **CSS Translation** — Your `style = """ ... """` string is parsed and converted to Android XML drawables, `dp` values, and color attributes.
4. **Java/XML Generation** — Full Java Activity classes and XML layout files are generated from scratch.
5. **ZIP Packaging** — Everything is bundled into a `.zip` file you can open directly in Android Studio.

---

## 3. Full Installation & Setup 📥

Getting started is instantly accessible. You **do not** need any prior knowledge of Android Studio to start designing.

```bash
pip install apkpy
```
*(Need the new features? Run `pip install --upgrade apkpy`)*

### Your First App — Full CLI Workflow

```bash
# 1. Create a new project
apkpy start my_project

# 2. Enter your project folder
cd my_project

# 3. Open writehere.py and design your app
# (edit it with any editor — VS Code, PyCharm, Notepad, etc.)

# 4. Preview it instantly on your computer (no Android needed!)
python writehere.py

# 5. When you're happy, build the native Android project
apkpy build
# → It will ask: "What do you want to call it?"
# → Type your app name, e.g: coffee_haven
# → A file called coffee_haven.zip is generated!

# 6. Open the .zip in Android Studio and compile your APK!
```

---

## 4. Complete Syntax Guide (v0.9.7.1 Standard) 🎨

ApkPy v0.9.7.1 introduces native SQLite database support and a powerful `json_get()` helper, making it easier than ever to build data-driven Android apps in pure Python.

### The Screen
Everything belongs to a `Screen`. Screens translate directly to native Android Activities.
```python
login_screen = Screen(id="login_container")
```

### The Container (Nesting)
Containers allow you to group components together, creating complex layouts like cards, headers, or custom grids.
```python
# Create a container on the screen
header_box = container(id="header_style", screen=login_screen)

# Add a label inside that container
label("Welcome Back", parent=header_box)
```

### The CSS Engine
Say goodbye to complex dictionary configurations. ApkPy uses a multi-line string approach with standard CSS syntax. No quotes are needed around values!

```python
style = """
login_container {
    gap: 15px;
    flex-direction: column;
}
"""
```

### New Layout & Styling Features (v0.9.3+)
Our Android-generation engine has been completely rewritten to use **XML-driven layouts**, ensuring 1:1 parity between your code and the native Android rendering.
- **`gap: 20px;`** – Automatically places calculated `dp` margins between elements in your layout container.
- **`flex-direction: row; / column;`** – Orients your components mapped directly to `android:orientation="horizontal"` or `"vertical"`.
- **`padding: 10px 20px;`** – Pushes text content away from your component edges.
- **`border-radius: 15px;`** – Generates native XML shape drawables for smooth rounded corners.
- **`border-color: #000;`** and **`border-width: 2px;`** – Easily define component outlines.
- **`pressed-color: #cccccc;`** – Defines the feedback color when a button is clicked (native `<selector>`).
- **`focus-border-color: #2196F3;`** – When a user taps your inputs, ApkPy dynamically swaps the border colors via native XML states!
- **`font-size: 18px;`** – Set text size in pixels (automatically converted to `sp` for Android).
- **`font-weight: bold;`** – Makes your text thicker. Supports `bold` or numeric values (`700`, `800`, `900`).
- **`font-family: 'sans-serif';`** – Choose between native font styles.

### Typography Support 🔠
ApkPy ensures your text looks great and consistent across platforms by mapping CSS generic families to native system fonts:
- **`sans-serif`**: The modern look. Maps to **Roboto** (Android) and **Segoe UI** (Windows) or **Helvetica** (macOS).
- **`serif`**: The classic look. Maps to **Times New Roman**.
- **`monospace`**: Perfect for code or alignment. Maps to **Consolas** (Windows) or **Courier**.

*Note: You can also use `font-style: italic;` to add emphasis to your labels.*

---

## 5. Component & Logic Workflow ⚙️

Adding elements and routing interactions is declarative and incredibly clean.

**Adding Components:**
Simply call the component and attach it to your screen. Give it an `id` to map it to your CSS string.
```python
btn = button("Login", id="primary_btn", screen=login_screen)
inputs("Your email", type="text", id="email_input", screen=login_screen)
```

**Nesting with `parent`:**
Every component (`label`, `button`, `inputs`, `container`) now supports a `parent` parameter. If set, the component will be rendered inside that container instead of directly on the screen.
```python
card = container(id="card_bg", screen=my_screen)
label("Title", parent=card)
button("Click Me", parent=card)
```

**Supported Input Types:**
ApkPy handles complex input mapping for you:
- `type="text"`: Standard keyboard entry.
- `type="password"`: Secure text entry with hidden characters.
- `type="search"`: Specialized search field with a clear (✕) button.
- `type="checkbox"`: Native Boolean toggle.
- `type="range"`: Interactive slider (0-100).
- `type="radio"`: Selection group (format: `inputs("Option1|Option2", type="radio")`).

**Linking Logic & Navigation:**
Instead of fighting with Android `Intent` classes, handle navigation with a single method.
```python
login_screen.on_click_navigate(button=btn, to=dashboard_screen)
```

**The Application Lifecycle:**
Your file must end by invoking the execution layer with `run()`.
```python
run(start_screen=login_screen)
```

---

## 6. The Two-Step Execution Flow 🔄

ApkPy makes the development lifecycle effortless via two distinct phases:

### Phase 1: Development (Hot Previewer)
Simply run your Python file normally:
```bash
python writehere.py
```
This instantly boots up our Tkinter-based Hot Previewer on your computer. You get immediate visual feedback for your screens, interactive inputs, focus colors, buttons, and navigation without needing an emulator!

### Phase 2: Production (Native Compilation)
When you're ready to deploy, run the CLI tool in your project folder:
```bash
apkpy build
```
This triggers the transpiler! ApkPy generates all Java classes, Manifests, **XML Layouts**, and Drawables completely from scratch. This new XML-driven approach ensures that complex layouts, margins, and alignments are handled natively by the Android OS for maximum stability. Open the resulting bundled `.zip` project and generate your production `.apk`!

---

## 7. What's New & Bug Fixes (v0.9.7.1) 🚀

We've been hard at work making ApkPy the most reliable Python-to-Android framework. Here's what's new in **v0.9.7.1**:

- 🗄️ **SQLite Database API**: Build fully offline, data-persistent Android apps with the new `db` object. Use `db.execute()` for writes and `db.query()` for reads — with zero Java knowledge required.
- 🌐 **HTTPS Network API**: Connect your app to any REST API on the internet with `https.get()` and `https.post()`. Supports custom `headers` for Bearer tokens and API keys. Runs in a background thread — no UI freezes. Compiles to native Android `HttpURLConnection`.
- 🔎 **`json_get()` Helper**: Safely navigate JSON results from `db.query()` or `https` responses using dot-notation paths (e.g., `json_get(result, "main.temp")`). Works identically in the Previewer and on real Android.
- **Cross-platform parity**: All new features are fully functional in Phase 1 (Tkinter Previewer) and compile to native Android code in Phase 2.

### Previous Highlights (v0.9.3)
- **XML Layout Engine**: Moved from programmatic Java UI to native Android XML layouts. This fixes 99% of layout inconsistencies.
- **Named Builds**: Running `apkpy build` now interactively asks you for the project name.
- **Pixel 9 Pro Previewer**: The Hot Previewer is now perfectly calibrated to match the Pixel 9 Pro screen.
- **Automatic Gravity & Centering**: Fixed bugs where elements wouldn't center correctly.
- **Animation Stability**: Fixed glitches in `@keyframes` animations.

---

## 8. FAQ (Quick Answers) ❓

**"Does it support Android APIs?"**
Yes! We are currently expanding support for native permissions, GPS, Camera, and more in upcoming versions.

**"Do I need the Android SDK installed?"**
To write and preview your app using `python writehere.py`, **no SDK is required**. However, `apkpy build` generates a native Android Studio project. To compile that project into a final `.apk`, you will need the Android SDK/Java installed on your machine (or just upload the generated folder to a CI/CD service like GitHub Actions).

**"Can I use images in my app?"**
Yes! See Section 10 below. Just put your image file next to `writehere.py` and use the `image()` component — ApkPy handles copying assets into Android's drawable folder automatically.

---

## 9. Spacing & Margins (Precision Layout) 📐

Margins allow you to create "invisible space" around your components. This is essential for moving buttons down, separating inputs, or creating breathing room between elements.

### Example Code:
```css
my_button {
    /* Move the button 50 pixels down from whatever is above it */
    margin-top: 50px;

    /* Push the button 20 pixels away from the left edge */
    margin-left: 20px;
}

header {
    /* Put a 30 pixel gap at the bottom of the title */
    margin-bottom: 30px;
}
```

### Margin Guide (For Absolute Beginners):

| Property | What it does (in simple terms) |
| :--- | :--- |
| **`margin`** | Adds space to **all four sides** (top, bottom, left, and right) at once. It's like putting a bubble around the whole component. |
| **`margin-top`** | Pushes the component **down**. It adds space to the top edge. Use this if you want something to move lower on the screen. |
| **`margin-bottom`** | Pushes the *next* component **away**. It adds space to the bottom edge. |
| **`margin-left`** | Pushes the component to the **right**. It adds space to the left side. |
| **`margin-right`** | Pushes the component to the **left**. It adds space to the right side. |

> [!TIP]
> In ApkPy, you can use `px` (like `20px`). The compiler automatically converts this to `dp` for Android, so your app looks perfect on every phone screen size!

---

## 10. Images & Toast Notifications 🖼️

### Images
The `image()` component renders a native Android `ImageView`. Just place your image file (`.png`, `.jpg`) in the **same folder as `writehere.py`** and reference it by filename. ApkPy will automatically copy it into the Android `res/drawable` folder during the build step.

```python
from apkpy_lib import image, Screen

home = Screen(id="home_screen")

# Just place 'logo.png' next to your writehere.py file!
image("logo.png", id="app_logo", screen=home)
```

You can fully style the image through CSS just like any other component:
```css
app_logo {
    width: 150px;
    height: 150px;
    border-radius: 75px;      /* Makes it circular! */
    margin-top: 60px;
    box-shadow: 0 8px 20px #000;
    animation-name: fadeIn;
    animation-duration: 1000ms;
}
```

> [!IMPORTANT]
> ApkPy automatically handles the conversion of your image file into an Android-compatible resource. You do **not** need to manually add it to any resource folder — just place it next to your script and it works.

---

### Toast Notifications 🍞

Toasts are small, temporary pop-up messages that appear at the bottom of the screen — a staple of Android UX. In ApkPy, triggering one is a single line of Python:

```python
from apkpy_lib import toast

def on_save():
    toast("Your data was saved! ✅")
```

In the **Hot Previewer** (Phase 1), toasts appear as an overlay message at the bottom. On a **real Android device** (Phase 2), they compile to the native `Toast.makeText(...)` Java call — identical to what professional apps use.

You can call `toast()` from **any function** — button clicks, storage operations, permission results, or even on app startup:
```python
from apkpy_lib import toast, run, Screen

home = Screen(id="home")
run(start_screen=home)
toast("Welcome back! 👋")  # Shows when the app launches
```

---

## 11. Storage & Persistence 💾

ApkPy provides a powerful, built-in `storage` API that allows you to **persistently save data** across app sessions — things like user preferences, saved form values, login tokens, and more.

### How It Works Under the Hood

| Environment | What `storage` uses |
| :--- | :--- |
| **Hot Previewer** (your computer) | A local `.json` file saved next to your script |
| **Android Build** (real device) | Native Android `SharedPreferences` — the fastest and most battery-efficient persistent storage on Android |

This means your code is **100% identical** in both environments. No special cases, no `if platform:` checks.

### Importing Storage

```python
from apkpy_lib import storage
```

### The Full API

| Method | Description | Example |
| :--- | :--- | :--- |
| `storage.set(key, value)` | Saves a value permanently | `storage.set("username", "Alice")` |
| `storage.get(key, default)` | Reads a value (returns `default` if not found) | `storage.get("username", "Guest")` |
| `storage.delete(key)` | Removes a single key | `storage.delete("token")` |
| `storage.clear()` | Wipes **all** stored data | `storage.clear()` |

### Basic Example — Saving a User's Name

```python
from apkpy_lib import Screen, inputs, button, toast, storage, run

my_screen = Screen(id="main")

name_field = inputs("Enter your name", type="text", id="name_field", screen=my_screen)

def save_name():
    name = name_field.get_value()
    if name != "":
        storage.set("username", name)
        toast(f"Saved: {name} ✅")

def load_name():
    saved = storage.get("username", "")
    if saved != "":
        name_field.set_value(saved)
        toast(f"Welcome back, {saved}! 👋")
    else:
        toast("No name saved yet.")

button("Save", id="btn_save", command=save_name, screen=my_screen)
button("Load", id="btn_load", command=load_name, screen=my_screen)

run(start_screen=my_screen)
```

### Advanced Example — Auto-loading Saved Preferences

One of the most useful patterns is **auto-loading** data when the app starts — so the user never has to type the same thing twice:

```python
from apkpy_lib import Screen, inputs, button, toast, storage, run

settings_screen = Screen(id="settings")

# Input fields
language_select = inputs("English|Portuguese|Spanish", type="radio", id="lang_radio", screen=settings_screen)
notifications_toggle = inputs("Enable notifications", type="checkbox", id="notif_toggle", screen=settings_screen)

# Auto-load saved preferences when the app opens
saved_language = storage.get("language", "English")
if saved_language != "":
    language_select.set_value(saved_language)

saved_notifs = storage.get("notifications", "false")
if saved_notifs == "true":
    notifications_toggle.set_value("true")

def save_settings():
    storage.set("language", language_select.get_value())
    storage.set("notifications", notifications_toggle.get_value())
    toast("Settings saved! ⚙️")

button("Save Settings", id="btn_settings", command=save_settings, screen=settings_screen)

run(start_screen=settings_screen)
```

> [!IMPORTANT]
> The `.get_value()` and `.set_value()` methods work on **virtually all interactive inputs** — text fields, checkboxes, radio button groups, sliders, and even labels. String comparisons with `==` or `!=` work natively in both the Previewer (Python) and on the final Android device (Java).

> [!TIP]
> Use `storage.get("key", "default_value")` to safely provide a fallback for first-time users who have no saved data yet. This prevents crashes and unexpected empty states.

---

## 12. Native Permissions & Features 📱

ApkPy allows you to interact directly with Android system features using a simple Python API.

### Declaring Manifest Permissions
Declare what your app needs so the compiler can update `AndroidManifest.xml` automatically.
```python
from apkpy_lib import declare_permissions
declare_permissions(["CAMERA", "LOCATION_FINE", "INTERNET"])
```

### Runtime Permission Requests & Toasts
Prompt users for permissions and provide instant feedback with native Toasts.
```python
from apkpy_lib import permissions, toast

def ask_camera():
    def on_result(granted):
        if granted:
            toast("Camera access granted! 📸")
        else:
            toast("We need camera permission to continue.")

    permissions.request("CAMERA", on_response=on_result)
```

---

## 13. Master Example: "Coffee Haven" ☕

This is a complete, real-world multi-screen app built entirely with ApkPy. It demonstrates **images, navigation, radio buttons, text inputs, storage persistence, toast notifications, and a fully custom CSS design** all working together.

```python
from apkpy_lib import Screen, button, label, inputs, image, run, toast, storage

# 1. Setup Screens
welcome_screen = Screen(id="welcome_container")
order_screen = Screen(id="order_container")

# 2. Logic: Handle Order
def place_order():
    # Save preferences to storage so the user's choices are remembered
    storage.set("coffee_select", coffee_select.get_value())
    storage.set("special_notes", special_notes.get_value())
    toast("Order placed! Your coffee will be ready soon. ☕")

# 3. Welcome Screen UI
image("logo.png", id="welcome_logo", screen=welcome_screen)
label("COFFEE HAVEN", id="welcome_title", screen=welcome_screen)
label("The best brew in town.", id="welcome_subtitle", screen=welcome_screen)
btn_start = button("EXPLORE MENU", id="btn_primary", screen=welcome_screen)

# Navigate to Order Screen on button click
welcome_screen.on_click_navigate(button=btn_start, to=order_screen)

# 4. Order Screen UI
label("SELECT YOUR COFFEE", id="menu_title", screen=order_screen)

# Radio buttons for coffee selection
coffee_select = inputs("Espresso|Latte|Cappuccino|Mocha", type="radio", id="coffee_select", screen=order_screen)

# Free-text for special instructions
special_notes = inputs("Special instructions (e.g., extra sugar)", type="text", id="special_notes", screen=order_screen)

# Auto-load saved preferences from last session!
saved_coffee = storage.get("coffee_select", "")
if saved_coffee != "":
    coffee_select.set_value(saved_coffee)

saved_notes = storage.get("special_notes", "")
if saved_notes != "":
    special_notes.set_value(saved_notes)

# Place Order button
button("PLACE ORDER", id="btn_order", command=place_order, screen=order_screen)

# 5. Full Custom CSS
style = """
welcome_container {
    background-color: #2D1E17;
    flex-direction: column;
    gap: 0px;
}

order_container {
    background-color: #FDF8F5;
    flex-direction: column;
    padding: 30px;
    gap: 20px;
}

welcome_logo {
    width: 180px;
    height: 180px;
    border-radius: 90px;
    margin-top: 100px;
    box-shadow: 0 10px 20px #000;
    animation-name: fadeInDown;
    animation-duration: 1000ms;
}

welcome_title {
    color: #FDF8F5;
    font-size: 32px;
    font-weight: bold;
    margin-top: 40px;
    animation-name: fadeInDown;
    animation-duration: 1200ms;
}

welcome_subtitle {
    color: #D4A373;
    font-size: 18px;
    margin-bottom: 60px;
    animation-name: fadeIn;
    animation-duration: 2000ms;
}

btn_primary {
    background-color: #D4A373;
    color: #2D1E17;
    border-radius: 30px;
    font-weight: bold;
    font-size: 18px;
    padding: 18px 45px;
    pressed-color: #B88B5B;
    animation-name: fadeInUp;
    animation-duration: 1000ms;
}

menu_title {
    color: #2D1E17;
    font-size: 24px;
    font-weight: bold;
    animation-name: fadeIn;
    animation-duration: 1000ms;
}

coffee_select {
    color: #3E2723;
    font-size: 18px;
}

special_notes {
    border-color: #D4A373;
    border-radius: 12px;
    padding: 20px;
    focus-border-color: #2D1E17;
}

btn_order {
    background-color: #2D1E17;
    color: #FDF8F5;
    border-radius: 15px;
    font-weight: bold;
    font-size: 18px;
    padding: 20px;
    pressed-color: #1A110D;
    margin-top: 30px;
    animation-name: zoomIn;
    animation-duration: 800ms;
}

@keyframes fadeInDown {
    from { opacity: 0; margin-top: -40px; }
    to   { opacity: 1; margin-top: 0px; }
}

@keyframes fadeInUp {
    from { opacity: 0; margin-top: 40px; }
    to   { opacity: 1; margin-top: 0px; }
}

@keyframes zoomIn {
    from { opacity: 0; scale: 0.8; }
    to   { opacity: 1; scale: 1.0; }
}

@keyframes fadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
"""

if __name__ == "__main__":
    run(start_screen=welcome_screen)
```

---

## 14. Master Example: Mini Profile App 👤

This example demonstrates inputs, permissions, toasts, and advanced CSS styling in a focused single-screen app.

```python
from apkpy_lib import Screen, button, label, inputs, run, toast, declare_permissions, permissions

# 1. Declare permission for the compiler
declare_permissions(["CAMERA"])

# 2. Setup the Screen
profile_screen = Screen(id="profile_container")

# 3. Logic: Handle Camera Request
def update_photo():
    def on_perm(granted):
        if granted:
            toast("Thanks! Accessing camera for your photo...")
        else:
            toast("We need camera access to take a photo!")

    permissions.request("CAMERA", on_response=on_perm)

# 4. Build the UI
label("Mini Profile App", id="header", screen=profile_screen)
inputs("Enter your Full Name", type="text", id="name_field", screen=profile_screen)
inputs("Short Bio", type="text", id="bio_field", screen=profile_screen)

btn_photo = button("Set Profile Picture", id="btn_outline", command=update_photo, screen=profile_screen)
btn_save  = button("Save Profile", id="btn_primary", screen=profile_screen)

# 5. Advanced CSS System
style = """
profile_container {
    flex-direction: column;
    gap: 20px;
    background-color: #ffffff;
    padding: 30px;
}

header {
    color: #1a1a1a;
    font-size: 24px;
    font-weight: bold;
}

name_field, bio_field {
    border-color: #e0e0e0;
    border-radius: 12px;
    padding: 14px;
    focus-border-color: #6200EE;
}

btn_outline {
    background-color: #ffffff;
    color: #6200EE;
    border-color: #6200EE;
    border-width: 2px;
    border-radius: 20px;
    pressed-color: #f3e5f5;
}

btn_primary {
    background-color: #6200EE;
    color: white;
    border-radius: 20px;
    pressed-color: #3700B3;
}
"""

run(start_screen=profile_screen)
```

---

## 15. Declarative CSS Animations 🎬

ApkPy supports **native declarative animations** using a syntax inspired by CSS Keyframes. You can define how a component should transition from one state to another, and the framework will generate the corresponding native Android `Animation` XML and Java logic.

### How it Works: The `@keyframes` Block

An animation is defined using the `@keyframes` keyword followed by a name. Inside, you define two states:
- **`from` (or `0%`)**: The starting state of the component when it appears.
- **`to` (or `100%`)**: The final state where the component should end.

```css
@keyframes slideUp {
  from {
      opacity: 0;
      margin-top: 50px;
  }
  to {
      opacity: 1;
      margin-top: 0px;
  }
}
```

### Applying the Animation

```css
my_button {
    animation-name: slideUp;
    animation-duration: 1500ms;
}
```

### Supported Properties:

| Property | Description | Example |
| :--- | :--- | :--- |
| **`opacity`** | Fades the component in or out (0.0 is invisible, 1.0 is solid). | `opacity: 0;` to `opacity: 1;` |
| **`margin-top`** | Moves the component vertically (Y-axis). | `margin-top: 100px;` to `0px;` |
| **`margin-left`** | Moves the component horizontally (X-axis). | `margin-left: -50px;` to `0px;` |
| **`scale`** | Resizes the component (1.0 is normal size). | `scale: 0.5;` to `scale: 1.0;` |

### Ready-to-Use Animation Presets:

#### 1. Smooth Fade-In
```css
@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}
```

#### 2. Slide Down From Top
```css
@keyframes fadeInDown {
    from { opacity: 0; margin-top: -40px; }
    to { opacity: 1; margin-top: 0px; }
}
```

#### 3. Slide Up From Bottom
```css
@keyframes fadeInUp {
    from { opacity: 0; margin-top: 40px; }
    to { opacity: 1; margin-top: 0px; }
}
```

#### 4. The "Pop" / Zoom Effect
```css
@keyframes zoomIn {
    from { scale: 0.5; opacity: 0; }
    to { scale: 1.0; opacity: 1; }
}
```

#### 5. Side Slide From Left
```css
@keyframes slideFromLeft {
    from { margin-left: -200px; opacity: 0; }
    to { margin-left: 0px; opacity: 1; }
}
```

> [!IMPORTANT]
> **Cross-Platform Support**: These animations are fully functional in the **Tkinter Previewer** (Phase 1) so you can test the "vibe" of your app, and they compile to **Native Android XML** (Phase 2) for maximum performance on real devices.

---

## 16. SQLite Database 🗄️

ApkPy now supports **native local databases** powered by SQLite. Build offline-first apps that store structured data permanently on the device — no internet required.

### How It Works Under the Hood

| Environment | What `db` uses |
| :--- | :--- |
| **Hot Previewer** (your computer) | Python's built-in `sqlite3` module, saved as `apkpy_app.db` next to your script |
| **Android Build** (real device) | Native `android.database.sqlite.SQLiteDatabase` — the same engine used by Google apps |

Your code is **100% identical** in both environments.

### Importing the Database

```python
from apkpy_lib import db, json_get
```

### The Full API

| Method | Description | Example |
| :--- | :--- | :--- |
| `db.execute(sql)` | Runs an SQL statement that **modifies** data | `db.execute("INSERT INTO users (name) VALUES ('Alice')")` |
| `db.query(sql)` | Runs a `SELECT` and returns a **JSON string** | `result = db.query("SELECT * FROM users")` |

### Reading Data with `json_get()`

Since `db.query()` returns a JSON string, use `json_get()` to read values without complex parsing:

```python
result = db.query("SELECT * FROM users ORDER BY id DESC")
first_name = json_get(result, "0.name")   # First row, "name" column
first_id   = json_get(result, "0.id")     # First row, "id" column
```

> [!TIP]
> The dot-notation path works like: `"<row_index>.<column_name>"`. So `"0.name"` means "the `name` column of the first row (index 0)".

### Full Example — Offline User Manager

```python
from apkpy_lib import Screen, button, label, input_field, run, toast, db, json_get

# Create the table once on startup
db.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)")

my_screen = Screen(id="main_container")

nome_input  = input_field("Enter a name", id="input_nome", screen=my_screen)
lbl_total   = label("Total users: 0", id="lbl_total", screen=my_screen)
lbl_last    = label("Last added: --", id="lbl_ultimo", screen=my_screen)

def refresh_ui():
    rows   = db.query("SELECT * FROM users ORDER BY id DESC")
    count  = db.query("SELECT COUNT(*) as total FROM users")
    lbl_last.set_value(f"Last: {json_get(rows, '0.name')}")
    lbl_total.set_value(f"Total users: {json_get(count, '0.total')}")

def add_user():
    name = nome_input.get_value()
    if name != "":
        db.execute(f"INSERT INTO users (name) VALUES ('{name}')")
        toast("User added! ✅")
        nome_input.set_value("")
        refresh_ui()

button("ADD USER", id="btn_add", command=add_user, screen=my_screen)
refresh_ui()

if __name__ == "__main__":
    run(start_screen=my_screen)
```

> [!IMPORTANT]
> Always create your table with `CREATE TABLE IF NOT EXISTS` — this is safe to run every time the app starts and won't overwrite existing data.

---

## 17. HTTPS & Network Requests 🌐

ApkPy gives you a simple, non-blocking HTTP client that works identically in both environments. Connect your app to any REST API on the internet using `https.get()` and `https.post()`.

### How It Works Under the Hood

| Environment | What `https` uses |
| :--- | :--- |
| **Hot Previewer** (your computer) | Python's `urllib.request` running in a **background thread** — the UI never freezes |
| **Android Build** (real device) | Native `HttpURLConnection` running in a Java background thread via `AsyncTask` pattern |

### Importing

```python
from apkpy_lib import https, json_get
```

### The Full API

| Method | Description |
| :--- | :--- |
| `https.get(url, headers={}, on_response=callback)` | Makes a GET request asynchronously |
| `https.post(url, data={}, headers={}, on_response=callback)` | Makes a POST request asynchronously |

The `on_response` callback always receives two arguments:
- `success` — `True` if the HTTP status was 2xx, `False` otherwise.
- `response` — The response body as a plain `String`.

### Basic GET Request

```python
from apkpy_lib import Screen, button, label, run, toast, https, json_get

my_screen = Screen(id="main")
result_lbl = label("Press the button!", id="result", screen=my_screen)

def on_response(success, response):
    if success:
        title = json_get(response, "title")  # Reads the 'title' key from JSON
        result_lbl.set_value(title)
    else:
        toast("Request failed: " + response)

def fetch_data():
    result_lbl.set_value("Loading...")
    https.get("https://jsonplaceholder.typicode.com/todos/1", on_response=on_response)

button("Fetch Data", id="btn", command=fetch_data, screen=my_screen)

if __name__ == "__main__":
    run(start_screen=my_screen)
```

### Using Headers (API Keys & Bearer Tokens)

The `headers` parameter lets you pass any HTTP headers as a Python dictionary. This is how you authenticate with APIs that require tokens or keys:

```python
# Example: Calling an API protected by a Bearer token
def fetch_private_data():
    my_headers = {
        "Authorization": "Bearer YOUR_TOKEN_HERE",
        "Content-Type": "application/json"
    }
    https.get("https://api.example.com/profile", headers=my_headers, on_response=on_response)
```

### POST Request with JSON Body

```python
def send_data():
    payload = {"title": "My Post", "body": "Hello World", "userId": 1}
    headers = {"Content-Type": "application/json"}
    https.post(
        "https://jsonplaceholder.typicode.com/posts",
        data=payload,
        headers=headers,
        on_response=on_post_response
    )
```

### Real-World Example — Weather App

```python
from apkpy_lib import Screen, button, label, inputs, run, toast, https, json_get

API_KEY = "your_openweathermap_api_key"

weather_screen = Screen(id="weather_screen")
city_input = inputs("Enter city...", type="text", id="city_input", screen=weather_screen)
temp_label  = label("-- °C", id="temp", screen=weather_screen)
desc_label  = label("---", id="desc", screen=weather_screen)

def on_weather(success, response):
    if success:
        temp = json_get(response, "main.temp")
        desc = json_get(response, "weather.0.description")
        temp_label.set_value(f"{temp} °C")
        desc_label.set_value(desc.capitalize())
    else:
        toast("Failed to get weather.")

def get_weather():
    city = city_input.get_value()
    if city != "":
        url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={API_KEY}&units=metric"
        https.get(url, on_response=on_weather)

button("GET WEATHER", id="btn_weather", command=get_weather, screen=weather_screen)

if __name__ == "__main__":
    run(start_screen=weather_screen)
```

> [!IMPORTANT]
> The `https` API is **always non-blocking**. Requests always run in a background thread, so your UI will never freeze while waiting for a response. The `on_response` callback is always called safely back on the main UI thread.

> [!TIP]
> Use `json_get()` to read specific fields from API responses without complex JSON parsing. The dot-notation supports nested objects (`"main.temp"`) and list indices (`"weather.0.description"`).

---

## 🤝 Community & Support

**Found a bug?** [Open an issue on GitHub!](https://github.com/apkpy-project/repo-apkpy/issues)

**Want to contribute?** We are looking for contributors to expand our Native Component library! Join us in making Python a first-class citizen for Android development.

---

## 📚 Full Documentation

This README covers the core features, but ApkPy has much more to offer. Our full documentation goes deeper into:

- Advanced multi-screen architectures & navigation stacks
- Deploying to the Google Play Store
- Customizing `build.gradle` and `AndroidManifest.xml`
- Using GitHub Actions to build APKs in the cloud (no local SDK needed)
- Full API reference for every component and CSS property

**👉 [View the ApkPy Repository on GitHub](https://github.com/apkpy-project/repo-apkpy)**

---

*Made with ❤️ for the Python Community.*
