# **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 ---