Skip to content

S2BR/nativephp-mobile-icon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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 & 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.


Requirements

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

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

Capability iOS Android
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

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:

Use Size Transparency
iOS primary (default.ios) 1024×1024 PNG Opaque — Apple rejects transparent app icons
iOS dark / tinted appearance 1024×1024 PNG Transparency expected
Android adaptive foreground 1024×1024 PNG Transparency expected (keep art in the centre safe zone)
Alternate variants 1024×1024 PNG Match the platform's primary rule

Any 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

Everything lives in config/mobile-icon.php.

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_appearance' => [
    'light' => 'resources/icons/app-light.png',
    'dark' => 'resources/icons/app-dark.png',
    'tinted' => 'resources/icons/app-tinted.png',
],

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

'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' => [
    ['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

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

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

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 <activity-alias>, 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 — icons can't work that way.


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 <activity-alias>), and embeds the schedule for on-launch resolution.
  • Runtime bridge functions apply a variant via setAlternateIconName (iOS) / PackageManager alias toggling (Android).

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

composer install
composer test

Credits

License

MIT.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors