# Android App Integration Guide (Kotlin & Retrofit)
This guide provides ready-to-use Kotlin code snippets for integrating your Android wallpaper application with the PHP REST API.
---
## 1. Gradle Dependencies (`build.gradle.kts` / `build.gradle`)
Add the following libraries to your Android app's `dependencies` block:
```kotlin
dependencies {
// Retrofit 2 & Moshi/Gson Converter
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
// Glide for High-Performance Image Loading & Caching
implementation("com.github.bumptech.glide:glide:4.16.0")
annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")
}
```
Ensure internet permission is enabled in `AndroidManifest.xml`:
```xml
```
---
## 2. Kotlin Data Models
```kotlin
package com.example.wallpaperhub.data.model
import com.google.gson.annotations.SerializedName
// Generic API Envelope
data class ApiResponse(
@SerializedName("status") val status: String,
@SerializedName("code") val code: Int,
@SerializedName("message") val message: String,
@SerializedName("pagination") val pagination: PaginationMetadata?,
@SerializedName("data") val data: T
)
// Pagination Metadata
data class PaginationMetadata(
@SerializedName("current_page") val currentPage: Int,
@SerializedName("total_pages") val totalPages: Int,
@SerializedName("limit") val limit: Int,
@SerializedName("total_records") val totalRecords: Int,
@SerializedName("has_next") val hasNext: Boolean
)
// Category Model
data class Category(
@SerializedName("id") val id: Int,
@SerializedName("name") val name: String,
@SerializedName("slug") val slug: String,
@SerializedName("image_url") val imageUrl: String?,
@SerializedName("description") val description: String?,
@SerializedName("wallpaper_count") val wallpaperCount: Int,
@SerializedName("sort_order") val sortOrder: Int
)
// Wallpaper Model
data class Wallpaper(
@SerializedName("id") val id: Int,
@SerializedName("category_id") val categoryId: Int,
@SerializedName("category_name") val categoryName: String,
@SerializedName("category_slug") val categorySlug: String,
@SerializedName("title") val title: String,
@SerializedName("slug") val slug: String,
@SerializedName("image_url") val imageUrl: String,
@SerializedName("thumbnail_url") val thumbnailUrl: String,
@SerializedName("file_size") val fileSize: Long,
@SerializedName("size_formatted") val sizeFormatted: String,
@SerializedName("dimensions") val dimensions: String,
@SerializedName("resolution") val resolution: String,
@SerializedName("aspect_ratio") val aspectRatio: String,
@SerializedName("views") val views: Int,
@SerializedName("downloads") val downloads: Int,
@SerializedName("is_featured") val isFeatured: Boolean,
@SerializedName("is_premium") val isPremium: Boolean,
@SerializedName("tags") val tags: List,
@SerializedName("related_wallpapers") val relatedWallpapers: List?
)
// Slider Model
data class HomeSlider(
@SerializedName("id") val id: Int,
@SerializedName("title") val title: String,
@SerializedName("subtitle") val subtitle: String?,
@SerializedName("image_url") val imageUrl: String,
@SerializedName("link_type") val linkType: String,
@SerializedName("link_id") val linkId: String?
)
// App Settings & Ads Configuration
data class AppSettings(
@SerializedName("app_name") val appName: String,
@SerializedName("privacy_policy_url") val privacyPolicyUrl: String,
@SerializedName("ads") val ads: AdsConfig
)
data class AdsConfig(
@SerializedName("admob_enabled") val admobEnabled: Boolean,
@SerializedName("admob_banner_id") val bannerId: String,
@SerializedName("admob_interstitial_id") val interstitialId: String,
@SerializedName("admob_rewarded_id") val rewardedId: String,
@SerializedName("admob_native_id") val nativeId: String
)
```
---
## 3. Retrofit API Interface (`WallpaperApiService.kt`)
```kotlin
package com.example.wallpaperhub.data.api
import com.example.wallpaperhub.data.model.*
import retrofit2.Response
import retrofit2.http.*
interface WallpaperApiService {
// 1. Fetch Categories
@GET("api/categories.php")
suspend fun getCategories(
@Query("page") page: Int = 1,
@Query("limit") limit: Int = 50,
@Query("sort") sort: String = "order"
): Response>>
// 2. Fetch Wallpapers (Feed, Category filter, Sorting)
@GET("api/wallpapers.php")
suspend fun getWallpapers(
@Query("category_id") categoryId: Int? = null,
@Query("type") type: String? = "latest", // "latest", "popular", "featured", "random"
@Query("tag") tag: String? = null,
@Query("page") page: Int = 1,
@Query("limit") limit: Int = 20
): Response>>
// 3. Fetch Single Wallpaper Details + Related
@GET("api/wallpaper_details.php")
suspend fun getWallpaperDetails(
@Query("id") id: Int
): Response>
// 4. Search Wallpapers
@GET("api/search.php")
suspend fun searchWallpapers(
@Query("q") query: String,
@Query("page") page: Int = 1,
@Query("limit") limit: Int = 20
): Response>>
// 5. Fetch Home Banner Sliders
@GET("api/sliders.php")
suspend fun getSliders(): Response>>
// 6. Increment View Count
@FormUrlEncoded
@POST("api/update_view.php")
suspend fun incrementView(
@Field("wallpaper_id") wallpaperId: Int
): Response>>
// 7. Increment Download Count
@FormUrlEncoded
@POST("api/update_download.php")
suspend fun incrementDownload(
@Field("wallpaper_id") wallpaperId: Int
): Response>>
// 8. Fetch App & Ads Configuration
@GET("api/settings.php")
suspend fun getAppSettings(): Response>
}
```
---
## 4. Retrofit Client Instance (`ApiClient.kt`)
```kotlin
package com.example.wallpaperhub.data.api
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
object ApiClient {
// Replace with your server IP / domain or 10.0.2.2 for Android Studio Emulator
private const val BASE_URL = "http://10.0.2.2/wall/"
private val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
private val okHttpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.build()
val apiService: WallpaperApiService by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(WallpaperApiService::class.java)
}
}
```
---
## 5. Loading Wallpapers with Glide in RecyclerView
```kotlin
// In your RecyclerView Adapter onBindViewHolder:
Glide.with(holder.itemView.context)
.load(wallpaper.thumbnailUrl) // Use fast HD thumbnail for grid
.placeholder(R.drawable.placeholder_wallpaper)
.error(R.drawable.error_image)
.transition(DrawableTransitionOptions.withCrossFade())
.centerCrop()
.into(holder.binding.ivWallpaper)
```
---
## 6. Setting Wallpaper Programmatically on Android
```kotlin
suspend fun setDeviceWallpaper(context: Context, fullImageUrl: String, lockScreenToo: Boolean) {
withContext(Dispatchers.IO) {
val bitmap = Glide.with(context)
.asBitmap()
.load(fullImageUrl) // Original 4K image
.submit()
.get()
val wallpaperManager = WallpaperManager.getInstance(context)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_SYSTEM)
if (lockScreenToo) {
wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_LOCK)
}
} else {
wallpaperManager.setBitmap(bitmap)
}
}
}
```