PHPackages                             wilsonatb/in-app-update - 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. wilsonatb/in-app-update

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

wilsonatb/in-app-update
=======================

Android Google Play Core in-app updates for NativePHP Mobile

1.0.1(1mo ago)19MITKotlinPHP ^8.2

Since Apr 23Pushed 1mo agoCompare

[ Source](https://github.com/wilsonatb/in-app-update)[ Packagist](https://packagist.org/packages/wilsonatb/in-app-update)[ RSS](/packages/wilsonatb-in-app-update/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (2)Versions (3)Used By (0)

InAppUpdate Plugin for NativePHP Mobile
=======================================

[](#inappupdate-plugin-for-nativephp-mobile)

Android-only NativePHP plugin for Google Play In-App Updates. Easily integrate native app updates into your PHP/Livewire or JavaScript frontend with support for both **Flexible** and **Immediate** flows.

[![PHP Version](https://camo.githubusercontent.com/f1a56437585677c70541ee9e539630cd72ed2dfae373fbbce804ec917bf72396/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f77696c736f6e6174622f696e2d6170702d7570646174652e7376673f636f6c6f723d626c7565)](https://packagist.org/packages/wilsonatb/in-app-update)[![Downloads](https://camo.githubusercontent.com/f61aeac8becc6794428c4a6aaf47ee93bb9a8e874316a022ed3eb559d8950c83/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f77696c736f6e6174622f696e2d6170702d7570646174652e7376673f636f6c6f723d726564)](https://packagist.org/packages/wilsonatb/in-app-update)[![License](https://camo.githubusercontent.com/db117dc1a38bba9760a9af7a93f05555bd096a371475bd2bf4e1ebcc1eab23b8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f77696c736f6e6174622f696e2d6170702d7570646174652e7376673f636f6c6f723d677265656e)](https://camo.githubusercontent.com/db117dc1a38bba9760a9af7a93f05555bd096a371475bd2bf4e1ebcc1eab23b8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f77696c736f6e6174622f696e2d6170702d7570646174652e7376673f636f6c6f723d677265656e)

 [![InAppUpdate Plugin Screenshot](https://private-user-images.githubusercontent.com/55840381/582909578-5923e8a9-8a16-464b-80ad-8dd1d9b90fb6.jpg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODAxMjkzOTUsIm5iZiI6MTc4MDEyOTA5NSwicGF0aCI6Ii81NTg0MDM4MS81ODI5MDk1NzgtNTkyM2U4YTktOGExNi00NjRiLTgwYWQtOGRkMWQ5YjkwZmI2LmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjA1MzAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwNTMwVDA4MTgxNVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWE0YTcxZTNlZTA0OGNjYjAzNWNlYmU1ZmFiN2QyNTA5NjU5MTFkMWVlZjVkMTNmMzVkM2QwYWQwMGM1YmQwMDgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JnJlc3BvbnNlLWNvbnRlbnQtdHlwZT1pbWFnZSUyRmpwZWcifQ.au4y4mGRKRuulXqa0Qb3-7ZjDC3pfcGpl00iO4WZWyc)](https://private-user-images.githubusercontent.com/55840381/582909578-5923e8a9-8a16-464b-80ad-8dd1d9b90fb6.jpg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODAxMjkzOTUsIm5iZiI6MTc4MDEyOTA5NSwicGF0aCI6Ii81NTg0MDM4MS81ODI5MDk1NzgtNTkyM2U4YTktOGExNi00NjRiLTgwYWQtOGRkMWQ5YjkwZmI2LmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjA1MzAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwNTMwVDA4MTgxNVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWE0YTcxZTNlZTA0OGNjYjAzNWNlYmU1ZmFiN2QyNTA5NjU5MTFkMWVlZjVkMTNmMzVkM2QwYWQwMGM1YmQwMDgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JnJlc3BvbnNlLWNvbnRlbnQtdHlwZT1pbWFnZSUyRmpwZWcifQ.au4y4mGRKRuulXqa0Qb3-7ZjDC3pfcGpl00iO4WZWyc)

Understanding Update Flows
--------------------------

[](#understanding-update-flows)

Google Play offers two ways to handle in-app updates. This plugin supports both:

- **Flexible:** The user can continue using the app while the update downloads in the background. Once downloaded, you prompt the user to install it.
- **Immediate:** A fullscreen blocking UI. The user must update and restart the app to continue using it.

---

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

[](#installation)

```
# 1. Install the package
composer require wilsonatb/in-app-update

# 2. Publish the plugins provider (first time only)
php artisan vendor:publish --tag=nativephp-plugins-provider

# 3. Register the plugin
php artisan native:plugin:register wilsonatb/in-app-update
```

### Platform Support

[](#platform-support)

PlatformSupportNotes**Android**✅ SupportedUses Google Play Core**iOS**❌ Not supportedReturns a controlled skipped response (`supported: false`) to prevent crashes.---

How It Works (The Recommended Flow)
-----------------------------------

[](#how-it-works-the-recommended-flow)

Whether you use PHP or JavaScript, the mental model for a successful update attempt is the same:

1. **Generate an ID:** Create one UUID (`id`) per update attempt.
2. **Listen to Events:** Register listeners for `InAppUpdateStateChanged` and `InAppUpdateFlowCompleted`.
3. **Check Availability:** Call `checkForUpdate(...)`.
4. **Start the Update:** If available, call `startImmediateUpdate(...)` or `startFlexibleUpdate(...)`.
5. **Complete (Flexible only):** When the `installStatus` changes to `downloaded`, call `completeFlexibleUpdate(...)` to apply it.

---

Usage Examples
--------------

[](#usage-examples)

### PHP / Livewire

[](#php--livewire)

This example demonstrates how to handle the async events triggered by the update flow using NativePHP's #\[OnNative\] attributes.

```
use Native\Mobile\Attributes\OnNative;
use Wilsonatb\InAppUpdate\Events\InAppUpdateFlowCompleted;
use Wilsonatb\InAppUpdate\Events\InAppUpdateStateChanged;
use Wilsonatb\InAppUpdate\Facades\InAppUpdate;

public ?string $updateFlowId = null;

public function checkUpdate(): void
{
    $this->updateFlowId = (string) str()->uuid();

    $result = InAppUpdate::checkForUpdate(
        preferredType: 'any', // flexible | immediate | any
        id: $this->updateFlowId,
    );

    // iOS-safe response: plugin gracefully skips execution
    if (($result->supported ?? true) === false) {
        return;
    }
}

#[OnNative(InAppUpdateStateChanged::class)]
public function onInAppUpdateStateChanged(
    string $status,
    ?string $updateType = null,
    ?string $id = null,
    ?string $installStatus = null,
    ?bool $isUpdateAvailable = null,
): void {
    // Ensure we are responding to the current flow
    if ($id !== $this->updateFlowId) {
        return;
    }

    if ($status === 'availability_checked' && $isUpdateAvailable) {
        InAppUpdate::startFlexibleUpdate(id: $id);
    }

    if (in_array($installStatus, ['downloaded'], true)) {
        InAppUpdate::completeFlexibleUpdate(id: $id);
    }
}

#[OnNative(InAppUpdateFlowCompleted::class)]
public function onInAppUpdateFlowCompleted(
    string $result,
    string $updateType,
    ?string $id = null,
): void {
    // Handle final results: installed | downloaded | canceled | failed
}
```

### JavaScript (Vue / React / Inertia)

[](#javascript-vue--react--inertia)

```
import { InAppUpdate, Events } from '@wilsonatb/in-app-update';
import { on, off } from '@nativephp/native';

const id = crypto.randomUUID();

const onState = (payload) => console.log('State changed:', payload);
const onFlowCompleted = (payload) => console.log('Flow completed:', payload);

// Register listeners
on(Events.InAppUpdateStateChanged, onState);
on(Events.InAppUpdateFlowCompleted, onFlowCompleted);

// Check for update
const check = await InAppUpdate.checkForUpdate({ preferredType: 'any', id });

if (!check?.supported) {
    console.log('Skipped: InAppUpdate not supported on iOS', check);
} else if (check?.isUpdateAvailable) {
    await InAppUpdate.startFlexibleUpdate({ id });
}

// Complete if already downloaded
const latestStatus = await InAppUpdate.getInstallStatus();
if (latestStatus?.installStatus === 'downloaded') {
    await InAppUpdate.completeFlexibleUpdate({ id });
}

// Remember to clean up listeners when the component unmounts
off(Events.InAppUpdateStateChanged, onState);
off(Events.InAppUpdateFlowCompleted, onFlowCompleted);
```

---

API Reference
-------------

[](#api-reference)

> **Note:** Always pass the same `id` across all method calls and event checks for a single update attempt.

### Methods

[](#methods)

MethodParametersWhat it doesReturns (Immediate)`checkForUpdate(...)``preferredType` (flexible|immediate|any, default: `flexible`), `minStalenessDays?` (int), `minPriority?` (int), `id?` (string)Checks availability and allowed update types.`{ status: "checking", ... }``startFlexibleUpdate(...)``allowAssetPackDeletion` (bool, default: `false`), `id?` (string)Starts Play Core flexible flow in the background.`{ status: "starting", updateType: "flexible", ... }``startImmediateUpdate(...)``allowAssetPackDeletion` (bool, default: `false`), `id?` (string)Starts Play Core immediate blocking flow.`{ status: "starting", updateType: "immediate", ... }``completeFlexibleUpdate(...)``id?` (string)Installs a flexible update that has finished downloading.`{ status: "completing", ... }``getInstallStatus()`*None*Returns last known native status snapshot.Last cached status object### Events

[](#events)

- **`InAppUpdateStateChanged`**: Fired for non-terminal lifecycle/progress updates.
    - *Key Payload Fields:* `status`, `updateType`, `id`, `installStatus`, `isUpdateAvailable`, `bytesDownloaded`, `totalBytesToDownload`.
    - *Status Values:* `availability_checked`, `flow_started`, `install_state_changed`, `downloaded_pending_completion`, `developer_triggered_update_in_progress`, `resuming_immediate_update`, `completing_flexible_update`, `resume_check_failed`.
- **`InAppUpdateFlowCompleted`**: Fired when the flow reaches a terminal outcome.
    - *Key Payload Fields:* `result`, `updateType`, `id`, `error`.
    - *Result Values:* `installed`, `downloaded`, `canceled`, `failed`.

---

Testing with Internal App Sharing
---------------------------------

[](#testing-with-internal-app-sharing)

Testing Android In-App Updates requires specific conditions. Using Google Play's Internal App Sharing is the recommended approach:

1. Install a base build of your app that already includes this plugin on your device.
2. Build a new version with a **higher `versionCode`**.
3. Upload this newer build to Internal App Sharing in the Play Console.
4. Open the generated sharing URL on your test device, but **do not click install** on the Play Store page.
5. Open your currently installed app and trigger your update logic.

### ⚠️ Common Troubleshooting

[](#️-common-troubleshooting)

- The Google account on the test device **must** have installed the app from Google Play at least once previously.
- Both the installed build and the uploaded build must share the **exact same `applicationId` and signing key**.
- `inAppUpdatePriority` constraints do not work during Internal App Sharing tests.

---

Requirements &amp; Support
--------------------------

[](#requirements--support)

- **Permissions:** No additional Android permissions are required.
- **Dependencies:** Plugin automatically includes `com.google.android.play:app-update:2.1.0` and `com.google.android.play:app-update-ktx:2.1.0`.

For issues, questions, or feature requests:

- **GitHub Issues:** [Open an issue](https://github.com/wilsonatb/in-app-update/issues)
- **Email:**

License
-------

[](#license)

MIT

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance90

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 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.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

47d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5f3a2ba30173b1230d9768f931bd8dd2afcbbec87cd9eed8586968d2fed0aedf?d=identicon)[wilsonatb](/maintainers/wilsonatb)

---

Top Contributors

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

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/wilsonatb-in-app-update/health.svg)

```
[![Health](https://phpackages.com/badges/wilsonatb-in-app-update/health.svg)](https://phpackages.com/packages/wilsonatb-in-app-update)
```

PHPackages © 2026

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