commit 2b9c7cf2570857e05b543732344116b9ba2d2c5c Author: litingting Date: Tue Apr 16 18:19:58 2024 +0800 V1.0.0(1) 无Ad版本 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2bfca55 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +.idea/ +app/release/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/LiveWallpaper.jks b/app/LiveWallpaper.jks new file mode 100644 index 0000000..8811adb Binary files /dev/null and b/app/LiveWallpaper.jks differ diff --git a/app/SignInfo b/app/SignInfo new file mode 100644 index 0000000..42749bf --- /dev/null +++ b/app/SignInfo @@ -0,0 +1,3 @@ +签名文件:LiveWallpaper.jks +别名:LiveWallpaperkey0 +密码:LiveWallpaper \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..62449b6 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,90 @@ +import java.util.Date +import java.text.SimpleDateFormat +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") +} +val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date()) +android { + namespace = "com.live.wallpaper.style.hd" + compileSdk = 34 + + defaultConfig { + applicationId = "com.live.wallpaper.style.hd" + minSdk = 23 + targetSdk = 34 + versionCode = 1 + versionName = "1.0.0" + setProperty("archivesBaseName", "Live Wallpaper_V" + versionName + "(${versionCode})_$timestamp") + testInstrumentationRunner = "androidx.hd.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + compose = true + viewBinding = true + buildConfig = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.3" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.9.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") + implementation("androidx.activity:activity-compose:1.8.2") + + implementation(libs.core.ktx) + implementation(libs.appcompat) + implementation(libs.material) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.test.ext.junit) + androidTestImplementation(libs.espresso.core) + + // MultiDexApplication + implementation(libs.androidx.multidex) + //Glide + implementation(libs.glide) + // viewModel + implementation(libs.lifecycle.viewmodel.ktx) + //viewModel初始化用 + implementation(libs.activity.ktx) + implementation(libs.fragment.ktx) + // RxBinding + implementation(libs.jakewharton.rxbinding4) + // smart refresh layout + implementation(libs.smart.refresh.kernel) + implementation(libs.smart.refresh.material.header) + implementation(libs.smart.refresh.classics.footer) + + implementation(libs.okhttp3.okhttp) + implementation(libs.commons.codec) + // progress bar + implementation(libs.com.akexorcist.progress.bar) + +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..95c77c7 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,33 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile +-keep class com.live.wallpaper.style.hd.bean.WallpaperImage { *; } +-keep class com.live.wallpaper.style.hd.bean.WallpaperImageListBean { *; } + +-dontwarn org.bouncycastle.jsse.BCSSLParameters +-dontwarn org.bouncycastle.jsse.BCSSLSocket +-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider +-dontwarn org.conscrypt.Conscrypt$Version +-dontwarn org.conscrypt.Conscrypt +-dontwarn org.conscrypt.ConscryptHostnameVerifier +-dontwarn org.openjsse.javax.net.ssl.SSLParameters +-dontwarn org.openjsse.javax.net.ssl.SSLSocket +-dontwarn org.openjsse.net.ssl.OpenJSSE \ No newline at end of file diff --git a/app/src/androidTest/java/com/live/wallpaper/style/hd/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/live/wallpaper/style/hd/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..4796e79 --- /dev/null +++ b/app/src/androidTest/java/com/live/wallpaper/style/hd/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.live.wallpaper.style.hd + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented hd, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under hd. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.live.wallpaper.style.hd", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0675f8a --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/live.json b/app/src/main/assets/live.json new file mode 100644 index 0000000..5f344b1 --- /dev/null +++ b/app/src/main/assets/live.json @@ -0,0 +1,1441 @@ +[{ + "title": "Yi_47", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191025/081307933210.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191025/024922917360.mp4", + "is_free": 1, + "category": 1, + "id": 957, + "cnt_like": 722346 +}, { + "title": "PitPig", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191122/034317827606.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191122/034318147323.mp4", + "is_free": 1, + "category": 1, + "id": 928, + "cnt_like": 722315 +}, { + "title": "RockImpactSeawater", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191119/023540414066.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191119/023540763132.mp4", + "is_free": 1, + "category": 13, + "id": 994, + "cnt_like": 722383 +}, { + "title": "Spongebob", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201224/104107541700.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201224/104108100135.mp4", + "is_free": 1, + "category": 1, + "id": 13536, + "cnt_like": 282565 +}, { + "title": "emoji", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200806/020311364184.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200806/020311595329.mp4", + "is_free": 1, + "category": 391, + "id": 10464, + "cnt_like": 481601 +}, { + "title": "AbstractArtPainting", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/121502686267.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/121503038393.mp4", + "is_free": 1, + "category": 1, + "id": 977, + "cnt_like": 722365 +}, { + "title": "Dropwater67", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201129/140138840907.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201129/140139102992.mp4", + "is_free": 1, + "category": 1, + "id": 11235, + "cnt_like": 316064 +}, { + "title": "cool", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200803/105544976103.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200803/105545206847.mp4", + "is_free": 1, + "category": 402, + "id": 10338, + "cnt_like": 485267 +}, { + "title": "Yi_60", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191029/041510289828.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191029/041510573099.mp4", + "is_free": 1, + "category": 15, + "id": 838, + "cnt_like": 722224 +}, { + "title": "Yi_76", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191029/090929370585.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191029/090929655608.mp4", + "is_free": 1, + "category": 4, + "id": 848, + "cnt_like": 722237 +}, { + "title": "dffd0c9e790a7895b0850195643eebe3.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/dffd0c9e790a7895b0850195643eebe3.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/dffd0c9e790a7895b0850195643eebe3.mp4", + "is_free": 1, + "category": 55702, + "id": 425, + "cnt_like": 98476 +}, { + "title": "1364480e863515784dc449cd064cd541.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/1364480e863515784dc449cd064cd541.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/1364480e863515784dc449cd064cd541.mp4", + "is_free": 1, + "category": 57135, + "id": 36, + "cnt_like": 94169 +}, { + "title": "emoji", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200806/020133523751.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200806/020133794779.mp4", + "is_free": 1, + "category": 391, + "id": 10462, + "cnt_like": 481601 +}, { + "title": "kpop", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210114/104925125240.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210114/104925288791.mp4", + "is_free": 1, + "category": 391, + "id": 23620, + "cnt_like": 262393 +}, { + "title": "MOV_2020", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191017/091737901782.JPG", + "preview": "http://d.c-launcher.com/wallpaper_video/20191023/041301491837.mp4", + "is_free": 1, + "category": 5, + "id": 775, + "cnt_like": 722160 +}, { + "title": "nature", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200409/145108878318.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200409/145109266448.mp4", + "is_free": 1, + "category": 391, + "id": 4834, + "cnt_like": 646565 +}, { + "title": "Special effects lion", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210331/031939783758.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210331/031940030806.mp4", + "is_free": 1, + "category": 371, + "id": 23700, + "cnt_like": 153442 +}, { + "title": "a5df8f05c867ba1f92576c8876456849.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/a5df8f05c867ba1f92576c8876456849.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/a5df8f05c867ba1f92576c8876456849.mp4", + "is_free": 1, + "category": 98157, + "id": 322, + "cnt_like": 23695 +}, { + "title": "fsdaaaa", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200525/101134341095.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200525/101134579459.mp4", + "is_free": 0, + "category": 370, + "id": 5434, + "cnt_like": 581165 +}, { + "title": "Cool", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201111/030844031241.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201111/030844271443.mp4", + "is_free": 1, + "category": 370, + "id": 11158, + "cnt_like": 342512 +}, { + "title": "BlackPanther", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/080257192790.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/080257608604.mp4", + "is_free": 1, + "category": 12, + "id": 868, + "cnt_like": 722256 +}, { + "title": "1df6302e2bd10061efce1dc4413aab1f.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/1df6302e2bd10061efce1dc4413aab1f.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/1df6302e2bd10061efce1dc4413aab1f.mp4", + "is_free": 1, + "category": 35841, + "id": 57, + "cnt_like": 63937 +}, { + "title": "emogi", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201119/062709006638.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201119/062709207912.mp4", + "is_free": 1, + "category": 386, + "id": 11178, + "cnt_like": 330814 +}, { + "title": "42d7e32b020fd8b2ee6ba19aa565ffc1.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/42d7e32b020fd8b2ee6ba19aa565ffc1.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/42d7e32b020fd8b2ee6ba19aa565ffc1.mp4", + "is_free": 1, + "category": 31586, + "id": 120, + "cnt_like": 15544 +}, { + "title": "lan_10", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191017/083614723679.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191029/023550003790.mp4", + "is_free": 1, + "category": 5, + "id": 796, + "cnt_like": 722181 +}, { + "title": "TiredBoy", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191209/091940751109.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191209/091941167919.mp4", + "is_free": 1, + "category": 49, + "id": 892, + "cnt_like": 722278 +}, { + "title": "bd708a4bdcd70f21267787a231fd183d.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/bd708a4bdcd70f21267787a231fd183d.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/bd708a4bdcd70f21267787a231fd183d.mp4", + "is_free": 1, + "category": 40443, + "id": 357, + "cnt_like": 91097 +}, { + "title": "BrownConyLove", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191209/122449290906.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191209/122449694258.mp4", + "is_free": 1, + "category": 49, + "id": 908, + "cnt_like": 722294 +}, { + "title": "Thanksgiving", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201126/033320578343.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201126/033320854443.mp4", + "is_free": 1, + "category": 394, + "id": 11209, + "cnt_like": 320978 +}, { + "title": "Clown", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/082201392486.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/082201741459.mp4", + "is_free": 1, + "category": 12, + "id": 762, + "cnt_like": 722150 +}, { + "title": "None", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201010/025612229386.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201010/025612966610.mp4", + "is_free": 1, + "category": 370, + "id": 10572, + "cnt_like": 388018 +}, { + "title": "rooster", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210518/030338172239.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210518/030338401666.mp4", + "is_free": 1, + "category": 367, + "id": 200003, + "cnt_like": 260659 +}, { + "title": "c69926a9d5cca8b428250d114039324f.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/c69926a9d5cca8b428250d114039324f.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/c69926a9d5cca8b428250d114039324f.mp4", + "is_free": 1, + "category": 87525, + "id": 370, + "cnt_like": 21884 +}, { + "title": "e33ec74ba27e4440763286c7b3a2e1f2.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/e33ec74ba27e4440763286c7b3a2e1f2.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/e33ec74ba27e4440763286c7b3a2e1f2.mp4", + "is_free": 1, + "category": 49031, + "id": 427, + "cnt_like": 88798 +}, { + "title": "FlowerRain04", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200605/101629359621.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200605/101629752869.mp4", + "is_free": 0, + "category": 374, + "id": 5529, + "cnt_like": 565416 +}, { + "title": "black ", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201105/093720327999.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201105/093720565434.mp4", + "is_free": 1, + "category": 367, + "id": 11132, + "cnt_like": 350737 +}, { + "title": "90abb7d0d35a66182b49411ae661c5e2.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/90abb7d0d35a66182b49411ae661c5e2.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/90abb7d0d35a66182b49411ae661c5e2.mp4", + "is_free": 1, + "category": 60923, + "id": 278, + "cnt_like": 6077 +}, { + "title": "1782e67a830fd24cfc633ef9110a067d.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/1782e67a830fd24cfc633ef9110a067d.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/1782e67a830fd24cfc633ef9110a067d.mp4", + "is_free": 1, + "category": 86219, + "id": 47, + "cnt_like": 44378 +}, { + "title": "Lighting2", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200310/093049652032.png", + "preview": "http://d.c-launcher.com/wallpaper_video/20200310/093050047396.mp4", + "is_free": 1, + "category": 367, + "id": 2267, + "cnt_like": 687480 +}, { + "title": "a7e23f8a46ccfee7d92e192de3c01704.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/a7e23f8a46ccfee7d92e192de3c01704.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/a7e23f8a46ccfee7d92e192de3c01704.mp4", + "is_free": 1, + "category": 65788, + "id": 327, + "cnt_like": 47258 +}, { + "title": "Naruto", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210608/022850478087.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210608/022850714853.mp4", + "is_free": 1, + "category": 0, + "id": 200100, + "cnt_like": 230582 +}, { + "title": "rain", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201204/163356195736.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201204/163356492131.mp4", + "is_free": 1, + "category": 391, + "id": 11302, + "cnt_like": 308768 +}, { + "title": "cute", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200803/110356370090.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200803/110356680630.mp4", + "is_free": 1, + "category": 403, + "id": 10350, + "cnt_like": 485270 +}, { + "title": "fc156aa774cfabb3a9abf5938935f954.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/fc156aa774cfabb3a9abf5938935f954.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/fc156aa774cfabb3a9abf5938935f954.mp4", + "is_free": 1, + "category": 60539, + "id": 468, + "cnt_like": 90413 +}, { + "title": "gott", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210125/105643192423.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210125/105643421067.mp4", + "is_free": 1, + "category": 14, + "id": 23652, + "cnt_like": 246585 +}, { + "title": "ce39e114d87c849e4e00ac3a8c93a2f3.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/ce39e114d87c849e4e00ac3a8c93a2f3.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/ce39e114d87c849e4e00ac3a8c93a2f3.mp4", + "is_free": 1, + "category": 3864, + "id": 387, + "cnt_like": 17386 +}, { + "title": "ad1921a7b2bc40e5e07ce8e275104fdd.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/ad1921a7b2bc40e5e07ce8e275104fdd.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/ad1921a7b2bc40e5e07ce8e275104fdd.mp4", + "is_free": 1, + "category": 93033, + "id": 335, + "cnt_like": 24480 +}, { + "title": "653c8ea491b6d4e0159fd37c96414dcc.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/653c8ea491b6d4e0159fd37c96414dcc.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/653c8ea491b6d4e0159fd37c96414dcc.mp4", + "is_free": 1, + "category": 81573, + "id": 198, + "cnt_like": 76134 +}, { + "title": "a2e342868d431a10e77ac1eacedab479.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/a2e342868d431a10e77ac1eacedab479.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/a2e342868d431a10e77ac1eacedab479.mp4", + "is_free": 1, + "category": 40753, + "id": 311, + "cnt_like": 92324 +}, { + "title": "341e96d256471b2f0b9299643a32ece8.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/341e96d256471b2f0b9299643a32ece8.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/341e96d256471b2f0b9299643a32ece8.mp4", + "is_free": 1, + "category": 72146, + "id": 95, + "cnt_like": 71093 +}, { + "title": "MP4_7", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191017/094104570143.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191017/081958839686.mp4", + "is_free": 1, + "category": 5, + "id": 787, + "cnt_like": 722172 +}, { + "title": "SkeletonKing", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201010/093551987065.png", + "preview": "http://d.c-launcher.com/wallpaper_video/20201010/093552213291.mp4", + "is_free": 1, + "category": 1, + "id": 10610, + "cnt_like": 387705 +}, { + "title": "f57caf07a7dfd82adfff313f8b1fcf79.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/f57caf07a7dfd82adfff313f8b1fcf79.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/f57caf07a7dfd82adfff313f8b1fcf79.mp4", + "is_free": 1, + "category": 28474, + "id": 460, + "cnt_like": 97493 +}, { + "title": "Naruto", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210621/112816137238.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210621/112816440902.mp4", + "is_free": 1, + "category": 0, + "id": 200128, + "cnt_like": 211351 +}, { + "title": "977b7f1450f1721cd0e3665d70d5aad7.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/977b7f1450f1721cd0e3665d70d5aad7.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/977b7f1450f1721cd0e3665d70d5aad7.mp4", + "is_free": 1, + "category": 72780, + "id": 293, + "cnt_like": 20719 +}, { + "title": "garden", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210625/123645451164.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210625/123645694853.mp4", + "is_free": 1, + "category": 368, + "id": 200139, + "cnt_like": 205486 +}, { + "title": "86f690f892c61238d9191132eb638bb5.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/86f690f892c61238d9191132eb638bb5.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/86f690f892c61238d9191132eb638bb5.mp4", + "is_free": 1, + "category": 11642, + "id": 260, + "cnt_like": 22698 +}, { + "title": "db5b5ae3bd5d96eafdb5a47a0cbbda75.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/db5b5ae3bd5d96eafdb5a47a0cbbda75.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/db5b5ae3bd5d96eafdb5a47a0cbbda75.mp4", + "is_free": 1, + "category": 3767, + "id": 413, + "cnt_like": 38347 +}, { + "title": "cute", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200827/092430501537.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200827/092430813833.mp4", + "is_free": 1, + "category": 391, + "id": 10509, + "cnt_like": 450968 +}, { + "title": "0bbd3edbb6fcfbf72be64031ec7f5ac1.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/0bbd3edbb6fcfbf72be64031ec7f5ac1.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/0bbd3edbb6fcfbf72be64031ec7f5ac1.mp4", + "is_free": 1, + "category": 88918, + "id": 21, + "cnt_like": 79130 +}, { + "title": "AbstractSpiderweb", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/095153473153.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/095153829550.mp4", + "is_free": 1, + "category": 15, + "id": 808, + "cnt_like": 722194 +}, { + "title": "5bc9f548f692f87c6ce88bc2ebe63c4c.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/5bc9f548f692f87c6ce88bc2ebe63c4c.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/5bc9f548f692f87c6ce88bc2ebe63c4c.mp4", + "is_free": 1, + "category": 24348, + "id": 174, + "cnt_like": 87592 +}, { + "title": "AbstractArt", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/100432223059.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/100432725043.mp4", + "is_free": 1, + "category": 15, + "id": 953, + "cnt_like": 722342 +}, { + "title": "guihi", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200525/102043540688.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200525/102043762055.mp4", + "is_free": 1, + "category": 14, + "id": 5447, + "cnt_like": 581222 +}, { + "title": "Naruto", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210607/015928659155.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210607/015928882252.mp4", + "is_free": 1, + "category": 0, + "id": 200081, + "cnt_like": 232035 +}, { + "title": "12975ade48c9f7dfc15faae1c818bedc.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/12975ade48c9f7dfc15faae1c818bedc.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/12975ade48c9f7dfc15faae1c818bedc.mp4", + "is_free": 1, + "category": 41208, + "id": 30, + "cnt_like": 54777 +}, { + "title": "FunnyPig", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191122/035633490975.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191122/035633873510.mp4", + "is_free": 1, + "category": 18, + "id": 929, + "cnt_like": 722316 +}, { + "title": "2e5c44cf17a994b150a557991d403023.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/2e5c44cf17a994b150a557991d403023.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/2e5c44cf17a994b150a557991d403023.mp4", + "is_free": 1, + "category": 55468, + "id": 85, + "cnt_like": 74772 +}, { + "title": "pubyu", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210113/095622066978.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210113/095623322742.mp4", + "is_free": 1, + "category": 4, + "id": 13581, + "cnt_like": 253855 +}, { + "title": "Yi_46", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191025/093035593828.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191025/024218123893.mp4", + "is_free": 1, + "category": 14, + "id": 824, + "cnt_like": 722210 +}, { + "title": "9e3e23be16624fafcab7cdf872291519.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/9e3e23be16624fafcab7cdf872291519.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/9e3e23be16624fafcab7cdf872291519.mp4", + "is_free": 1, + "category": 86781, + "id": 299, + "cnt_like": 55039 +}, { + "title": "067c94d17283812fa788b22657542865.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/067c94d17283812fa788b22657542865.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/067c94d17283812fa788b22657542865.mp4", + "is_free": 1, + "category": 33550, + "id": 10, + "cnt_like": 45792 +}, { + "title": "94bc14323a76ff8c0403c364d892045d.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/94bc14323a76ff8c0403c364d892045d.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/94bc14323a76ff8c0403c364d892045d.mp4", + "is_free": 1, + "category": 56003, + "id": 287, + "cnt_like": 248 +}, { + "title": "heart", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200804/024926946585.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200804/024927228402.mp4", + "is_free": 1, + "category": 373, + "id": 10365, + "cnt_like": 484298 +}, { + "title": "Rose butterfly", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201010/094243197108.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201010/094243537321.mp4", + "is_free": 1, + "category": 1, + "id": 10618, + "cnt_like": 387710 +}, { + "title": "4dfc5fcb93dcc758142b16841f0a6c88.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/4dfc5fcb93dcc758142b16841f0a6c88.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/4dfc5fcb93dcc758142b16841f0a6c88.mp4", + "is_free": 1, + "category": 38803, + "id": 137, + "cnt_like": 43424 +}, { + "title": "naruto", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210114/021953737203.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210114/021954459582.mp4", + "is_free": 1, + "category": 0, + "id": 18600, + "cnt_like": 257891 +}, { + "title": "Undertaker", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210118/113325391084.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210118/113325658424.mp4", + "is_free": 1, + "category": 1, + "id": 23645, + "cnt_like": 256622 +}, { + "title": "fsafsaf", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200525/075427176770.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200525/075427441907.mp4", + "is_free": 0, + "category": 370, + "id": 5422, + "cnt_like": 581292 +}, { + "title": "7234ff144ac3b7af58834ca229aa9235.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/7234ff144ac3b7af58834ca229aa9235.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/7234ff144ac3b7af58834ca229aa9235.mp4", + "is_free": 1, + "category": 2342, + "id": 214, + "cnt_like": 46935 +}, { + "title": "love", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201130/114040774562.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201130/114040938311.mp4", + "is_free": 1, + "category": 367, + "id": 11245, + "cnt_like": 314729 +}, { + "title": " astronaut", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200803/105304131460.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200803/105304389110.mp4", + "is_free": 1, + "category": 394, + "id": 10334, + "cnt_like": 485266 +}, { + "title": "girl", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201010/092703425113.png", + "preview": "http://d.c-launcher.com/wallpaper_video/20201010/092703766424.mp4", + "is_free": 1, + "category": 1, + "id": 10603, + "cnt_like": 387707 +}, { + "title": "frvzqw", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200525/102433052730.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200525/102433269893.mp4", + "is_free": 1, + "category": 14, + "id": 5452, + "cnt_like": 581222 +}, { + "title": "Wolverine", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/090449177084.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/090449512482.mp4", + "is_free": 1, + "category": 12, + "id": 778, + "cnt_like": 722163 +}, { + "title": "c723749550e4a334893d35dad24f5ba6.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/c723749550e4a334893d35dad24f5ba6.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/c723749550e4a334893d35dad24f5ba6.mp4", + "is_free": 1, + "category": 92026, + "id": 372, + "cnt_like": 51936 +}, { + "title": "dragon", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210625/123409020713.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210625/123409389163.mp4", + "is_free": 1, + "category": 368, + "id": 200137, + "cnt_like": 205491 +}, { + "title": "3eed5ffd230cfcf43673f58472a0bac3.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/3eed5ffd230cfcf43673f58472a0bac3.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/3eed5ffd230cfcf43673f58472a0bac3.mp4", + "is_free": 1, + "category": 36478, + "id": 117, + "cnt_like": 92329 +}, { + "title": "SmokeFluid", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/112958339192.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/112958723120.mp4", + "is_free": 1, + "category": 15, + "id": 827, + "cnt_like": 722213 +}, { + "title": "fsgfdsg", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200526/025025241992.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200526/025025541814.mp4", + "is_free": 1, + "category": 49, + "id": 5479, + "cnt_like": 580264 +}, { + "title": "DTMP", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201207/112325208607.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201207/112325369482.mp4", + "is_free": 1, + "category": 367, + "id": 11313, + "cnt_like": 304737 +}, { + "title": "91b6b71fecacd38d17f38b4898f3ddf1.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/91b6b71fecacd38d17f38b4898f3ddf1.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/91b6b71fecacd38d17f38b4898f3ddf1.mp4", + "is_free": 1, + "category": 16829, + "id": 281, + "cnt_like": 617 +}, { + "title": "Yi_40", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191024/094257667365.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191024/094359519903.mp4", + "is_free": 1, + "category": 15, + "id": 814, + "cnt_like": 722200 +}, { + "title": "83cd4c489f51907da00c66822309f342.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/83cd4c489f51907da00c66822309f342.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/83cd4c489f51907da00c66822309f342.mp4", + "is_free": 1, + "category": 71480, + "id": 253, + "cnt_like": 36648 +}, { + "title": "GlassWaterIronMan  ", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/084545344859.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/084545692730.mp4", + "is_free": 1, + "category": 12, + "id": 768, + "cnt_like": 722153 +}, { + "title": "girly", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200804/081022085348.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200804/081022360020.mp4", + "is_free": 1, + "category": 1, + "id": 10413, + "cnt_like": 484073 +}, { + "title": "StarryUniverseView  ", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/093358232191.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/093358552183.mp4", + "is_free": 1, + "category": 15, + "id": 943, + "cnt_like": 722330 +}, { + "title": "ghfdhfh", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200526/025406797409.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200526/025407069762.mp4", + "is_free": 1, + "category": 49, + "id": 5481, + "cnt_like": 580260 +}, { + "title": "GreenForestRailroadTrack", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191119/013907574549.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191119/013907941434.mp4", + "is_free": 1, + "category": 4, + "id": 979, + "cnt_like": 722367 +}, { + "title": "lighting", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200803/105150461948.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200803/105150744153.mp4", + "is_free": 1, + "category": 391, + "id": 10333, + "cnt_like": 485266 +}, { + "title": "DTMP", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201207/111557917642.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201207/111558164025.mp4", + "is_free": 1, + "category": 367, + "id": 11312, + "cnt_like": 304740 +}, { + "title": "uchiha", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210621/072027724172.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210621/072027953032.mp4", + "is_free": 1, + "category": 368, + "id": 200121, + "cnt_like": 211544 +}, { + "title": "flowers3", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210104/111242953615.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210104/111243348783.mp4", + "is_free": 1, + "category": 367, + "id": 13579, + "cnt_like": 266690 +}, { + "title": "fbea89fc001f5f8c3c29cfa83c811aca.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/fbea89fc001f5f8c3c29cfa83c811aca.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/fbea89fc001f5f8c3c29cfa83c811aca.mp4", + "is_free": 1, + "category": 46701, + "id": 467, + "cnt_like": 27550 +}, { + "title": "Sea", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200804/075308132878.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200804/075308457532.mp4", + "is_free": 1, + "category": 13, + "id": 10394, + "cnt_like": 484076 +}, { + "title": "Elephant", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200909/104516885168.png", + "preview": "http://d.c-launcher.com/wallpaper_video/20200909/104517481129.mp4", + "is_free": 1, + "category": 402, + "id": 10526, + "cnt_like": 432186 +}, { + "title": "Buttery", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200914/012033692297.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200914/012034353060.mp4", + "is_free": 0, + "category": 374, + "id": 10534, + "cnt_like": 425519 +}, { + "title": "3be129497a24855c58583d03dca35a7b.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/3be129497a24855c58583d03dca35a7b.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/3be129497a24855c58583d03dca35a7b.mp4", + "is_free": 1, + "category": 62241, + "id": 111, + "cnt_like": 94555 +}, { + "title": "emoji", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200806/020717574876.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200806/020717804055.mp4", + "is_free": 1, + "category": 1, + "id": 10466, + "cnt_like": 481612 +}, { + "title": "cdd319d741fe14904fe062bca773aead.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/cdd319d741fe14904fe062bca773aead.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/cdd319d741fe14904fe062bca773aead.mp4", + "is_free": 1, + "category": 50147, + "id": 386, + "cnt_like": 68528 +}, { + "title": "1a03dc2b974295966a49ff6133ae41bc.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/1a03dc2b974295966a49ff6133ae41bc.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/1a03dc2b974295966a49ff6133ae41bc.mp4", + "is_free": 1, + "category": 27986, + "id": 52, + "cnt_like": 92422 +}, { + "title": "SeaCuteAnimals", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191209/095441659486.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191209/095442031090.mp4", + "is_free": 1, + "category": 49, + "id": 901, + "cnt_like": 722287 +}, { + "title": "gsgsdfg", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200526/030753047830.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200526/030753262473.mp4", + "is_free": 0, + "category": 367, + "id": 5484, + "cnt_like": 580199 +}, { + "title": "6cfe90cc764f406d9b0ffa2aacaeac33.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/6cfe90cc764f406d9b0ffa2aacaeac33.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/6cfe90cc764f406d9b0ffa2aacaeac33.mp4", + "is_free": 1, + "category": 67071, + "id": 205, + "cnt_like": 93968 +}, { + "title": "RedMeteor", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/112638237654.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/112638641565.mp4", + "is_free": 1, + "category": 15, + "id": 956, + "cnt_like": 722345 +}, { + "title": "bts", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201218/104958879658.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201218/104959149603.mp4", + "is_free": 1, + "category": 14, + "id": 11368, + "cnt_like": 289031 +}, { + "title": "flash", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201125/120014583483.png", + "preview": "http://d.c-launcher.com/wallpaper_video/20201125/120014789084.mp4", + "is_free": 1, + "category": 1, + "id": 11201, + "cnt_like": 321912 +}, { + "title": "Girl66", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201201/112157093563.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201201/112157400999.mp4", + "is_free": 1, + "category": 1, + "id": 11266, + "cnt_like": 313376 +}, { + "title": "gafdfaf", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200525/102513208923.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200525/102513507705.mp4", + "is_free": 1, + "category": 14, + "id": 5453, + "cnt_like": 581223 +}, { + "title": "135ca6681d0ab422a16e7649b6892f2f.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/135ca6681d0ab422a16e7649b6892f2f.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/135ca6681d0ab422a16e7649b6892f2f.mp4", + "is_free": 1, + "category": 61911, + "id": 35, + "cnt_like": 38988 +}, { + "title": "Iron Man", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201218/105352658113.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201218/105352970587.mp4", + "is_free": 1, + "category": 15, + "id": 11370, + "cnt_like": 289028 +}, { + "title": "7833e754ba53e97db50c173a2d11e64c.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/7833e754ba53e97db50c173a2d11e64c.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/7833e754ba53e97db50c173a2d11e64c.mp4", + "is_free": 1, + "category": 82073, + "id": 232, + "cnt_like": 16112 +}, { + "title": "2eae1b1802d1c5271ab396b109fdbb7a.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/2eae1b1802d1c5271ab396b109fdbb7a.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/2eae1b1802d1c5271ab396b109fdbb7a.mp4", + "is_free": 1, + "category": 41918, + "id": 86, + "cnt_like": 91789 +}, { + "title": "59c46457e54205332b01d2494a19e1a5.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/59c46457e54205332b01d2494a19e1a5.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/59c46457e54205332b01d2494a19e1a5.mp4", + "is_free": 1, + "category": 71058, + "id": 169, + "cnt_like": 42504 +}, { + "title": "cool", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201225/101558598645.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201225/101558989358.mp4", + "is_free": 1, + "category": 367, + "id": 11172, + "cnt_like": 330817 +}, { + "title": "waterfall", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201201/103325144334.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201201/103325402854.mp4", + "is_free": 1, + "category": 1, + "id": 11263, + "cnt_like": 313420 +}, { + "title": "767d1525fe685c007d20f646ab2a43b1.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/767d1525fe685c007d20f646ab2a43b1.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/767d1525fe685c007d20f646ab2a43b1.mp4", + "is_free": 1, + "category": 29820, + "id": 223, + "cnt_like": 32165 +}, { + "title": "cute", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200826/105208630181.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200826/105208866788.mp4", + "is_free": 1, + "category": 394, + "id": 10502, + "cnt_like": 452314 +}, { + "title": "girl", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210319/102940810332.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210319/102941120109.mp4", + "is_free": 1, + "category": 0, + "id": 23694, + "cnt_like": 170326 +}, { + "title": "fsdfsdfsdf", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200525/100855093089.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200525/100855326978.mp4", + "is_free": 0, + "category": 370, + "id": 5431, + "cnt_like": 581167 +}, { + "title": "28c97b5c5238e02c77a5ed8f191471c2.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/28c97b5c5238e02c77a5ed8f191471c2.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/28c97b5c5238e02c77a5ed8f191471c2.mp4", + "is_free": 1, + "category": 63535, + "id": 79, + "cnt_like": 7959 +}, { + "title": " astronaut", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200803/110626242115.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200803/110626537395.mp4", + "is_free": 1, + "category": 391, + "id": 10353, + "cnt_like": 485270 +}, { + "title": "034b34bec07f38500644ad739037cf99.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/034b34bec07f38500644ad739037cf99.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/034b34bec07f38500644ad739037cf99.mp4", + "is_free": 1, + "category": 72172, + "id": 5, + "cnt_like": 16768 +}, { + "title": "5beaedc6e9248ac3cfa39ce3b1db33a3.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/5beaedc6e9248ac3cfa39ce3b1db33a3.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/5beaedc6e9248ac3cfa39ce3b1db33a3.mp4", + "is_free": 1, + "category": 45142, + "id": 175, + "cnt_like": 88755 +}, { + "title": "Love", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/114856149618.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/114856488007.mp4", + "is_free": 1, + "category": 5, + "id": 967, + "cnt_like": 722355 +}, { + "title": "929570d5384e5c9a24588c79d3e76869.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/929570d5384e5c9a24588c79d3e76869.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/929570d5384e5c9a24588c79d3e76869.mp4", + "is_free": 1, + "category": 19425, + "id": 283, + "cnt_like": 20352 +}, { + "title": "d72d01c6eca549ca367f293d37ffa47c.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/d72d01c6eca549ca367f293d37ffa47c.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/d72d01c6eca549ca367f293d37ffa47c.mp4", + "is_free": 1, + "category": 11584, + "id": 407, + "cnt_like": 73233 +}, { + "title": "Yi_49", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191025/031506254796.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191025/031506533421.mp4", + "is_free": 1, + "category": 5, + "id": 830, + "cnt_like": 722216 +}, { + "title": "clock", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200925/120705105400.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200925/120705654818.mp4", + "is_free": 1, + "category": 1, + "id": 10549, + "cnt_like": 409093 +}, { + "title": "Bear", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191209/121526491942.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191209/092415611793.mp4", + "is_free": 1, + "category": 49, + "id": 895, + "cnt_like": 722281 +}, { + "title": "fire", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201204/163206696342.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201204/163206919434.mp4", + "is_free": 1, + "category": 391, + "id": 11301, + "cnt_like": 308769 +}, { + "title": "fe72829bc5fbf234c8441e4a1e23c5e1.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/fe72829bc5fbf234c8441e4a1e23c5e1.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/fe72829bc5fbf234c8441e4a1e23c5e1.mp4", + "is_free": 1, + "category": 84194, + "id": 473, + "cnt_like": 91166 +}, { + "title": "coool", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210127/102919489677.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210127/102919714189.mp4", + "is_free": 1, + "category": 15, + "id": 23656, + "cnt_like": 243739 +}, { + "title": "Shake2", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200708/131257561446.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200708/131257866722.mp4", + "is_free": 1, + "category": 371, + "id": 10310, + "cnt_like": 522499 +}, { + "title": "PinkWave", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191119/085401323981.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191119/085401672840.mp4", + "is_free": 1, + "category": 13, + "id": 1000, + "cnt_like": 722389 +}, { + "title": "2382faa68e1f9ea6edd227f783a71693.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/2382faa68e1f9ea6edd227f783a71693.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/2382faa68e1f9ea6edd227f783a71693.mp4", + "is_free": 1, + "category": 41479, + "id": 69, + "cnt_like": 71251 +}, { + "title": "QUIK", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201207/112632088302.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201207/112632287282.mp4", + "is_free": 1, + "category": 370, + "id": 11315, + "cnt_like": 304736 +}, { + "title": "MOV_31", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191017/100544319939.JPG", + "preview": "http://d.c-launcher.com/wallpaper_video/20191017/100544533503.MOV", + "is_free": 1, + "category": 5, + "id": 803, + "cnt_like": 722189 +}, { + "title": "ClearSeaWater", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191119/024142961490.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191119/024143328630.mp4", + "is_free": 1, + "category": 13, + "id": 996, + "cnt_like": 722385 +}, { + "title": "bob", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210623/092238051444.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210623/092238351366.mp4", + "is_free": 1, + "category": 0, + "id": 200131, + "cnt_like": 209903 +}, { + "title": "SnowScene", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191209/092647958453.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191209/092648373084.mp4", + "is_free": 1, + "category": 49, + "id": 899, + "cnt_like": 722285 +}, { + "title": "a10b973ac7dd5265e4038d914c038abe.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/a10b973ac7dd5265e4038d914c038abe.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/a10b973ac7dd5265e4038d914c038abe.mp4", + "is_free": 1, + "category": 92980, + "id": 305, + "cnt_like": 51360 +}, { + "title": "6c86e53b6954b52b1d819d4eac34efe1.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/6c86e53b6954b52b1d819d4eac34efe1.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/6c86e53b6954b52b1d819d4eac34efe1.mp4", + "is_free": 1, + "category": 29815, + "id": 204, + "cnt_like": 96030 +}, { + "title": "bbab5fc915344ba2a5b28cce39de103f.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/bbab5fc915344ba2a5b28cce39de103f.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/bbab5fc915344ba2a5b28cce39de103f.mp4", + "is_free": 1, + "category": 20706, + "id": 354, + "cnt_like": 85458 +}, { + "title": "LazyTom", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191209/090430792993.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191209/090431136155.mp4", + "is_free": 1, + "category": 49, + "id": 781, + "cnt_like": 722166 +}, { + "title": "060497321dc25e0e0f310e1b4772e3db.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/060497321dc25e0e0f310e1b4772e3db.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/060497321dc25e0e0f310e1b4772e3db.mp4", + "is_free": 1, + "category": 11324, + "id": 9, + "cnt_like": 55078 +}, { + "title": "Clock", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200409/135848888131.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200409/135849328663.mp4", + "is_free": 1, + "category": 391, + "id": 4804, + "cnt_like": 646587 +}, { + "title": "MOV_3535", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191017/092223726603.JPG", + "preview": "http://d.c-launcher.com/wallpaper_video/20191024/095304952294.mp4", + "is_free": 1, + "category": 15, + "id": 785, + "cnt_like": 722170 +}, { + "title": "b682e0d9babc9b96429ea95330f3891d.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/b682e0d9babc9b96429ea95330f3891d.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/b682e0d9babc9b96429ea95330f3891d.mp4", + "is_free": 1, + "category": 40552, + "id": 347, + "cnt_like": 87714 +}, { + "title": "Sea", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200804/075056026992.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200804/075056297617.mp4", + "is_free": 1, + "category": 1, + "id": 10390, + "cnt_like": 484070 +}, { + "title": "AnimeBoy", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/120439111822.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/120439536260.mp4", + "is_free": 1, + "category": 1, + "id": 974, + "cnt_like": 722362 +}, { + "title": "AbstractConstellation", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/100941915880.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/100942367066.mp4", + "is_free": 1, + "category": 15, + "id": 954, + "cnt_like": 722343 +}, { + "title": "Fish", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201110/093659899969.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201110/093700162907.mp4", + "is_free": 1, + "category": 367, + "id": 11133, + "cnt_like": 343539 +}, { + "title": "Yi_55", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191029/034605534515.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191029/034606177785.mp4", + "is_free": 1, + "category": 14, + "id": 835, + "cnt_like": 722221 +}, { + "title": "xueren", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20210113/105104385225.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20210113/105104774314.mp4", + "is_free": 1, + "category": 367, + "id": 18599, + "cnt_like": 258771 +}, { + "title": "7cdd8f14e9747618012923be46343bf9.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/7cdd8f14e9747618012923be46343bf9.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/7cdd8f14e9747618012923be46343bf9.mp4", + "is_free": 1, + "category": 30358, + "id": 239, + "cnt_like": 361 +}, { + "title": "c45c9ba5ddc74a577b6589e9de063360.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/c45c9ba5ddc74a577b6589e9de063360.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/c45c9ba5ddc74a577b6589e9de063360.mp4", + "is_free": 1, + "category": 60615, + "id": 365, + "cnt_like": 23386 +}, { + "title": "fsgsgsaaaa", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200525/102640191949.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200525/102640414501.mp4", + "is_free": 1, + "category": 14, + "id": 5455, + "cnt_like": 581224 +}, { + "title": "landscape", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200804/080942231462.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200804/080942463408.mp4", + "is_free": 1, + "category": 1, + "id": 10412, + "cnt_like": 484078 +}, { + "title": "362bbb5894e9c3923d471b2efc964f05.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/362bbb5894e9c3923d471b2efc964f05.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/362bbb5894e9c3923d471b2efc964f05.mp4", + "is_free": 1, + "category": 75700, + "id": 99, + "cnt_like": 50620 +}, { + "title": "lighting", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200803/104458610127.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200803/104459008654.mp4", + "is_free": 1, + "category": 391, + "id": 10324, + "cnt_like": 485265 +}, { + "title": "4784e95aee5007e40a6a1b4c39188865.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/4784e95aee5007e40a6a1b4c39188865.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/4784e95aee5007e40a6a1b4c39188865.mp4", + "is_free": 1, + "category": 40268, + "id": 129, + "cnt_like": 15599 +}, { + "title": "93fc90fec019a419cfa4f38a520855bc.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/93fc90fec019a419cfa4f38a520855bc.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/93fc90fec019a419cfa4f38a520855bc.mp4", + "is_free": 1, + "category": 36019, + "id": 285, + "cnt_like": 68014 +}, { + "title": "fire", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20201204/163107574309.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20201204/163107814554.mp4", + "is_free": 1, + "category": 391, + "id": 11300, + "cnt_like": 308773 +}, { + "title": "dc9cd6660b9c349e5bfdfb5c4423e111.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/dc9cd6660b9c349e5bfdfb5c4423e111.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/dc9cd6660b9c349e5bfdfb5c4423e111.mp4", + "is_free": 1, + "category": 82142, + "id": 417, + "cnt_like": 91456 +}, { + "title": "ShiningCaptainAmerica  ", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20191118/091411512190.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20191118/091411855410.mp4", + "is_free": 1, + "category": 12, + "id": 940, + "cnt_like": 722327 +}, { + "title": "deabed3b964e57b9285d4cd715f0f2e3.jpg", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/deabed3b964e57b9285d4cd715f0f2e3.jpg", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/deabed3b964e57b9285d4cd715f0f2e3.mp4", + "is_free": 1, + "category": 37663, + "id": 422, + "cnt_like": 77647 +}, { + "title": "b4d771475ee51f39fbd2816021fa9501.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/b4d771475ee51f39fbd2816021fa9501.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/b4d771475ee51f39fbd2816021fa9501.mp4", + "is_free": 1, + "category": 58250, + "id": 345, + "cnt_like": 93902 +}, { + "title": "Sea", + "thumbnail": "http://d.c-launcher.com/wallpaper_video/20200803/110534554895.jpg", + "preview": "http://d.c-launcher.com/wallpaper_video/20200803/110534950027.mp4", + "is_free": 1, + "category": 391, + "id": 10352, + "cnt_like": 485270 +}, { + "title": "eb6269152c45e824d7104400e2970f4b.png", + "thumbnail": "https://cdn.webinnovationstudio.co.in/wallpaper/live_thumb/eb6269152c45e824d7104400e2970f4b.png", + "preview": "https://cdn.webinnovationstudio.co.in/wallpaper/live/eb6269152c45e824d7104400e2970f4b.mp4", + "is_free": 1, + "category": 19897, + "id": 439, + "cnt_like": 75255 +}] \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/LiveWallpaper.kt b/app/src/main/java/com/live/wallpaper/style/hd/LiveWallpaper.kt new file mode 100644 index 0000000..c2f8da8 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/LiveWallpaper.kt @@ -0,0 +1,26 @@ +package com.live.wallpaper.style.hd + +import androidx.multidex.MultiDexApplication +import com.live.wallpaper.style.hd.mytools.WallpaperDataUtil + +class LiveWallpaper : MultiDexApplication() { + companion object { + lateinit var app: LiveWallpaper + const val URL_TAG = "url_tag" + const val KEY_EXTRA_LIST = "key_extra_list" + const val URL_Video = "url_video" + const val KEY_EXTRA__POS = "key_extra_pos" + + } + + override fun onCreate() { + super.onCreate() + app = this + + WallpaperDataUtil.assestGet() + } + + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ContactFragment.kt b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ContactFragment.kt new file mode 100644 index 0000000..0a292cd --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ContactFragment.kt @@ -0,0 +1,111 @@ +package com.live.wallpaper.style.hd.actandfrag + +import android.content.Intent +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.net.Uri +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import androidx.fragment.app.DialogFragment +import androidx.recyclerview.widget.LinearLayoutManager +import com.live.wallpaper.style.hd.databinding.FragmentContactBinding +import com.live.wallpaper.style.hd.recycleradapter.AdapterStar + + +class ContactFragment() : DialogFragment() { + + private lateinit var binding: FragmentContactBinding + private lateinit var mAdapter: AdapterStar + + companion object { + val EXTRA_KEY = "task" + val ADD_TASK_TYPE_KEY = "add_task_type_key" + + @JvmStatic + fun newInstance(param1: Int, param2: Int) = + ContactFragment().apply { + arguments = Bundle().apply { + putInt(EXTRA_KEY, param1) + putInt(ADD_TASK_TYPE_KEY, param2) + } + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentContactBinding.inflate(layoutInflater) + return binding.root + } + + + override fun onStart() { + super.onStart() + dialog?.run { + setCanceledOnTouchOutside(false) + setCancelable(false) + window?.run { + attributes = attributes.apply { + gravity = Gravity.CENTER + width = WindowManager.LayoutParams.WRAP_CONTENT + height = WindowManager.LayoutParams.WRAP_CONTENT + } + } + val decorView = window!!.decorView + decorView.setPadding(0, 0, 0, 0) + decorView.background = ColorDrawable(Color.TRANSPARENT) + } + init() + } + private fun goRate() { + val intent = Intent("android.intent.action.VIEW") + val stringBuilder = "https://play.google.com/store/apps/details?id=${requireContext().packageName}" + intent.data = Uri.parse(stringBuilder) + startActivity(intent) + } + private fun init() { + + binding.run { + + mAdapter = AdapterStar(requireContext()) { + tvRateIt.run { + isSelected = true + isClickable = true + } + } + recyclerStart.apply { + adapter = mAdapter + layoutManager = LinearLayoutManager(requireContext()).apply { + orientation = LinearLayoutManager.HORIZONTAL + } + } + tvRateIt.run { + isSelected = false + isClickable = false + } + tvCancel.setOnClickListener { dismiss() } + tvRateIt.setOnClickListener { + mAdapter.getRate()?.let { + if (it >= 3) { + goRate() + dismiss() + } else { + dismiss() + } + } + + } + } + + + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/FirstActivity.kt b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/FirstActivity.kt new file mode 100644 index 0000000..9cb67c7 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/FirstActivity.kt @@ -0,0 +1,37 @@ +package com.live.wallpaper.style.hd.actandfrag + +import android.content.Intent +import android.view.View +import com.live.wallpaper.style.hd.databinding.ActFirstBinding +import com.live.wallpaper.style.hd.mytools.Common.countDown + +class FirstActivity : ParentActivity() { + private lateinit var binding: ActFirstBinding + private var countTime = 2 + + override fun getContentView(): View { + binding = ActFirstBinding.inflate(layoutInflater) + return binding.root + } + + override fun initViews() { + super.initViews() + + startCountDown() + } + + private fun startCountDown() { + countDown(countTime, start = { + }, next = { + + }) { + intoMain() + } + } + private fun intoMain() { + if (!isFinishing) { + startActivity(Intent(this, MainActivity::class.java)) + finish() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/InfoFragment.kt b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/InfoFragment.kt new file mode 100644 index 0000000..9f81e28 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/InfoFragment.kt @@ -0,0 +1,110 @@ +package com.live.wallpaper.style.hd.actandfrag + +import android.content.Intent +import android.view.View +import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.GridLayoutManager +import com.live.wallpaper.style.hd.LiveWallpaper +import com.live.wallpaper.style.hd.bean.WallpaperImage +import com.live.wallpaper.style.hd.bean.WallpaperImageListBean +import com.live.wallpaper.style.hd.databinding.FragmentWallpaperBinding +import com.live.wallpaper.style.hd.recycleradapter.AdapterWall +import com.live.wallpaper.style.hd.mytools.SpaceDecoration +import com.live.wallpaper.style.hd.mytools.Common.onMain +import com.live.wallpaper.style.hd.viewm.WallpaperViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class InfoFragment : ParentFragment() { + + private lateinit var binding: FragmentWallpaperBinding + private val mViewModel: WallpaperViewModel by viewModels() + private var mAdapter: AdapterWall? = null + private var mList: MutableList = mutableListOf() + private var mCurPos: Int = -1 + + companion object { + private const val ARG_TAG = "arg_tag" + + fun newInstance(): InfoFragment { + val fragment = InfoFragment() + return fragment + } + } + + override fun getContentView(): View { + binding = FragmentWallpaperBinding.inflate(layoutInflater) + return binding.root + } + + override fun initViews() { + super.initViews() + + + + mAdapter = AdapterWall(requireActivity(), mList) + mAdapter?.setOnItemClickListener(object : + AdapterWall.OnItemClickListener { + override fun onItemClick(pos: Int) { + toPreview(pos) + } + }) + binding.rv.layoutManager = GridLayoutManager(requireActivity(), 2) + binding.rv.addItemDecoration( + SpaceDecoration(4, 16) + ) + binding.rv.adapter = mAdapter!! + + + binding.refreshLayout.setOnRefreshListener { + mCurPos = -1 + if (mViewModel.isLoading.get()) { + return@setOnRefreshListener + } + lifecycleScope.launch(Dispatchers.IO) { + mViewModel.updateWallpaper() + } + } + + binding.refreshLayout.setOnLoadMoreListener { + mCurPos = -1 + if (mViewModel.isLoading.get()) { + return@setOnLoadMoreListener + } + mViewModel.loadWallpaper() + } + + mViewModel.getData().observe(this) { list -> + mList.clear() + mList.addAll(list) + onMain { + binding.refreshLayout.finishRefresh() + binding.refreshLayout.finishLoadMore() + mAdapter?.notifyDataSetChanged() + } + } + if (!reCreated) { + lifecycleScope.launch(Dispatchers.IO) { + mViewModel.updateWallpaper() + } + } + } + + + + + private fun toPreview(pos: Int) { + mCurPos = pos + if (activity != null) { + val intent = Intent(requireActivity(), PreVideoActivity::class.java) + val listBean = WallpaperImageListBean() + listBean.list = mList + intent.putExtra(LiveWallpaper.KEY_EXTRA_LIST, listBean) + intent.putExtra(LiveWallpaper.KEY_EXTRA__POS, pos) + startActivity(intent) + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/MainActivity.kt b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/MainActivity.kt new file mode 100644 index 0000000..c26d6bd --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/MainActivity.kt @@ -0,0 +1,81 @@ +package com.live.wallpaper.style.hd.actandfrag + +import android.view.View +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentStatePagerAdapter +import androidx.viewpager.widget.ViewPager +import com.live.wallpaper.style.hd.databinding.ActivityMainBinding +import com.live.wallpaper.style.hd.mytools.Common.throttleClicks + +class MainActivity : ParentActivity() { + + private lateinit var binding: ActivityMainBinding + private val mFragments: MutableList = ArrayList() + + + override fun getContentView(): View { + binding = ActivityMainBinding.inflate(layoutInflater) + return binding.root + } + + override fun initViews() { + super.initViews() + + updateTab(0) + setViewPager() + + binding.llHome.throttleClicks { + binding.viewPager.currentItem = 0 + + } + binding.llSettings.throttleClicks { + binding.viewPager.currentItem = 1 + } + } + private fun updateTab(index: Int) { + when (index) { + 0 -> { + binding.ivHome.isSelected = true + binding.ivSettings.isSelected = false + } + 1 -> { + binding.ivHome.isSelected = false + binding.ivSettings.isSelected = true + } + } + } + private fun setViewPager() { + mFragments.add(InfoFragment.newInstance()) + mFragments.add(SetFragment()) + binding.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { + } + + override fun onPageSelected(position: Int) { + updateTab(position) + + } + + override fun onPageScrollStateChanged(state: Int) { + + } + + }) + binding.viewPager.adapter = object : FragmentStatePagerAdapter(supportFragmentManager) { + override fun getCount(): Int { + return mFragments.size + } + + override fun getItem(position: Int): Fragment { + return mFragments[position] + } + + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ParentActivity.kt b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ParentActivity.kt new file mode 100644 index 0000000..72b8bbd --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ParentActivity.kt @@ -0,0 +1,59 @@ +package com.live.wallpaper.style.hd.actandfrag + +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import android.view.Window +import android.view.WindowManager +import androidx.annotation.ColorInt +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.WindowCompat +import com.live.wallpaper.style.hd.R + +abstract class ParentActivity: AppCompatActivity() { + + var reCreated = false + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStatusBarUpperAPI21(resources.getColor(R.color.white)) + setContentView(getContentView()) + //设置壁纸后,Activity会被销毁重建,但viewModel不会,此处判断是否是设置壁纸重建activity执行的onCreate(),此时不展示广告 +// if (mConfigurationViewModel.originalConfiguration == null) { +// mConfigurationViewModel.originalConfiguration = resources.configuration +// } else { +// val diff = resources.configuration.diff(mConfigurationViewModel.originalConfiguration) +// reCreated = (diff.toLong() and 0x80000000) != 0L +// mConfigurationViewModel.originalConfiguration = resources.configuration +// } + + initViews() + } + + abstract fun getContentView(): View + + open fun initViews() {} + + + + private fun setStatusBarUpperAPI21(@ColorInt color: Int) { + val window = window + //取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏 + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + + //需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色 + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + //设置状态栏颜色 + //由于setStatusBarColor()这个API最低版本支持21, 本人的是15,所以如果要设置颜色,自行到style中通过配置文件设置 + window.statusBarColor = color + val mContentView = findViewById(Window.ID_ANDROID_CONTENT) as ViewGroup + val mChildView = mContentView.getChildAt(0) + if (mChildView != null) { + //注意不是设置 ContentView 的 FitsSystemWindows, 而是设置 ContentView 的第一个子 View . 预留出系统 View 的空间. + mChildView.fitsSystemWindows = true + } + val wc = WindowCompat.getInsetsController(window, window.decorView) + wc.isAppearanceLightStatusBars = true + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ParentFragment.kt b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ParentFragment.kt new file mode 100644 index 0000000..0affa83 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/ParentFragment.kt @@ -0,0 +1,39 @@ +package com.live.wallpaper.style.hd.actandfrag + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment + +abstract class ParentFragment: Fragment() { + + var reCreated = false + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return getContentView() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + //设置壁纸后,Activity会被销毁重建,但viewModel不会,此处判断是否是设置壁纸重建activity执行的onCreate(),此时不展示广告 +// if (mConfigurationViewModel.originalConfiguration == null) { +// mConfigurationViewModel.originalConfiguration = resources.configuration +// } else { +// val diff = resources.configuration.diff(mConfigurationViewModel.originalConfiguration) +// reCreated = (diff.toLong() and 0x80000000) != 0L +// mConfigurationViewModel.originalConfiguration = resources.configuration +// } + initViews() + } + + abstract fun getContentView(): View + + open fun initViews(){ + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/PreVideoActivity.kt b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/PreVideoActivity.kt new file mode 100644 index 0000000..c1af849 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/PreVideoActivity.kt @@ -0,0 +1,286 @@ +package com.live.wallpaper.style.hd.actandfrag + +import android.app.WallpaperManager +import android.content.ComponentName +import android.content.Intent +import android.media.MediaPlayer +import android.net.Uri +import android.os.Build +import android.view.SurfaceHolder +import android.view.View +import androidx.core.view.isVisible +import androidx.viewpager2.widget.ViewPager2 +import com.live.wallpaper.style.hd.LiveWallpaper +import com.live.wallpaper.style.hd.R +import com.live.wallpaper.style.hd.bean.WallpaperImage +import com.live.wallpaper.style.hd.bean.WallpaperImageListBean +import com.live.wallpaper.style.hd.customerDialog.DownDialog +import com.live.wallpaper.style.hd.databinding.ActPreLiveBinding +import com.live.wallpaper.style.hd.myliveservice.LiveService +import com.live.wallpaper.style.hd.mytools.Common.getMyStr +import com.live.wallpaper.style.hd.mytools.Common.hide +import com.live.wallpaper.style.hd.mytools.Common.onMain +import com.live.wallpaper.style.hd.mytools.Common.show +import com.live.wallpaper.style.hd.mytools.Common.throttleClicks +import com.live.wallpaper.style.hd.mytools.Sp +import com.live.wallpaper.style.hd.mytools.download.DownloadUtil +import com.live.wallpaper.style.hd.recycleradapter.AdapterLive + +class PreVideoActivity : ParentActivity(){ + private lateinit var binding: ActPreLiveBinding + private var mList: MutableList = mutableListOf() + private var mImage: WallpaperImage? = null + private var mImagePagerAdapter: AdapterLive? = null + private var mCurPos: Int = 0 + private var mMediaPlayer: MediaPlayer? = null + private var mDownDialog: DownDialog? = null + private var mAction = 0 + + override fun getContentView(): View { + binding = ActPreLiveBinding.inflate(layoutInflater) + return binding.root + } + + override fun initViews() { + super.initViews() + + var listBean: WallpaperImageListBean? = null + if (intent.hasExtra(LiveWallpaper.KEY_EXTRA_LIST)) { + listBean = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + intent.getSerializableExtra(LiveWallpaper.KEY_EXTRA_LIST, WallpaperImageListBean::class.java) + } else { + intent.getSerializableExtra(LiveWallpaper.KEY_EXTRA_LIST) as WallpaperImageListBean? + } + } + if (listBean == null) { + finish() + return + } + mList.clear() + mList.addAll(listBean.list) + + if (mList.size == 0) { + finish() + return + } + mCurPos = intent.getIntExtra(LiveWallpaper.KEY_EXTRA__POS, 0) + mImage = mList[mCurPos] + + mImagePagerAdapter = AdapterLive(this, mList) + mImagePagerAdapter?.setOnItemClickListener(object : + AdapterLive.OnItemClickListener { + override fun onItemClick(pos: Int) { + mAction = 2 + if (isExist()) { + playVideo() + } else { + showDownloadDialog() + } + } + }) + binding.viewPager.adapter = mImagePagerAdapter!! + binding.viewPager.setCurrentItem(mCurPos, false) + binding.viewPager.registerOnPageChangeCallback(object : + ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + mCurPos = position + mImage = mList[mCurPos] + } + + }) + + + binding.ivBack.throttleClicks { + onBackPressed() + } + + binding.tvSet.throttleClicks { + if (isExist()) { + setLiveWallpaper() + } else { + showDownloadDialog() + } + } + + binding.ivClose.throttleClicks { + stopHideVideo() + } + } + + override fun onResume() { + super.onResume() + if (binding.flPlay.isVisible) { + try { + mMediaPlayer?.start() + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + override fun onPause() { + super.onPause() + if (binding.flPlay.isVisible) { + try { + stopHideVideo() + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + + + override fun onDestroy() { + super.onDestroy() + mDownDialog?.dismiss() + mMediaPlayer?.stop() + mMediaPlayer?.release() + mMediaPlayer = null + } + + override fun onBackPressed() { + super.onBackPressed() + if (binding.flPlay.isVisible) { + stopHideVideo() + return + } + finish() + } + + private fun playVideo() { + val uri = getVideoUrl() ?: return + try { + if (mMediaPlayer == null) { + mMediaPlayer = MediaPlayer() + binding.surfaceVideo.holder.addCallback(object : SurfaceHolder.Callback { + override fun surfaceCreated(holder: SurfaceHolder) { + try { + mMediaPlayer?.reset() + mMediaPlayer?.setDataSource(this@PreVideoActivity, getVideoUrl()!!) + mMediaPlayer?.setDisplay(holder) + mMediaPlayer?.isLooping = true + mMediaPlayer?.setVolume(0f, 0f) + mMediaPlayer?.setOnPreparedListener { + try { + it.start() + } catch (e: Exception) { + e.printStackTrace() + } + } + mMediaPlayer?.prepareAsync() +// mMediaPlayer?.start() + } catch (e: Exception) { + e.printStackTrace() + } + } + + override fun surfaceChanged( + holder: SurfaceHolder, + format: Int, + width: Int, + height: Int + ) { + } + + override fun surfaceDestroyed(holder: SurfaceHolder) {} + + }) + } else { + mMediaPlayer?.reset() + mMediaPlayer?.setDataSource(this@PreVideoActivity, uri) + mMediaPlayer?.isLooping = true + mMediaPlayer?.setVolume(0f, 0f) + mMediaPlayer?.prepare() + } + binding.flPlay.show() + } catch (_: Exception) { + + } + } + + private fun stopHideVideo() { + try { + mMediaPlayer?.stop() + } catch (e: Exception) { + e.printStackTrace() + } + binding.flPlay.hide() + } + + + private fun getVideoUrl(): Uri? { + val file = DownloadUtil.getFile(mImage!!.preview, mImage!!.getTag()) + val uri = if (file.isFile && file.exists()) { + Uri.fromFile(file) + } else { + null + } + return uri + } + + private fun setLiveWallpaper() { + mImage?.let { video -> + Sp.video_url = video.preview + Sp.video_url_tag = video.getTag() + val manager = WallpaperManager.getInstance(this@PreVideoActivity) + val cn = ComponentName(this@PreVideoActivity, LiveService::class.java) + val info = manager.wallpaperInfo + if (info == null || info.component != cn) { + try { + val intent = Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER) + intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, cn) + startActivity(intent) + finish() + } catch (e: Exception) { + e.printStackTrace() + } + } else { + try { + val intent = Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER) + intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, cn) + startActivity(intent) + finish() + } catch (e: Exception) { + e.printStackTrace() + } + } + } + } + + + + + private fun isExist(): Boolean { + return DownloadUtil.isExist(mImage!!.preview, mImage!!.getTag()) + } + + private fun showDownloadDialog() { + mDownDialog = DownDialog( + this, + mutableListOf(mImage!!.preview), + mImage!!.getTag(), + R.string.loading_video.getMyStr() + ) { + onDownloadSuccess = { + if (mAction == 0) { + setLiveWallpaper() + } else { + playVideo() + } + mImagePagerAdapter?.notifyItemChanged(mCurPos) + } + onDownloadFailed = { + + } + } + if (!isFinishing) { + onMain { + mDownDialog?.show() + } + } + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/SetFragment.kt b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/SetFragment.kt new file mode 100644 index 0000000..6934a54 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/actandfrag/SetFragment.kt @@ -0,0 +1,33 @@ +package com.live.wallpaper.style.hd.actandfrag + +import android.content.pm.PackageManager +import android.view.View +import com.live.wallpaper.style.hd.LiveWallpaper +import com.live.wallpaper.style.hd.databinding.FragmentSettingsBinding + +class SetFragment: ParentFragment() { + + private lateinit var binding: FragmentSettingsBinding + + override fun getContentView(): View { + binding = FragmentSettingsBinding.inflate(layoutInflater) + return binding.root + } + override fun initViews() { + super.initViews() + binding.tvVersion.text = getAppVersionName() + binding.tvRateUs.setOnClickListener { + ContactFragment.newInstance(0, 0).show(childFragmentManager,"") + } + } + fun getAppVersionName(): String { + return try { + val pm: PackageManager = LiveWallpaper.app.packageManager + val pi = pm.getPackageInfo(LiveWallpaper.app.packageName, 0) + if (pi == null) "" else pi.versionName + } catch (e: PackageManager.NameNotFoundException) { + e.printStackTrace() + "" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/bean/InfoFile.kt b/app/src/main/java/com/live/wallpaper/style/hd/bean/InfoFile.kt new file mode 100644 index 0000000..7a6915d --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/bean/InfoFile.kt @@ -0,0 +1,5 @@ +package com.live.wallpaper.style.hd.bean + +class InfoFile(var url: String, var filePath: String? = null, var fileName: String? = null) { + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/bean/WallpaperImage.kt b/app/src/main/java/com/live/wallpaper/style/hd/bean/WallpaperImage.kt new file mode 100644 index 0000000..f087af0 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/bean/WallpaperImage.kt @@ -0,0 +1,22 @@ +package com.live.wallpaper.style.hd.bean + +import java.io.Serializable + +class WallpaperImage : Serializable { + var id: Long = 0 + + var wallpaperId: Long = 0 + + var title: String = "" + + var thumbnail: String = "" + + var category: Int = 0 + + var preview: String = "" + + + fun getTag(): String { + return "$wallpaperId" + } +} diff --git a/app/src/main/java/com/live/wallpaper/style/hd/bean/WallpaperImageListBean.kt b/app/src/main/java/com/live/wallpaper/style/hd/bean/WallpaperImageListBean.kt new file mode 100644 index 0000000..2915d34 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/bean/WallpaperImageListBean.kt @@ -0,0 +1,7 @@ +package com.live.wallpaper.style.hd.bean + +import java.io.Serializable + +class WallpaperImageListBean: Serializable { + var list: MutableList = mutableListOf() +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/customerDialog/DownDialog.kt b/app/src/main/java/com/live/wallpaper/style/hd/customerDialog/DownDialog.kt new file mode 100644 index 0000000..8b63311 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/customerDialog/DownDialog.kt @@ -0,0 +1,111 @@ +package com.live.wallpaper.style.hd.customerDialog + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import android.text.TextUtils +import android.view.LayoutInflater +import com.live.wallpaper.style.hd.R +import com.live.wallpaper.style.hd.databinding.ViewDownloadBinding +import com.live.wallpaper.style.hd.mytools.Common +import com.live.wallpaper.style.hd.mytools.Common.throttleClicks +import com.live.wallpaper.style.hd.mytools.asynchronous.asynchronousMan +import com.live.wallpaper.style.hd.mytools.download.NetListener +import com.live.wallpaper.style.hd.mytools.download.NetManager +import java.util.concurrent.atomic.AtomicInteger + +class DownDialog ( + private val ctx: Context, + private val urls: MutableList, + private val tag: String, + private val title: String = "", + init: DownDialog.() -> Unit +) : Dialog(ctx, R.style.AppDialog) { + + private lateinit var binding: ViewDownloadBinding + var onDownloadSuccess: (() -> Unit)? = null + var onDownloadFailed: (() -> Unit)? = null + private var mCount: AtomicInteger = AtomicInteger(0) + + init { + init() + } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ViewDownloadBinding.inflate(LayoutInflater.from(ctx)) + setContentView(binding.root) + + val p = window!!.attributes + p.width = (Common.getScreenWidth(ctx) * 0.8).toInt() //设置dialog的宽度为当前手机屏幕的宽度*0.8 + window!!.attributes = p + initViews() + } + + + private fun initViews() { + setCancelable(false) + setCanceledOnTouchOutside(false) + initView() + startDownload() + } + + private fun initView() { + if (!TextUtils.isEmpty(title)) { + binding.tvTitle.text = title + } + binding.ivClose.throttleClicks { + dismiss() + } + } + + private fun startDownload() { + binding.pbb.progress = 0f + for (url in urls) { + NetManager.instance.add(url, tag, object : NetListener { + override fun onFinished(url: String) { + if (urls.size > 1 && isShowing) { + val cur = if (mCount.get() >= urls.size - 1) { + 100 + } else { + (100 / urls.size) * mCount.get() + (100 / urls.size) + } + + binding.pbb.progress = cur.toFloat() + binding.tvPercent.text = "$cur%" + } + + mCount.incrementAndGet() + if (mCount.get() >= urls.size) { + if (isShowing) { + asynchronousMan.scheduleTaskOnUiThread(400) { + dismiss() + onDownloadSuccess?.invoke() + } + } + } + } + + override fun onProgress(url: String, progress: Float) { + if (urls.size == 1 && isShowing) { + binding.pbb.progress = progress * 100 + binding.tvPercent.text = "${(progress * 100).toInt()}%" + } + } + + override fun onPause(url: String) { + } + + override fun onCancel(url: String) { + if (isShowing) { + dismiss() + onDownloadFailed?.invoke() + } + } + + }) + } + asynchronousMan.scheduleTaskOnUiThread(200) { + NetManager.instance.download(urls) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/myliveservice/LiveService.kt b/app/src/main/java/com/live/wallpaper/style/hd/myliveservice/LiveService.kt new file mode 100644 index 0000000..b6ca7cf --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/myliveservice/LiveService.kt @@ -0,0 +1,145 @@ +package com.live.wallpaper.style.hd.myliveservice + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.media.MediaPlayer +import android.net.Uri +import android.service.wallpaper.WallpaperService +import android.util.Log +import android.view.SurfaceHolder +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.live.wallpaper.style.hd.LiveWallpaper +import com.live.wallpaper.style.hd.mytools.download.DownloadUtil +import com.live.wallpaper.style.hd.mytools.Sp + +class LiveService : WallpaperService() { + + companion object { + const val ACTION_SET_WALLPAPER = "LiveService" + } + + private lateinit var mBroadcastManager: LocalBroadcastManager + + override fun onCreate() { + super.onCreate() + Log.d("tep", "LiveService: onCreate") + mBroadcastManager = LocalBroadcastManager.getInstance(this) + } + + override fun onDestroy() { + super.onDestroy() + Log.d("tep", "LiveService: onCreate") + } + + override fun onCreateEngine(): Engine { + return VideoWallpaperEngine() + } + + inner class VideoWallpaperEngine : WallpaperService.Engine() { + + private var mMediaPlayer: MediaPlayer? = null + + //LiveWallpaperService正在运行时,更新替换视频 + private var mReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + Log.d("tep", "VideoWallpaperEngine: onReceive") + updateVideo() + } + + } + + override fun onCreate(surfaceHolder: SurfaceHolder?) { + super.onCreate(surfaceHolder) + Log.d("tep", "VideoWallpaperEngine: onCreate") + val filter = IntentFilter(ACTION_SET_WALLPAPER) + mBroadcastManager.registerReceiver(mReceiver, filter) + } + + override fun onSurfaceCreated(holder: SurfaceHolder?) { + super.onSurfaceCreated(holder) + Log.d("tep", "VideoWallpaperEngine: onSurfaceCreated") + val uri = getVideoUrl() + if (uri == null) { + Log.d("tep", "onSurfaceCreated video uri is null") + return + } + mMediaPlayer = MediaPlayer.create(LiveWallpaper.app, uri) + mMediaPlayer?.setSurface(holder!!.surface) + mMediaPlayer?.isLooping = true + mMediaPlayer?.setVolume(0f, 0f) + mMediaPlayer?.start() + } + + override fun onVisibilityChanged(visible: Boolean) { + super.onVisibilityChanged(visible) + Log.d( + "tep", + "VideoWallpaperEngine: onVisibilityChanged visible: $visible" + ) + if (visible) { + mMediaPlayer?.start() + } else { + mMediaPlayer?.pause() + } + } + + override fun onSurfaceDestroyed(holder: SurfaceHolder?) { + super.onSurfaceDestroyed(holder) + Log.d("tep", "VideoWallpaperEngine: onSurfaceDestroyed") + } + + override fun onDestroy() { + super.onDestroy() + Log.d("tep", "VideoWallpaperEngine: onDestroy") + mMediaPlayer?.let { + if (it.isPlaying) { + it.stop() + } + } + mMediaPlayer?.release() + mBroadcastManager.unregisterReceiver(mReceiver) + } + + override fun onSurfaceChanged( + holder: SurfaceHolder?, + format: Int, + width: Int, + height: Int + ) { + super.onSurfaceChanged(holder, format, width, height) + Log.d("tep", "VideoWallpaperEngine: onSurfaceChanged") + } + + private fun getVideoUrl(): Uri? { + val file = DownloadUtil.getFile(Sp.video_url, Sp.video_url_tag) + + val uri = if (file.isFile && file.exists()) { + Uri.fromFile(file) + } else { + null + } + Log.d("tep", "video uri: $uri") + return uri + } + + private fun updateVideo() { + Log.d("tep", "updateVideo...") + + val uri = getVideoUrl() + if (uri == null) { + Log.d("tep", "updateVideo video uri is null") + return + } + + //setDataSource()要结合reset()和prepare()一起用才会生效且不报错 + mMediaPlayer?.reset() +// mMediaPlayer?.setSurface(surfaceHolder.surface) + mMediaPlayer?.setDataSource(this@LiveService, uri) + mMediaPlayer?.isLooping = true + mMediaPlayer?.setVolume(0f, 0f) + mMediaPlayer?.prepare() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/Common.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/Common.kt new file mode 100644 index 0000000..a24d18c --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/Common.kt @@ -0,0 +1,83 @@ +package com.live.wallpaper.style.hd.mytools + +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope +import com.jakewharton.rxbinding4.view.clicks +import com.live.wallpaper.style.hd.LiveWallpaper +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.launch +import java.util.concurrent.TimeUnit + +object Common { + fun onMain(operation: () -> Unit) = Handler(Looper.getMainLooper()).post(operation) + + fun Int.getMyStr(): String = getCustString(this) + fun Int.dp2PxInt(): Int = dp2Px(this) + + fun getCustString(resId: Int): String { + return LiveWallpaper.app.getString(resId) + } + fun dp2Px(dp: Int): Int { + val scale: Float = LiveWallpaper.app.resources.displayMetrics.density + return (dp * scale + 0.5f).toInt() + } + + + fun getScreenHeight(context: Context): Int { + return context.resources.displayMetrics.heightPixels + } + + + fun getScreenWidth(context: Context): Int { + return context.resources.displayMetrics.widthPixels + } + + + fun View.throttleClicks(time: Long = 1000, block: (View) -> Unit) { + this.clicks().throttleFirst(time, TimeUnit.MILLISECONDS).subscribe { block(this) } + } + + + fun View.show() { + this.visibility = View.VISIBLE + } + + fun View.hide() { + this.visibility = View.GONE + } + + fun AppCompatActivity.countDown( + time: Int = 15, + start: (scop: CoroutineScope) -> Unit, + next: (time: String) -> Unit, + end: () -> Unit + ) { + lifecycleScope.launch { + + flow { + (time downTo 0).forEach { + delay(1000) + emit(it) + } + }.onStart { + start(this@launch) + }.onCompletion { + end() + }.catch { + + }.collect { + + next(it.toString()) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/Sp.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/Sp.kt new file mode 100644 index 0000000..bc1e1fb --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/Sp.kt @@ -0,0 +1,48 @@ +package com.live.wallpaper.style.hd.mytools + +import android.content.Context +import android.content.SharedPreferences +import com.live.wallpaper.style.hd.LiveWallpaper + +object Sp { + + var video_url: String + get() = queryString( + LiveWallpaper.URL_Video, + "" + ) + set(value) { + saveString(LiveWallpaper.URL_Video, value) + } + + var video_url_tag: String + get() = queryString( + LiveWallpaper.URL_TAG, + "" + ) + set(value) { + saveString(LiveWallpaper.URL_TAG, value) + } + + + private const val defaultFile = "chat_mate" + + private fun read(ctx: Context, file: String? = defaultFile): SharedPreferences { + return ctx.getSharedPreferences(file, Context.MODE_PRIVATE) + } + + private fun write(ctx: Context, file: String? = defaultFile): SharedPreferences.Editor { + return ctx.getSharedPreferences(file, Context.MODE_PRIVATE).edit() + } + + fun saveString(key: String, value: String) { + write(LiveWallpaper.app) + .putString(key, value).apply() + } + + fun queryString(key: String, defaultValue: String): String { + return read(LiveWallpaper.app) + .getString(key, defaultValue).orEmpty() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/SpaceDecoration.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/SpaceDecoration.kt new file mode 100644 index 0000000..d6cab92 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/SpaceDecoration.kt @@ -0,0 +1,70 @@ +package com.live.wallpaper.style.hd.mytools + +import android.graphics.Rect +import android.view.View +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.live.wallpaper.style.hd.mytools.Common.dp2PxInt + +class SpaceDecoration : RecyclerView.ItemDecoration { + + + private var verticalSpacing = 0 + private var horizontalSpacing = 0 + private var extraSpacing = 0 + var needVerticalSpacingInSingleLine = true + var needHorizontalSpacingInSingleLine = true + + constructor(spacing: Int) { + initSpacing(spacing, spacing, 0) + } + + constructor(spacing: Int, extraSpacing: Int) { + initSpacing(spacing, spacing, extraSpacing) + } + + constructor(verticalSpacing: Int, horizontalSpacing: Int, extraSpacing: Int) { + initSpacing(verticalSpacing, horizontalSpacing, extraSpacing) + } + + private fun initSpacing(verticalSpacing: Int, horizontalSpacing: Int, extraSpacing: Int) { + this.horizontalSpacing = horizontalSpacing.dp2PxInt() + this.verticalSpacing = verticalSpacing.dp2PxInt() + this.extraSpacing = extraSpacing.dp2PxInt() + } + + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + val position = parent.getChildAdapterPosition(view) + var spanCount = 1 + var spanSize = 1 + var spanIndex = 0 + + parent.layoutManager?.run { + if(this is GridLayoutManager){ + spanCount = this.spanCount + spanSize = this.spanSizeLookup.getSpanSize(position) + spanIndex = (view.layoutParams as GridLayoutManager.LayoutParams).spanIndex + } + } + + if (spanSize == spanCount) { + outRect.left = + if (needVerticalSpacingInSingleLine) verticalSpacing + extraSpacing else 0 + outRect.right = + if (needVerticalSpacingInSingleLine) verticalSpacing + extraSpacing else 0 + outRect.bottom = if (needHorizontalSpacingInSingleLine) horizontalSpacing else 0 + } else { + val itemAllSpacing = (verticalSpacing * (spanCount + 1) + extraSpacing * 2) / spanCount + val left = verticalSpacing * (spanIndex + 1) - itemAllSpacing * spanIndex + extraSpacing + val right = itemAllSpacing - left + outRect.left = left + outRect.right = right + outRect.bottom = horizontalSpacing + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/WallpaperDataUtil.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/WallpaperDataUtil.kt new file mode 100644 index 0000000..a112a8d --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/WallpaperDataUtil.kt @@ -0,0 +1,72 @@ +package com.live.wallpaper.style.hd.mytools + +import com.live.wallpaper.style.hd.LiveWallpaper +import com.live.wallpaper.style.hd.bean.WallpaperImage +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import org.json.JSONArray +import java.io.BufferedReader +import java.io.InputStreamReader +import java.io.Reader +import java.io.StringWriter +import java.nio.charset.StandardCharsets + +object WallpaperDataUtil { + + var liveList = mutableListOf() + + fun assestGet() { + GlobalScope.launch(Dispatchers.IO) { + + val jsonLive = getdataString("live.json") + if (jsonLive.isNotEmpty()) { + val list = covertBean(jsonLive) + if (list.isNotEmpty()) { + liveList.addAll(list) + } + } + } + } + + private fun getdataString(name: String): String { + var json = "" + try { + val inputStream = LiveWallpaper.app.assets.open(name) + val writer = StringWriter() + val buffer = CharArray(inputStream.available()) + val reader: Reader = + BufferedReader(InputStreamReader(inputStream, StandardCharsets.UTF_8)) + var n: Int + while (reader.read(buffer).also { n = it } != -1) { + writer.write(buffer, 0, n) + } + json = writer.toString() + } catch (e: Exception) { + e.printStackTrace() + } + return json + } + + + private fun covertBean(json: String): MutableList { + val list = mutableListOf() + val jsonArray = JSONArray(json) + for (i in 0 until jsonArray.length()) { + try { + val obj = jsonArray.getJSONObject(i) + val bean = WallpaperImage() + bean.wallpaperId = obj.getLong("id") + bean.title = obj.getString("title") + bean.thumbnail = obj.getString("thumbnail") + bean.preview = obj.getString("preview") + bean.category = obj.getInt("category") + list.add(bean) + } catch (_: Exception) { + continue + } + } + return list + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/AsynQueue.java b/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/AsynQueue.java new file mode 100644 index 0000000..60d4a14 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/AsynQueue.java @@ -0,0 +1,46 @@ +package com.live.wallpaper.style.hd.mytools.asynchronous; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public class AsynQueue extends Thread{ + private BlockingQueue mQueue; + + public AsynQueue() { + mQueue = new LinkedBlockingQueue(); + } + + public AsynQueue(String name) { + this(); + setName(name); + } + + public void stopTaskQueue() { + // use 'Poison Pill Shutdown' to stop the task queue + // add a non-Runnable object, which will be recognized as the command + // by the thread to break the infinite loop + mQueue.add(new Object()); + } + + public void scheduleTask(Runnable task) { + mQueue.add(task); + } + + @Override + public void run() { + while (true) { + try { + Object obj = mQueue.take(); + + if (obj instanceof Runnable) { + ((Runnable) obj).run(); + obj = null; + } else { + break; + } + + } catch (InterruptedException e) { + } + } + } +} diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/MyPool.java b/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/MyPool.java new file mode 100644 index 0000000..c3afd3b --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/MyPool.java @@ -0,0 +1,47 @@ +package com.live.wallpaper.style.hd.mytools.asynchronous; + +import android.os.Handler; +import android.os.Looper; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class MyPool { + private static final Long IDLE_THREAD_KEEP_ALIVE_TIME = 60L; + private ExecutorService mThreadPoolExecutor; + private Handler mMainHandler; + private AsynQueue mActionQueue; + private ScheduledThreadPoolExecutor mScheduledThreadPoolExecutor; + + + + public MyPool(int activeThreadCount, int maxThreadCount, int maxScheTaskThread) { + mThreadPoolExecutor = new ThreadPoolExecutor(activeThreadCount, maxThreadCount, + IDLE_THREAD_KEEP_ALIVE_TIME, TimeUnit.SECONDS, + new LinkedBlockingQueue()); + + if (maxScheTaskThread > 0) { + mScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(maxScheTaskThread); + } + + mMainHandler = new Handler(Looper.getMainLooper()); + mActionQueue = new AsynQueue(asynchronousMan.class.getName()); + mActionQueue.start(); + } + + + + + + public void scheduleTaskOnUiThread(long delay, Runnable task) { + if (task == null) { + return; + } + mMainHandler.postDelayed(task, delay); + } + + +} diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/asynchronousMan.java b/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/asynchronousMan.java new file mode 100644 index 0000000..4d617ae --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/asynchronous/asynchronousMan.java @@ -0,0 +1,27 @@ +package com.live.wallpaper.style.hd.mytools.asynchronous; + +public class asynchronousMan { + private static MyPool sMyPool; + + private static MyPool getThreadPoolExecutorWrapper() { + if (sMyPool == null) { + synchronized (asynchronousMan.class) { + if (sMyPool == null) { + sMyPool = new MyPool(12, 12, 10); +// if (BuildConfig.DEBUG) +// LogUtil.d(LogFilterDef.APP_INIT, LogHelper.getFileLineMethod(1)); + } + } + } + + return sMyPool; + } + + + + public static void scheduleTaskOnUiThread(long delay, Runnable task) { + getThreadPoolExecutorWrapper().scheduleTaskOnUiThread(delay, task); + } + + +} diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/DownloadUtil.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/DownloadUtil.kt new file mode 100644 index 0000000..35828fe --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/DownloadUtil.kt @@ -0,0 +1,26 @@ +package com.live.wallpaper.style.hd.mytools.download + +import android.text.TextUtils +import java.io.File + +object DownloadUtil { + + fun getFileName(url: String, tag: String?): String { + return if (TextUtils.isEmpty(tag)) { + url.substring(url.lastIndexOf("/") + 1) + } else { + tag + url.substring(url.lastIndexOf("/") + 1) + } + } + fun getFilePath(url: String, tag: String?): String { + return FileTools.getDownloadDirectory() + File.separator + getFileName(url, tag) + } + + fun getFile(url: String, tag: String?): File { + return File(getFilePath(url, tag)) + } + + fun isExist(url: String, tag: String?): Boolean { + return File(getFilePath(url, tag)).exists() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/FileTools.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/FileTools.kt new file mode 100644 index 0000000..d4192b6 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/FileTools.kt @@ -0,0 +1,205 @@ +package com.live.wallpaper.style.hd.mytools.download + +import android.content.ContentResolver +import android.content.ContentUris +import android.content.Context +import android.database.Cursor +import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.DocumentsContract +import android.provider.MediaStore +import android.util.Log +import com.live.wallpaper.style.hd.LiveWallpaper +import java.io.File +import java.io.IOException +import java.io.InputStream +import java.io.OutputStream + + +object FileTools { + private const val DIR_FILE_NAME = "tep" + private const val DIR_DOWNLOAD = "download" + private fun getDefaultDirectory(): String { + var dirName = "" + if (LiveWallpaper.app.getExternalFilesDir(DIR_FILE_NAME) != null) {//外部存储可用 + if (Build.VERSION.SDK_INT >= 29) { + dirName = LiveWallpaper.app.getExternalFilesDir(DIR_FILE_NAME)!!.path + } else if (Build.VERSION.SDK_INT < 29) { + dirName = LiveWallpaper.app.getExternalFilesDir(DIR_FILE_NAME)!!.absolutePath + } + } else {//外部存储不可用 + dirName = LiveWallpaper.app.filesDir.absolutePath + } + return dirName + } + fun getDownloadDirectory(): String { + return getDefaultDirectory() + File.separator + DIR_DOWNLOAD + } + + /** + * @param path 文件绝对路径 + */ + fun isExists(path: String): Boolean { + return File(path).exists() + } + + /** + * 获取下载文件的名称 + 后缀名 + */ + fun getFileNameAndSuffix(path: String): String { + return path.substring(path.lastIndexOf("/") + 1) + } + + fun getFileName(path: String): String? { + val start = path.lastIndexOf("/") + val end = path.lastIndexOf(".") + return if (start != -1 && end != -1) { + path.substring(start + 1, end) + } else { + null + } + } + + /** + * 1.URI 为 content://com.android.providers.media.documents/document/image%3A235700 + * 因为在 Android 4.4 及以上的机型,使用了 DocumentUri 来代表获取到文件的 URI + * 要对于 DocumentUri 进行适配 + * 2.URI 为 content://media/extenral/images/media/17766 而我们需要得到对应的文件路径。 + * 参考:https://blog.csdn.net/rjc_lihui/article/details/127020909 + */ + fun getFilePathByUri(context: Context, uri: Uri): String? { + var path: String? = null + // 以 file:// 开头的 + if (ContentResolver.SCHEME_FILE == uri.scheme) { + path = uri.path + return path + } + // 以 content:// 开头的,比如 content://media/extenral/images/media/17766 + if (ContentResolver.SCHEME_CONTENT == uri.scheme && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + val cursor = context.contentResolver.query( + uri, + arrayOf(MediaStore.Images.Media.DATA), + null, + null, + null + ) + if (cursor != null) { + if (cursor.moveToFirst()) { + val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) + if (columnIndex > -1) { + path = cursor.getString(columnIndex) + } + } + cursor.close() + } + return path + } + // 4.4及之后的 是以 content:// 开头的,比如 content://com.android.providers.media.documents/document/image%3A235700 + if (ContentResolver.SCHEME_CONTENT == uri.scheme && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (DocumentsContract.isDocumentUri(context, uri)) { + if (isExternalStorageDocument(uri)) { + // ExternalStorageProvider + val docId = DocumentsContract.getDocumentId(uri) + val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() } + .toTypedArray() + val type = split[0] + if ("primary".equals(type, ignoreCase = true)) { + path = Environment.getExternalStorageDirectory().toString() + "/" + split[1] + return path + } + } else if (isDownloadsDocument(uri)) { + // DownloadsProvider + val id = DocumentsContract.getDocumentId(uri) + val contentUri = ContentUris.withAppendedId( + Uri.parse("content://downloads/public_downloads"), + java.lang.Long.valueOf(id) + ) + path = getDataColumn(context, contentUri, null, null) + return path + } else if (isMediaDocument(uri)) { + // MediaProvider + val docId = DocumentsContract.getDocumentId(uri) + val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() } + .toTypedArray() + val type = split[0] + var contentUri: Uri? = null + if ("image" == type) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI + } else if ("video" == type) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI + } else if ("audio" == type) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + } + val selection = "_id=?" + val selectionArgs = arrayOf(split[1]) + path = getDataColumn(context, contentUri, selection, selectionArgs) + return path + } + } + } + return null + } + + private fun getDataColumn( + context: Context, + uri: Uri?, + selection: String?, + selectionArgs: Array? + ): String? { + var cursor: Cursor? = null + val column = "_data" + val projection = arrayOf(column) + try { + cursor = + context.contentResolver.query(uri!!, projection, selection, selectionArgs, null) + if (cursor != null && cursor.moveToFirst()) { + val column_index = cursor.getColumnIndexOrThrow(column) + return cursor.getString(column_index) + } + } finally { + cursor?.close() + } + return null + } + + private fun isExternalStorageDocument(uri: Uri): Boolean { + return "com.android.externalstorage.documents" == uri.authority + } + + private fun isDownloadsDocument(uri: Uri): Boolean { + return "com.android.providers.downloads.documents" == uri.authority + } + + private fun isMediaDocument(uri: Uri): Boolean { + return "com.android.providers.media.documents" == uri.authority + } + + fun getFileName(contentResolver: ContentResolver, uri: Uri): String? { + val projection = arrayOf(MediaStore.MediaColumns.DISPLAY_NAME) + contentResolver.query(uri, projection, null, null, null)?.use { + if (it.moveToFirst()) { + return it.getString(0) + + } + } + return null + } + + fun getFileInputStream(fileUri: Uri): InputStream? = + try { + LiveWallpaper.app.contentResolver.openInputStream(fileUri) + } catch (e: IOException) { + val errorInfo = "Error opening external file at $fileUri: $e" + Log.d("tep", errorInfo) + null + } + fun getFileOutStream(fileName: String): OutputStream? = + try { + LiveWallpaper.app.openFileOutput(fileName, Context.MODE_PRIVATE) + } catch (e: IOException) { + val errorInfo = "Error opening internal file: $fileName: $e" + Log.d("tep", errorInfo) + null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/HttpNet.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/HttpNet.kt new file mode 100644 index 0000000..cc777db --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/HttpNet.kt @@ -0,0 +1,72 @@ +package com.live.wallpaper.style.hd.mytools.download + +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import java.io.IOException +import java.util.concurrent.TimeUnit + +class HttpNet { + private var mOkHttpClient: OkHttpClient? = null + + companion object { + val mInstance: HttpNet by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { + HttpNet() + } + } + + private val CONNECT_TIMEOUT: Long = 60 //超时时间,秒 + + private val READ_TIMEOUT: Long = 60 //读取时间,秒 + + private val WRITE_TIMEOUT: Long = 60 //写入时间,秒 + + init { + val builder: OkHttpClient.Builder = OkHttpClient.Builder() + .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS) + .readTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS) + mOkHttpClient = builder.build() + } + + + /** + * @param url 下载链接 + * @param startIndex 下载起始位置 + * @param endIndex 结束为止 + * @param callback 回调 + * @throws IOException + */ + @Throws(IOException::class) + fun downloadFileByRange(url: String, startIndex: Long, endIndex: Long, callback: Callback) { + // 创建一个Request + // 设置分段下载的头信息。 Range:做分段数据请求,断点续传指示下载的区间。格式: Range bytes=0-1024或者bytes:0-1024 + val request: Request = Request.Builder().header("RANGE", "bytes=$startIndex-$endIndex") + .url(url) + .build() + doAsync(request, callback) + } + + @Throws(IOException::class) + fun getContentLength(url: String, callback: Callback) { + // 创建一个Request + val request: Request = Request.Builder() + .url(url) + .build() + doAsync(request, callback) + } + + + /** + * 异步请求 + */ + @Throws(IOException::class) + private fun doAsync(request: Request, callback: Callback) { + //创建请求会话 + val call = mOkHttpClient!!.newCall(request) + //同步执行会话请求 + call.enqueue(callback) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/MyTask.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/MyTask.kt new file mode 100644 index 0000000..932e531 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/MyTask.kt @@ -0,0 +1,358 @@ +package com.live.wallpaper.style.hd.mytools.download + +import android.os.Handler +import android.os.Message +import android.util.Log +import com.live.wallpaper.style.hd.BuildConfig +import com.live.wallpaper.style.hd.bean.InfoFile +import okhttp3.Call +import okhttp3.Response +import java.io.Closeable +import java.io.File +import java.io.IOException +import java.io.RandomAccessFile +import java.util.concurrent.atomic.AtomicInteger + +class MyTask(point: InfoFile, l: NetListener?) : Handler() { + + private val TAG = "MyTask" + private val THREAD_COUNT = 3 //线程数 + + private var mPoint: InfoFile + private var mFileLength: Long = 0 + + @Volatile + private var isDownloading = false + private val childCancelCount = AtomicInteger(0) //子线程取消数量 + private val childPauseCount = AtomicInteger(0) //子线程暂停数量 + private val childFinishCount = AtomicInteger(0) //子线程完成数量 + + private var mHttpNet: HttpNet + private var mProgress: LongArray + private var mCacheFiles: Array + private var mTmpFile: File? = null//临时占位文件 + + @Volatile + private var pause = false //是否暂停 + + @Volatile + private var cancel = false //是否取消下载 + private val MSG_PROGRESS = 1 //进度 + + private val MSG_FINISH = 2 //完成下载 + + private val MSG_PAUSE = 3 //暂停 + + private val MSG_CANCEL = 4 //暂停 + + private var mListener: NetListener? = null //下载回调监听 + + init { + mPoint = point + mListener = l + mProgress = LongArray(THREAD_COUNT) + mCacheFiles = arrayOfNulls(THREAD_COUNT) + mHttpNet = HttpNet.mInstance + } + + /** + * 任务回调消息 + * + * @param msg + */ + override fun handleMessage(msg: Message) { + if (null == mListener) { + return + } + when (msg.what) { + MSG_PROGRESS -> { + var progress: Long = 0 + var i = 0 + val length = mProgress.size + while (i < length) { + progress += mProgress[i] + i++ + } + + val p = progress * 1.0f / mFileLength + +// if (BuildConfig.DEBUG) { +// Log.d(TAG, "${mPoint.getUrl()} is downloading: $p") +// } + mListener!!.onProgress(mPoint.url, p) + } + + MSG_PAUSE -> { + if (confirmStatus(childPauseCount)) return + resetStutus() + if (BuildConfig.DEBUG) { + Log.d(TAG, "${mPoint.url} is pause") + } + mListener!!.onPause(mPoint.url) + } + + MSG_FINISH -> { + if (confirmStatus(childFinishCount)) return + //下载完毕后,重命名目标文件名 + val renameResult = mTmpFile!!.renameTo( + File( + mPoint.filePath, + mPoint.fileName + ) + ) + resetStutus() + if (BuildConfig.DEBUG) { + Log.d( + TAG, + "重命名结果:$renameResult" + ) + Log.d( + TAG, + "file is downloaded, path: ${mTmpFile!!.absolutePath}" + ) + } + mListener!!.onFinished(mPoint.url) + } + + MSG_CANCEL -> { + if (confirmStatus(childCancelCount)) return + resetStutus() + mProgress = LongArray(THREAD_COUNT) + if (BuildConfig.DEBUG) { + Log.d(TAG, "${mPoint.url} is cancel") + } + mListener!!.onCancel(mPoint.url) + } + } + } + + @Synchronized + fun start() { + try { + if (isDownloading) return + isDownloading = true + + if (BuildConfig.DEBUG) { + Log.d( + TAG, + "start: ${mPoint.url}" + ) + } + mHttpNet.getContentLength(mPoint.url, object : okhttp3.Callback { + + override fun onResponse(call: Call, response: Response) { + if (BuildConfig.DEBUG) { + Log.d( + TAG, + "start: ${mPoint.url} response.code: ${response.code}" + ) + } + + if (response.code != 200) { + close(response.body) + resetStutus() + return + } + // 获取资源大小 + mFileLength = response.body!!.contentLength() + if (mFileLength < 0) { + return + } + close(response.body) + // 在本地创建一个与资源同样大小的文件来占位 + mTmpFile = File(mPoint.filePath, mPoint.fileName.toString() + ".tmp") + if (!mTmpFile!!.parentFile.exists()) { + mTmpFile!!.parentFile.mkdirs() + } + val tmpAccessFile = RandomAccessFile(mTmpFile, "rw") + tmpAccessFile.setLength(mFileLength) + /*将下载任务分配给每个线程*/ + val blockSize = mFileLength / THREAD_COUNT // 计算每个线程理论上下载的数量. + + /*为每个线程配置并分配任务*/ + for (threadId in 0 until THREAD_COUNT) { + val startIndex = threadId * blockSize // 线程开始下载的位置 + var endIndex = (threadId + 1) * blockSize - 1 // 线程结束下载的位置 + if (threadId == THREAD_COUNT - 1) { // 如果是最后一个线程,将剩下的文件全部交给这个线程完成 + endIndex = mFileLength - 1 + } + download(startIndex, endIndex, threadId) // 开启线程下载 + } + } + + override fun onFailure(call: Call, e: IOException) { + if (BuildConfig.DEBUG) { + Log.e(TAG, e.toString()) + } + resetStutus() + } + }) + } catch (e: Exception) { + if (BuildConfig.DEBUG) { + Log.e(TAG, e.toString()) + } + resetStutus() + } + } + + @Throws(IOException::class) + private fun download(startIndex: Long, endIndex: Long, threadId: Int) { + if (BuildConfig.DEBUG) { + Log.d( + TAG, + "download: ${mPoint.url}" + ) + } + var newStartIndex = startIndex + // 分段请求网络连接,分段将文件保存到本地. + // 加载下载位置缓存文件 + val cacheFile: File = + File(mPoint.filePath, "thread" + threadId + "_" + mPoint.fileName + ".cache") + mCacheFiles[threadId] = cacheFile + val cacheAccessFile = RandomAccessFile(cacheFile, "rwd") + if (cacheFile.exists()) { // 如果文件存在 + val startIndexStr = cacheAccessFile.readLine() + try { + newStartIndex = startIndexStr.toInt().toLong() //重新设置下载起点 + } catch (e: Exception) { + if (BuildConfig.DEBUG) { + Log.e(TAG, e.toString()) + } + e.printStackTrace() + } + } + val finalStartIndex = newStartIndex + if (BuildConfig.DEBUG) { + Log.d( + TAG, + "finalStartIndex: $finalStartIndex" + ) + Log.d( + TAG, + "endIndex: $endIndex" + ) + } + mHttpNet.downloadFileByRange( + mPoint.url, + finalStartIndex, + endIndex, + object : okhttp3.Callback { + + override fun onResponse(call: Call, response: Response) { + if (BuildConfig.DEBUG) { + Log.d( + TAG, + "download: ${mPoint.url} response.code: ${response.code}" + ) + } + if (response.code != 206) { // 206:请求部分资源成功码 + resetStutus() + return + } + val stream = response.body!!.byteStream() // 获取流 + val tmpAccessFile = RandomAccessFile(mTmpFile, "rw") // 获取前面已创建的文件. + tmpAccessFile.seek(finalStartIndex) // 文件写入的开始位置. + /* 将网络流中的文件写入本地*/ + val buffer = ByteArray(1024 shl 2) + var length = -1 + var total = 0 // 记录本次下载文件的大小 + var progress: Long = 0 + while (stream.read(buffer).also { length = it } > 0) { + if (cancel) { + //关闭资源 + close(cacheAccessFile, stream, response.body) + cleanFile(cacheFile) + sendEmptyMessage(MSG_CANCEL) + return + } + if (pause) { + //关闭资源 + close(cacheAccessFile, stream, response.body) + //发送暂停消息 + sendEmptyMessage(MSG_PAUSE) + return + } + tmpAccessFile.write(buffer, 0, length) + total += length + progress = finalStartIndex + total + + //将当前现在到的位置保存到文件中 + cacheAccessFile.seek(0) + cacheAccessFile.write((progress.toString() + "").toByteArray(charset("UTF-8"))) + //发送进度消息 + mProgress[threadId] = progress - startIndex + sendEmptyMessage(MSG_PROGRESS) + } + //关闭资源 + close(cacheAccessFile, stream, response.body) + // 删除临时文件 + cleanFile(cacheFile) + //发送完成消息 + sendEmptyMessage(MSG_FINISH) + } + + override fun onFailure(call: Call, e: IOException) { + isDownloading = false + } + }) + } + + /** + * 关闭资源 + * + * @param closeables + */ + private fun close(vararg closeables: Closeable?) { + val length = closeables.size + try { + for (i in 0 until length) { + val closeable = closeables[i] + if (null != closeable) closeables[i]!!.close() + } + } catch (e: IOException) { + if (BuildConfig.DEBUG) { + Log.e(TAG, e.toString()) + } + e.printStackTrace() + } finally { + for (i in 0 until length) { +// closeables[i] = null + } + } + } + + /** + * 删除临时文件 + */ + private fun cleanFile(vararg files: File?) { + var i = 0 + val length = files.size + while (i < length) { + if (null != files[i]) files[i]!!.delete() + i++ + } + } + + + + /** + * 重置下载状态 + */ + private fun resetStutus() { + pause = false + cancel = false + isDownloading = false + } + + /** + * 确认下载状态 + * + * @param count + * @return + */ + private fun confirmStatus(count: AtomicInteger): Boolean { + return count.incrementAndGet() % THREAD_COUNT != 0 + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/NetListener.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/NetListener.kt new file mode 100644 index 0000000..167d4e0 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/NetListener.kt @@ -0,0 +1,11 @@ +package com.live.wallpaper.style.hd.mytools.download + +interface NetListener { + fun onFinished(url: String) + + fun onProgress(url: String, progress: Float) + + fun onPause(url: String) + + fun onCancel(url: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/NetManager.kt b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/NetManager.kt new file mode 100644 index 0000000..39dd126 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/mytools/download/NetManager.kt @@ -0,0 +1,70 @@ +package com.live.wallpaper.style.hd.mytools.download + +import android.text.TextUtils +import com.live.wallpaper.style.hd.bean.InfoFile + +class NetManager { + + private var DEFAULT_FILE_DIR: String? = null //默认下载目录 + private var mMyTasks: MutableMap = + mutableMapOf() //文件下载任务索引,String为url,用来唯一区别并操作下载的文件 + + companion object { + val instance: NetManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { + NetManager() + } + } + + /** + * 添加下载任务 + * tag是用来区别下载文件的文件名相同的情况 + */ + fun add(url: String, tag: String, l: NetListener?) { + add(url, null, null, tag, l) + } + + /** + * 添加下载任务 + * tag是用来区别下载文件的文件名相同的情况 + */ + fun add(url: String, filePath: String?, fileName: String?, tag: String?, l: NetListener?) { + var filePath = filePath + var fileName = fileName + if (TextUtils.isEmpty(filePath)) { //没有指定下载目录,使用默认目录 + filePath = FileTools.getDownloadDirectory() + } + if (TextUtils.isEmpty(fileName)) { + fileName = DownloadUtil.getFileName(url, tag) + } + mMyTasks[url] = MyTask(InfoFile(url, filePath, fileName), l) + } + + /** + * 下载文件 要放在主线程中运行 否则 Can't create handler inside thread Thread[pool-13-thread-2,5,main] that has not called Looper.prepare() + */ + fun download(urls: MutableList) { + //单任务开启下载或多任务开启下载 + urls.forEach { url -> + if (mMyTasks.containsKey(url)) { + mMyTasks[url]!!.start() + } + } + } + + /** + * 下载文件 + */ + fun download(vararg urls: String?) { + //单任务开启下载或多任务开启下载 + var i = 0 + val length = urls.size + while (i < length) { + val url = urls[i] + if (mMyTasks.containsKey(url)) { + mMyTasks[url]!!.start() + } + i++ + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterLive.kt b/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterLive.kt new file mode 100644 index 0000000..75a1dd1 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterLive.kt @@ -0,0 +1,106 @@ +package com.live.wallpaper.style.hd.recycleradapter + +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.live.wallpaper.style.hd.bean.WallpaperImage +import com.live.wallpaper.style.hd.databinding.ItemPreviewLiveBinding +import com.live.wallpaper.style.hd.mytools.download.DownloadUtil +import com.bumptech.glide.Glide +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.target.Target +import com.live.wallpaper.style.hd.mytools.Common.hide +import com.live.wallpaper.style.hd.mytools.Common.show + +class AdapterLive (private val ctx: Context, private val list: MutableList) : + RecyclerView.Adapter() { + + private var mListener: OnItemClickListener? = null + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH { + return VH(ItemPreviewLiveBinding.inflate(LayoutInflater.from(ctx), parent, false)) + } + + override fun onBindViewHolder(holder: VH, position: Int) { + if (list.isEmpty()) { + return + } + if (position >= list.size) { + return + } + val bean = list[position] + holder.mItemBinding?.ivPlaceholder?.show() + + + val url = if (DownloadUtil.isExist(bean.preview, bean.getTag())) { + DownloadUtil.getFilePath(bean.preview, bean.getTag()) + } else { + bean.thumbnail + } +// val url = bean.thumbnail + holder.mItemBinding?.ivWallpaper?.let { + Glide.with(ctx) + .load(url) + .transition(DrawableTransitionOptions.withCrossFade()) + .listener(object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: Target?, + isFirstResource: Boolean + ): Boolean { + holder.mItemBinding?.ivPlaceholder?.show() + Log.d("-----------","----------fail--$url") + return false + } + + override fun onResourceReady( + resource: Drawable?, + model: Any?, + target: Target?, + dataSource: DataSource?, + isFirstResource: Boolean + ): Boolean { + holder.mItemBinding?.ivPlaceholder?.hide() + return false + } + }) + .into(it) + } + holder.mItemBinding?.ivPlay?.let { + it.setOnClickListener { mListener?.onItemClick(holder.adapterPosition) } + } + } + + override fun getItemCount(): Int { + return list.size + } + + fun setOnItemClickListener(listener: OnItemClickListener) { + mListener = listener + } + + interface OnItemClickListener { + fun onItemClick(pos: Int) + } + + class VH(itemView: View) : RecyclerView.ViewHolder(itemView) { + + var mItemBinding: ItemPreviewLiveBinding? = null + + constructor(binding: ItemPreviewLiveBinding) : this(binding.root) { + this.mItemBinding = binding + } + + fun getRoot(): View? { + return mItemBinding?.root + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterStar.kt b/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterStar.kt new file mode 100644 index 0000000..184fa0b --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterStar.kt @@ -0,0 +1,54 @@ +package com.live.wallpaper.style.hd.recycleradapter + +import android.annotation.SuppressLint +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.live.wallpaper.style.hd.databinding.ItemRateStartBinding + +class AdapterStar(private val context: Context, private var clickAction: (Int) -> Unit) : + RecyclerView.Adapter() { + + + private var clickPos: Int? = null + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder = MyViewHolder( + ItemRateStartBinding.inflate( + LayoutInflater.from(parent.context), parent, false + ) + ) + + override fun getItemCount(): Int = 5 + + override fun onBindViewHolder(holder: MyViewHolder, position: Int) { + holder.bind(position) + + } + + @SuppressLint("NotifyDataSetChanged") + inner class MyViewHolder(private val binding: ItemRateStartBinding) : + RecyclerView.ViewHolder(binding.root) { + init { +// binding.root.setOnClickListener { +// val position = bindingAdapterPosition +// if (position != RecyclerView.NO_POSITION) { +// clickAction.invoke(position) +// } +// +// } + } + + fun bind(position: Int) { + clickPos?.let { + binding.imStart.isSelected = position <= it + } + binding.consStart.setOnClickListener { + clickAction.invoke(position) + clickPos = position + notifyDataSetChanged() + } + } + } + fun getRate(): Int? = clickPos +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterWall.kt b/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterWall.kt new file mode 100644 index 0000000..c387a55 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/recycleradapter/AdapterWall.kt @@ -0,0 +1,108 @@ +package com.live.wallpaper.style.hd.recycleradapter + +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.target.Target +import com.live.wallpaper.style.hd.bean.WallpaperImage +import com.live.wallpaper.style.hd.databinding.ItemWallpaperBinding +import com.live.wallpaper.style.hd.mytools.Common +import com.live.wallpaper.style.hd.mytools.Common.dp2PxInt +import com.live.wallpaper.style.hd.mytools.Common.hide +import com.live.wallpaper.style.hd.mytools.Common.show + +class AdapterWall (private val ctx: Context, private val list: MutableList) : + RecyclerView.Adapter() { + + private var mListener: OnItemClickListener? = null + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH { + return VH(ItemWallpaperBinding.inflate(LayoutInflater.from(ctx), parent, false)) + } + + override fun onBindViewHolder(holder: VH, position: Int) { + if (list.isEmpty()) { + return + } + if (position >= list.size) { + return + } + val bean = list[position] + holder.mItemBinding?.ivPlaceholder?.show() + holder.mItemBinding?.ivWallpaper?.let { + Glide.with(ctx) + .load(bean.thumbnail) + .transition(DrawableTransitionOptions.withCrossFade()) + .listener(object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: Target?, + isFirstResource: Boolean + ): Boolean { + Log.d("-----------","----------fail--${bean.thumbnail}") + holder.mItemBinding?.ivPlaceholder?.show() + return false + } + + override fun onResourceReady( + resource: Drawable?, + model: Any?, + target: Target?, + dataSource: DataSource?, + isFirstResource: Boolean + ): Boolean { + Log.d("-----------","----------fail--${bean.thumbnail}") + holder.mItemBinding?.ivPlaceholder?.hide() + return false + } + }) + .into(it) + } + holder.getRoot()?.let { + it.setOnClickListener { mListener?.onItemClick(holder.adapterPosition) } + val params = it.layoutParams + val itemWidth = (Common.getScreenWidth(ctx) - 48.dp2PxInt()) / 2f + params.width = itemWidth.toInt() + val itemHeight = + ((itemWidth * Common.getScreenHeight(ctx) / Common.getScreenWidth(ctx) * 1f)).toInt() + params.height = itemHeight + it.layoutParams = params + } + + } + + override fun getItemCount(): Int { + return list.size + } + + fun setOnItemClickListener(listener: OnItemClickListener) { + mListener = listener + } + + interface OnItemClickListener { + fun onItemClick(pos: Int) + } + + class VH(itemView: View) : RecyclerView.ViewHolder(itemView) { + + var mItemBinding: ItemWallpaperBinding? = null + + constructor(binding: ItemWallpaperBinding) : this(binding.root) { + this.mItemBinding = binding + } + + fun getRoot(): View? { + return mItemBinding?.root + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/live/wallpaper/style/hd/viewm/WallpaperViewModel.kt b/app/src/main/java/com/live/wallpaper/style/hd/viewm/WallpaperViewModel.kt new file mode 100644 index 0000000..ee83477 --- /dev/null +++ b/app/src/main/java/com/live/wallpaper/style/hd/viewm/WallpaperViewModel.kt @@ -0,0 +1,88 @@ +package com.live.wallpaper.style.hd.viewm + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.live.wallpaper.style.hd.bean.WallpaperImage +import com.live.wallpaper.style.hd.mytools.WallpaperDataUtil +import java.util.concurrent.atomic.AtomicBoolean + +class WallpaperViewModel : ViewModel() { + private var mCurListLiveData: MutableLiveData> = MutableLiveData() + private var mCurList: MutableList = mutableListOf() + private var mPoolList: MutableList = mutableListOf() + var isLoading = AtomicBoolean(false) + + + fun getData(): MutableLiveData> { + return mCurListLiveData + } + + fun updateWallpaper() { + if (isLoading.get()) { + return + } + try { + isLoading.set(true) + mCurList.clear() + mPoolList.clear() + mPoolList.addAll(getDataLIst()) + val list = mPoolList.randomList(40) + mCurList.addAll(list) + mPoolList.removeAll(list) + } catch (e: Exception) { + e.printStackTrace() + } finally { + mCurListLiveData.postValue(mCurList) + isLoading.set(false) + } + } + + + fun getDataLIst(): MutableList { + return WallpaperDataUtil.liveList + + } + fun loadWallpaper() { + if (isLoading.get()) { + return + } + + try { + isLoading.set(true) + val list = mPoolList.randomList(20) + mCurList.addAll(list) + mPoolList.removeAll(list) + } catch (e: Exception) { + e.printStackTrace() + } finally { + mCurListLiveData.postValue(mCurList) + isLoading.set(false) + } + } + fun List.randomList(needListSize: Int): List { + return if (this.isNotEmpty()) { + if (needListSize > 0) { + val counts = if (needListSize > this.size) this.size else needListSize + val randomSet = mutableSetOf() + for (index in this.indices) { + if (randomSet.size == counts) { + break + } + val randomIndex = (this.indices).random() + randomSet.add(this[randomIndex]) + } + randomSet.toList() + } else { + this + } + } else { + emptyList() + } + } + + + + override fun onCleared() { + super.onCleared() + } +} \ No newline at end of file diff --git a/app/src/main/res/color/selector_rate_it.xml b/app/src/main/res/color/selector_rate_it.xml new file mode 100644 index 0000000..bd5d2be --- /dev/null +++ b/app/src/main/res/color/selector_rate_it.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/home_false.xml b/app/src/main/res/drawable/home_false.xml new file mode 100644 index 0000000..1490d71 --- /dev/null +++ b/app/src/main/res/drawable/home_false.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/home_true.xml b/app/src/main/res/drawable/home_true.xml new file mode 100644 index 0000000..2c6dbc3 --- /dev/null +++ b/app/src/main/res/drawable/home_true.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_back.xml b/app/src/main/res/drawable/ic_back.xml new file mode 100644 index 0000000..e7b27ca --- /dev/null +++ b/app/src/main/res/drawable/ic_back.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_play.xml b/app/src/main/res/drawable/ic_play.xml new file mode 100644 index 0000000..be62053 --- /dev/null +++ b/app/src/main/res/drawable/ic_play.xml @@ -0,0 +1,20 @@ + + + + diff --git a/app/src/main/res/drawable/img_x.xml b/app/src/main/res/drawable/img_x.xml new file mode 100644 index 0000000..5892813 --- /dev/null +++ b/app/src/main/res/drawable/img_x.xml @@ -0,0 +1,20 @@ + + + + diff --git a/app/src/main/res/drawable/selector_home_tab.xml b/app/src/main/res/drawable/selector_home_tab.xml new file mode 100644 index 0000000..7553139 --- /dev/null +++ b/app/src/main/res/drawable/selector_home_tab.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_set_tab.xml b/app/src/main/res/drawable/selector_set_tab.xml new file mode 100644 index 0000000..cb6175e --- /dev/null +++ b/app/src/main/res/drawable/selector_set_tab.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_start.xml b/app/src/main/res/drawable/selector_start.xml new file mode 100644 index 0000000..3a4431a --- /dev/null +++ b/app/src/main/res/drawable/selector_start.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/settings_false.xml b/app/src/main/res/drawable/settings_false.xml new file mode 100644 index 0000000..57b766b --- /dev/null +++ b/app/src/main/res/drawable/settings_false.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/drawable/settings_true.xml b/app/src/main/res/drawable/settings_true.xml new file mode 100644 index 0000000..4718a53 --- /dev/null +++ b/app/src/main/res/drawable/settings_true.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_set_wallpaper_bg.xml b/app/src/main/res/drawable/shape_set_wallpaper_bg.xml new file mode 100644 index 0000000..457cb01 --- /dev/null +++ b/app/src/main/res/drawable/shape_set_wallpaper_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_theme_gray_8.xml b/app/src/main/res/drawable/shape_theme_gray_8.xml new file mode 100644 index 0000000..584ed96 --- /dev/null +++ b/app/src/main/res/drawable/shape_theme_gray_8.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/star_normal.xml b/app/src/main/res/drawable/star_normal.xml new file mode 100644 index 0000000..eb572c2 --- /dev/null +++ b/app/src/main/res/drawable/star_normal.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/star_selected.xml b/app/src/main/res/drawable/star_selected.xml new file mode 100644 index 0000000..d309848 --- /dev/null +++ b/app/src/main/res/drawable/star_selected.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/act_first.xml b/app/src/main/res/layout/act_first.xml new file mode 100644 index 0000000..bc8f130 --- /dev/null +++ b/app/src/main/res/layout/act_first.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/act_pre_live.xml b/app/src/main/res/layout/act_pre_live.xml new file mode 100644 index 0000000..b501a0b --- /dev/null +++ b/app/src/main/res/layout/act_pre_live.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4f34eee --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_contact.xml b/app/src/main/res/layout/fragment_contact.xml new file mode 100644 index 0000000..17696ad --- /dev/null +++ b/app/src/main/res/layout/fragment_contact.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml new file mode 100644 index 0000000..c5a67b0 --- /dev/null +++ b/app/src/main/res/layout/fragment_settings.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wallpaper.xml b/app/src/main/res/layout/fragment_wallpaper.xml new file mode 100644 index 0000000..81a49eb --- /dev/null +++ b/app/src/main/res/layout/fragment_wallpaper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_preview_live.xml b/app/src/main/res/layout/item_preview_live.xml new file mode 100644 index 0000000..7f04300 --- /dev/null +++ b/app/src/main/res/layout/item_preview_live.xml @@ -0,0 +1,32 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_rate_start.xml b/app/src/main/res/layout/item_rate_start.xml new file mode 100644 index 0000000..8ec86bc --- /dev/null +++ b/app/src/main/res/layout/item_rate_start.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_wallpaper.xml b/app/src/main/res/layout/item_wallpaper.xml new file mode 100644 index 0000000..ff74c44 --- /dev/null +++ b/app/src/main/res/layout/item_wallpaper.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_download.xml b/app/src/main/res/layout/view_download.xml new file mode 100644 index 0000000..53a7042 --- /dev/null +++ b/app/src/main/res/layout/view_download.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/first_img.jpg b/app/src/main/res/mipmap-xxxhdpi/first_img.jpg new file mode 100644 index 0000000..c7ce9ea Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/first_img.jpg differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/live_logo.png b/app/src/main/res/mipmap-xxxhdpi/live_logo.png new file mode 100644 index 0000000..84c9f1a Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/live_logo.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..31a19af --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,12 @@ + + + #FF000000 + #FFFFFFFF + + #FFcb39a7 + #FFfffa64 + #FFEEEEEE + #FF000000 + #999999 + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..8be3c3a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,11 @@ + + LiveWallpaper + Settings + Set Wallpaper + We hope this app is useful for you, if it does, would youplease give us a 5 sar and a mice revtew on Google Play, it really helps! + CANCEL + RATE IT + Loading video... + Version + Rate us + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..27e3a7b --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..7e48465 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 0000000..fa0f996 --- /dev/null +++ b/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 0000000..9ee9997 --- /dev/null +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/wallpaper.xml b/app/src/main/res/xml/wallpaper.xml new file mode 100644 index 0000000..0fb22c3 --- /dev/null +++ b/app/src/main/res/xml/wallpaper.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/test/java/com/live/wallpaper/style/hd/ExampleUnitTest.kt b/app/src/test/java/com/live/wallpaper/style/hd/ExampleUnitTest.kt new file mode 100644 index 0000000..785d4a0 --- /dev/null +++ b/app/src/test/java/com/live/wallpaper/style/hd/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.live.wallpaper.style.hd + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit hd, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/app/testlivewallpaper.jks b/app/testlivewallpaper.jks new file mode 100644 index 0000000..5ad5d1c Binary files /dev/null and b/app/testlivewallpaper.jks differ diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..78089b3 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,5 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id("com.android.application") version "8.1.3" apply false + id("org.jetbrains.kotlin.android") version "1.8.10" apply false +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..1a982b5 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,24 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..20d6d4a --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,60 @@ +[versions] +agp = "7.3.0" +appLovin-quality-service-gradleplugin = "4.13.2" +google-material = "1.11.0" +kotlin = "1.8.21" +core-ktx = "1.9.0" +junit = "4.13.2" +androidx-test-ext-junit = "1.1.5" +espresso-core = "3.5.1" +appcompat = "1.6.1" +material = "1.11.0" + +multidex = "2.0.1" +glide = "4.15.1" +lifecycle = "2.6.1" +activity-ktx = "1.7.2" +fragment-ktx = "1.6.1" +rxbinding = "4.0.0" +smart-refresh-layout = "2.0.6" + +flyco-tabLayout = "3.0.0" +commons-codec = "1.15" +okhttp3-okhttp = "4.10.0" +progress-bar = "2.1.2" + +google-services = "4.3.15" +firebase-crashlytics = "2.9.9" + +[libraries] +core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" } +espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" } +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } + +androidx-multidex = { module = "androidx.multidex:multidex", version.ref = "multidex" } +glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" } +lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" } +activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activity-ktx" } +fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragment-ktx" } +jakewharton-rxbinding4 = { module = "com.jakewharton.rxbinding4:rxbinding", version.ref = "rxbinding" } +material-1_11_0 = { module = "com.google.android.material:material", version.ref = "google-material" } +smart-refresh-kernel = { module = "io.github.scwang90:refresh-layout-kernel", version.ref = "smart-refresh-layout" } +smart-refresh-material-header = { module = "io.github.scwang90:refresh-header-material", version.ref = "smart-refresh-layout" } +smart-refresh-classics-footer = { module = "io.github.scwang90:refresh-footer-classics", version.ref = "smart-refresh-layout" } +flyco-tabLayout = { module = "io.github.h07000223:flycoTabLayout", version.ref = "flyco-tabLayout" } + +commons-codec = { module = "commons-codec:commons-codec", version.ref = "commons-codec" } +okhttp3-okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp3-okhttp" } +com-akexorcist-progress-bar = { group = "com.akexorcist", name = "round-corner-progress-bar", version.ref = "progress-bar" } + +[plugins] +androidApplication = { id = "com.android.application", version.ref = "agp" } +kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } + +googleServices = { id = "com.google.gms.google-services", version.ref = "google-services" } +firebaseCrashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics" } +[bundles] + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..46a6935 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Mar 15 15:37:22 CST 2024 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..94d4006 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,19 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { setUrl("https://jitpack.io") } + } +} + +rootProject.name = "LiveWallpaper" +include(":app") + \ No newline at end of file