Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
📱 Android App (Kotlin + XML)  ·  Lesson 27

App Release और API Hosting

Go-live plan

Hosting पर databaseबनाएँ + database.sql importBackend uploadpublic_html/karteasyconfig.phpDB details + https BASE_URLCheckapi/ + admin + smoke testApp release URLbuild.gradle.kts में BASE_URLSigned AABGenerate Signed BundlePlay Consolelisting, testing, production
पहले server, फिर app

Step 1: Database बनाएँ

  1. 1hPanel → Databases → MySQL Databases
  2. 2Database name karteasy, user kart, strong password → Create। Hostinger prefix जोड़ता है: u123456789_karteasy, u123456789_kart
  3. 3उस database के लिए Enter phpMyAdmin दबाएँ
  4. 4Import → database.sql चुनें → Go → 14 tables दिखेंगी
Hostinger hPanel (cPanel लगभग वैसा ही है: MySQL Database Wizard)
🔒 hpanel.hostinger.com – MySQL DatabasesDatabase name: u123456789_karteasyUsername: u123456789_kartPassword: ••••••••••••Create✔ Database created · Enter phpMyAdmin →

Step 2: Backend upload करें

  1. 1hPanel → File Manager → public_html
  2. 2karteasy folder बनाएँ
  3. 3backend folder के content की ZIP upload करके Extract दबाएँ (बहुत सारी अलग files से तेज़)
  4. 4Check करें कि .htaccess जैसी hidden files हैं (File Manager → Settings → Show hidden files)
File Manager से upload
📁 public_html/
  📁 karteasy/
    .htaccess
    database.sql      (.htaccess से protected – चाहें तो अब delete कर दें)
    📁 api/  admin/  includes/  uploads/  tests/
Live folder

Step 3: config.php edit करें

File Manager में karteasy/includes/config.php खोलें और default values को अपने database details और domain से बदलें:

PHP – includes/config.php
// includes/config.php on Hostinger (example values – use yours from hPanel)
define('DB_HOST', getenv('KE_DB_HOST') ?: 'localhost');
define('DB_PORT', getenv('KE_DB_PORT') ?: '3306');
define('DB_NAME', getenv('KE_DB_NAME') ?: 'u123456789_karteasy');
define('DB_USER', getenv('KE_DB_USER') ?: 'u123456789_kart');
define('DB_PASS', getenv('KE_DB_PASS') ?: 'Your-Strong-DB-Password');

define('BASE_URL', rtrim(getenv('KE_BASE_URL') ?: 'https://yourdomain.com/karteasy', '/'));
define('DEBUG', getenv('KE_DEBUG') === '1'); // stays false online
🔒 पहले SSL on करें

hPanel → Security → SSL → free certificate install करें और Force HTTPS enable करें। App का release build सिर्फ https से बात करता है।

Step 4: Online check करें

  1. 1https://yourdomain.com/karteasy/api/ खोलें → "database": "connected", "products": 16
  2. 2एक image खोलें: …/karteasy/uploads/products/p7.png
  3. 3…/karteasy/includes/config.php खोलें → 403 Forbidden आना चाहिए
  4. 4…/karteasy/admin/ में login करके admin password बदलें
  5. 5अपने computer से: php tests/smoke-test.php https://yourdomain.com/karteasy
App छूने से पहले पाँच checks
Terminal – pass होने वाला run ऐसा दिखता है (local test)
KartEasy API test → http://127.0.0.1:8200/api/ PASS API is running and DB connected PASS home.php has banners, categories and products PASS products.php search sorted by price PASS unknown product gives 404 PASS cart without token gives 401 PASS register a new customer PASS same email again gives 409 PASS me.php returns the new user PASS add to cart PASS too many gives 409 PASS update quantity to 2 PASS total = subtotal - discount + delivery PASS wishlist toggle on PASS wishlist toggle off PASS bad phone gives 422 PASS save address (first one is default) PASS invalid coupon gives 422 PASS place order PASS cart is empty after the order PASS order detail has items and timeline PASS review before delivery gives 403 PASS cancel order (stock goes back) PASS cancel again gives 409 PASS cannot open another user's order (404) PASS logout PASS old token no longer works 26 passed, 0 failed

Step 5: App को live API पर point करें

सिर्फ release block बदलता है। आख़िरी slash रखें — Retrofit को चाहिए।

Kotlin DSL – app/build.gradle.kts
// app/build.gradle.kts – release block
release {
    buildConfigField("String", "BASE_URL", "\"https://yourdomain.com/karteasy/\"")
    resValue("string", "app_name", "KartEasy")
    isMinifyEnabled = true
    isShrinkResources = true
    …
}

defaultConfig {
    versionCode = 1        // +1 for every Play Store upload
    versionName = "1.0"    // what users see
}

Publish से पहले fragment_login.xml और LoginFragment.kt से Use demo account button हटाएँ, और admin panel में demo shop data को अपने असली products से बदलें।

Step 6: Signing key और release build

Play Store apps signed होनी चाहिए। अपनी upload key एक बार बनाएँ: Android Studio → Build → Generate Signed App Bundle / APK → Android App Bundle → Create new… (.jks file safe रखें)। फिर project में passwords डाले बिना Gradle को use करने दें:

Properties – ~/.gradle/gradle.properties
# ~/.gradle/gradle.properties  (in your user folder – NOT inside the project, never commit it)
KARTEASY_STORE_FILE=/home/you/keys/karteasy-upload.jks
KARTEASY_STORE_PASSWORD=your-store-password
KARTEASY_KEY_ALIAS=upload
KARTEASY_KEY_PASSWORD=your-key-password

app/build.gradle.kts का signingConfigs block (Setup lesson) ये चार values पढ़ता है। Bundle build करें:

Terminal
# Windows: gradlew.bat bundleRelease
./gradlew bundleRelease

# Result:
app/build/outputs/bundle/release/app-release.aab

APK

  • phone पर सीधे install
  • test build share करने के लिए अच्छा
  • Build → Build APK(s)

AAB (App Bundle)

  • Google Play के लिए ज़रूरी
  • Play हर device के लिए छोटे APK बनाता है
  • bundleRelease
.aab को Play Console में upload करें

R8 और ProGuard rules

isMinifyEnabled = true से R8 बिना use का code हटाता है और classes rename करता है — app छोटी और reverse-engineer करने में मुश्किल होती है। पर Gson reflection से field names पढ़ता है, इसलिए model classes को जैसा है वैसा रखना होगा:

ProGuard – app/proguard-rules.pro
# Gson creates the model classes with reflection, so R8 must keep their fields.
-keep class com.codingeasily.karteasy.data.model.** { *; }

# Retrofit + coroutines: keep generic signatures of suspend functions.
-keepattributes Signature, InnerClasses, EnclosingMethod, *Annotation*
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation

# Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-dontwarn okhttp3.internal.platform.**
⚠️ Release build हमेशा test करें

Upload से पहले release build phone पर install करें। Missing keep rule सिर्फ release में खाली lists या zero prices के रूप में दिखता है, debug में कभी नहीं।

Step 7: Google Play पर publish

  1. 1Google Play developer account बनाएँ (एक बार fee) और नई app KartEasy
  2. 2Store listing: short और full description, 512 × 512 icon, 1024 × 500 feature graphic, कम से कम 2 phone screenshots
  3. 3App content: privacy policy URL (आप name, email, phone और address लेते हैं), data safety form, content rating, target audience
  4. 4Testing → Internal testing: .aab upload करें, testers जोड़ें, Play link से install करें
  5. 5नए personal developer accounts को production से पहले असली testers के साथ closed test चलाना होता है — Play Console की checklist follow करें
  6. 6Production → release बनाएँ → वही या नया .aab upload → rollout
AAB से Play Store तक

Android course में इस पर पूरा lesson है: Release on Play Store।

बाद में update करना

बदलावक्या करें
Products, prices, banners, couponsसिर्फ admin panel — app update नहीं
किसी API file में bugठीक की गई PHP file upload करें — हर phone को तुरंत fix मिलता है
नई screen या app bugversionCode + 1, नया .aab, Play Console में नया release
नया API fieldपहले PHP में जोड़ें (पुरानी apps unknown fields ignore करती हैं), फिर app में use करें

Download वाला backend README यही steps दोहराता है:

Markdown – backend/README.md
# KartEasy Backend (PHP + MySQL REST API + Admin Panel)

Backend for the **KartEasy** Android shopping app from the CodingEasily tutorial
(https://codingeasily.in/tutorial/android-ecommerce/).

Works on **PHP 7.2 or newer** (tested on PHP 8.3) and **MySQL 5.7+ / MariaDB 10.3+**.
No Composer, no framework: upload and it runs on any shared hosting (Hostinger, cPanel, XAMPP).

## Folder structure

```
karteasy/
├── .htaccess            passes the Authorization header, hides database.sql
├── database.sql         tables + sample data (16 products, 6 categories, 3 banners, 2 coupons)
├── includes/            config, DB connection, helpers (blocked from the browser)
├── api/                 JSON endpoints used by the app
│   ├── home.php categories.php banners.php products.php product.php
│   ├── auth/      register login logout me update
│   ├── cart/      list add update remove
│   ├── wishlist/  list toggle
│   ├── address/   list save delete
│   ├── coupons/   list apply
│   ├── orders/    place list detail cancel
│   └── reviews/   list add
├── admin/               admin panel (login, dashboard, orders, products, categories, banners, coupons, customers)
├── uploads/             product / category / banner images (PHP execution disabled)
└── tests/smoke-test.php  26 automatic API checks (run from the command line)
```

## Install on Hostinger (or any cPanel hosting)

1. **Create a database**: hPanel → Databases → MySQL Databases. Note the database name, user and password.
2. **Import tables**: open phpMyAdmin for that database → Import → choose `database.sql` → Go.
3. **Upload files**: File Manager → `public_html` → create folder `karteasy` → upload everything from this folder into it.
4. **Edit `includes/config.php`**: set `DB_NAME`, `DB_USER`, `DB_PASS` and `BASE_URL`
   (for example `https://yourdomain.com/karteasy`).
5. **Test**: open `https://yourdomain.com/karteasy/api/` → you should see `"database":"connected"`.
6. **Admin panel**: `https://yourdomain.com/karteasy/admin/`
   login `admin@karteasy.in` / `Admin@123` → **change this password** (see below).

Demo customer for the app: `test@karteasy.in` / `Test@123`.

### Change the admin password

Run this once in a PHP file or `php -r`, then put the output in phpMyAdmin → `admins.password_hash`:

```php
<?php echo password_hash('YourNewStrongPassword', PASSWORD_DEFAULT);
```

## Run locally (XAMPP / PHP built-in server)

```bash
mysql -u root -p -e "CREATE DATABASE karteasy CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
mysql -u root -p karteasy < database.sql
# edit includes/config.php (DB_USER=root, BASE_URL=http://10.0.2.2:8000) then:
php -S 0.0.0.0:8000
```

The Android emulator reaches your computer at `http://10.0.2.2:8000/`.
A real phone on the same Wi-Fi uses your computer's IP, e.g. `http://192.168.1.5:8000/`.

## Test the API

```bash
php tests/smoke-test.php http://localhost:8000
php tests/smoke-test.php https://yourdomain.com/karteasy
```

It registers a fresh test customer and runs a full flow (cart, wishlist, address, order, cancel, logout).
You should see `26 passed, 0 failed`.

## Response format

Every endpoint returns the same JSON shape:

```json
{ "success": true, "message": "Added to cart.", "data": { ... } }
```

Errors use a proper HTTP status (401 not logged in, 404 not found, 409 conflict such as stock,
422 validation) with `"success": false` and a readable `message`.

## Authentication

`auth/login.php` and `auth/register.php` return a 64-character `token`.
Send it on every protected request:

```
Authorization: Bearer <token>
```

Only the SHA-256 hash of the token is stored in `user_tokens`, tokens expire after 30 days,
and `auth/logout.php` deletes it.

## Security checklist (already done)

- Prepared statements everywhere (no SQL injection), whitelisted sort columns
- `password_hash()` / `password_verify()` for passwords
- Prices, coupons and totals are always calculated on the server
- Order placement runs in one transaction with `SELECT ... FOR UPDATE` (no overselling)
- Admin: session login, `session_regenerate_id`, CSRF token on every form, login rate limit,
  `htmlspecialchars` on all output
- Uploads: real image check with `getimagesize`, 2 MB limit, random file names, no PHP in `uploads/`
- `includes/` and `database.sql` cannot be opened from the browser

Before going live: use HTTPS, change the admin password, keep `DEBUG` off.

अक्सर पूछे जाने वाले प्रश्न (FAQ)

क्या api.mysite.com जैसा subdomain use कर सकते हैं?
हाँ। hPanel में subdomain बनाएँ, backend files उसके folder में upload करें, और BASE_URL को https://api.mysite.com करें (और app का release BASE_URL https://api.mysite.com/)।
Upload key खो गई — अब क्या?
Play App Signing (default) में असली app signing key Google रखता है। Play Console में upload key reset request कर सकते हैं। फिर भी .jks file और passwords कहीं safe backup रखें।
Release app में images load नहीं होतीं, debug में होती हैं।
Check करें कि config.php का BASE_URL https और सही है — image URLs उसी से बनते हैं। Release में plain http image URLs network security config से block होते हैं।
← E-commerce App Tutorial
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicE-commerce Project Viva Questions आपकी प्रगति: 27 / 28 (96%) · Lesson 28 / 28 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें