PHPackages                             s2br/nativephp-mobile-icon - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. s2br/nativephp-mobile-icon

ActiveNativephp-plugin[Utility &amp; Helpers](/categories/utility)

s2br/nativephp-mobile-icon
==========================

Per-platform, variant-aware app icons for NativePHP Mobile — light/dark/tinted (iOS), adaptive/themed (Android), and date-scheduled alternate icons.

315↓50%1[1 PRs](https://github.com/S2BR/nativephp-mobile-icon/pulls)PHP

Since Jun 13Pushed 1mo agoCompare

[ Source](https://github.com/S2BR/nativephp-mobile-icon)[ Packagist](https://packagist.org/packages/s2br/nativephp-mobile-icon)[ RSS](/packages/s2br-nativephp-mobile-icon/feed)WikiDiscussions dev Synced 1w ago

READMEChangelogDependenciesVersions (1)Used By (0)

NativePHP Mobile Icon
=====================

[](#nativephp-mobile-icon)

A NativePHP Mobile plugin for **app icons** that goes beyond a single `icon.png`: per-platform primary icons, iOS 18 light/dark/tinted appearances, Android adaptive &amp; themed icons, and named **alternate icons** you can switch on a schedule (Christmas, Black Friday, …) — all driven by one config file.

> ⚠️ **Read this first — app icons are not splash screens.**The home-screen icon is owned by the OS and **baked into the app at build time**. Unlike a splash animation, you **cannot download a new icon and apply it at runtime**. Runtime switching only works among variants you bundled at build time; adding a new one needs a rebuild + app release. See [Platform Constraints](#platform-constraints).

---

Requirements
------------

[](#requirements)

- PHP 8.2+ with **`ext-gd`** (image generation)
- NativePHP Mobile 3.0+
- Minimum platforms: **Android 8 (API 26)**, **iOS 18.0**

---

Installation
------------

[](#installation)

```
composer require s2br/nativephp-mobile-icon
php artisan vendor:publish --tag=mobile-icon-config
php artisan native:plugin:register s2br/nativephp-mobile-icon
```

(`native:plugin:register` wires it into your `NativeServiceProvider`; publish the provider first with `php artisan vendor:publish --tag=nativephp-plugins-provider` if you haven't.)

---

What it does
------------

[](#what-it-does)

CapabilityiOSAndroid**Per-platform primary icon**✅✅**Light / dark / tinted appearances** (iOS 18)✅—**Adaptive icon** (foreground/background)—✅**Themed/monochrome icon** (Android 13+)—✅**Named alternate icons** (bundled)✅✅**Scheduled switching** (date/season)✅\*✅\***Remote/downloadable icons (no rebuild)**❌❌\* among build-time-bundled variants only — see constraints.

---

Where to put your icons
-----------------------

[](#where-to-put-your-icons)

Save your icon files in your **app's** `resources/icons/` directory, and reference them with a path **relative to the project root** (resolved via `base_path()` at build time — the same convention the splashscreen plugin uses for `resources/animations/`):

```
your-app/
└── resources/
    └── icons/                ← create this folder
        ├── app-ios.png
        ├── app-android.png
        └── christmas-ios.png …

```

```
MOBILE_ICON_IOS="resources/icons/app-ios.png"
MOBILE_ICON_ANDROID="resources/icons/app-android.png"
```

**Image requirements:**

UseSizeTransparencyiOS primary (`default.ios`)1024×1024 PNG**Opaque** — Apple rejects transparent app iconsiOS dark / tinted appearance1024×1024 PNGTransparency expectedAndroid adaptive `foreground`1024×1024 PNGTransparency expected (keep art in the centre safe zone)Alternate variants1024×1024 PNGMatch the platform's primary ruleAny location under the project root works, but `resources/icons/` is the recommended spot. A missing file surfaces as a build-time warning from the plugin's `validate()`.

---

Configuration
-------------

[](#configuration)

Everything lives in `config/mobile-icon.php`.

### Primary icon (per platform)

[](#primary-icon-per-platform)

```
'default' => [
    'ios' => 'resources/icons/app-ios.png',       // 1024×1024 PNG, no transparency
    'android' => 'resources/icons/app-android.png',
],
```

### iOS 18 appearances

[](#ios-18-appearances)

```
'ios_appearance' => [
    'light' => 'resources/icons/app-light.png',
    'dark' => 'resources/icons/app-dark.png',
    'tinted' => 'resources/icons/app-tinted.png',
],
```

### Android adaptive / themed

[](#android-adaptive--themed)

```
'android_adaptive' => [
    'foreground' => 'resources/icons/fg.png',
    'background' => '#079F3D',                 // hex color OR a PNG path
    'monochrome' => 'resources/icons/mono.png', // optional, powers themed icons
],
```

### Alternate icon variants

[](#alternate-icon-variants)

```
'variants' => [
    'christmas' => [
        'ios' => 'resources/icons/christmas-ios.png',
        'android' => 'resources/icons/christmas-android.png',
    ],
    'black_friday' => [
        'ios' => 'resources/icons/bf-ios.png',
        'android' => 'resources/icons/bf-android.png',
    ],
],
```

### Schedule

[](#schedule)

```
'schedule' => [
    ['variant' => 'christmas', 'from' => '12-24', 'to' => '12-26'],   // recurs yearly
    ['variant' => 'black_friday', 'from' => '2026-11-27', 'to' => '2026-11-28'], // that year only
],
```

Dates use `MM-DD` (recurs every year) or `YYYY-MM-DD` (specific year); a full-date entry wins over a recurring one — the same rule as the splashscreen plugin.

---

Runtime API
-----------

[](#runtime-api)

```
use S2BR\MobileIcon\Facades\MobileIcon;

MobileIcon::set('christmas'); // switch to a bundled variant
MobileIcon::reset();          // back to the primary icon
MobileIcon::supported();      // is runtime switching available?
MobileIcon::current();        // active variant
```

After applying, native dispatches **`S2BR\MobileIcon\Events\AppIconChanged`** (`variant`, `success`).

```
use Livewire\Attributes\On;

#[On('native:'.\S2BR\MobileIcon\Events\AppIconChanged::class)]
public function onIconChanged(string $variant, bool $success): void {}
```

JS:

```
import { MobileIcon } from './vendor/.../mobileIcon.js';
MobileIcon.set('christmas');
const off = MobileIcon.onChanged(({ variant, success }) => console.log(variant, success));
```

---

App Icon Badge
--------------

[](#app-icon-badge)

Show a notification count on the app icon (the red number).

```
use S2BR\MobileIcon\Facades\MobileIcon;

MobileIcon::setBadge(3);                            // show "3"
MobileIcon::setBadge(3, 'S2BR', '3 new messages');  // custom Android notification text
MobileIcon::setBadge(0);                            // clear
MobileIcon::clearBadge();                           // clear
```

```
MobileIcon.setBadge(3);
MobileIcon.clearBadge();
```

**Platform reality — read this before relying on it:**

- **iOS** sets the exact number via `UNUserNotificationCenter.setBadgeCount`. It requires badge/notification permission (NativePHP's push enrollment requests it). iOS never decrements the badge on its own — call `setBadge()`/`clearBadge()` as the user reads notifications to keep it in sync.
- **Android has no API to put an arbitrary number on the launcher icon.** The badge is driven by a single quiet local notification this plugin posts, so:
    - Supporting launchers (Samsung, Xiaomi, …) show the **count**; stock/Pixel shows a **dot**.
    - It needs the `POST_NOTIFICATIONS` runtime permission on Android 13+ (declared by the plugin; you still request it at runtime).
    - The badge implies a real, silent notification sits in the shade — pass `title`/`body` to make it meaningful. `setBadge(0)`/`clearBadge()` cancels it.

So: **iOS = exact number; Android = a dot, or a count on launchers that support it.**

---

Platform Constraints
--------------------

[](#platform-constraints)

These are **OS limitations**, not plugin shortcomings — know them before designing around dynamic icons:

- **Build-time only.** Every variant must be compiled into the app. There is no way to download and apply a brand-new icon at runtime on either platform.
- **iOS** shows a system alert (“You have changed the icon for …”) on every `setAlternateIconName` call. There is **no App-Store-safe way** to suppress it. Plan your UX around one deliberate switch, not frequent flips.
- **Android** switches by enabling an ``, which typically **restarts the app** and can behave differently per launcher/OEM; pinned shortcuts may not follow.

If you need a splash that updates remotely without an app release, that's the [splashscreen plugin](https://github.com/S2BR/nativephp-mobile-splashscreen) — icons can't work that way.

---

How It Works
------------

[](#how-it-works)

- **`copy_assets`** validates your source PNGs.
- **`pre_compile`** generates per-platform icons with GD, writes the iOS asset catalog / Android adaptive resources, registers alternate icons (iOS `CFBundleAlternateIcons`, Android ``), and embeds the schedule for on-launch resolution.
- **Runtime** bridge functions apply a variant via `setAlternateIconName` (iOS) / `PackageManager` alias toggling (Android).

---

Status &amp; Roadmap
--------------------

[](#status--roadmap)

This is an early, **structurally complete** plugin. Build-time orchestration, the runtime bridge, config, and the GD pipeline are in place; some native write-back seams (Info.plist merge, AndroidManifest alias injection, exact build paths) are marked with `TODO(on-device)` and need verification against a real NativePHP build.

- **MVP:** per-platform icons + iOS appearances + Android adaptive/themed (no runtime jank).
- **Phase 2:** scheduled switching among bundled variants, with the constraints above clearly surfaced.

Contributions and ideas welcome.

---

Running tests
-------------

[](#running-tests)

```
composer install
composer test
```

---

Credits
-------

[](#credits)

- [Israel Pereira](https://github.com/Israel5)

License
-------

[](#license)

MIT.

###  Health Score

23

—

LowBetter than 25% of packages

Maintenance60

Regular maintenance activity

Popularity13

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/292329455?v=4)[S2BR](/maintainers/s2br)[@S2BR](https://github.com/S2BR)

---

Top Contributors

[![Israel5](https://avatars.githubusercontent.com/u/63180786?v=4)](https://github.com/Israel5 "Israel5 (4 commits)")

### Embed Badge

![Health badge](/badges/s2br-nativephp-mobile-icon/health.svg)

```
[![Health](https://phpackages.com/badges/s2br-nativephp-mobile-icon/health.svg)](https://phpackages.com/packages/s2br-nativephp-mobile-icon)
```

###  Alternatives

[pedroborges/kirby-meta-tags

HTML meta tags generator for Kirby 3.

9623.3k2](/packages/pedroborges-kirby-meta-tags)[amasty/module-mage-248-fix

Fix several issues on Magento 2.4.8 version by Amasty

11242.2k](/packages/amasty-module-mage-248-fix)[hunternnm/laravel-roadrunner

Bridge for high-performance PHP application server - RoadRunner

471.2k](/packages/hunternnm-laravel-roadrunner)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
