App Release और API Hosting
Go-live plan
Step 1: Database बनाएँ
- 1hPanel → Databases → MySQL Databases
- 2Database name
karteasy, userkart, strong password → Create। Hostinger prefix जोड़ता है:u123456789_karteasy,u123456789_kart - 3उस database के लिए Enter phpMyAdmin दबाएँ
- 4Import →
database.sqlचुनें → Go → 14 tables दिखेंगी
Step 2: Backend upload करें
- 1hPanel → File Manager →
public_html - 2
karteasyfolder बनाएँ - 3
backendfolder के content की ZIP upload करके Extract दबाएँ (बहुत सारी अलग files से तेज़) - 4Check करें कि
.htaccessजैसी hidden files हैं (File Manager → Settings → Show hidden files)
📁 public_html/ 📁 karteasy/ .htaccess database.sql (.htaccess से protected – चाहें तो अब delete कर दें) 📁 api/ admin/ includes/ uploads/ tests/
Step 3: config.php edit करें
File Manager में karteasy/includes/config.php खोलें और default values को अपने database details और domain से बदलें:
// 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 onlinehPanel → Security → SSL → free certificate install करें और Force HTTPS enable करें। App का release build सिर्फ https से बात करता है।
Step 4: Online check करें
- 1
https://yourdomain.com/karteasy/api/खोलें →"database": "connected","products": 16 - 2एक image खोलें:
…/karteasy/uploads/products/p7.png - 3
…/karteasy/includes/config.phpखोलें → 403 Forbidden आना चाहिए - 4
…/karteasy/admin/में login करके admin password बदलें - 5अपने computer से:
php tests/smoke-test.php https://yourdomain.com/karteasy
Step 5: App को live API पर point करें
सिर्फ release block बदलता है। आख़िरी slash रखें — Retrofit को चाहिए।
// 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 करने दें:
# ~/.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 करें:
# 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
R8 और ProGuard rules
isMinifyEnabled = true से R8 बिना use का code हटाता है और classes rename करता है — app छोटी और reverse-engineer करने में मुश्किल होती है। पर Gson reflection से field names पढ़ता है, इसलिए model classes को जैसा है वैसा रखना होगा:
# 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.**Upload से पहले release build phone पर install करें। Missing keep rule सिर्फ release में खाली lists या zero prices के रूप में दिखता है, debug में कभी नहीं।
Step 7: Google Play पर publish
- 1Google Play developer account बनाएँ (एक बार fee) और नई app KartEasy
- 2Store listing: short और full description, 512 × 512 icon, 1024 × 500 feature graphic, कम से कम 2 phone screenshots
- 3App content: privacy policy URL (आप name, email, phone और address लेते हैं), data safety form, content rating, target audience
- 4Testing → Internal testing: .aab upload करें, testers जोड़ें, Play link से install करें
- 5नए personal developer accounts को production से पहले असली testers के साथ closed test चलाना होता है — Play Console की checklist follow करें
- 6Production → release बनाएँ → वही या नया .aab upload → rollout
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 bug | versionCode + 1, नया .aab, Play Console में नया release |
| नया API field | पहले PHP में जोड़ें (पुरानी apps unknown fields ignore करती हैं), फिर app में use करें |
Download वाला backend README यही steps दोहराता है:
# 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.