Advanced Configuration
On this page
#Secrets & Environment Variables
Plugins that require API keys, tokens, or other sensitive configuration can declare required environment variables using
the secrets field. NativePHP validates these before building.
{ "secrets": { "MAPBOX_DOWNLOADS_TOKEN": { "description": "Mapbox SDK download token from mapbox.com/account/access-tokens", "required": true }, "FIREBASE_API_KEY": { "description": "Firebase project API key", "required": false } }}
Each secret has:
- description — Instructions for obtaining the value
- required — Whether the build should fail if missing (default:
true)
#Using Secrets
Reference secrets anywhere in your manifest using ${ENV_VAR} syntax:
{ "android": { "repositories": [ { "url": "https://api.mapbox.com/downloads/v2/releases/maven", "credentials": { "password": "${MAPBOX_DOWNLOADS_TOKEN}" } } ] }}
Placeholders are substituted at build time. If a required secret is missing, the build fails with a helpful message
telling users exactly which variables to set in their .env file.
#Android Manifest Components
Plugins can register Android components (Activities, Services, Receivers, Providers) that get merged into the app's
AndroidManifest.xml:
{ "android": { "activities": [ { "name": ".MyPluginActivity", "theme": "style=""/Theme.AppCompat.Light.NoActionBar", "exported": false, "configChanges": "orientation|screenSize" } ], "services": [ { "name": ".BackgroundSyncService", "exported": false, "foregroundServiceType": "dataSync" } ], "receivers": [ { "name": ".BootReceiver", "exported": true, "intent-filters": [ { "action": "android.intent.action.BOOT_COMPLETED", "category": "android.intent.category.DEFAULT" } ] } ], "providers": [ { "name": ".MyContentProvider", "authorities": "${applicationId}.myplugin.provider", "exported": false, "grantUriPermissions": true } ] }}
#Component Names
Names starting with . are relative to your plugin's package. For example, if your plugin uses the package
com.nativephp.plugins.mlplugin, then .MyActivity becomes com.nativephp.plugins.mlplugin.MyActivity.
Use fully qualified names for components outside your plugin's package.
#Activity Attributes
| Attribute | Description |
|---|---|
name |
Component class name (required) |
theme |
Activity theme resource |
exported |
Whether other apps can start this activity |
configChanges |
Configuration changes the activity handles itself |
launchMode |
Launch mode (standard, singleTop, singleTask, singleInstance) |
screenOrientation |
Orientation lock (portrait, landscape, etc.) |
intent-filters |
Array of intent filter configurations |
#Service Attributes
| Attribute | Description |
|---|---|
name |
Component class name (required) |
exported |
Whether other apps can bind to this service |
permission |
Permission required to access the service |
foregroundServiceType |
Type for foreground services (camera, microphone, location, etc.). Supports array format for multiple types. |
#Android Features
Declare hardware or software features your plugin requires using the features array. These are added as
<uses-feature> elements in AndroidManifest.xml:
{ "android": { "features": [ {"name": "android.hardware.camera", "required": true}, {"name": "android.hardware.camera.autofocus", "required": false}, {"name": "android.hardware.bluetooth_le", "required": true} ] }}
Each feature has:
- name — The feature name (e.g.,
android.hardware.camera) - required — Whether the app requires this feature (default:
true)
Setting required: false allows your app to be installed on devices without the feature, but you must check
for availability at runtime.
#Android Meta-Data
Add application-level <meta-data> elements for SDK configuration:
{ "android": { "meta_data": [ { "name": "com.google.android.geo.API_KEY", "value": "${GOOGLE_MAPS_API_KEY}" }, { "name": "com.google.firebase.messaging.default_notification_icon", "value": "@drawable/ic_notification" } ] }}
Each entry has:
- name — The meta-data key
- value — The value (supports
${ENV_VAR}placeholders)
#Declarative Assets
Copy static files to the native projects using the assets field. This is simpler than writing a copy_assets hook for
basic file copying:
{ "assets": { "android": { "models/detector.tflite": "assets/ml/detector.tflite", "config/settings.xml": "res/raw/plugin_settings.xml" }, "ios": { "models/detector.mlmodel": "Resources/ml/detector.mlmodel", "config/settings.plist": "Resources/plugin_settings.plist" } }}
The format is "source": "destination":
- source — Relative path from your plugin's
resources/directory - destination — Where to place the file in the native project
#Android Destinations
assets/...— App assets (accessible viaAssetManager)res/raw/...— Raw resources (accessible viaR.raw.*)res/drawable/...— Drawable resources
#iOS Destinations
Resources/...— Bundle resources
#Placeholder Substitution
Text-based assets (XML, JSON, plist, etc.) support ${ENV_VAR} placeholders that are replaced with environment
variable values during the build:
<!-- resources/config/api.xml --><config> <api-key>${MY_PLUGIN_API_KEY}</api-key></config>
#iOS Background Modes
Enable background execution capabilities with the background_modes array. These values are added to
UIBackgroundModes in Info.plist:
{ "ios": { "background_modes": ["audio", "fetch", "processing", "location"] }}
Common values:
audio— Audio playback or recordingfetch— Background fetchprocessing— Background processing taskslocation— Location updatesremote-notification— Push notification processingbluetooth-central— Bluetooth LE central modebluetooth-peripheral— Bluetooth LE peripheral mode
#iOS Entitlements
Configure app entitlements for capabilities like Maps, App Groups, HealthKit, or iCloud:
{ "ios": { "entitlements": { "com.apple.developer.maps": true, "com.apple.security.application-groups": ["group.com.example.shared"], "com.apple.developer.associated-domains": ["applinks:example.com"], "com.apple.developer.healthkit": true } }}
Values can be:
- Boolean —
true/falsefor simple capabilities - Array — For capabilities requiring multiple values (App Groups, Associated Domains)
- String — For single-value entitlements
Entitlements are written to NativePHP.entitlements. If the file doesn't exist, it's created automatically.
#iOS Capabilities
Declare iOS capabilities your plugin requires. These are separate from entitlements and are used for Xcode project configuration:
{ "ios": { "capabilities": ["push-notifications", "background-modes", "healthkit"] }}
#Minimum Platform Versions
Specify minimum platform versions your plugin requires:
{ "android": { "min_version": 33 }, "ios": { "min_version": "18.0" }}
- Android — Minimum SDK version (integer, e.g.,
33for Android 13) - iOS — Minimum iOS version (string, e.g.,
"18.0")
NativePHP currently requires a minimum of Android SDK 33 and iOS 18. Your plugin's minimum versions cannot be lower than these. Use this field when your plugin requires a higher version than NativePHP's baseline.
If a user's app targets a lower version than your plugin requires, they'll receive a warning during plugin validation.
#Initialization Functions
Plugins can specify native functions to call during app initialization. This is useful for SDKs that require early setup before any bridge functions are called:
{ "android": { "init_function": "com.myvendor.plugins.myplugin.MyPluginInit.initialize" }, "ios": { "init_function": "MyPluginInit.initialize" }}
The init function is called once when the app starts, before any bridge functions are available. Use this for:
- SDK initialization that must happen early
- Setting up global state or singletons
- Registering observers or listeners
#Complete Example
Here's a complete manifest for a plugin that integrates Firebase ML Kit with a custom Activity:
{ "namespace": "FirebaseML", "bridge_functions": [ { "name": "FirebaseML.Analyze", "android": "com.nativephp.plugins.firebaseml.AnalyzeFunctions.Analyze", "ios": "FirebaseMLFunctions.Analyze" } ], "events": [ "Vendor\\FirebaseML\\Events\\AnalysisComplete" ], "android": { "permissions": [ "android.permission.CAMERA", "android.permission.INTERNET" ], "features": [ {"name": "android.hardware.camera", "required": true} ], "dependencies": { "implementation": [ "com.google.firebase:firebase-ml-vision:24.1.0", "com.google.firebase:firebase-core:21.1.1" ] }, "activities": [ { "name": ".CameraPreviewActivity", "theme": "style=""/Theme.AppCompat.Light.NoActionBar", "exported": false, "configChanges": "orientation|screenSize|keyboardHidden" } ], "meta_data": [ { "name": "com.google.firebase.ml.vision.DEPENDENCIES", "value": "ocr" } ] }, "ios": { "info_plist": { "NSCameraUsageDescription": "Camera is used for ML analysis" }, "dependencies": { "pods": [ {"name": "Firebase/MLVision", "version": "~> 10.0"}, {"name": "Firebase/Core", "version": "~> 10.0"} ] }, "background_modes": ["processing"], "entitlements": { "com.apple.developer.associated-domains": ["applinks:example.com"] } }, "assets": { "android": { "google-services.json": "google-services.json" }, "ios": { "GoogleService-Info.plist": "Resources/GoogleService-Info.plist" } }, "secrets": { "FIREBASE_API_KEY": { "description": "Firebase API key from Firebase Console", "required": true } }, "hooks": { "pre_compile": "nativephp:firebase-ml:setup" }}
#Official Plugins & Dev Kit
Browse ready-made plugins for common use cases, or get the Plugin Dev Kit to build your own. Visit the NativePHP Plugin Marketplace →