V1.0.1(2) 广告展示由firebase remoteConfig设置的间隔时间控制

This commit is contained in:
litingting 2024-08-08 14:42:29 +08:00
parent d11595cbb8
commit d12ca103a4
32 changed files with 1395 additions and 121 deletions

View File

@ -5,6 +5,8 @@ plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
kotlin("kapt")
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
}
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
@ -13,11 +15,12 @@ android {
compileSdk = 34
defaultConfig {
//com.wall.photography
applicationId = "com.wall.photography"
minSdk = 23
targetSdk = 34
versionCode = 1
versionName = "1.0.0"
versionCode = 2
versionName = "1.0.1"
setProperty("archivesBaseName", "Photography Wallpapers_V" + versionName + "(${versionCode})_$timestamp")
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@ -40,6 +43,7 @@ android {
}
buildFeatures {
viewBinding = true
buildConfig = true
}
}
@ -69,4 +73,73 @@ dependencies {
implementation("com.squareup.okhttp3:okhttp:4.11.0")
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:33.1.1"))
// Add the dependencies for the Crashlytics and Analytics libraries
// When using the BoM, you don't specify versions in Firebase library dependencies
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-config")
//-----------------------------------------------TopOn(pangle、IronSource、mintegral、unityads、liftoff(vungle)、Bigo)
//Anythink (Necessary)
implementation("com.anythink.sdk:core-tpn:6.3.68")
implementation("com.anythink.sdk:nativead-tpn:6.3.68")
implementation("com.anythink.sdk:banner-tpn:6.3.68")
implementation("com.anythink.sdk:interstitial-tpn:6.3.68")
implementation("com.anythink.sdk:rewardedvideo-tpn:6.3.68")
implementation("com.anythink.sdk:splash-tpn:6.3.68")
//Androidx (Necessary)
implementation("androidx.appcompat:appcompat:1.1.0")
implementation("androidx.browser:browser:1.4.0")
//Vungle
implementation("com.anythink.sdk:adapter-tpn-vungle:6.3.68")
implementation("com.vungle:vungle-ads:7.3.2")
implementation("com.google.android.gms:play-services-basement:18.1.0")
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
//UnityAds
implementation("com.anythink.sdk:adapter-tpn-unityads:6.3.68")
implementation("com.unity3d.ads:unity-ads:4.9.3")
//Ironsource
implementation("com.anythink.sdk:adapter-tpn-ironsource:6.3.68")
implementation("com.ironsource.sdk:mediationsdk:8.1.0")
implementation("com.google.android.gms:play-services-appset:16.0.2")
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
implementation("com.google.android.gms:play-services-basement:18.1.0")
//Bigo
implementation("com.anythink.sdk:adapter-tpn-bigo:6.3.68")
implementation("com.bigossp:bigo-ads:4.7.4")
//Pangle
implementation("com.anythink.sdk:adapter-tpn-pangle-nonchina:6.3.68.1")
implementation( "com.pangle.global:ads-sdk:6.0.0.3")
implementation( "com.google.android.gms:play-services-ads-identifier:18.0.1")
//Mintegral
implementation("com.anythink.sdk:adapter-tpn-mintegral-nonchina:6.3.68")
implementation("com.mbridge.msdk.oversea:reward:16.7.51")
implementation("com.mbridge.msdk.oversea:newinterstitial:16.7.51")
implementation("com.mbridge.msdk.oversea:mbnative:16.7.51")
implementation("com.mbridge.msdk.oversea:mbnativeadvanced:16.7.51")
implementation("com.mbridge.msdk.oversea:mbsplash:16.7.51")
implementation("com.mbridge.msdk.oversea:mbbanner:16.7.51")
implementation("com.mbridge.msdk.oversea:mbbid:16.7.51")
implementation("androidx.recyclerview:recyclerview:1.1.0")
//Tramini
implementation("com.anythink.sdk:tramini-plugin-tpn:6.3.68")
// Debugger UI Tools
implementation ("com.anythink.sdk:debugger-ui:1.0.7")
//----------------------------------------------TopOn
}

29
app/google-services.json Normal file
View File

@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "486670482005",
"project_id": "photography-wallpapers-236db",
"storage_bucket": "photography-wallpapers-236db.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:486670482005:android:1ac3da593dd52e1ee8f2dc",
"android_client_info": {
"package_name": "com.wall.photography"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyAaJZFpzRNLYYO3ffvpW70BUkzP6N_Zjps"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@ -35,4 +35,91 @@
#-keepclassmembers class com.wall.photography.wallpaper.data { *; }
-keep class com.wall.photography.wallpaper.room.MyDataBase { *; }
-keep class com.wall.photography.wallpaper.room.BeanDao { *; }
-keep class com.wall.photography.wallpaper.room.BeanDao { *; }
#---------------------------------------------Topon
# Vungle
-dontwarn com.vungle.ads.**
-keepclassmembers class com.vungle.ads.** {
*;
}
# Google
-keep class com.google.android.gms.** { *; }
-dontwarn com.google.android.gms.**
# START OkHttp + Okio
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
# OkHttp platform used only on JVM and when Conscrypt and other security providers are available.
-dontwarn okhttp3.internal.platform.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**
-dontwarn org.openjsse.**
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
# END OkHttp + Okio
# START Protobuf
-dontwarn com.google.protobuf.**
-keepclassmembers class com.google.protobuf.** {
*;
}
-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }
# END Protobuf
-keepclassmembers class com.ironsource.sdk.controller.IronSourceWebView$JSInterface {
public *;
}
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keep public class com.google.android.gms.ads.** {
public *;
}
-keep class com.ironsource.adapters.** { *;
}
-dontwarn com.ironsource.mediationsdk.**
-dontwarn com.ironsource.adapters.**
-keepattributes JavascriptInterface
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
-keep class com.bytedance.sdk.** { *; }
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.mbridge.** {*; }
-keep interface com.mbridge.** {*; }
-keep class android.support.v4.** { *; }
-dontwarn com.mbridge.**
-keep class **.R$* { public static final int mbridge*; }
-keep public class com.mbridge.* extends androidx.** { *; }
-keep public class androidx.viewpager.widget.PagerAdapter{ *; }
-keep public class androidx.viewpager.widget.ViewPager.OnPageChangeListener{ *; }
-keep interface androidx.annotation.IntDef{ *; }
-keep interface androidx.annotation.Nullable{ *; }
-keep interface androidx.annotation.CheckResult{ *; }
-keep interface androidx.annotation.NonNull{ *; }
-keep public class androidx.fragment.app.Fragment{ *; }
-keep public class androidx.core.content.FileProvider{ *; }
-keep public class androidx.core.app.NotificationCompat{ *; }
-keep public class androidx.appcompat.widget.AppCompatImageView { *; }
-keep public class androidx.recyclerview.*{ *; }
#---------------------------------------------Topon

View File

@ -19,6 +19,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.PhotographyWallpaper"
tools:targetApi="31">
<activity
android:name=".activivty.PrivacyActivity"
android:exported="false" />
<activity
android:name=".activivty.AboutActivity"
android:exported="false" />

View File

@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Privacy Policy</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
padding: 20px;
}
h1, h2 {
color: #333;
}
h2 {
margin-top: 20px;
}
p {
margin: 10px 0;
}
ul {
margin: 10px 0;
padding-left: 20px;
}
</style>
</head>
<body>
<h1>Privacy Policy</h1>
<p><strong>Date:</strong> August 8, 2024</p>
<p>We provide this Privacy Policy to help you understand how we collect, use, and disclose information, including what you may provide to us or that we obtain from our products and services. We treat your privacy very seriously. Your privacy is important to us.</p>
<h2>Information Collection and Use</h2>
<p>For a better experience, while using our Service, we may require you to provide us with certain personally identifiable information, such as users' name, address, location, pictures, etc. The information that we request will be retained on your device and is not collected or retained by us in any way and used as described in this privacy policy.</p>
<p>The app does use third-party services that may collect information used to identify you.</p>
<p>Please refer to the privacy policy of the third-party service provider used by the application:</p>
<ul>
<li>Google Play Services</li>
<li>Google Analytics for Firebase</li>
<li>Firebase Crashlytics</li>
<li>Unity</li>
<li>AppLovin</li>
<li>Pangle</li>
<li>Mintegral</li>
<li>Bigo</li>
<li>Ironsource</li>
<li>Vungle</li>
</ul>
<h2>Log Data</h2>
<p>We want to inform you that whenever you use our Service, in case of an error in the app, we collect data and information (through third-party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing our Service, the time and date of your use of the Service, and other statistics.</p>
<h2>Cookies</h2>
<p>Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.</p>
<p>This Service does not use these “cookies” explicitly. However, the app may use third-party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service.</p>
<h2>Service Providers</h2>
<p>We may employ third-party companies and individuals due to the following reasons:</p>
<ul>
<li>To facilitate our Service</li>
<li>To provide the Service on our behalf</li>
<li>To perform Service-related services</li>
<li>To assist us in analyzing how our Service is used</li>
</ul>
<p>We want to inform users of this Service that these third parties have access to their Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.</p>
<h2>Security</h2>
<p>We value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and we cannot guarantee its absolute security.</p>
<h2>Links to Other Sites</h2>
<p>This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by us. Therefore, we strongly advise you to review the Privacy Policy of these websites. We have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.</p>
<h2>Childrens Privacy</h2>
<p>These Services do not address anyone under the age of 13. We do not knowingly collect personally identifiable information from children under 13 years of age. In the case we discover that a child under 13 has provided us with personal information, we will immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact us so that we will be able to take the necessary actions.</p>
<h2>Changes to This Privacy Policy</h2>
<p>We may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. We will notify you of any changes by posting the new Privacy Policy on this page.</p>
<h2>Privacy Questions</h2>
<p>We may update the Privacy Policy from time to time. When we change the policy in a material way, a notice will be posted on our website along with the updated Privacy Policy.</p>
<p>If you have any questions or concerns about our Privacy Policy or data processing, please contact us: <a href="ml0944887MarieLatham1983445@gmail.com">ml0944887MarieLatham1983445@gmail.com</a>.</p>
</body>
</html>

View File

@ -2,13 +2,19 @@ package com.wall.photography.wallpaper
import android.app.Application
import android.util.Log
import com.anythink.core.api.ATSDK
import com.anythink.core.api.NetTrafficeCallback
import com.anythink.debug.api.ATDebuggerUITest
import com.wall.photography.wallpaper.data.Bean
import com.wall.photography.wallpaper.firebase.RemoteConfigNew
import com.wall.photography.wallpaper.manager.DealData
import com.wall.photography.wallpaper.room.MyDataBase
import com.wall.photography.wallpaper.topon.AdManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MyApp : Application() {
companion object {
lateinit var application: Application
@ -29,19 +35,26 @@ class MyApp : Application() {
lateinit var strings: Array<String>
}
private val APPId = "h66b1d37c22a77"
private val AppKey = "a3f5e17582cca6e43dcbb0732c125dec8"
private val debug_Key = "63db2183733f4027ed5333d9ea59e1540d46b1a6"
override fun onCreate() {
super.onCreate()
application = this
Log.d(TAG, "---------------onCreate")
Log.d(TAG, "--------------Application-onCreate")
RemoteConfigNew.instance.init(this)
initTopOnSDK()
CoroutineScope(Dispatchers.IO).launch {
Log.d(TAG, "---------------协程开始" + Thread.currentThread().name)
Log.d(TAG, "---------------协程开始")
strings = resources.getStringArray(R.array.category_name)
val allWallpaper = MyDataBase.getInstance().getBeanDao().getCategoryCovert(strings[7])
if (allWallpaper != null) {
Log.d(TAG, "---------------协程结束 --" + Thread.currentThread().name)
Log.d(TAG, "---------------协程结束 --")
return@launch
}
for (i in 0 until 8) {
@ -53,9 +66,9 @@ class MyApp : Application() {
}
dataAlready = true
Log.d(TAG, "---------------协程结束 --" + Thread.currentThread().name)
Log.d(TAG, "---------------协程结束 --")
}
Log.d(TAG, "---------------onCreate end")
Log.d(TAG, "---------------Application onCreate end")
}
private fun initData(fileName: String): List<Bean> {
@ -67,5 +80,25 @@ class MyApp : Application() {
return bean
}
private fun initTopOnSDK() {
ATSDK.checkIsEuTraffic(this, object : NetTrafficeCallback {
override fun onResultCallback(isEU: Boolean) {
Log.e(TAG, "onResultCallback:$isEU")
if (isEU && ATSDK.getGDPRDataLevel(this@MyApp) == ATSDK.UNKNOWN) {
ATSDK.showGdprAuth(this@MyApp)
}
}
override fun onErrorCallback(errorMsg: String) {
Log.e(TAG, "onErrorCallback:$errorMsg")
}
})
ATSDK.init(this, APPId, AppKey)
AdManager.loadAllAd()
//测试工具
// ATDebuggerUITest.showDebuggerUI(this, debug_Key)
// ATSDK.setNetworkLogDebug(true)
}
}

View File

@ -9,6 +9,7 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.wall.photography.wallpaper.R
import com.wall.photography.wallpaper.databinding.ActivityAboutBinding
import com.wall.photography.wallpaper.topon.AdManager
class AboutActivity : AppCompatActivity() {
@ -17,17 +18,18 @@ class AboutActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
vb = ActivityAboutBinding.inflate(layoutInflater)
setContentView(vb.root)
AdManager.loadAllAd()
val appVersionName = getAppVersionName()
appVersionName?.run {
vb.tvVersion.text = String.format(getString(R.string.version), this.versionName)
} ?: run {
vb.tvVersion.text = String.format(getString(R.string.version), "1.0.0")
}
vb.back.setOnClickListener { finish() }
vb.back.setOnClickListener {
AdManager.showTopOn(this@AboutActivity) {
finish()
}
}
vb.layoutRate.setOnClickListener {
try {
val uri = String.format(getString(R.string.google_link), packageName)
@ -43,6 +45,20 @@ class AboutActivity : AppCompatActivity() {
).show()
}
}
vb.layoutPrivacy.setOnClickListener {
AdManager.showTopOn(this@AboutActivity) {
startActivity(Intent(this@AboutActivity, PrivacyActivity::class.java))
}
}
}
override fun onBackPressed() {
super.onBackPressed()
AdManager.showTopOn(this@AboutActivity) {
}
}
private fun getAppVersionName(): PackageInfo? {

View File

@ -14,6 +14,7 @@ import com.wall.photography.wallpaper.databinding.ActivityListBinding
import com.wall.photography.wallpaper.databinding.ActivityMainBinding
import com.wall.photography.wallpaper.fragment.HomeViewModel
import com.wall.photography.wallpaper.manager.MyItemDecoration
import com.wall.photography.wallpaper.topon.AdManager
import com.wall.photography.wallpaper.viewmode.ListActivityViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -22,31 +23,38 @@ import kotlinx.coroutines.launch
class ListActivity : AppCompatActivity() {
private lateinit var vb: ActivityListBinding
companion object{
companion object {
const val KEY = "category_name"
}
private lateinit var viewModel:ListActivityViewModel
private lateinit var viewModel: ListActivityViewModel
private lateinit var adapterHomepaging: AdapterHomePaing
private lateinit var name:String
private lateinit var name: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vb = ActivityListBinding.inflate(layoutInflater)
AdManager.loadAllAd()
setContentView(vb.root)
viewModel = ViewModelProvider(this)[ListActivityViewModel::class.java]
name = intent.getStringExtra(KEY)!!
vb.tvName.text = name
vb.back.setOnClickListener {
finish()
AdManager.showTopOn(this@ListActivity) {
finish()
}
}
adapterHomepaging = AdapterHomePaing(mContext=this@ListActivity){
startActivity(Intent(this, SetWallpaperActivity::class.java).apply {
putExtra(SetWallpaperActivity.KEY_DATA, it)
})
adapterHomepaging = AdapterHomePaing(mContext = this@ListActivity) {
AdManager.showTopOn(this@ListActivity) {
startActivity(Intent(this, SetWallpaperActivity::class.java).apply {
putExtra(SetWallpaperActivity.KEY_DATA, it)
putExtra(SetWallpaperActivity.KEY_MAIN_ENTER, false)
})
}
}
CoroutineScope(Dispatchers.Main).launch{
CoroutineScope(Dispatchers.Main).launch {
viewModel.getPagingData(name).collectLatest {
Log.d(MyApp.TAG,"------------collectLatest ")
Log.d(MyApp.TAG, "------------collectLatest ")
adapterHomepaging.submitData(it)
}
}
@ -54,6 +62,13 @@ class ListActivity : AppCompatActivity() {
}
override fun onBackPressed() {
super.onBackPressed()
AdManager.showTopOn(this@ListActivity) {
}
}
private fun initWallpaper() {
vb.list.run {
layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)

View File

@ -14,6 +14,7 @@ import com.wall.photography.wallpaper.fragment.CategoryFragment
import com.wall.photography.wallpaper.fragment.HomeFragment
import com.wall.photography.wallpaper.fragment.LoveFragment
import com.wall.photography.wallpaper.manager.DealData
import com.wall.photography.wallpaper.topon.AdManager
class MainActivity : AppCompatActivity() {
private lateinit var vb: ActivityMainBinding
@ -31,9 +32,12 @@ class MainActivity : AppCompatActivity() {
initVp2()
vb.iconSet.setOnClickListener {
startActivity(Intent(this@MainActivity,AboutActivity::class.java).apply {
AdManager.showTopOn(this@MainActivity) {
startActivity(Intent(this@MainActivity, AboutActivity::class.java).apply {
})
}
})
}
vb.bottomNavigation.setOnItemSelectedListener { menu ->
when (menu.itemId) {
@ -43,6 +47,7 @@ class MainActivity : AppCompatActivity() {
val cateFragment = listOf[1] as CategoryFragment
cateFragment.refreshCate()
}
R.id.love -> {
vb.viewpager2.currentItem = 2
val loveFragment = listOf[2] as LoveFragment
@ -73,6 +78,7 @@ class MainActivity : AppCompatActivity() {
val cateFragment = listOf[1] as CategoryFragment
cateFragment.refreshCate()
}
2 -> {
vb.bottomNavigation.selectedItemId = R.id.love
val loveFragment = listOf[2] as LoveFragment

View File

@ -4,16 +4,19 @@ import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.CountDownTimer
import android.util.Log
import com.wall.photography.wallpaper.MyApp
import com.wall.photography.wallpaper.R
import com.wall.photography.wallpaper.databinding.ActivityMainBinding
import com.wall.photography.wallpaper.databinding.ActivityWelcomeBinding
import com.wall.photography.wallpaper.topon.AdManager
import kotlin.math.roundToInt
class MyWelComeActivity : AppCompatActivity() {
private lateinit var vb:ActivityWelcomeBinding
private lateinit var goTimer:CountDownTimer
private val countTime = 2000L
private lateinit var vb: ActivityWelcomeBinding
private var goTimer: CountDownTimer? = null
private val countTime = 11000L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vb = ActivityWelcomeBinding.inflate(layoutInflater)
@ -21,24 +24,33 @@ class MyWelComeActivity : AppCompatActivity() {
init()
}
private fun init(){
goTimer = object :CountDownTimer(countTime,500){
override fun onTick(millisUntilFinished: Long) {
private fun init() {
}
override fun onFinish() {
goTimer =
AdManager.showWelcomeAd(this@MyWelComeActivity, countTime, { millisUntilFinished ->
val percentage: Float = 100 - millisUntilFinished.toFloat() / countTime * 100
val round = percentage.roundToInt()
vb.progressbar.progress = round
if (AdManager.place1LoadFail && AdManager.place2LoadFail && AdManager.place3LoadFail) {
goTimer?.cancel()
enterMain()
Log.d(MyApp.TAG, "-------------cancel")
}
}) {
enterMain()
}
}
goTimer.start()
goTimer?.start()
}
private fun enterMain(){
private fun enterMain() {
startActivity(Intent(this@MyWelComeActivity, MainActivity::class.java))
finish()
}
override fun onDestroy() {
super.onDestroy()
goTimer?.cancel()
}
}

View File

@ -0,0 +1,33 @@
package com.wall.photography.wallpaper.activivty
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.wall.photography.wallpaper.R
import com.wall.photography.wallpaper.databinding.ActivityPrivacyBinding
import com.wall.photography.wallpaper.topon.AdManager
class PrivacyActivity : AppCompatActivity() {
private lateinit var vb: ActivityPrivacyBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AdManager.loadAllAd()
vb = ActivityPrivacyBinding.inflate(layoutInflater)
setContentView(vb.root)
vb.webView.loadUrl("file:///android_asset/privacy.html")
vb.back.setOnClickListener {
AdManager.showTopOn(this@PrivacyActivity) {
finish()
}
}
}
override fun onBackPressed() {
super.onBackPressed()
AdManager.showTopOn(this@PrivacyActivity) {
}
}
}

View File

@ -3,20 +3,16 @@ package com.wall.photography.wallpaper.activivty
import android.app.WallpaperManager
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.widget.RelativeLayout
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.core.view.marginBottom
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
@ -25,12 +21,13 @@ import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.wall.photography.wallpaper.MyApp
import com.wall.photography.wallpaper.R
import com.wall.photography.wallpaper.Test
import com.wall.photography.wallpaper.util.Utils
import com.wall.photography.wallpaper.data.Bean
import com.wall.photography.wallpaper.databinding.ActivitySetWallpaperBinding
import com.wall.photography.wallpaper.manager.DealData
import com.wall.photography.wallpaper.manager.Other
import com.wall.photography.wallpaper.room.MyDataBase
import com.wall.photography.wallpaper.topon.AdManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -42,6 +39,7 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
companion object {
const val KEY_DATA = "key_data"
const val KEY_MAIN_ENTER = "key_main_enter"
}
private var code = 1
@ -52,15 +50,19 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var data: Bean
private lateinit var vb: ActivitySetWallpaperBinding
private var mainEnter = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(MyApp.TAG, "----------SetWallpaperActivity--onCreate=$this")
AdManager.loadAllAd()
vb = ActivitySetWallpaperBinding.inflate(layoutInflater)
setContentView(vb.root)
vb.loadingView.isVisible = true
initBar()
data = intent.getSerializableExtra(KEY_DATA) as Bean
mainEnter = intent.getBooleanExtra(KEY_MAIN_ENTER, true)
wallpaperManager = WallpaperManager.getInstance(this)
CoroutineScope(Dispatchers.IO).launch {
data = MyDataBase.getInstance().getBeanDao().getCurWallpaper(data.id)
@ -97,7 +99,7 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
if (navigationBarHeight != 0) {
val newLayoutParams = vb.relayout.layoutParams as ConstraintLayout.LayoutParams
vb.relayout.layoutParams = newLayoutParams.apply {
bottomMargin = navigationBarHeight+Other.dpToPx(20,MyApp.application)
bottomMargin = navigationBarHeight + Other.dpToPx(20, MyApp.application)
}
}
@ -166,7 +168,7 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
} else {
val newFile = File(it)
// val saveToGallery = DealData.saveToGallery(this@SetWallpaperActivity, newFile)
val saveToGallery = Test.saveToGallery(this@SetWallpaperActivity, newFile)
val saveToGallery = Utils.saveToGallery(this@SetWallpaperActivity, newFile)
if (saveToGallery != null) getString(R.string.save_ok) else getString(
R.string.save_fail
)
@ -222,7 +224,7 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
.diskCacheStrategy(DiskCacheStrategy.ALL)
.error(R.drawable.placeholder)
.placeholder(R.drawable.placeholder)
.listener(object : RequestListener<Drawable>{
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
@ -252,20 +254,19 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
}
private fun loadRegular() {
Glide.with(MyApp.application)
.asDrawable()
.load(data.urls.regular)
.thumbnail(0.2f)
.error(R.drawable.placeholder)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.drawable.placeholder)
.into(vb.preview)
Glide.with(MyApp.application)
.asDrawable()
.load(data.urls.regular)
.thumbnail(0.2f)
.error(R.drawable.placeholder)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.drawable.placeholder)
.into(vb.preview)
}
private fun initBar() {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
@ -287,23 +288,47 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
}
override fun onBackPressed() {
super.onBackPressed()
AdManager.showTopOn(this@SetWallpaperActivity) {
}
}
override fun onClick(v: View?) {
v?.run {
vb.run {
when (v) {
back -> {
finish()
AdManager.showTopOn(this@SetWallpaperActivity) {
finish()
}
}
imLove -> {
imLove.isSelected = !imLove.isSelected
AdManager.showTopOn(this@SetWallpaperActivity) {
imLove.isSelected = !imLove.isSelected
var msg: String = if (imLove.isSelected) {
getString(R.string.like_success)
} else {
getString(R.string.cancel_like_success)
}
Toast.makeText(this@SetWallpaperActivity, msg, Toast.LENGTH_SHORT)
.show()
}
}
imSetWallpaper -> {
if (dialog == null) {
dialog = SelectDialog {
vb.loadingView.visibility = View.VISIBLE
Log.d(MyApp.TAG, "-------------isVisible ${Thread.currentThread().name}")
Log.d(
MyApp.TAG,
"-------------isVisible ${Thread.currentThread().name}"
)
data.downloadFilePath?.let { filePath ->
val file = File(filePath)
if (file.exists()) {
@ -337,12 +362,11 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
}
imDownload -> {
if (Other.requestPermission(this@SetWallpaperActivity, code)) {
startSaveIm()
} else {
AdManager.showTopOn(this@SetWallpaperActivity) {
if (Other.requestPermission(this@SetWallpaperActivity, code)) {
startSaveIm()
}
}
}
else -> {}
@ -356,14 +380,20 @@ class SetWallpaperActivity : AppCompatActivity(), View.OnClickListener {
private fun launchSet(type: Int, file: File) {
CoroutineScope(Dispatchers.Main).launch {
var msg: String = try {
startSetWallpaper(type, file)
getString(R.string.set_success)
} catch (ex: Exception) {
getString(R.string.set_fail)
AdManager.showTopOn(
this@SetWallpaperActivity
) {
var msg: String = try {
startSetWallpaper(type, file)
getString(R.string.set_success)
} catch (ex: Exception) {
getString(R.string.set_fail)
}
saveResultToast(msg)
Log.d(MyApp.TAG, "------------end SetWallpaper")
}
saveResultToast(msg)
Log.d(MyApp.TAG, "------------end SetWallpaper")
}
}

View File

@ -0,0 +1,245 @@
package com.wall.photography.wallpaper.firebase
object RemoteConfigKey {
//配置在firebase中的key通过它取出自己配置的json
const val KEY_AD_SHOW_INTERVAL = "key_ad_show_interval"
const val DEFAULT_AD_JSON = """
{
"AD_SHOW_LIMIT": {
"admob_inst": 100,
"admob_native": 100,
"max_banner": 100,
"max_inst": 100,
"max_native": 100
},
"sounds_inst_show_interval": 25000,
"LOLAds_EXPIRE_HOURS_NEW_USER": 20,
"sounds_inst_splash": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-2419639357236809/7376891200": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
},
"sounds_inst_into_play": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-2419639357236809/9750976941": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
},
"sounds_inst_exit_sounds_list": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-2419639357236809/9844693327": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
},
"sounds_android_native_musicList": {
"data": [{
"config": [
[
"admob_native",
{
"ca-app-pub-2419639357236809/9811482858": 100
}
]
],
"block": {
"admob_native": {
"delay": 0,
"rate": 0
},
"max_native": {
"delay": 0,
"rate": 0
}
},
"click": {
"admob_native": [
100,
100,
100,
100,
100
],
"max_native": [
100,
100,
100,
100,
100
]
},
"after_click": {
"admob_native": "next",
"max_native": "next"
},
"limit": {
"admob_native": 100,
"max_native": 100
}
}]
},
"sounds_android_native_play": {
"data": [{
"config": [
[
"admob_native",
{
"ca-app-pub-2419639357236809/8134642941": 100
}
]
],
"block": {
"admob_native": {
"delay": 0,
"rate": 0
},
"max_native": {
"delay": 0,
"rate": 0
}
},
"click": {
"admob_native": [
100,
100,
100,
100,
100
],
"max_native": [
100,
100,
100,
100,
100
]
},
"after_click": {
"admob_native": "next",
"max_native": "next"
},
"limit": {
"admob_native": 100,
"max_native": 100
}
}]
}
}
"""
//"{\"AD_SHOW_LIMIT\":{\"max_banner\":100,\"max_inst\":100,\"max_native\":100},\"sounds_inst_show_interval\":25000,\"LOLAds_EXPIRE_HOURS_NEW_USER\":20,\"sounds_inst_splash\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"f685a8fc471fd92b\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_inst_into_sounds_list\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"2a1e13e10c0358c9\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_inst_into_play\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"2a1e13e10c0358c9\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_inst_into_play2\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"2a1e13e10c0358c9\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_inst_exit_sounds_list\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"b0c27a89f370cbed\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_inst_exit_play\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"b0c27a89f370cbed\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_inst_exit_play2\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"b0c27a89f370cbed\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_inst_exit_edit\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"b0c27a89f370cbed\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_inst_create_next\":{\"data\":[{\"after_click\":{\"max_inst\":\"keep\"},\"block\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"close\":{\"max_inst\":{\"delay\":0,\"rate\":0}},\"config\":[[\"max_inst\",{\"66d99619cea2243d\":100}]],\"limit\":{\"max_inst\":100},\"cycle\":0,\"timeout\":15000,\"showIntervalEnable\":false}]},\"sounds_android_native_musicList\":{\"data\":[{\"config\":[[\"max_native\",{\"2aa4162b650aa26d\":100}]],\"block\":{\"max_native\":{\"delay\":0,\"rate\":0}},\"click\":{\"max_native\":[100,100,100,100,100]},\"after_click\":{\"max_native\":\"next\"},\"limit\":{\"max_native\":100}}]},\"sounds_android_native_play\":{\"data\":[{\"config\":[[\"max_native\",{\"35f6847f26ddcd76\":100}]],\"block\":{\"max_native\":{\"delay\":0,\"rate\":0}},\"click\":{\"max_native\":[100,100,100,100,100]},\"after_click\":{\"max_native\":\"next\"},\"limit\":{\"max_native\":100}}]}}"
}

View File

@ -0,0 +1,142 @@
package com.wall.photography.wallpaper.firebase
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.text.TextUtils
import android.util.Log
import com.google.firebase.remoteconfig.ConfigUpdate
import com.google.firebase.remoteconfig.ConfigUpdateListener
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.FirebaseRemoteConfigException
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings
import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue
import com.wall.photography.wallpaper.MyApp
import java.lang.ref.WeakReference
import com.wall.photography.wallpaper.BuildConfig
import com.wall.photography.wallpaper.util.Sp
class RemoteConfigNew {
private var ctx: Context? = null
private var mFirebaseRemoteConfig: FirebaseRemoteConfig? = null
//配置是否初始化成功
private var isInit = false
//上次获取数据的时间
private var lastFetchTime: Long = 0
private val handler = MHandler(this)
companion object {
const val MSG_REFRESH_CONFIG = 1
val instance: RemoteConfigNew by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
RemoteConfigNew()
}
}
fun init(ctx: Application) {
this.ctx = ctx
initConfig()
fetchConfig()
onConfigUpdate()
}
private fun initConfig() {
var intervalTime = (60 * 10).toLong()
//如果是开发状态,则将提取时间缩短
if (BuildConfig.DEBUG) {
intervalTime = (60 * 5).toLong()
}
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
val configSettings =
FirebaseRemoteConfigSettings.Builder() //默认值12小时的最短提取间隔如果在间隔内取值则优先取上次的结果
.setMinimumFetchIntervalInSeconds(intervalTime).build()
mFirebaseRemoteConfig!!.setConfigSettingsAsync(configSettings)
}
private fun onConfigUpdate() {
mFirebaseRemoteConfig!!.addOnConfigUpdateListener(object : ConfigUpdateListener {
override fun onUpdate(configUpdate: ConfigUpdate) {
Log.d(MyApp.TAG, "Updated keys: " + configUpdate.updatedKeys)
try {
mFirebaseRemoteConfig!!.activate().addOnCompleteListener { task ->
if (task.isSuccessful) {
updateData("onConfigUpdate", mFirebaseRemoteConfig!!.all)
}
}
} catch (ignore: Exception) {
}
}
override fun onError(error: FirebaseRemoteConfigException) {
Log.d(MyApp.TAG, "Config update error with code: " + error.code)
}
})
}
private fun fetchConfig() {
//这里可能会抛出异常 FirebaseRemoteConfigFetchThrottledException
try {
mFirebaseRemoteConfig!!.fetchAndActivate().addOnCompleteListener { task ->
if (task.isSuccessful) {
isInit = true
lastFetchTime = System.currentTimeMillis()
updateData("fetchAndActivate", mFirebaseRemoteConfig!!.all)
//24小时后重新再去获取
handler.removeMessages(MSG_REFRESH_CONFIG)
handler.sendEmptyMessageDelayed(
MSG_REFRESH_CONFIG, (1000 * 60 * 60 * 24).toLong()
)
} else {
//15分钟后重新再去获取
handler.removeMessages(MSG_REFRESH_CONFIG)
handler.sendEmptyMessageDelayed(MSG_REFRESH_CONFIG, (1000 * 60 * 15).toLong())
}
}
} catch (ignore: Exception) {
}
}
private fun updateData(from: String, all: Map<String, FirebaseRemoteConfigValue>) {
for ((key, value) in all) {
try {
Log.d(
MyApp.TAG, "from = " + from + "Key = " + key + " Value = " + value.asString()
)
if (TextUtils.equals(RemoteConfigKey.KEY_AD_SHOW_INTERVAL, key)) {
Sp.getInstance(MyApp.application)
.putLong(RemoteConfigKey.KEY_AD_SHOW_INTERVAL, value.asLong()).commit()
}
} catch (ignore: Exception) {
}
}
}
private class MHandler(remoteConfig: RemoteConfigNew) : Handler(Looper.getMainLooper()) {
private val weakReference: WeakReference<RemoteConfigNew>
init {
weakReference = WeakReference(remoteConfig)
}
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
val remoteConfig = weakReference.get()
if (remoteConfig?.ctx != null) {
if (msg.what == MSG_REFRESH_CONFIG) {
remoteConfig.fetchConfig()
}
}
}
}
}

View File

@ -17,6 +17,7 @@ import com.wall.photography.wallpaper.adapter.AdapterCategory
import com.wall.photography.wallpaper.databinding.FragmentCategoryBinding
import com.wall.photography.wallpaper.databinding.FragmentHomeBinding
import com.wall.photography.wallpaper.manager.MyItemDecoration
import com.wall.photography.wallpaper.topon.AdManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -27,7 +28,7 @@ class CategoryFragment : Fragment() {
fun newInstance() = CategoryFragment()
}
private var viewModel: CategoryViewModel? = null
private var viewModel: CategoryViewModel? = null
private lateinit var vb: FragmentCategoryBinding
private lateinit var mAdapter: AdapterCategory
override fun onCreateView(
@ -44,10 +45,12 @@ class CategoryFragment : Fragment() {
CoroutineScope(Dispatchers.IO).launch {
viewModel?.getData()
}
mAdapter = AdapterCategory(requireContext()){
startActivity(Intent(requireActivity(),ListActivity::class.java).apply {
putExtra(ListActivity.KEY,it.cateName)
})
mAdapter = AdapterCategory(requireContext()) {
AdManager.showTopOn(requireActivity()) {
startActivity(Intent(requireActivity(), ListActivity::class.java).apply {
putExtra(ListActivity.KEY, it.cateName)
})
}
}
viewModel?.data?.observe(requireActivity()) {
@ -61,7 +64,8 @@ class CategoryFragment : Fragment() {
addItemDecoration(MyItemDecoration(requireContext(), 8, 8, 0))
}
}
fun refreshCate(){
fun refreshCate() {
CoroutineScope(Dispatchers.IO).launch {
viewModel?.getData()
}

View File

@ -20,6 +20,7 @@ import com.wall.photography.wallpaper.adapter.AdapterHomePaing
import com.wall.photography.wallpaper.data.Bean
import com.wall.photography.wallpaper.databinding.FragmentHomeBinding
import com.wall.photography.wallpaper.manager.MyItemDecoration
import com.wall.photography.wallpaper.topon.AdManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest
@ -50,16 +51,14 @@ class HomeFragment : Fragment() {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
Log.d(MyApp.TAG, "------------onActivityCreated homeFragment=$this")
if (savedInstanceState != null) {
// 恢复之前的状态
Log.d(MyApp.TAG, "------------onActivityCreated homeFragment list=${list.size}")
}
adapterHomepaging = AdapterHomePaing(mContext = requireContext()) {
startActivity(Intent(requireActivity(), SetWallpaperActivity::class.java).apply {
putExtra(SetWallpaperActivity.KEY_DATA, it)
})
AdManager.showTopOn(requireActivity()){
startActivity(Intent(requireActivity(), SetWallpaperActivity::class.java).apply {
putExtra(SetWallpaperActivity.KEY_DATA, it)
})
}
}
viewModel = ViewModelProvider(this)[HomeViewModel::class.java]

View File

@ -20,6 +20,7 @@ import com.wall.photography.wallpaper.adapter.AdapterLoves
import com.wall.photography.wallpaper.data.Bean
import com.wall.photography.wallpaper.databinding.FragmentLoveBinding
import com.wall.photography.wallpaper.manager.MyItemDecoration
import com.wall.photography.wallpaper.topon.AdManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest
@ -35,7 +36,7 @@ class LoveFragment : Fragment() {
private lateinit var vb: FragmentLoveBinding
private lateinit var adapterLove: AdapterLoves
private var adapterLovePaging: AdapterHomePaing? = null
private var adapterLovePaging: AdapterHomePaing? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@ -53,26 +54,24 @@ class LoveFragment : Fragment() {
}
private fun initWallpaper() {
// adapterLove = AdapterLoves(requireContext()) {
// startActivity(Intent(requireActivity(), SetWallpaperActivity::class.java).apply {
// putExtra(SetWallpaperActivity.KEY_DATA, it)
// })
// }
adapterLovePaging = AdapterHomePaing(true,requireContext()) {
startActivity(Intent(requireActivity(), SetWallpaperActivity::class.java).apply {
putExtra(SetWallpaperActivity.KEY_DATA, it)
})
adapterLovePaging = AdapterHomePaing(true, requireContext()) {
AdManager.showTopOn(requireActivity()) {
startActivity(Intent(requireActivity(), SetWallpaperActivity::class.java).apply {
putExtra(SetWallpaperActivity.KEY_DATA, it)
})
}
}.apply {
addLoadStateListener {
if(it.source.refresh is LoadState.NotLoading && adapterLovePaging?.itemCount == 0){
Log.d(MyApp.TAG, "------------love-空")
vb.tvNoLove.isVisible = true
vb.loveRecycler.isVisible = false
}else{
Log.d(MyApp.TAG, "------------love-不空")
vb.tvNoLove.isVisible = false
vb.loveRecycler.isVisible = true
}
if (it.source.refresh is LoadState.NotLoading && adapterLovePaging?.itemCount == 0) {
Log.d(MyApp.TAG, "------------love-空")
vb.tvNoLove.isVisible = true
vb.loveRecycler.isVisible = false
} else {
Log.d(MyApp.TAG, "------------love-不空")
vb.tvNoLove.isVisible = false
vb.loveRecycler.isVisible = true
}
}
}
@ -83,10 +82,7 @@ class LoveFragment : Fragment() {
}
}
// viewModel.getLoves().observe(viewLifecycleOwner) {
// Log.d(MyApp.TAG, "-----------love-update ")
// adapterLove.updateData(it)
// }
vb.loveRecycler.run {
layoutManager = LinearLayoutManager(requireContext())
adapter = adapterLovePaging
@ -95,14 +91,11 @@ class LoveFragment : Fragment() {
}
fun refreshLoves(){
fun refreshLoves() {
adapterLovePaging?.refresh()
}
override fun onResume() {
super.onResume()
Log.d(MyApp.TAG, "------------love onResume")
}
}

View File

@ -0,0 +1,11 @@
package com.wall.photography.wallpaper.topon
interface AdListener {
fun loadFail(placeId: String)
fun showSuccess()
fun showFail()
fun showClose()
}

View File

@ -0,0 +1,243 @@
package com.wall.photography.wallpaper.topon
import android.app.Activity
import android.os.CountDownTimer
import android.util.Log
import com.anythink.core.api.ATAdInfo
import com.anythink.core.api.AdError
import com.anythink.interstitial.api.ATInterstitial
import com.anythink.interstitial.api.ATInterstitialListener
import com.wall.photography.wallpaper.MyApp
import com.wall.photography.wallpaper.firebase.RemoteConfigKey
import com.wall.photography.wallpaper.util.Sp
object AdManager {
//默认的广告展示间隔时间20s
const val VALUE_SHOW_INTERVAL = 1000 * 30L
//上次广告展示时刻
var LAST_AD_SHOW = 0L
const val type_no_cache = 0
const val type_has_cache = 1
const val type_show_success = 2
const val type_show_close = 3
const val type_show_fail = 4
/**
n66b1d3d019590
n66b1d3cfebd3c
n66b1d3cfc4f3b
*/
const val place1Id = "n66b1d3d019590"
const val place2Id = "n66b1d3cfebd3c"
const val place3Id = "n66b1d3cfc4f3b"
var place1LoadFail = false
var place2LoadFail = false
var place3LoadFail = false
val list = mutableListOf<ATInterstitial>()
@JvmStatic
fun loadAllAd() {
if (list.size <= 0) {
val mInterstitialAd1 = ATInterstitial(MyApp.application, place1Id)
val mInterstitialAd2 = ATInterstitial(MyApp.application, place2Id)
val mInterstitialAd3 = ATInterstitial(MyApp.application, place3Id)
list.add(mInterstitialAd1)
list.add(mInterstitialAd2)
list.add(mInterstitialAd3)
}
for (ad in list) {
if (!ad.isAdReady) {
setCallBack(ad, object : AdListener {
override fun loadFail(placeId: String) {
if (placeId == place1Id) {
place1LoadFail = true
}
if (placeId == place2Id) {
place2LoadFail = true
}
if (placeId == place3Id) {
place3LoadFail = true
}
}
override fun showSuccess() {
}
override fun showFail() {
}
override fun showClose() {
}
})
ad.load()
}
}
}
@JvmStatic
fun getReadyAd(): ATInterstitial? {
if (LAST_AD_SHOW > 0L) {
val adInterval =
Sp.getInstance(MyApp.application).getLongValue(RemoteConfigKey.KEY_AD_SHOW_INTERVAL)
val curInterval = System.currentTimeMillis() - LAST_AD_SHOW
Log.d(
MyApp.TAG,
"-广告判断------------LAST_AD_SHOW=${LAST_AD_SHOW} curInterval=${curInterval} adInterval=${adInterval}"
)
if (curInterval < adInterval) {
Log.d(
MyApp.TAG,
"-没有广告--------"
)
return null
}
}
list.shuffle()
for (ad in list) {
if (ad.isAdReady) {
Log.d(MyApp.TAG, "-有广告------------")
return ad
}
}
Log.d(MyApp.TAG, "-没有广告------------")
return null
}
@JvmStatic
fun showWelcomeAd(
activity: Activity,
totalTim: Long,
countAction: (millisUntilFinished: Long) -> Unit,
goMain: () -> Unit
): CountDownTimer {
var alreadyShow = false
var timer = object : CountDownTimer(totalTim, 100) {
override fun onTick(millisUntilFinished: Long) {
countAction.invoke(millisUntilFinished)
if (!alreadyShow) {
showAD(activity) {
if (it == type_has_cache) {
alreadyShow = true
}
if (it == type_show_close || it == type_show_fail) {
goMain.invoke()
}
}
}
}
override fun onFinish() {
if (!alreadyShow) {
showAD(activity) {
if (it == type_show_close || it == type_show_fail || it == type_no_cache) {
goMain.invoke()
}
}
}
}
}
return timer
}
private fun setCallBack(ad: ATInterstitial, listener: AdListener) {
ad.setAdListener(object : ATInterstitialListener {
override fun onInterstitialAdLoaded() {
Log.d(MyApp.TAG, "LoadLoaded ${ad.mPlacementId}")
}
override fun onInterstitialAdLoadFail(p0: AdError?) {
Log.d(MyApp.TAG, "LoadFail:${p0?.code} ${p0?.desc}")
}
override fun onInterstitialAdClicked(p0: ATAdInfo?) {
}
override fun onInterstitialAdShow(p0: ATAdInfo?) {
Log.d(MyApp.TAG, "AdShow ${p0?.showId} ")
listener.showSuccess()
ad.load()
}
override fun onInterstitialAdClose(p0: ATAdInfo?) {
listener.showClose()
}
override fun onInterstitialAdVideoStart(p0: ATAdInfo?) {
}
override fun onInterstitialAdVideoEnd(p0: ATAdInfo?) {
}
override fun onInterstitialAdVideoError(p0: AdError?) {
listener.showFail()
}
})
}
@JvmStatic
private fun showAD(activity: Activity, action: (type: Int) -> Unit) {
val readyAd = getReadyAd()
if (readyAd != null) {
Log.d(MyApp.TAG, "readyAd ${readyAd.mPlacementId} ")
action.invoke(type_has_cache)
setCallBack(readyAd, object : AdListener {
override fun loadFail(placeId: String) {
}
override fun showSuccess() {
action.invoke(type_show_success)
LAST_AD_SHOW = System.currentTimeMillis()
}
override fun showFail() {
action.invoke(type_show_fail)
}
override fun showClose() {
action.invoke(type_show_close)
}
})
readyAd.show(activity)
} else {
action.invoke(type_no_cache)
}
}
@JvmStatic
fun showTopOn(activity: Activity, listener: onActionListener) {
showAD(activity) { type ->
if (type == type_no_cache || type == type_show_close || type == type_show_fail) {
listener.onAction()
}
}
}
}

View File

@ -0,0 +1,34 @@
package com.wall.photography.wallpaper.topon;
import androidx.annotation.NonNull;
import com.google.firebase.remoteconfig.ConfigUpdate;
import com.google.firebase.remoteconfig.ConfigUpdateListener;
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
import com.google.firebase.remoteconfig.FirebaseRemoteConfigException;
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings;
public class FirebaseConfig {
public static void initFireBaseConfig(){
FirebaseRemoteConfig mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setMinimumFetchIntervalInSeconds(3600)
.build();
mFirebaseRemoteConfig.setConfigSettingsAsync(configSettings);
mFirebaseRemoteConfig.addOnConfigUpdateListener(new ConfigUpdateListener() {
@Override
public void onUpdate(@NonNull ConfigUpdate configUpdate) {
}
@Override
public void onError(@NonNull FirebaseRemoteConfigException error) {
}
});
}
}

View File

@ -0,0 +1,6 @@
package com.wall.photography.wallpaper.topon;
public interface onActionListener {
void onAction();
}

View File

@ -0,0 +1,43 @@
package com.wall.photography.wallpaper.util;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import com.wall.photography.wallpaper.MyApp;
import com.wall.photography.wallpaper.topon.AdManager;
public class Sp {
private static String spName = "AD_SHOW";
private static Sp instance;
private SharedPreferences.Editor editor;
private SharedPreferences preferences;
private Sp(Application context) {
preferences = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
editor = preferences.edit();
}
public static Sp getInstance(Application context) {
if (instance == null) {
instance = new Sp(context);
}
return instance;
}
public Sp putLong(String key, long value) {
editor.putLong(key, value);
return this;
}
public boolean commit() {
return editor.commit();
}
public long getLongValue(String key) {
return preferences.getLong(key, AdManager.VALUE_SHOW_INTERVAL);
}
}

View File

@ -1,4 +1,4 @@
package com.wall.photography.wallpaper;
package com.wall.photography.wallpaper.util;
import android.content.ContentResolver;
import android.content.ContentValues;
@ -11,7 +11,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
public class Test {
public class Utils {
public static Uri saveToGallery(Context context, File photoFile) {
String displayName = System.currentTimeMillis()+".jpg";
@ -60,4 +60,6 @@ public class Test {
return null;
}
}
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="10dp" />
<solid android:color="@color/pb_bg" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="10dp" />
<gradient
android:angle="0"
android:endColor="@color/pb_end_color"
android:startColor="@color/pb_start_color" />
</shape>
</clip>
</item>
</layer-list>

View File

@ -11,7 +11,7 @@
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginStart="12dp"
android:layout_marginTop="23dp"
android:layout_marginTop="8dp"
android:padding="10dp"
android:src="@drawable/back"
app:layout_constraintLeft_toLeftOf="parent"
@ -78,9 +78,32 @@
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:id="@+id/view"
android:background="@color/set_loading_color"
app:layout_constraintTop_toBottomOf="@id/layout_rate"
android:layout_marginStart="25dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="25dp"/>
<LinearLayout
android:id="@+id/layout_privacy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="35dp"
android:orientation="vertical"
android:padding="5dp"
app:layout_constraintTop_toBottomOf="@id/view">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/privacy_policy"
android:textColor="@color/black"
android:textSize="16sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".activivty.PrivacyActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/back"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginStart="12dp"
android:padding="10dp"
android:src="@drawable/back" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:text="@string/privacy_policy"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<WebView
android:id="@+id/webView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/back"
android:text="@string/privacy_policy"
android:textColor="@color/black"
android:textSize="15sp"
tools:ignore="WebViewLayout" />
</RelativeLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -28,4 +28,19 @@
android:textSize="18sp"
app:layout_constraintTop_toBottomOf="@id/icon" />
<ProgressBar
android:id="@+id/progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginStart="33dp"
android:layout_marginEnd="33dp"
android:layout_marginBottom="40dp"
android:progress="10"
app:layout_constraintBottom_toBottomOf="parent"
android:progressDrawable="@drawable/progressbar" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -7,4 +7,8 @@
<color name="gray">#cdd5d5</color>
<color name="category_aplah">#80FFFFFF</color>
<color name="set_loading_color">#80414548</color>
<color name="pb_bg">#898989</color>
<color name="pb_start_color">#B9F6F1</color>
<color name="pb_end_color">#2fe7f3</color>
</resources>

View File

@ -14,9 +14,12 @@
<string name="no_love">You haven not collected any wallpapers yet</string>
<string name="version">App Version V%s</string>
<string name="rate_us">Rate App</string>
<string name="privacy_policy">Privacy Policy</string>
<string name="rate_us_content">Consider giving us a review on the Google Play Store</string>
<string name="google_link">https://play.google.com/store/apps/details?id=%s</string>
<string name="to_gp_exception">An exception occurred. Please try again later.</string>
<string name="like_success">Successfully collected!</string>
<string name="cancel_like_success">Successfully canceled the collection!</string>
<string-array name="category_name">
<item>Wallpaper</item>
<item>Animals</item>
@ -27,4 +30,6 @@
<item>Patterns</item>
<item>Travel</item>
</string-array>
</resources>

View File

@ -9,7 +9,7 @@ import org.junit.Assert.*
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
class ExampleUnitUtils {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)

View File

@ -3,4 +3,6 @@ plugins {
id("com.android.application") version "8.1.3" apply false
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
kotlin("kapt") version "1.9.0"
id("com.google.gms.google-services") version "4.3.15" apply false
id ("com.google.firebase.crashlytics") version "2.9.2" apply false
}

View File

@ -10,6 +10,17 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
//Anythink(Core)
maven("https://jfrog.anythinktech.com/artifactory/overseas_sdk")
//Ironsource
maven("https://android-sdk.is.com/")
//Mintegral
maven("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
//Pangle
maven ( "https://artifact.bytedance.com/repository/pangle")
//TopOn集成测试工具
maven ( "https://jfrog.anythinktech.com/artifactory/debugger")
}
}