# **Chapter 15: Creating a Mobile App with SartajPHP Mobile + Kotlin + Android Studio**
## Creating a Mobile App with SartajPHP Mobile + Kotlin + Android Studio
---
## 15.1 Introduction
SartajPHP Mobile App is not a wrapper, emulator, or hybrid workaround.
It is a **true mobile application architecture** where:
* **UI is written in SartajPHP**
* **JavaScript logic is structured via SJS**
* **Native Android logic is written in Kotlin**
* **Build system is pure Gradle**
* **Android Studio and VS Code share the same project**
This chapter explains how to create a **production-ready Android Mobile App** using:
* SartajPHP MobileGate in PHP Extended With BasicGate
* Kotlin Native bridge
* SartajPHP KotlinGate in Kotlin
* VS Code as the primary IDE
* Android Studio as an optional native editor
No code generation tools.
No CLI wrappers.
No Electron.
No Cordova.
---
## 15.2 Unified Project Philosophy
Unlike traditional frameworks, SartajPHP Mobile App uses **one shared project directory**.
```
project-root/
├─ apps/ (SartajPHP Gate code)
│ ├─ android (Android Files)
│ │ ├─ config.xml (AndroidManifest.xml)
│ │ ├─ MainActivity.kt (Main Activity)
│ │ ├─ build.gradle.kts (Gradle Build File)
│ │ ├─ java/ (Extra Java Files)
│ │ ├─ res/ (Icon Files)
│ │ ├─ cpp/ (C++ Files with CMakeLists.txt)
│ │ ├─ libs (Extra Libraries Files)
│ ├─ IndexGate.php (MobileGate which Convert Web Server Code as Browser Code)
│ ├─ fronts/ (HTML base design in Front Files)
│ ├─ jslib/ (Extra JS Files to run inside WebView on Mobile App)
│ ├─ kotlin_apps/ (Design Gate Classes to handle requests Extend with KotlinGate From SartajPHP Kotlin SDK)
│ └─ sjs/ (Sartaj JS Files, Easy Embed JS Event code to Front File on Server Side)
├─ www/ (Generated web assets)
├─ build/ (Generated Android Gradle Project OR it generate app folder for Android Studio)
│ ├─ app/
│ ├─ settings.gradle.kts
│ ├─ build.gradle.kts
│ └─ gradlew
```
### Key Idea
* **Android Studio creates the project as Empty Activity**
* **SartajPHP fills it**
* **Gradle builds it**
* **VS Code edits everything**
This means:
* Kotlin developers and PHP developers work together
* No duplication of UI logic
* Native APIs are first-class citizens
**SartajPHP Mobile Gate Kotlin Model**
JS call → KotlinGate created → process → destroyed
JS call → KotlinGate created
↓
Access KotlinApi
↓
Get persistent Object
↓
Execute action
↓
Return response
↓
KotlinGate destroyed
✔ Object Store in KotlinApi stays alive
✔ UI remains stateless
✔ Very scalable
---
## 15.3 Creating the Android Project
### Step 1: Create Android Project (Once)
Using **Android Studio**:
* Create an **Empty Activity**
* Language: **Kotlin**
* Minimum SDK: As required
* Project location: `build/`
This step creates:
* Gradle wrapper
* settings.gradle.kts
* AndroidManifest.xml
* app module
After this step, **Android Studio is optional**.
---
## 15.4 Creating SartajPHP Mobile App
Open **VS Code**, then:
```
Ctrl + Shift + P
→ Create SartajPHP Mobile App
```
This creates:
```
apps/
├─ IndexGate.php
├─ fronts/ (Front Files)
│ ├─ index_main.front (Home Page of Mobile App)
│ ├─ page2.front (Other Page)
│ ├─ page3.front (Other Page)
│ └─ toolbar.front (OnSen UI ToolBar to Insert into Pages)
└─ sjs/ (Sartaj JS Files, Name should match with Front files)
├─ index_main.sjs (Home Page SJS File)
├─ page2.sjs (Other Page SJS File)
└─ page3.sjs
```
The Android project remains untouched — SartajPHP **integrates**, it does not replace.
---
## 15.5 The MobileGate Entry Point
The file `apps/IndexGate.php` extends `MobileApp`.
```php
<?php
/**
* Create Android Studio Project with new and empty activity then open same folder in
* VS Code and run "SartajPHP:Create Mobile App" command with ctrl + shift + p.
* Set start.php file settings to
* SartajPHP Framework path
* $sharedpath = "..";
* $respath = "../res";
* $slibversion = "Slib";
* $libversion = "Sphp";
* and run this Gate file Index.php with press F7 command. VS Code will find SphpDesk and try to run SartajPHP project.
* It will generate all necessary files for Android Studio to compile.
* You can open that project in Android Studio and run on emulator or real device.
* It will show a page with button. Click on button to see the alert message from the app.
*/
class Index extends \Sphp\tools\MobileGate{
public function page_new() {
$this->mobappname = "HelloSartajPHP";
// use autoversion
//$this->mobappversion = "1.0.0";
$this->mobappdes = "A sample SartajPHP application that responds to the deviceready event.";
$this->mobappauthor = "SartajPHP Team";
$this->mobappauthoremail = "sartajphp@gmail.com";
$this->mobappauthorweb = "https://sartajphp.com";
// force overwrite existing android project files
//$this->setForceCopyGen();
// disable android studio project generation
//$this->disableAndroidStudio();
$this->minSdkVersion = "25";
$this->targetSdkVersion = "34";
$this->compileSdkVersion = "34";
/*
// add permissions
$this->addAndroidSetting("permission", '<uses-permission android:name="android.permission.INTERNET" />');
// add reciver code
$this->addAndroidSetting("receiver", '<receiver android:name="com.sartajphp.MyReceiver" android:exported="true">
<intent-filter>
<action android:name="com.sartajphp.MY_ACTION" />
</intent-filter>
</receiver>');
// add service code
$this->addAndroidSetting("service", '<service android:name="com.sartajphp.MyService" android:exported="true" />');
// add content provider code
$this->addAndroidSetting("provider", '<provider android:name="com.sartajphp.MyProvider" android:exported="true" />');
// anything extra inside application tag
$this->addAndroidSetting("application", '<provider android:name="com.sartajphp.MyProvider" android:exported="true" />');
// add in android section of build gradle
$this->addAndroidSetting("android", '');
// add in dependencies section of build gradle
$this->addAndroidSetting("dependency", '');
*/
SphpJsM::addBootStrap();
$this->addDistLib($this->phppath . "/jslib/twitter/bootstrap5");
$this->addDistLib($this->phppath . "/jslib/onsen");
$this->addPage(new Sphp\tools\FrontFile($this->mypath . "/fronts/page2.front"));
//$this->addPage(new Sphp\tools\FrontFile($this->mypath . "/fronts/page3.front"));
// servers which access via ajax
$hostlist = "http://domain.com ";
$meta = '<meta http-equiv="Content-Security-Policy" content="default-src \'self\'
data: gap: '. $hostlist .' https://ssl.gstatic.com ;
script-src \'self\' '. $hostlist .' \'unsafe-inline\'
\'unsafe-eval\';style-src \'self\' '. $hostlist .' \'unsafe-inline\';
media-src *; img-src * data: content:; frame-src '. $hostlist .' ;
connect-src \'self\' '. $hostlist .' ;">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
';
$this->setSpecialMetaTag($meta);
}
}
```
### What this does
* Defines app identity
* Injects UI libraries
* Registers pages
* Publishes Android assets automatically
No manual Gradle edits required.
---
## 15.6 Front Files – UI Layer
Front files define **UI components** using HTML-like syntax with server awareness.
### index_main.front
```html
<ons-list id="menu" runat="server" path="comppath/uikitdef/onsen/SideMenu.php">
<ons-list-item onclick="onsen.loadPage('home.html')" tappable>
Home
</ons-list-item>
<ons-list-item onclick="onsen.loadPage('page2.html')" tappable>
Settings
</ons-list-item>
</ons-list>
<ons-page id="home" runat="server" path="comppath/uikitdef/onsen/OnsenPage.php">
<include id="toolbar" runat="server" fun-setFrontFile="apps/fronts/toolbar.front" >toolbar</include>
<ons-page-content style="padding:15px; padding-bottom:80px; background:#f5f6fa;">
<!-- Page content goes here -->
<!-- STATUS CARD -->
<ons-card style="border-radius:15px;">
<div class="title">
<ons-icon icon="md-info-outline"></ons-icon>
System Status
</div>
<div class="content">
<span id="spnstatus">Ready to scan cameras</span>
</div>
</ons-card>
<button id="btn1" class="btn btn-primary">Call Gate:- Index</button>
<!-- Page content ends here -->
</ons-page-content>
<ons-bottom-toolbar modifier="material">
<div style="display:flex; justify-content:space-around; width:100%;">
<ons-toolbar-button onclick="onsen.loadPage('home.html')">
<ons-icon icon="md-home"></ons-icon>
</ons-toolbar-button>
<ons-toolbar-button onclick="callKotlinGateEvent('index','scanCam')">
<ons-icon icon="md-search"></ons-icon>
</ons-toolbar-button>
<ons-toolbar-button onclick="toggleAddForm()">
<ons-icon icon="md-plus"></ons-icon>
</ons-toolbar-button>
</div>
</ons-bottom-toolbar>
</ons-page>
```
Front files:
* Are rendered server-side
* Become static assets for Android
* Bind automatically to SJS
---
## 15.7 Toolbar and Page Reuse
Components can be reused via `<include>`.
```html
<ons-toolbar modifier="material">
<div class="left">
<ons-toolbar-button onclick="menu.open()">
<ons-icon icon="md-menu"></ons-icon>
</ons-toolbar-button>
</div>
<div class="center">
<ons-icon icon="md-videocam"></ons-icon>
App Title
</div>
<div class="right">
<ons-toolbar-button onclick="callKotlinGateEvent('index','scanCam')">
<ons-icon icon="md-refresh"></ons-icon>
</ons-toolbar-button>
</div>
</ons-toolbar>
```
This avoids UI duplication and keeps layouts consistent.
---
## 15.8 SJS – The Heart of SartajPHP Mobile
SJS (Sartaj JavaScript) is **not normal JavaScript files**.
It is:
* Parsed server-side
* Injected context-aware
* Bound automatically to UI components
### Key Rule
> **Only JavaScript code is allowed inside SJS functions**
---
## 15.9 SJS Function Prefix System
SJS behavior is defined entirely by **function name prefixes**.
### `ofjs_` – Browser-Only Event Binding
```js
function ofjs_p3_click(eventer) {
alert("p3 click");
}
```
* Binds click event to element with `id="p3"`
* Runs only on client
* No server call
---
### `ofjs_*_comp_*_init` – Component-Scoped Binding
```js
function ofjs_btnpage3_click_comp_page3_init(eventer) {
onsen.loadPage("home.html");
}
```
* Binds only when component `page3` is active
* Automatically unbound on destroy
* Prevents memory leaks
---
### `jq_` – jQuery + Mobile Events
```js
function jq_deviceready(eventer) {
logMe("device ready");
}
```
Examples:
* `jq_keyevent_global`
* `jq_drag_global`
* `jq_deviceready`
These work without writing any jQuery boilerplate.
---
### `comp_` – Component Lifecycle Hooks
```js
function comp_home_init(eventer) {
logMe("home init");
}
function comp_home_destroy(eventer) {
logMe("home destroyed");
}
```
Mapped directly to Onsen UI lifecycle:
* init
* show
* hide
* destroy
---
### `onjs_` – Client + Server Event
`onjs_` works like `ofjs_`, but also triggers:
* BasicGate server event
* AJAX call
* Optional WebSocket communication
Ideal for:
* SIP calls
* GSM gateway control
* Native device operations
---
## 15.10 Calling Kotlin from JavaScript
```js
Android.ShowToast("Hello from SartajPHP");
callKotlinGate("index", {});
callKotlinGateEvent("index","test","evtp", {});
```
This bridges:
* JavaScript → Kotlin → Native Android
* No WebView hacks
* No reflection abuse
```kotlin
package com.sartajphp.gate
class SipGate : KotlinGate() {
private fun getEngine(): SipEngine {
if(!KotlinApi.isProp("sip.engine")){
val engine = SipEngine()
engine.start()
KotlinApi.addProp("sip.engine", engine)
}
return KotlinApi.getProp("sip.engine") as SipEngine
}
private fun ensureSipPermissions(): Boolean {
val perms = arrayOf(
"android.permission.RECORD_AUDIO"
)
if(!KotlinApi.hasAllPermissions(*perms)){
KotlinApi.requestAllPermissions(*perms)
return false
}
return true
}
override fun page_new() {
if(!ensureSipPermissions()){
JSServer.addJSONHTMLBlock("sipstatus","Permission Required")
JSServer.flush()
return
}
val engine = getEngine()
JSServer.addJSONHTMLBlock("sipstatus","SIP Engine Ready")
JSServer.flush()
}
fun page_event_register(evtp:String){
val engine = getEngine()
val user = data["user"].toString()
val pass = data["pass"].toString()
val domain = data["domain"].toString()
engine.register(user, pass, domain)
JSServer.addJSONHTMLBlock("sipstatus","Registered")
JSServer.flush()
}
}
```
---
## 15.11 Why This Architecture Matters
| Feature | SartajPHP Mobile |
| ----------- | ------------------------ |
| UI | Server-generated |
| JS | Context-aware |
| Native | First-class |
| IDE | VS Code + Android Studio |
| Build | Pure Gradle |
| Performance | Native WebView |
This is **not hybrid** — this is **layered native architecture**.
---
## 15.12 Foundation for Mobile App
With this structure, the Mobile Gate can:
* Use **SJS File for bind UI events to FrontFile HTML Tags**
* Use **KotlinGate for Native Programming**
* Use **KotlinApi for Create and use Object for Long Processing and set and check Gate wide Permissions**
* Use **MobileGate for Generating HTML,css,js and project Files and Configuration**
* Use **FrontFile for Generating HTML,css,js and Components to make easy UI**
* Use **WebSocket for real-time calls to NativeGate**
* Use **AJAX for calls to BasicGate**
* Use **Java Code for any native operations**
* Use **C++ Code for any native operations**
* Use **libs folder to use pre compiled libraries**
No battery-heavy SphpServer required on device that is used for Gate develop for different purposes.
---
## 15.13 How to use C++ Code with SartajPHP MobileApp
C++ code need external compiler tools like cmake. Put all your code inside your project folder
apps/android/cpp folder with cmake and then you need add build settings in apps/android/build.gradle.kts
file:-
```
android {
...
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt" // relative path
version "3.22.1+" // optional - your CMake version
}
}
}
```
Create a cmkae CMakeLists.txt inside apps/android/cpp file:-
```
cmake_minimum_required(VERSION 3.22.1)
project("MyNativeLib")
add_library( # Creates your shared library
native-lib # Name of the .so file → libnative-lib.so
SHARED # Must be SHARED for Android
native-lib.cpp # ← list ALL your .cpp files here
myclass.cpp
)
find_library(log-lib log) # Android logging library
target_link_libraries( # Link libraries your code needs
native-lib
${log-lib}
)
```
and example c++ file:-
```cpp
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapp_MainActivity_stringFromJNI(JNIEnv* env, jobject /* this */) {
std::string hello = "Hello from C++!";
return env->NewStringUTF(hello.c_str());
}
```
and use in kotlin/java
```java
class MainActivity : MainActivityBase() {
external fun stringFromJNI(): String // declare native method
companion object {
init {
System.loadLibrary("native-lib") // matches add_library name
}
}
}
```
## 15.13 Summary
In this chapter, you learned:
* How SartajPHP Mobile Gate integrates with Android Studio
* How Front files define UI
* How SJS binds JavaScript cleanly
* How Kotlin and PHP coexist
* Why this architecture scales for SIP Gateway Apps
---