# 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) } } } ```