Skip to content

Commit c4573ea

Browse files
committed
More updates
1 parent a713a3c commit c4573ea

File tree

7 files changed

+544
-84
lines changed

7 files changed

+544
-84
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
---
2+
title: Advanced Configuration
3+
order: 750
4+
---
5+
6+
## Secrets & Environment Variables
7+
8+
Plugins that require API keys, tokens, or other sensitive configuration can declare required environment variables using
9+
the `secrets` field. NativePHP validates these before building.
10+
11+
```json
12+
{
13+
"secrets": {
14+
"MAPBOX_DOWNLOADS_TOKEN": {
15+
"description": "Mapbox SDK download token from mapbox.com/account/access-tokens",
16+
"required": true
17+
},
18+
"FIREBASE_API_KEY": {
19+
"description": "Firebase project API key",
20+
"required": false
21+
}
22+
}
23+
}
24+
```
25+
26+
Each secret has:
27+
- **description** — Instructions for obtaining the value
28+
- **required** — Whether the build should fail if missing (default: `true`)
29+
30+
### Using Secrets
31+
32+
Reference secrets anywhere in your manifest using `${ENV_VAR}` syntax:
33+
34+
```json
35+
{
36+
"android": {
37+
"repositories": [
38+
{
39+
"url": "https://api.mapbox.com/downloads/v2/releases/maven",
40+
"credentials": {
41+
"password": "${MAPBOX_DOWNLOADS_TOKEN}"
42+
}
43+
}
44+
]
45+
}
46+
}
47+
```
48+
49+
Placeholders are substituted at build time. If a required secret is missing, the build fails with a helpful message
50+
telling users exactly which variables to set in their `.env` file.
51+
52+
## Android Manifest Components
53+
54+
Plugins can register Android components (Activities, Services, Receivers, Providers) that get merged into the app's
55+
`AndroidManifest.xml`:
56+
57+
```json
58+
{
59+
"android": {
60+
"activities": [
61+
{
62+
"name": ".MyPluginActivity",
63+
"theme": "@style/Theme.AppCompat.Light.NoActionBar",
64+
"exported": false,
65+
"configChanges": "orientation|screenSize"
66+
}
67+
],
68+
"services": [
69+
{
70+
"name": ".BackgroundSyncService",
71+
"exported": false,
72+
"foregroundServiceType": "dataSync"
73+
}
74+
],
75+
"receivers": [
76+
{
77+
"name": ".BootReceiver",
78+
"exported": true,
79+
"intent-filters": [
80+
{
81+
"action": "android.intent.action.BOOT_COMPLETED",
82+
"category": "android.intent.category.DEFAULT"
83+
}
84+
]
85+
}
86+
],
87+
"providers": [
88+
{
89+
"name": ".MyContentProvider",
90+
"authorities": "${applicationId}.myplugin.provider",
91+
"exported": false,
92+
"grantUriPermissions": true
93+
}
94+
]
95+
}
96+
}
97+
```
98+
99+
### Component Names
100+
101+
Names starting with `.` are relative to your plugin's package. For example, if your plugin uses the package
102+
`com.nativephp.plugins.mlplugin`, then `.MyActivity` becomes `com.nativephp.plugins.mlplugin.MyActivity`.
103+
104+
Use fully qualified names for components outside your plugin's package.
105+
106+
### Activity Attributes
107+
108+
| Attribute | Description |
109+
|-----------|-------------|
110+
| `name` | Component class name (required) |
111+
| `theme` | Activity theme resource |
112+
| `exported` | Whether other apps can start this activity |
113+
| `configChanges` | Configuration changes the activity handles itself |
114+
| `launchMode` | Launch mode (standard, singleTop, singleTask, singleInstance) |
115+
| `screenOrientation` | Orientation lock (portrait, landscape, etc.) |
116+
| `intent-filters` | Array of intent filter configurations |
117+
118+
### Service Attributes
119+
120+
| Attribute | Description |
121+
|-----------|-------------|
122+
| `name` | Component class name (required) |
123+
| `exported` | Whether other apps can bind to this service |
124+
| `permission` | Permission required to access the service |
125+
| `foregroundServiceType` | Type for foreground services (camera, microphone, location, etc.) |
126+
127+
## Declarative Assets
128+
129+
Copy static files to the native projects using the `assets` field. This is simpler than writing a `copy_assets` hook for
130+
basic file copying:
131+
132+
```json
133+
{
134+
"assets": {
135+
"android": {
136+
"models/detector.tflite": "assets/ml/detector.tflite",
137+
"config/settings.xml": "res/raw/plugin_settings.xml"
138+
},
139+
"ios": {
140+
"models/detector.mlmodel": "Resources/ml/detector.mlmodel",
141+
"config/settings.plist": "Resources/plugin_settings.plist"
142+
}
143+
}
144+
}
145+
```
146+
147+
The format is `"source": "destination"`:
148+
- **source** — Relative path from your plugin's `resources/` directory
149+
- **destination** — Where to place the file in the native project
150+
151+
### Android Destinations
152+
153+
- `assets/...` — App assets (accessible via `AssetManager`)
154+
- `res/raw/...` — Raw resources (accessible via `R.raw.*`)
155+
- `res/drawable/...` — Drawable resources
156+
157+
### iOS Destinations
158+
159+
- `Resources/...` — Bundle resources
160+
161+
### Placeholder Substitution
162+
163+
Text-based assets (XML, JSON, plist, etc.) support `${ENV_VAR}` placeholders that are replaced with environment
164+
variable values during the build:
165+
166+
```xml
167+
<!-- resources/config/api.xml -->
168+
<config>
169+
<api-key>${MY_PLUGIN_API_KEY}</api-key>
170+
</config>
171+
```
172+
173+
<aside>
174+
175+
Use [lifecycle hooks](lifecycle-hooks.md) for complex asset handling like downloading large files, unzipping archives,
176+
or conditional asset placement.
177+
178+
</aside>
179+
180+
## Complete Example
181+
182+
Here's a complete manifest for a plugin that integrates Firebase ML Kit with a custom Activity:
183+
184+
```json
185+
{
186+
"name": "vendor/firebase-ml-plugin",
187+
"namespace": "FirebaseML",
188+
"version": "2.0.0",
189+
"description": "Firebase ML Kit integration for NativePHP",
190+
"bridge_functions": [
191+
{
192+
"name": "FirebaseML.Analyze",
193+
"android": "com.nativephp.plugins.firebaseml.AnalyzeFunctions.Analyze",
194+
"ios": "FirebaseMLFunctions.Analyze"
195+
}
196+
],
197+
"events": [
198+
"Vendor\\FirebaseML\\Events\\AnalysisComplete"
199+
],
200+
"android": {
201+
"permissions": [
202+
"android.permission.CAMERA",
203+
"android.permission.INTERNET"
204+
],
205+
"dependencies": {
206+
"implementation": [
207+
"com.google.firebase:firebase-ml-vision:24.1.0",
208+
"com.google.firebase:firebase-core:21.1.1"
209+
]
210+
},
211+
"activities": [
212+
{
213+
"name": ".CameraPreviewActivity",
214+
"theme": "@style/Theme.AppCompat.Light.NoActionBar",
215+
"exported": false,
216+
"configChanges": "orientation|screenSize|keyboardHidden"
217+
}
218+
]
219+
},
220+
"ios": {
221+
"permissions": {
222+
"NSCameraUsageDescription": "Camera is used for ML analysis"
223+
},
224+
"dependencies": {
225+
"pods": [
226+
{"name": "Firebase/MLVision", "version": "~> 10.0"},
227+
{"name": "Firebase/Core", "version": "~> 10.0"}
228+
]
229+
}
230+
},
231+
"assets": {
232+
"android": {
233+
"google-services.json": "google-services.json"
234+
},
235+
"ios": {
236+
"GoogleService-Info.plist": "Resources/GoogleService-Info.plist"
237+
}
238+
},
239+
"secrets": {
240+
"FIREBASE_API_KEY": {
241+
"description": "Firebase API key from Firebase Console",
242+
"required": true
243+
}
244+
},
245+
"hooks": {
246+
"pre_compile": "nativephp:firebase-ml:setup"
247+
},
248+
"service_provider": "Vendor\\FirebaseML\\FirebaseMLServiceProvider"
249+
}
250+
```

resources/views/docs/mobile/2/plugins/bridge-functions.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ In your `nativephp.json`, declare each function with its platform implementation
2424
{
2525
"name": "MyPlugin.DoSomething",
2626
"ios": "MyPluginFunctions.DoSomething",
27-
"android": "com.vendor.plugin.myplugin.MyPluginFunctions.DoSomething",
27+
"android": "com.myvendor.plugins.myplugin.MyPluginFunctions.DoSomething",
2828
"description": "Does something useful"
2929
}
3030
]
@@ -33,6 +33,12 @@ In your `nativephp.json`, declare each function with its platform implementation
3333

3434
The `name` is what PHP uses. The platform-specific values point to your native class and method.
3535

36+
### Naming Convention
37+
38+
- **`name`** — A unique identifier like `MyPlugin.DoSomething`. This is what PHP code uses.
39+
- **`ios`** — Swift enum/class path: `EnumName.ClassName`
40+
- **`android`** — Full Kotlin class path including your vendor package (e.g., `com.myvendor.plugins.myplugin.ClassName`)
41+
3642
## Swift Implementation (iOS)
3743

3844
Create your functions in `resources/ios/Sources/`:
@@ -64,13 +70,13 @@ Key points:
6470

6571
## Kotlin Implementation (Android)
6672

67-
Create your functions in `resources/android/src/.../`:
73+
Create your functions in `resources/android/src/`. Use your own vendor-namespaced package:
6874

6975
```kotlin
70-
package com.vendor.plugin.myplugin
76+
package com.myvendor.plugins.myplugin
7177

72-
import com.example.androidphp.bridge.BridgeFunction
73-
import com.example.androidphp.bridge.BridgeResponse
78+
import com.nativephp.mobile.bridge.BridgeFunction
79+
import com.nativephp.mobile.bridge.BridgeResponse
7480

7581
object MyPluginFunctions {
7682

@@ -89,13 +95,8 @@ object MyPluginFunctions {
8995
}
9096
```
9197

92-
<aside>
93-
94-
#### Package Naming
95-
96-
Use your plugin's namespace in the Kotlin package name. The scaffolding command sets this up correctly.
97-
98-
</aside>
98+
The package declaration determines where your file is placed during compilation. Using `com.myvendor.plugins.myplugin` ensures
99+
your code is isolated from other plugins and the core NativePHP code.
99100

100101
## Calling from PHP
101102

0 commit comments

Comments
 (0)