Commit 83fae7df authored by wanglei's avatar wanglei

....

parent 2beef962
...@@ -107,8 +107,9 @@ dependencies { ...@@ -107,8 +107,9 @@ dependencies {
//firebase //firebase
implementation platform('com.google.firebase:firebase-bom:32.3.1') implementation platform('com.google.firebase:firebase-bom:32.3.1')
implementation 'com.google.firebase:firebase-analytics:21.6.2'
implementation("com.google.firebase:firebase-messaging") implementation("com.google.firebase:firebase-messaging")
implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-analytics:21.6.2'
//google 内购订阅 //google 内购订阅
......
...@@ -25,9 +25,6 @@ ...@@ -25,9 +25,6 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.DataRecovery" android:theme="@style/Theme.DataRecovery"
tools:targetApi="34"> tools:targetApi="34">
<activity
android:name=".billing.BillingActivity"
android:exported="false" />
<activity <activity
android:name=".activity.SplashActivity" android:name=".activity.SplashActivity"
android:exported="true" android:exported="true"
......
...@@ -9,7 +9,6 @@ import com.base.filerecoveryrecyclebin.activity.SplashActivity ...@@ -9,7 +9,6 @@ import com.base.filerecoveryrecyclebin.activity.SplashActivity
import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper
import com.base.filerecoveryrecyclebin.ads.admob.AdmobOpenUtils import com.base.filerecoveryrecyclebin.ads.admob.AdmobOpenUtils
import com.base.filerecoveryrecyclebin.bean.ConstObject.ifAgreePrivacy import com.base.filerecoveryrecyclebin.bean.ConstObject.ifAgreePrivacy
import com.base.filerecoveryrecyclebin.billing.BillingClientLifecycle
import com.base.filerecoveryrecyclebin.fcm.FCMManager import com.base.filerecoveryrecyclebin.fcm.FCMManager
import com.base.filerecoveryrecyclebin.fcm.RecoveryTimerManager import com.base.filerecoveryrecyclebin.fcm.RecoveryTimerManager
import com.base.filerecoveryrecyclebin.fcm.ScreenStatusReceiver import com.base.filerecoveryrecyclebin.fcm.ScreenStatusReceiver
...@@ -32,8 +31,6 @@ class MyApplication : BaseApplication() { ...@@ -32,8 +31,6 @@ class MyApplication : BaseApplication() {
private val TAG = "MyApplication" private val TAG = "MyApplication"
var uuid = "" var uuid = ""
val billingClientLifecycle: BillingClientLifecycle
get() = BillingClientLifecycle.getInstance(this)
companion object { companion object {
@JvmField @JvmField
......
...@@ -7,10 +7,7 @@ import androidx.core.view.updatePadding ...@@ -7,10 +7,7 @@ import androidx.core.view.updatePadding
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.base.filerecoveryrecyclebin.adapter.MediaAdapter import com.base.filerecoveryrecyclebin.adapter.MediaAdapter
import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper
import com.base.filerecoveryrecyclebin.ads.admob.AdmobInterstitialUtils
import com.base.filerecoveryrecyclebin.ads.admob.AdmobInterstitialUtils.showInterAdSp import com.base.filerecoveryrecyclebin.ads.admob.AdmobInterstitialUtils.showInterAdSp
import com.base.filerecoveryrecyclebin.ads.admob.AdmobNativeUtils
import com.base.filerecoveryrecyclebin.ads.max.AdMaxInterstitialUtils
import com.base.filerecoveryrecyclebin.bean.MediaBean import com.base.filerecoveryrecyclebin.bean.MediaBean
import com.base.filerecoveryrecyclebin.bean.MediaTimeBean import com.base.filerecoveryrecyclebin.bean.MediaTimeBean
import com.base.filerecoveryrecyclebin.databinding.ActivityRepeatBinding import com.base.filerecoveryrecyclebin.databinding.ActivityRepeatBinding
......
...@@ -6,6 +6,7 @@ import android.util.Log; ...@@ -6,6 +6,7 @@ import android.util.Log;
import com.base.filerecoveryrecyclebin.BuildConfig; import com.base.filerecoveryrecyclebin.BuildConfig;
import com.base.filerecoveryrecyclebin.help.BaseApplication; import com.base.filerecoveryrecyclebin.help.BaseApplication;
import com.base.filerecoveryrecyclebin.utils.AppPreferences;
import com.base.filerecoveryrecyclebin.utils.EventUtils; import com.base.filerecoveryrecyclebin.utils.EventUtils;
import com.base.filerecoveryrecyclebin.utils.LogEx; import com.base.filerecoveryrecyclebin.utils.LogEx;
...@@ -18,37 +19,47 @@ import java.util.Date; ...@@ -18,37 +19,47 @@ import java.util.Date;
import java.util.Locale; import java.util.Locale;
public class AdDisplayUtils { public class AdDisplayUtils {
private static final int DEFAULT_MAX_AD_DISPLAY_COUNT = 45; // 总广告展示次数限制默认值 private String TAG = "AdDisplayUtils";
private static final int DEFAULT_MAX_AD_CLICK_COUNT = 10; // 单个广告点击次数限制默认值 public static final int DEFAULT_MAX_AD_REQUEST_COUNT = 100; // 广告请求次数限制默认值
private static final int DEFAULT_MAX_AD_REQUEST_FAIL_COUNT = 20; // 单个广告点击次数限制默认值 public static final int DEFAULT_MAX_AD_REQUEST_FAIL_COUNT = 20; // 单个广告点击次数限制默认值
public static final int DEFAULT_MAX_AD_DISPLAY_COUNT = 45; // 总广告展示次数限制默认值
public static final int DEFAULT_MAX_AD_CLICK_COUNT = 10; // 单个广告点击次数限制默认值
private static final String AD_PREFS_NAME = "ad_prefs"; // SharedPreferences 名称 private static final String AD_PREFS_NAME = "ad_prefs"; // SharedPreferences 名称
private static final String AD_DISPLAY_COUNT_KEY = "ad_display_count"; // 广告展示次数的键
private static final String AD_CLICK_COUNT_KEY = "ad_click_count"; // 广告点击次数的键
private static final String MAX_AD_DISPLAY_COUNT_KEY = "max_ad_display_count"; // 总广告展示次数限制的键
private static final String MAX_AD_CLICK_COUNT_KEY = "max_ad_click_count"; // 单个广告点击次数限制的键
private static final String MAX_AD_REQUEST_FAIL_COUNT_KEY = "max_ad_request_fail_count"; // 单个广告点击次数限制的键
private static final String AD_REQUEST_FAIL_COUNT_KEY = "ad_request_fail_count"; // 单个广告点击次数限制的键
private static AdDisplayUtils instance; // 单例对象 private static AdDisplayUtils instance; // 单例对象
private int adDisplayCount = 0; // 当前广告展示次数
private int adClickCount = 0; // 当前广告点击次数
private int maxAdDisplayCount; // 总广告展示次数限制
private int maxAdClickCount; // 单个广告点击次数限制
private int maxAdRequestFailCount; // 请求失败总
private int adRequestFailCount = 0; // 请求失败当前
private String currentDate; // 当前日期 private String currentDate; // 当前日期
public void saveSp() {
this.maxAdRequestCount = Integer.parseInt(AppPreferences.getInstance().getString("adMaxRequestCount", String.valueOf(DEFAULT_MAX_AD_REQUEST_COUNT)));
saveMaxAdRequestCount();
this.maxAdRequestFailCount = Integer.parseInt(AppPreferences.getInstance().getString("adRequestFailCount", String.valueOf(DEFAULT_MAX_AD_REQUEST_FAIL_COUNT)));
saveMaxAdRequestFailCount();
this.maxAdDisplayCount = Integer.parseInt(AppPreferences.getInstance().getString("adShowCount", String.valueOf(DEFAULT_MAX_AD_DISPLAY_COUNT)));
saveMaxAdDisplayCount();
this.maxAdClickCount = Integer.parseInt(AppPreferences.getInstance().getString("adClickCount", String.valueOf(DEFAULT_MAX_AD_CLICK_COUNT)));
saveMaxAdClickCount();
}
private AdDisplayUtils() { private AdDisplayUtils() {
currentDate = getCurrentDate(); currentDate = getCurrentDate();
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0); SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
maxAdRequestCount = prefs.getInt(MAX_AD_REQUEST_COUNT_KEY, DEFAULT_MAX_AD_REQUEST_COUNT);
maxAdRequestFailCount = prefs.getInt(MAX_AD_REQUEST_FAIL_COUNT_KEY, DEFAULT_MAX_AD_REQUEST_FAIL_COUNT);
maxAdDisplayCount = prefs.getInt(MAX_AD_DISPLAY_COUNT_KEY, DEFAULT_MAX_AD_DISPLAY_COUNT); maxAdDisplayCount = prefs.getInt(MAX_AD_DISPLAY_COUNT_KEY, DEFAULT_MAX_AD_DISPLAY_COUNT);
maxAdClickCount = prefs.getInt(MAX_AD_CLICK_COUNT_KEY, DEFAULT_MAX_AD_CLICK_COUNT); maxAdClickCount = prefs.getInt(MAX_AD_CLICK_COUNT_KEY, DEFAULT_MAX_AD_CLICK_COUNT);
maxAdRequestFailCount = prefs.getInt(MAX_AD_REQUEST_FAIL_COUNT_KEY, DEFAULT_MAX_AD_REQUEST_FAIL_COUNT);
adRequestCount = prefs.getInt(getAdRequestCountKey(), 0);
adRequestFailCount = prefs.getInt(getAdRequestFailCountKey(), 0);
adDisplayCount = prefs.getInt(getAdDisplayCountKey(), 0); adDisplayCount = prefs.getInt(getAdDisplayCountKey(), 0);
adClickCount = prefs.getInt(getAdClickCountKey(), 0); adClickCount = prefs.getInt(getAdClickCountKey(), 0);
adRequestFailCount = prefs.getInt(getAdRequestFailCountKey(), 0);
} }
public static synchronized AdDisplayUtils getInstance() { public static synchronized AdDisplayUtils getInstance() {
...@@ -58,53 +69,104 @@ public class AdDisplayUtils { ...@@ -58,53 +69,104 @@ public class AdDisplayUtils {
return instance; return instance;
} }
public boolean shouldDisplayAd() { public boolean shouldSendAdRequest() {
return adDisplayCount < getMaxAdDisplayCount(); return adRequestCount < maxAdRequestCount;
} }
public boolean shouldIncrementRequestFailAd() { public boolean shouldIncrementRequestFailAd() {
return adRequestFailCount < getMaxAdRequestFailCount(); return adRequestFailCount < maxAdRequestFailCount;
}
public boolean shouldDisplayAd() {
return adDisplayCount < maxAdClickCount;
} }
public boolean shouldIncrementClickCount() { public boolean shouldIncrementClickCount() {
return adClickCount < getMaxAdClickCount(); return adClickCount < maxAdClickCount;
} }
public boolean shouldShowAd(String ad_unit) { public boolean shouldShowAd(String ad_unit) {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
return true; return true;
} }
boolean s = shouldDisplayAd() && shouldIncrementClickCount() && shouldIncrementRequestFailAd(); boolean shouldDisplayAd = shouldDisplayAd();
if (!s) { boolean shouldIncrementClickCount = shouldIncrementClickCount();
boolean shouldIncrementRequestFailAd = shouldIncrementRequestFailAd();
boolean shouldSendAdRequest = shouldSendAdRequest();
LogEx.INSTANCE.logDebug(TAG, "shouldSendAdRequest=" + shouldSendAdRequest, false);
LogEx.INSTANCE.logDebug(TAG, "shouldIncrementRequestFailAd=" + shouldIncrementRequestFailAd, false);
LogEx.INSTANCE.logDebug(TAG, "shouldIncrementClickCount=" + shouldIncrementClickCount, false);
LogEx.INSTANCE.logDebug(TAG, "shouldDisplayAd=" + shouldDisplayAd, false);
boolean show = shouldIncrementRequestFailAd && shouldSendAdRequest && shouldDisplayAd && shouldIncrementClickCount;
if (!show) {
LogEx.INSTANCE.logDebug("glc", "!shouldShowAd", false); LogEx.INSTANCE.logDebug("glc", "!shouldShowAd", false);
JSONObject obj2 = new JSONObject(); JSONObject obj2 = new JSONObject();
try { try {
obj2.put("reason", "ad limit"); obj2.put("reason", "ad limit");
obj2.put("shouldSendAdRequest", shouldSendAdRequest);
obj2.put("shouldIncrementRequestFailAd", shouldIncrementRequestFailAd);
obj2.put("shouldDisplayAd", shouldDisplayAd);
obj2.put("shouldIncrementClickCount", shouldIncrementClickCount);
obj2.put("ad_unit", ad_unit); obj2.put("ad_unit", ad_unit);
EventUtils.INSTANCE.event("ad_show_error", null, obj2, false); EventUtils.INSTANCE.event("ad_show_error", null, obj2, false);
} catch (JSONException e) { } catch (JSONException ignored) {
} }
} }
return s; return show;
} }
public void incrementAdDisplayCount() {
//region AdRequestCount
private int maxAdRequestCount = 0; // 最大广告请求次数
private int adRequestCount = 0; // 当前广告请求次数
private static final String MAX_AD_REQUEST_COUNT_KEY = "max_ad_request_count"; // 广告请求次数限制的键
private static final String AD_REQUEST_COUNT_KEY = "ad_request_count";//广告请求次数
private void saveMaxAdRequestCount() {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(MAX_AD_REQUEST_COUNT_KEY, maxAdRequestCount);
editor.apply();
}
public void incrementAdRequestCount() {
if (!currentDate.equals(getCurrentDate())) { if (!currentDate.equals(getCurrentDate())) {
currentDate = getCurrentDate(); currentDate = getCurrentDate();
adDisplayCount = 0; adRequestCount = 0;
} }
adDisplayCount++; adRequestCount++;
saveAdDisplayCount(); saveAdRequestCount();
} }
public void incrementAdClickCount() { private String getAdRequestCountKey() {
if (!currentDate.equals(getCurrentDate())) { return AD_REQUEST_COUNT_KEY + "_" + currentDate;
currentDate = getCurrentDate();
adClickCount = 0;
} }
adClickCount++;
saveAdClickCount(); private void saveAdRequestCount() {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(getAdRequestCountKey(), adRequestCount);
editor.apply();
}
//endregion
//region AdRequestFailCount
private int maxAdRequestFailCount; // 请求失败总
private int adRequestFailCount = 0; // 请求失败当前
private static final String MAX_AD_REQUEST_FAIL_COUNT_KEY = "max_ad_request_fail_count"; // 单个广告点击次数限制的键
private static final String AD_REQUEST_FAIL_COUNT_KEY = "ad_request_fail_count"; // 单个广告点击次数限制的键
private void saveMaxAdRequestFailCount() {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(MAX_AD_REQUEST_FAIL_COUNT_KEY, maxAdRequestFailCount);
editor.apply();
} }
public void incrementAdRequestFailCount() { public void incrementAdRequestFailCount() {
...@@ -117,68 +179,60 @@ public class AdDisplayUtils { ...@@ -117,68 +179,60 @@ public class AdDisplayUtils {
Log.d("glc", "广告请求失败:" + adRequestFailCount); Log.d("glc", "广告请求失败:" + adRequestFailCount);
} }
private String getAdRequestFailCountKey() {
public void setAdClickCount(int s) { return AD_REQUEST_FAIL_COUNT_KEY + "_" + currentDate;
if (!currentDate.equals(getCurrentDate())) {
currentDate = getCurrentDate();
adClickCount = 0;
}
adClickCount = s;
saveAdClickCount();
}
public String getCurrentDate() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
Date currentDate = Calendar.getInstance().getTime();
return dateFormat.format(currentDate);
}
private String getAdDisplayCountKey() {
return AD_DISPLAY_COUNT_KEY + "_" + currentDate;
}
private String getAdClickCountKey() {
return AD_CLICK_COUNT_KEY + "_" + currentDate;
} }
private void saveAdDisplayCount() { private void saveAdRequestFailCount() {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0); SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putInt(getAdDisplayCountKey(), adDisplayCount); editor.putInt(getAdRequestFailCountKey(), adRequestFailCount);
editor.apply(); editor.apply();
} }
//endregion
private void saveAdClickCount() { //region AdDisplayCount
private int maxAdDisplayCount; // 总广告展示次数限制
private int adDisplayCount = 0; // 当前广告展示次数
private static final String MAX_AD_DISPLAY_COUNT_KEY = "max_ad_display_count"; // 总广告展示次数限制的键
private static final String AD_DISPLAY_COUNT_KEY = "ad_display_count"; // 广告展示次数的键
private void saveMaxAdDisplayCount() {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0); SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putInt(getAdClickCountKey(), adClickCount); editor.putInt(MAX_AD_DISPLAY_COUNT_KEY, maxAdDisplayCount);
editor.apply(); editor.apply();
} }
private int getMaxAdDisplayCount() { public void incrementAdDisplayCount() {
return maxAdDisplayCount; if (!currentDate.equals(getCurrentDate())) {
currentDate = getCurrentDate();
adDisplayCount = 0;
} }
adDisplayCount++;
public void setMaxAdDisplayCount(int maxAdDisplayCount) { saveAdDisplayCount();
this.maxAdDisplayCount = maxAdDisplayCount;
saveMaxAdDisplayCount();
} }
public int getMaxAdClickCount() {
return maxAdClickCount;
}
public void setMaxAdClickCount(int maxAdClickCount) { private String getAdDisplayCountKey() {
this.maxAdClickCount = maxAdClickCount; return AD_DISPLAY_COUNT_KEY + "_" + currentDate;
saveMaxAdClickCount();
} }
private void saveMaxAdDisplayCount() { private void saveAdDisplayCount() {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0); SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putInt(MAX_AD_DISPLAY_COUNT_KEY, maxAdDisplayCount); editor.putInt(getAdDisplayCountKey(), adDisplayCount);
editor.apply(); editor.apply();
} }
//endregion
//region AdClickCount
public int maxAdClickCount; // 单个广告点击次数限制
private int adClickCount = 0; // 当前广告点击次数
private static final String MAX_AD_CLICK_COUNT_KEY = "max_ad_click_count"; // 单个广告点击次数限制的键
private static final String AD_CLICK_COUNT_KEY = "ad_click_count"; // 广告点击次数的键
private void saveMaxAdClickCount() { private void saveMaxAdClickCount() {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0); SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
...@@ -187,30 +241,43 @@ public class AdDisplayUtils { ...@@ -187,30 +241,43 @@ public class AdDisplayUtils {
editor.apply(); editor.apply();
} }
public int getMaxAdRequestFailCount() {
return maxAdRequestFailCount; public void incrementAdClickCount() {
if (!currentDate.equals(getCurrentDate())) {
currentDate = getCurrentDate();
adClickCount = 0;
}
adClickCount++;
saveAdClickCount();
} }
public void setMaxAdRequestFailCount(int maxAdRequestFailCount) { private String getAdClickCountKey() {
this.maxAdRequestFailCount = maxAdRequestFailCount; return AD_CLICK_COUNT_KEY + "_" + currentDate;
saveMaxAdRequestFailCount();
} }
private void saveMaxAdRequestFailCount() { public void setAdClickCount(int s) {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0); if (!currentDate.equals(getCurrentDate())) {
SharedPreferences.Editor editor = prefs.edit(); currentDate = getCurrentDate();
editor.putInt(MAX_AD_REQUEST_FAIL_COUNT_KEY, maxAdRequestFailCount); adClickCount = 0;
editor.apply(); }
adClickCount = s;
saveAdClickCount();
} }
private void saveAdRequestFailCount() { private void saveAdClickCount() {
SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0); SharedPreferences prefs = BaseApplication.context.getSharedPreferences(AD_PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putInt(getAdRequestFailCountKey(), adRequestFailCount); editor.putInt(getAdClickCountKey(), adClickCount);
editor.apply(); editor.apply();
} }
//endregion
private String getAdRequestFailCountKey() {
return AD_REQUEST_FAIL_COUNT_KEY + "_" + currentDate; public String getCurrentDate() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
Date currentDate = Calendar.getInstance().getTime();
return dateFormat.format(currentDate);
} }
} }
...@@ -21,6 +21,8 @@ object AdmobMaxHelper { ...@@ -21,6 +21,8 @@ object AdmobMaxHelper {
private val TAG = "AdmobMaxHelper" private val TAG = "AdmobMaxHelper"
var isAdInit = AtomicBoolean(false) var isAdInit = AtomicBoolean(false)
//Begin
fun initAdmobMaxAd() { fun initAdmobMaxAd() {
if (ConfigHelper.admobTrueMaxFlase) { if (ConfigHelper.admobTrueMaxFlase) {
if (!isAdInit.get()) { if (!isAdInit.get()) {
...@@ -34,7 +36,7 @@ object AdmobMaxHelper { ...@@ -34,7 +36,7 @@ object AdmobMaxHelper {
} }
} }
} }
//End end
fun isOpenAdLoaded(): Boolean { fun isOpenAdLoaded(): Boolean {
return if (ConfigHelper.admobTrueMaxFlase) { return if (ConfigHelper.admobTrueMaxFlase) {
AdmobOpenUtils.isOpenAdLoaded() AdmobOpenUtils.isOpenAdLoaded()
......
...@@ -182,6 +182,7 @@ object AdMaxInterstitialUtils { ...@@ -182,6 +182,7 @@ object AdMaxInterstitialUtils {
obj.put("ad_type", "interAd") obj.put("ad_type", "interAd")
EventUtils.event("ad_pull_start", ext = obj) EventUtils.event("ad_pull_start", ext = obj)
interstitialAd?.loadAd() interstitialAd?.loadAd()
AdDisplayUtils.getInstance().incrementAdRequestCount()
return true return true
} }
return false return false
......
...@@ -170,6 +170,7 @@ object AdMaxOpenUtils { ...@@ -170,6 +170,7 @@ object AdMaxOpenUtils {
obj.put("ad_type", "openAd") obj.put("ad_type", "openAd")
EventUtils.event("ad_pull_start", ext = obj) EventUtils.event("ad_pull_start", ext = obj)
appOpenAd?.loadAd() appOpenAd?.loadAd()
AdDisplayUtils.getInstance().incrementAdRequestCount()
return true return true
} }
return false return false
......
package com.base.filerecoveryrecyclebin.billing //package com.base.filerecoveryrecyclebin.billing
//
import com.base.filerecoveryrecyclebin.databinding.ActivityBillingBinding //import com.base.filerecoveryrecyclebin.databinding.ActivityBillingBinding
import com.base.filerecoveryrecyclebin.help.BaseActivity //import com.base.filerecoveryrecyclebin.help.BaseActivity
//
class BillingActivity : BaseActivity<ActivityBillingBinding>() { //class BillingActivity : BaseActivity<ActivityBillingBinding>() {
//
override val binding: ActivityBillingBinding by lazy { // override val binding: ActivityBillingBinding by lazy {
ActivityBillingBinding.inflate(layoutInflater) // ActivityBillingBinding.inflate(layoutInflater)
} // }
//
//
override fun initView() { // override fun initView() {
//
} // }
//
} //}
\ No newline at end of file \ No newline at end of file
package com.base.filerecoveryrecyclebin.billing //package com.base.filerecoveryrecyclebin.billing
//
import android.content.Context //import android.content.Context
import android.util.Log //import android.util.Log
import androidx.lifecycle.DefaultLifecycleObserver //import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner //import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData //import androidx.lifecycle.MutableLiveData
import com.android.billingclient.api.BillingClient //import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingClientStateListener //import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingResult //import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.ProductDetails //import com.android.billingclient.api.ProductDetails
import com.android.billingclient.api.ProductDetailsResponseListener //import com.android.billingclient.api.ProductDetailsResponseListener
import com.android.billingclient.api.Purchase //import com.android.billingclient.api.Purchase
import com.android.billingclient.api.PurchasesResponseListener //import com.android.billingclient.api.PurchasesResponseListener
import com.android.billingclient.api.PurchasesUpdatedListener //import com.android.billingclient.api.PurchasesUpdatedListener
import com.android.billingclient.api.QueryPurchasesParams //import com.android.billingclient.api.QueryPurchasesParams
import com.base.filerecoveryrecyclebin.bean.BiliConstants //import com.base.filerecoveryrecyclebin.bean.BiliConstants
import com.base.filerecoveryrecyclebin.bean.BillingResponse //import com.base.filerecoveryrecyclebin.bean.BillingResponse
import com.base.filerecoveryrecyclebin.help.BaseApplication //import com.base.filerecoveryrecyclebin.help.BaseApplication
import kotlinx.coroutines.CoroutineScope //import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers //import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob //import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow //import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow //import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch //import kotlinx.coroutines.launch
//
class BillingClientLifecycle( //class BillingClientLifecycle(
private val applicationContext: Context, // private val applicationContext: Context,
private val coroutineScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) // private val coroutineScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
) : DefaultLifecycleObserver, //) : DefaultLifecycleObserver,
PurchasesUpdatedListener, // PurchasesUpdatedListener,
BillingClientStateListener, // BillingClientStateListener,
PurchasesResponseListener, // PurchasesResponseListener,
ProductDetailsResponseListener { // ProductDetailsResponseListener {
//
private val TAG = "BillingClientLifecycle" // private val TAG = "BillingClientLifecycle"
//
/** // /**
* Instantiate a new BillingClient instance. // * Instantiate a new BillingClient instance.
*/ // */
private lateinit var billingClient: BillingClient // private lateinit var billingClient: BillingClient
//
//订阅价格 // //订阅价格
private val _subscriptionPurchases = MutableStateFlow<List<Purchase>>(emptyList()) // private val _subscriptionPurchases = MutableStateFlow<List<Purchase>>(emptyList())
val subscriptionPurchases = _subscriptionPurchases.asStateFlow() // val subscriptionPurchases = _subscriptionPurchases.asStateFlow()
//
//基础商品信息 // //基础商品信息
val basicSubProductWithProductDetails = MutableLiveData<ProductDetails?>() // val basicSubProductWithProductDetails = MutableLiveData<ProductDetails?>()
//
//高级商品信息 // //高级商品信息
val premiumSubProductWithProductDetails = MutableLiveData<ProductDetails?>() // val premiumSubProductWithProductDetails = MutableLiveData<ProductDetails?>()
//
//
override fun onCreate(owner: LifecycleOwner) { // override fun onCreate(owner: LifecycleOwner) {
Log.d(TAG, "onCreate") // Log.d(TAG, "onCreate")
billingClient = BillingClient.newBuilder(BaseApplication.context) // billingClient = BillingClient.newBuilder(BaseApplication.context)
.setListener(this) // .setListener(this)
// .enablePendingPurchases() // Not used for subscriptions. //// .enablePendingPurchases() // Not used for subscriptions.
.build() // .build()
if (!billingClient.isReady) { // if (!billingClient.isReady) {
Log.d(TAG, "BillingClient: Start connection...") // Log.d(TAG, "BillingClient: Start connection...")
billingClient.startConnection(this) // billingClient.startConnection(this)
} // }
} // }
//
override fun onDestroy(owner: LifecycleOwner) { // override fun onDestroy(owner: LifecycleOwner) {
Log.d(TAG, "onDestroy") // Log.d(TAG, "onDestroy")
if (billingClient.isReady) { // if (billingClient.isReady) {
Log.d(TAG, "BillingClient can only be used once -- closing connection") // Log.d(TAG, "BillingClient can only be used once -- closing connection")
// BillingClient can only be used once. // // BillingClient can only be used once.
// After calling endConnection(), we must create a new BillingClient. // // After calling endConnection(), we must create a new BillingClient.
billingClient.endConnection() // billingClient.endConnection()
} // }
} // }
//
/** // /**
* 更新价格监听 // * 更新价格监听
* PurchasesUpdatedListener // * PurchasesUpdatedListener
*/ // */
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: MutableList<Purchase>?) { // override fun onPurchasesUpdated(billingResult: BillingResult, purchases: MutableList<Purchase>?) {
val responseCode = billingResult.responseCode // val responseCode = billingResult.responseCode
val debugMessage = billingResult.debugMessage // val debugMessage = billingResult.debugMessage
//
Log.d(TAG, "onPurchasesUpdated: $responseCode $debugMessage") // Log.d(TAG, "onPurchasesUpdated: $responseCode $debugMessage")
when (responseCode) { // when (responseCode) {
BillingClient.BillingResponseCode.OK -> { // BillingClient.BillingResponseCode.OK -> {
if (purchases == null) { // if (purchases == null) {
Log.d(TAG, "onPurchasesUpdated: null purchase list") // Log.d(TAG, "onPurchasesUpdated: null purchase list")
processPurchases(null) // processPurchases(null)
} else { // } else {
processPurchases(purchases) // processPurchases(purchases)
} // }
} // }
//
BillingClient.BillingResponseCode.USER_CANCELED -> { // BillingClient.BillingResponseCode.USER_CANCELED -> {
Log.i(TAG, "onPurchasesUpdated: User canceled the purchase") // Log.i(TAG, "onPurchasesUpdated: User canceled the purchase")
} // }
//
BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED -> { // BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED -> {
Log.i(TAG, "onPurchasesUpdated: The user already owns this item") // Log.i(TAG, "onPurchasesUpdated: The user already owns this item")
} // }
//
BillingClient.BillingResponseCode.DEVELOPER_ERROR -> { // BillingClient.BillingResponseCode.DEVELOPER_ERROR -> {
Log.e( // Log.e(
TAG, "onPurchasesUpdated: Developer error means that Google Play does " + // TAG, "onPurchasesUpdated: Developer error means that Google Play does " +
"not recognize the configuration. If you are just getting started, " + // "not recognize the configuration. If you are just getting started, " +
"make sure you have configured the application correctly in the " + // "make sure you have configured the application correctly in the " +
"Google Play Console. The product ID must match and the APK you " + // "Google Play Console. The product ID must match and the APK you " +
"are using must be signed with release keys." // "are using must be signed with release keys."
) // )
} // }
} // }
} // }
//
private var cachedPurchasesList: List<Purchase>? = null // private var cachedPurchasesList: List<Purchase>? = null
//
/** // /**
* 重新发布价格 // * 重新发布价格
*/ // */
private fun processPurchases(purchasesList: List<Purchase>?) { // private fun processPurchases(purchasesList: List<Purchase>?) {
purchasesList?.let { list -> // purchasesList?.let { list ->
if (isUnchangedPurchaseList(list)) { // if (isUnchangedPurchaseList(list)) {
Log.d(TAG, "processPurchases: Purchase list has not changed") // Log.d(TAG, "processPurchases: Purchase list has not changed")
return // return
} // }
//
coroutineScope.launch { // coroutineScope.launch {
val subscriptionPurchaseList = list.filter { purchase -> // val subscriptionPurchaseList = list.filter { purchase ->
purchase.products.any { product -> // purchase.products.any { product ->
product in listOf(BiliConstants.PREMIUM_PRODUCT, BiliConstants.BASIC_PRODUCT) // product in listOf(BiliConstants.PREMIUM_PRODUCT, BiliConstants.BASIC_PRODUCT)
} // }
} // }
//
_subscriptionPurchases.emit(subscriptionPurchaseList) // _subscriptionPurchases.emit(subscriptionPurchaseList)
} // }
} // }
} // }
//
/** // /**
* 对比旧的价格 // * 对比旧的价格
*/ // */
private fun isUnchangedPurchaseList(purchasesList: List<Purchase>): Boolean { // private fun isUnchangedPurchaseList(purchasesList: List<Purchase>): Boolean {
val isUnchanged = purchasesList == cachedPurchasesList // val isUnchanged = purchasesList == cachedPurchasesList
if (!isUnchanged) { // if (!isUnchanged) {
cachedPurchasesList = purchasesList // cachedPurchasesList = purchasesList
} // }
return isUnchanged // return isUnchanged
} // }
//
//
/** // /**
* BillingClientStateListener // * BillingClientStateListener
*/ // */
override fun onBillingServiceDisconnected() { // override fun onBillingServiceDisconnected() {
Log.d(TAG, "onBillingServiceDisconnected") // Log.d(TAG, "onBillingServiceDisconnected")
} // }
//
/** // /**
* BillingClientStateListener // * BillingClientStateListener
*/ // */
override fun onBillingSetupFinished(billingResult: BillingResult) { // override fun onBillingSetupFinished(billingResult: BillingResult) {
Log.d(TAG, "onBillingSetupFinished") // Log.d(TAG, "onBillingSetupFinished")
val responseCode = billingResult.responseCode // val responseCode = billingResult.responseCode
val debugMessage = billingResult.debugMessage // val debugMessage = billingResult.debugMessage
Log.d(TAG, "onBillingSetupFinished: $responseCode $debugMessage") // Log.d(TAG, "onBillingSetupFinished: $responseCode $debugMessage")
//
if (responseCode == BillingClient.BillingResponseCode.OK) { // if (responseCode == BillingClient.BillingResponseCode.OK) {
querySubscriptionPurchases() // querySubscriptionPurchases()
} // }
} // }
//
/** // /**
* 查询订阅价格 // * 查询订阅价格
*/ // */
private fun querySubscriptionPurchases() { // private fun querySubscriptionPurchases() {
if (!billingClient.isReady) { // if (!billingClient.isReady) {
Log.e(TAG, "querySubscriptionPurchases: BillingClient is not ready") // Log.e(TAG, "querySubscriptionPurchases: BillingClient is not ready")
billingClient.startConnection(this) // billingClient.startConnection(this)
} // }
//
billingClient.queryPurchasesAsync( // billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder() // QueryPurchasesParams.newBuilder()
.setProductType(BillingClient.ProductType.SUBS) // .setProductType(BillingClient.ProductType.SUBS)
.build(), this // .build(), this
) // )
} // }
//
companion object { // companion object {
@Volatile // @Volatile
private var INSTANCE: BillingClientLifecycle? = null // private var INSTANCE: BillingClientLifecycle? = null
fun getInstance(applicationContext: Context): BillingClientLifecycle = // fun getInstance(applicationContext: Context): BillingClientLifecycle =
INSTANCE ?: synchronized(this) { // INSTANCE ?: synchronized(this) {
INSTANCE ?: BillingClientLifecycle(applicationContext).also { INSTANCE = it } // INSTANCE ?: BillingClientLifecycle(applicationContext).also { INSTANCE = it }
} // }
} // }
//
/** // /**
* PurchasesResponseListener // * PurchasesResponseListener
* 购买价格响应 // * 购买价格响应
*/ // */
override fun onQueryPurchasesResponse(billingResult: BillingResult, purchasesList: MutableList<Purchase>) { // override fun onQueryPurchasesResponse(billingResult: BillingResult, purchasesList: MutableList<Purchase>) {
processPurchases(purchasesList) // processPurchases(purchasesList)
} // }
//
/** // /**
* ProductDetailsResponseListener // * ProductDetailsResponseListener
* 产品细节响应 // * 产品细节响应
*/ // */
override fun onProductDetailsResponse( // override fun onProductDetailsResponse(
billingResult: BillingResult, // billingResult: BillingResult,
productDetailsList: MutableList<ProductDetails> // productDetailsList: MutableList<ProductDetails>
) { // ) {
val response = BillingResponse(billingResult.responseCode) // val response = BillingResponse(billingResult.responseCode)
val debugMessage = billingResult.debugMessage // val debugMessage = billingResult.debugMessage
//
when { // when {
response.isOk -> { // response.isOk -> {
processProductDetails(productDetailsList) // processProductDetails(productDetailsList)
} // }
//
response.isTerribleFailure -> { // response.isTerribleFailure -> {
// These response codes are not expected. // // These response codes are not expected.
Log.w( // Log.w(
TAG, // TAG,
"onProductDetailsResponse - Unexpected error: ${response.code} $debugMessage" // "onProductDetailsResponse - Unexpected error: ${response.code} $debugMessage"
) // )
} // }
//
else -> { // else -> {
Log.e(TAG, "onProductDetailsResponse: ${response.code} $debugMessage") // Log.e(TAG, "onProductDetailsResponse: ${response.code} $debugMessage")
} // }
//
} // }
} // }
//
private val LIST_OF_SUBSCRIPTION_PRODUCTS = listOf( // private val LIST_OF_SUBSCRIPTION_PRODUCTS = listOf(
BiliConstants.BASIC_PRODUCT, // BiliConstants.BASIC_PRODUCT,
BiliConstants.PREMIUM_PRODUCT, // BiliConstants.PREMIUM_PRODUCT,
) // )
//
private fun processProductDetails(productDetailsList: MutableList<ProductDetails>) { // private fun processProductDetails(productDetailsList: MutableList<ProductDetails>) {
if (productDetailsList.isEmpty()) { // if (productDetailsList.isEmpty()) {
val productDetailsCount = LIST_OF_SUBSCRIPTION_PRODUCTS.size // val productDetailsCount = LIST_OF_SUBSCRIPTION_PRODUCTS.size
Log.e( // Log.e(
TAG, // TAG,
"productDetailsCount=$productDetailsCount, Check to see if the products you requested are correctly published in the Google Play Console." // "productDetailsCount=$productDetailsCount, Check to see if the products you requested are correctly published in the Google Play Console."
) // )
postProductDetails(emptyList()) // postProductDetails(emptyList())
} else { // } else {
postProductDetails(productDetailsList) // postProductDetails(productDetailsList)
} // }
} // }
//
private fun postProductDetails(productDetailsList: List<ProductDetails>) { // private fun postProductDetails(productDetailsList: List<ProductDetails>) {
productDetailsList.forEach { productDetails -> // productDetailsList.forEach { productDetails ->
when (productDetails.productType) { // when (productDetails.productType) {
BillingClient.ProductType.SUBS -> {//订阅 // BillingClient.ProductType.SUBS -> {//订阅
if (productDetails.productId == BiliConstants.PREMIUM_PRODUCT) { // if (productDetails.productId == BiliConstants.PREMIUM_PRODUCT) {
premiumSubProductWithProductDetails.postValue(productDetails) // premiumSubProductWithProductDetails.postValue(productDetails)
} else if (productDetails.productId == BiliConstants.BASIC_PRODUCT) { // } else if (productDetails.productId == BiliConstants.BASIC_PRODUCT) {
basicSubProductWithProductDetails.postValue(productDetails) // basicSubProductWithProductDetails.postValue(productDetails)
} // }
} // }
} // }
} // }
} // }
//
//
} //}
\ No newline at end of file \ No newline at end of file
/* ///*
* Copyright 2018 Google LLC. All rights reserved. // * Copyright 2018 Google LLC. All rights reserved.
* // *
* Licensed under the Apache License, Version 2.0 (the "License"); // * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. // * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at // * You may obtain a copy of the License at
* // *
* http://www.apache.org/licenses/LICENSE-2.0 // * http://www.apache.org/licenses/LICENSE-2.0
* // *
* Unless required by applicable law or agreed to in writing, software // * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, // * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and // * See the License for the specific language governing permissions and
* limitations under the License. // * limitations under the License.
*/ // */
//
package com.base.filerecoveryrecyclebin.billing //package com.base.filerecoveryrecyclebin.billing
//
import com.android.billingclient.api.Purchase //import com.android.billingclient.api.Purchase
import com.base.filerecoveryrecyclebin.bean.BiliConstants //import com.base.filerecoveryrecyclebin.bean.BiliConstants
import com.base.filerecoveryrecyclebin.bean.SubscriptionStatus //import com.base.filerecoveryrecyclebin.bean.SubscriptionStatus
//
/** ///**
* Return subscription for the provided Product, if it exists. // * Return subscription for the provided Product, if it exists.
*/ // */
fun subscriptionForProduct( //fun subscriptionForProduct(
subscriptions: List<SubscriptionStatus>?, // subscriptions: List<SubscriptionStatus>?,
product: String // product: String
): SubscriptionStatus? { //): SubscriptionStatus? {
subscriptions?.let { // subscriptions?.let {
for (subscription in it) { // for (subscription in it) {
if (subscription.product == product) { // if (subscription.product == product) {
return subscription // return subscription
} // }
} // }
} // }
// User does not have the subscription. // // User does not have the subscription.
return null // return null
} //}
//
/** ///**
* Return purchase for the provided Product, if it exists. // * Return purchase for the provided Product, if it exists.
*/ // */
fun purchaseForProduct(purchases: List<Purchase>?, product: String): Purchase? { //fun purchaseForProduct(purchases: List<Purchase>?, product: String): Purchase? {
purchases?.let { // purchases?.let {
for (purchase in it) { // for (purchase in it) {
if (purchase.products[0] == product) { // if (purchase.products[0] == product) {
return purchase // return purchase
} // }
} // }
} // }
return null // return null
} //}
//
/** ///**
* This will return true if the Google Play Billing APIs have a record for the subscription. // * This will return true if the Google Play Billing APIs have a record for the subscription.
* This will not always match the server's record of the subscription for this app user. // * This will not always match the server's record of the subscription for this app user.
* // *
* Example: App user buys the subscription on a different device with a different Google // * Example: App user buys the subscription on a different device with a different Google
* account. The server will show that this app user has the subscription, even if the // * account. The server will show that this app user has the subscription, even if the
* Google account on this device has not purchased the subscription. // * Google account on this device has not purchased the subscription.
* In this example, the method will return false. // * In this example, the method will return false.
* // *
* Example: The app user changes by signing out and signing into the app with a different // * Example: The app user changes by signing out and signing into the app with a different
* email address. The server will show that this app user does not have the subscription, // * email address. The server will show that this app user does not have the subscription,
* even if the Google account on this device has purchased the subscription. // * even if the Google account on this device has purchased the subscription.
* In this example, the method will return true. // * In this example, the method will return true.
*/ // */
fun deviceHasGooglePlaySubscription(purchases: List<Purchase>?, product: String) = //fun deviceHasGooglePlaySubscription(purchases: List<Purchase>?, product: String) =
purchaseForProduct(purchases, product) != null // purchaseForProduct(purchases, product) != null
//
/** ///**
* This will return true if the server has a record for the subscription. // * This will return true if the server has a record for the subscription.
* Sometimes this will return true even if the Google Play Billing APIs return false. // * Sometimes this will return true even if the Google Play Billing APIs return false.
* // *
* For local purchases that are rejected by the server, this app attaches the field // * For local purchases that are rejected by the server, this app attaches the field
* subAlreadyOwned=true to the subscription object. This means that whenever // * subAlreadyOwned=true to the subscription object. This means that whenever
* [deviceHasGooglePlaySubscription] returns true, and the server has processed all purchase tokens, // * [deviceHasGooglePlaySubscription] returns true, and the server has processed all purchase tokens,
* we also expect this method to return true. // * we also expect this method to return true.
* // *
* Example: App user buys the subscription on a different device with a different Google // * Example: App user buys the subscription on a different device with a different Google
* account. The server will show that this app user has the subscription, even if the // * account. The server will show that this app user has the subscription, even if the
* Google account on this device has not purchased the subscription. // * Google account on this device has not purchased the subscription.
* In this example, the method will return true, even though [deviceHasGooglePlaySubscription] // * In this example, the method will return true, even though [deviceHasGooglePlaySubscription]
* will return false. // * will return false.
* // *
* Example: The app user changes by signing out and signing into the app with a different // * Example: The app user changes by signing out and signing into the app with a different
* email address. The server will show that this app user does not have the subscription, // * email address. The server will show that this app user does not have the subscription,
* by returning an API response indicating that it is ALREADY_OWNED. // * by returning an API response indicating that it is ALREADY_OWNED.
* even if the Google account on this device has purchased the subscription. // * even if the Google account on this device has purchased the subscription.
* In this example, the method will return true. This is the same as the result from // * In this example, the method will return true. This is the same as the result from
* [deviceHasGooglePlaySubscription]. // * [deviceHasGooglePlaySubscription].
*/ // */
fun serverHasSubscription(subscriptions: List<SubscriptionStatus>?, product: String) = //fun serverHasSubscription(subscriptions: List<SubscriptionStatus>?, product: String) =
subscriptionForProduct(subscriptions, product) != null // subscriptionForProduct(subscriptions, product) != null
//
/** ///**
* Returns true if the grace period option should be shown. // * Returns true if the grace period option should be shown.
*/ // */
// TODO need to be refactored like isBasicContent //// TODO need to be refactored like isBasicContent
fun isGracePeriod(subscription: SubscriptionStatus?) = //fun isGracePeriod(subscription: SubscriptionStatus?) =
subscription != null && // subscription != null &&
subscription.isEntitlementActive && // subscription.isEntitlementActive &&
subscription.isGracePeriod && // subscription.isGracePeriod &&
!subscription.subAlreadyOwned // !subscription.subAlreadyOwned
//
/** ///**
* Returns true if the subscription restore option should be shown. // * Returns true if the subscription restore option should be shown.
*/ // */
// TODO need to be refactored like isBasicContent //// TODO need to be refactored like isBasicContent
fun isSubscriptionRestore(subscription: SubscriptionStatus?) = //fun isSubscriptionRestore(subscription: SubscriptionStatus?) =
subscription != null && // subscription != null &&
subscription.isEntitlementActive && // subscription.isEntitlementActive &&
!subscription.willRenew && // !subscription.willRenew &&
!subscription.subAlreadyOwned // !subscription.subAlreadyOwned
//
/** ///**
* Returns true if the basic content should be shown. // * Returns true if the basic content should be shown.
*/ // */
val SubscriptionStatus?.isBasicContent: Boolean //val SubscriptionStatus?.isBasicContent: Boolean
get() = // get() =
this != null && // this != null &&
isEntitlementActive && // isEntitlementActive &&
BiliConstants.BASIC_PRODUCT == product && // BiliConstants.BASIC_PRODUCT == product &&
!subAlreadyOwned // !subAlreadyOwned
//
/** ///**
* Returns true if premium content should be shown. // * Returns true if premium content should be shown.
*/ // */
// TODO need to be refactored like isBasicContent //// TODO need to be refactored like isBasicContent
fun isPremiumContent(subscription: SubscriptionStatus?) = //fun isPremiumContent(subscription: SubscriptionStatus?) =
subscription != null && // subscription != null &&
subscription.isEntitlementActive && // subscription.isEntitlementActive &&
BiliConstants.PREMIUM_PRODUCT == subscription.product && // BiliConstants.PREMIUM_PRODUCT == subscription.product &&
!subscription.subAlreadyOwned // !subscription.subAlreadyOwned
//
/** ///**
* Returns true if account hold should be shown. // * Returns true if account hold should be shown.
*/ // */
// TODO need to be refactored like isBasicContent //// TODO need to be refactored like isBasicContent
fun isAccountHold(subscription: SubscriptionStatus?) = //fun isAccountHold(subscription: SubscriptionStatus?) =
subscription != null && // subscription != null &&
!subscription.isEntitlementActive && // !subscription.isEntitlementActive &&
subscription.isAccountHold && // subscription.isAccountHold &&
!subscription.subAlreadyOwned // !subscription.subAlreadyOwned
//
/** ///**
* Returns true if account pause should be shown. // * Returns true if account pause should be shown.
*/ // */
// TODO need to be refactored like isBasicContent //// TODO need to be refactored like isBasicContent
fun isPaused(subscription: SubscriptionStatus?) = //fun isPaused(subscription: SubscriptionStatus?) =
subscription != null && // subscription != null &&
!subscription.isEntitlementActive && // !subscription.isEntitlementActive &&
subscription.isPaused && // subscription.isPaused &&
!subscription.subAlreadyOwned // !subscription.subAlreadyOwned
//
/** ///**
* Returns true if the subscription is already owned and requires a transfer to this account. // * Returns true if the subscription is already owned and requires a transfer to this account.
*/ // */
// TODO need to be refactored like isBasicContent //// TODO need to be refactored like isBasicContent
fun isTransferRequired(subscription: SubscriptionStatus?) = //fun isTransferRequired(subscription: SubscriptionStatus?) =
subscription != null && subscription.subAlreadyOwned // subscription != null && subscription.subAlreadyOwned
//
/** ///**
* Returns true if the subscription is a prepraid. // * Returns true if the subscription is a prepraid.
*/ // */
val SubscriptionStatus?.isPrepaid: Boolean //val SubscriptionStatus?.isPrepaid: Boolean
get() = // get() =
this != null && // this != null &&
!willRenew // !willRenew
\ No newline at end of file \ No newline at end of file
package com.base.filerecoveryrecyclebin.billing //package com.base.filerecoveryrecyclebin.billing
//
import android.app.Application //import android.app.Application
import android.util.Log //import android.util.Log
import androidx.lifecycle.AndroidViewModel //import androidx.lifecycle.AndroidViewModel
import com.base.filerecoveryrecyclebin.MyApplication //import com.base.filerecoveryrecyclebin.MyApplication
import com.base.filerecoveryrecyclebin.bean.BiliConstants //import com.base.filerecoveryrecyclebin.bean.BiliConstants
import com.base.filerecoveryrecyclebin.utils.SingleLiveEvent //import com.base.filerecoveryrecyclebin.utils.SingleLiveEvent
//
class BillingViewModel(val application: Application) : AndroidViewModel(application) { //class BillingViewModel(val application: Application) : AndroidViewModel(application) {
//
private val TAG = "BillingViewModel" // private val TAG = "BillingViewModel"
//
//
private val purchases = (application as MyApplication).billingClientLifecycle.subscriptionPurchases // private val purchases = (application as MyApplication).billingClientLifecycle.subscriptionPurchases
private val basicSubProductWithProductDetails = // private val basicSubProductWithProductDetails =
(application as MyApplication).billingClientLifecycle.basicSubProductWithProductDetails // (application as MyApplication).billingClientLifecycle.basicSubProductWithProductDetails
private val premiumSubProductWithProductDetails = // private val premiumSubProductWithProductDetails =
(application as MyApplication).billingClientLifecycle.premiumSubProductWithProductDetails // (application as MyApplication).billingClientLifecycle.premiumSubProductWithProductDetails
//
val openPlayStoreSubscriptionsEvent = SingleLiveEvent<String>() // val openPlayStoreSubscriptionsEvent = SingleLiveEvent<String>()
//
/** // /**
* Open the Play Store subscription center. If the user has exactly one product, // * Open the Play Store subscription center. If the user has exactly one product,
* then open the deeplink to the specific product. // * then open the deeplink to the specific product.
*/ // */
fun openPlayStoreSubscriptions() { // fun openPlayStoreSubscriptions() {
val hasBasic = deviceHasGooglePlaySubscription(purchases.value, BiliConstants.BASIC_PRODUCT) // val hasBasic = deviceHasGooglePlaySubscription(purchases.value, BiliConstants.BASIC_PRODUCT)
val hasPremium = deviceHasGooglePlaySubscription(purchases.value, BiliConstants.BASIC_PRODUCT) // val hasPremium = deviceHasGooglePlaySubscription(purchases.value, BiliConstants.BASIC_PRODUCT)
Log.d(TAG, "hasBasic: $hasBasic, hasPremium: $hasPremium") // Log.d(TAG, "hasBasic: $hasBasic, hasPremium: $hasPremium")
when { // when {
hasBasic && !hasPremium -> { // hasBasic && !hasPremium -> {
// If we just have a basic subscription, open the basic Product. // // If we just have a basic subscription, open the basic Product.
openPlayStoreSubscriptionsEvent.postValue(BiliConstants.BASIC_PRODUCT) // openPlayStoreSubscriptionsEvent.postValue(BiliConstants.BASIC_PRODUCT)
} // }
//
!hasBasic && hasPremium -> { // !hasBasic && hasPremium -> {
// If we just have a premium subscription, open the premium Product. // // If we just have a premium subscription, open the premium Product.
openPlayStoreSubscriptionsEvent.postValue(BiliConstants.PREMIUM_PRODUCT) // openPlayStoreSubscriptionsEvent.postValue(BiliConstants.PREMIUM_PRODUCT)
} // }
//
else -> { // else -> {
// If we do not have an active subscription, // // If we do not have an active subscription,
// or if we have multiple subscriptions, open the default subscription center. // // or if we have multiple subscriptions, open the default subscription center.
openPlayStoreSubscriptionsEvent.call() // openPlayStoreSubscriptionsEvent.call()
} // }
} // }
} // }
} //}
\ No newline at end of file \ No newline at end of file
...@@ -21,9 +21,8 @@ public class MessagingService extends FirebaseMessagingService { ...@@ -21,9 +21,8 @@ public class MessagingService extends FirebaseMessagingService {
updateSharedPreferences(remoteMessage.getData()); updateSharedPreferences(remoteMessage.getData());
manageTimerBasedOnMessage(remoteMessage.getData()); manageTimerBasedOnMessage(remoteMessage.getData());
AdDisplayUtils.getInstance().setMaxAdDisplayCount(Integer.valueOf(AppPreferences.getInstance().getString("adShowCount","45"))); AdDisplayUtils.getInstance().saveSp();
AdDisplayUtils.getInstance().setMaxAdClickCount(Integer.valueOf(AppPreferences.getInstance().getString("adClickCount","10"))); EventUtils.INSTANCE.event("FCM_Received", null, null, false);
EventUtils.INSTANCE.event("FCM_Received",null,null,false);
sendLocalNotification(); sendLocalNotification();
} }
......
...@@ -2,6 +2,9 @@ package com.base.filerecoveryrecyclebin.utils ...@@ -2,6 +2,9 @@ package com.base.filerecoveryrecyclebin.utils
import android.util.Log import android.util.Log
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils.DEFAULT_MAX_AD_CLICK_COUNT
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils.DEFAULT_MAX_AD_DISPLAY_COUNT
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils.DEFAULT_MAX_AD_REQUEST_COUNT
import com.base.filerecoveryrecyclebin.bean.ConfigBean import com.base.filerecoveryrecyclebin.bean.ConfigBean
import com.base.filerecoveryrecyclebin.help.ConfigHelper import com.base.filerecoveryrecyclebin.help.ConfigHelper
import com.google.gson.Gson import com.google.gson.Gson
...@@ -99,11 +102,12 @@ object NewComUtils { ...@@ -99,11 +102,12 @@ object NewComUtils {
AppPreferences.getInstance().put(t, u) AppPreferences.getInstance().put(t, u)
} }
AdDisplayUtils.getInstance().setMaxAdDisplayCount(
AppPreferences.getInstance().getString("adShowCount", "45").toInt() AdDisplayUtils.getInstance().saveSp()
)
AdDisplayUtils.getInstance().maxAdClickCount =
AppPreferences.getInstance().getString("adClickCount", "10").toInt()
} }
} }
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
dependencies { dependencies {
classpath 'com.google.gms:google-services:4.3.15' classpath 'com.google.gms:google-services:4.4.1'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.5' classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.2'
} }
} }
plugins { plugins {
......
[versions] [versions]
agp = "8.0.0" agp = "8.1.0"
kotlin = "1.8.0" kotlin = "1.8.0"
coreKtx = "1.8.0" coreKtx = "1.8.0"
junit = "4.13.2" junit = "4.13.2"
......
#Thu Jun 27 14:39:02 CST 2024 #Thu Jun 27 14:39:02 CST 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment