Commit 31ba5030 authored by 周文华's avatar 周文华

【新增&删除】1.新增弹窗基本逻辑与样式。2.删除无用库与类.

parent 30195c7f
......@@ -176,7 +176,7 @@ dependencies {
implementation("com.google.firebase:firebase-messaging")
implementation("com.google.firebase:firebase-analytics-ktx")
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-config")
//implementation("com.google.firebase:firebase-config")
//广告
//admob渠道
......@@ -197,9 +197,9 @@ dependencies {
val work_version = "2.8.1"
implementation("androidx.work:work-runtime-ktx:$work_version")
val billing_version = "7.1.1"
implementation("com.android.billingclient:billing:$billing_version")
implementation("com.android.billingclient:billing-ktx:$billing_version")
// val billing_version = "7.1.1"
// implementation("com.android.billingclient:billing:$billing_version")
// implementation("com.android.billingclient:billing-ktx:$billing_version")
......
......@@ -13,8 +13,6 @@
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
......@@ -46,14 +44,15 @@
<activity
android:name=".ui.splash.SplashActivity"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/splash.theme"
tools:ignore="DiscouragedApi,LockedOrientationActivity">
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
<!-- </intent-filter>-->
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.main.MainActivity"
......@@ -68,16 +67,7 @@
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
<!-- </intent-filter> -->
</activity>
<activity
android:name=".business.pangle.PangleActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.language.LanguageActivity"
android:exported="false"
......@@ -239,6 +229,54 @@
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id" />
<activity
android:name=".ui.guide2.GuideAc"
android:exported="false"
android:screenOrientation="portrait"
android:theme="@style/Guide.Theme"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.guide2.Guide2Ac"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:taskAffinity=""
android:theme="@style/Guide.Theme"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<service
android:name=".ui.guide2.NotifyService"
android:enabled="true"
android:exported="false" />
<activity-alias
android:name=".OtherAcAlias"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/logo"
android:label="@string/app_name"
android:launchMode="singleTop"
android:roundIcon="@mipmap/logo"
android:targetActivity=".ui.splash.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity
android:name=".ui.guide2.Guide0Activity"
android:enabled="false"
android:excludeFromRecents="true"
android:exported="true"
android:launchMode="singleTop"
android:noHistory="true"
android:theme="@style/Guide.Theme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.INFO" />
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
......@@ -71,7 +71,7 @@ class MyApplication : Application() {
initUUid()
initGid()
initApp()
// initLifeListener()
initLifeListener()
initLanguage()
}
......@@ -226,15 +226,15 @@ class MyApplication : Application() {
"flag=$flag" + " activity:" + activity.localClassName + " topActivity=${topActivity?.localClassName}"
)
if (flag) {
topActivity?.startActivity(
Intent(
topActivity, SplashActivity::class.java
).apply {
putExtra("isHotLaunch", true)
putExtra("type", -1)
})
}
// if (flag) {
// topActivity?.startActivity(
// Intent(
// topActivity, SplashActivity::class.java
// ).apply {
// putExtra("isHotLaunch", true)
// putExtra("type", -1)
// })
// }
}
lastTimeResume = 0
}
......
......@@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.LayoutRes
import com.base.appzxhy.BuildConfig
//import com.applovin.sdk.AppLovinMediationProvider
//import com.applovin.sdk.AppLovinSdk
//import com.applovin.sdk.AppLovinSdkInitializationConfiguration
......@@ -176,27 +177,27 @@ object AdsMgr {
return PAGConfig.Builder()
.appId(GlobalConfig.ID_PANGLE_APPLICATION)
.appIcon(R.mipmap.logo)
.debugLog(true)
.debugLog(BuildConfig.DEBUG)
.supportMultiProcess(false)
.build()
}
fun initPangle(context: Context) {
val pAGInitConfig = buildNewConfig(context)
PAGSdk.init(context, pAGInitConfig, object : PAGInitCallback {
override fun success() {
val version = PAGSdk.getSDKVersion()
val isInitSuccess = PAGSdk.isInitSuccess()
context.toast("pangle init success $version")
}
override fun fail(code: Int, msg: String?) {
context.toast("pangle init fail code=$code msg=$msg")
}
})
fun initPangle(context: Context, next: ((isInit:Boolean) -> Unit)? = null) {
val pAGInitConfig = buildNewConfig(context)
PAGSdk.init(context, pAGInitConfig, object : PAGInitCallback {
override fun success() {
val version = PAGSdk.getSDKVersion()
val isInitSuccess = PAGSdk.isInitSuccess()
next?.invoke(isInitSuccess)
//context.toast("pangle init success $version")
}
override fun fail(code: Int, msg: String?) {
next?.invoke(false)
//context.toast("pangle init fail code=$code msg=$msg")
}
})
}
......@@ -333,7 +334,11 @@ object AdsMgr {
*
* @param parent 展示广告的父布局容器
*/
fun showBanner(parent: FrameLayout, collapsible: Boolean = true, adClose: (() -> Unit)? = null) {
fun showBanner(
parent: FrameLayout,
collapsible: Boolean = true,
adClose: (() -> Unit)? = null
) {
if (!adsConfigBean.isAdShow) {
parent.visibility = View.GONE
return
......
package com.base.appzxhy.business.billing
import android.app.Activity
import android.os.Bundle
import android.util.Log
import com.android.billingclient.api.AcknowledgePurchaseParams
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingFlowParams
import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.PendingPurchasesParams
import com.android.billingclient.api.ProductDetails
import com.android.billingclient.api.ProductDetails.SubscriptionOfferDetails
import com.android.billingclient.api.Purchase
import com.android.billingclient.api.PurchasesUpdatedListener
import com.android.billingclient.api.QueryProductDetailsParams
import com.android.billingclient.api.QueryPurchasesParams
import com.android.billingclient.api.acknowledgePurchase
import com.android.billingclient.api.queryProductDetails
import com.base.appzxhy.MyApplication
import com.base.appzxhy.bean.config.VipConfigBean
import com.base.appzxhy.business.helper.EventUtils
import com.base.appzxhy.utils.AppPreferences
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject
object GoogleSubUtil {
private val TAG = "GoogleSubUtil"
const val KEY_SP_VIP = "spVip"
/**
* vip历史状态
* 用来判断没拿到数据时是否是vip,是否展示广告判断用这个
*/
fun getSpVip(): Boolean {
return AppPreferences.getInstance().getBoolean(KEY_SP_VIP, false)
}
/**
* 用来实时为UI提供状态
* null表示未知状态
*/
val vipResult: MutableStateFlow<Boolean?> = MutableStateFlow(null)
/**
* 定义连接状态
*/
val connectionResult = MutableStateFlow(false)
/**
*年产品详情
*/
var yearProductFlow: MutableStateFlow<ProductDetails?> = MutableStateFlow(null)
/**
*月产品详情
*/
var monthProductFlow: MutableStateFlow<ProductDetails?> = MutableStateFlow(null)
/**
*周产品详情
*/
var weekProductFlow: MutableStateFlow<ProductDetails?> = MutableStateFlow(null)
/**
* 订阅详情是否已经准备
*/
var subOffDetailReady = MutableStateFlow(false)
/**
* 获取订阅详情
*/
fun getSubOffDetail(productDetails: ProductDetails, basePlanId: String, offId: String): SubscriptionOfferDetails? {
val subOffDetails = productDetails.subscriptionOfferDetails
return if (subOffDetails.isNullOrEmpty()) {
null
} else {
subOffDetails.find { it.basePlanId == basePlanId && it.offerId == offId } ?: subOffDetails[0]
}
}
/**
* 更新sp里面的vip状态
*/
fun vipSpObserveForever() {
MainScope().launch {
vipResult.collectLatest {
if (it != null) {
AppPreferences.getInstance().putBoolean(KEY_SP_VIP, it)
}
}
}
}
private val client by lazy {
vipSpObserveForever()
BillingClient.newBuilder(MyApplication.appContext)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases(
PendingPurchasesParams.newBuilder().enableOneTimeProducts().build()
)
// Configure other settings.
.build()
}
/**
* 购买状态更新监听
*/
private val purchasesUpdatedListener = object : PurchasesUpdatedListener {
override fun onPurchasesUpdated(
billingResult: BillingResult,
purchases: MutableList<Purchase>?,
) {
var purchase = purchases?.firstOrNull()
eventJSON.apply { put("purchaseToken", purchase?.purchaseToken) }
when (billingResult.responseCode) {
BillingClient.BillingResponseCode.OK -> {
purchase = purchases?.firstOrNull { it.purchaseState == Purchase.PurchaseState.PURCHASED } ?: return
MainScope().launch {
val flag = acknowledgePurchase(purchase)
vipResult.update { flag }
}
EventUtils.event("google_billing_success", value = "success", ext = eventJSON)
val bundle = Bundle()
bundle.putString(FirebaseAnalytics.Param.CURRENCY, eventJSON.get(FirebaseAnalytics.Param.CURRENCY) as String)
bundle.putDouble(FirebaseAnalytics.Param.VALUE, eventJSON.get(FirebaseAnalytics.Param.VALUE) as Double)
bundle.putString(FirebaseAnalytics.Param.ITEM_ID, eventJSON.get(FirebaseAnalytics.Param.ITEM_ID) as String)
Firebase.analytics.logEvent(FirebaseAnalytics.Event.PURCHASE, bundle)
}
BillingClient.BillingResponseCode.BILLING_UNAVAILABLE -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "处理过程中发生用户计费错误。")
})
}
BillingClient.BillingResponseCode.DEVELOPER_ERROR -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "API操作期间发生致命错误。")
})
}
BillingClient.BillingResponseCode.ERROR -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "错误使用API导致的错误。")
})
}
BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "当前设备上的Play商店不支持请求的功能。")
})
}
BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "购买失败,因为该物品已被拥有。")
})
}
BillingClient.BillingResponseCode.ITEM_NOT_OWNED -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "对该项目请求的操作失败,因为它不属于用户。")
})
}
BillingClient.BillingResponseCode.ITEM_UNAVAILABLE -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "所请求的产品不可购买。")
})
}
BillingClient.BillingResponseCode.NETWORK_ERROR -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "操作过程中发生网络错误。")
})
}
BillingClient.BillingResponseCode.SERVICE_DISCONNECTED -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "该应用程序未通过Google Play计费库连接到Play商店服务。")
})
}
BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "该服务当前不可用。")
})
}
BillingClient.BillingResponseCode.USER_CANCELED -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "交易已被用户取消。")
})
}
else -> {
EventUtils.event("google_billing_error", ext = eventJSON.apply {
put("info", "未知错误。")
})
}
}
}
}
fun endConnection() {
client.endConnection()
connectionResult.update { false }
}
fun startConnection() {
Log.e(TAG, "startConnection")
if (client.isReady) {
return
}
if (connectionResult.value == true) {
return
}
var time = 3
MainScope().launch {
while (!connectionResult.value && time > 0) {
time--
realStartConnection()
delay(1500)
}
}
}
private fun realStartConnection() {
client.startConnection(object : BillingClientStateListener {
override fun onBillingServiceDisconnected() {
Log.e(TAG, "onBillingServiceDisconnected")
connectionResult.update { false }
}
override fun onBillingSetupFinished(billingResult: BillingResult) {
Log.e(TAG, "onBillingSetupFinished")
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
Log.e(TAG, "onBillingSetupFinished ok")
connectionResult.update { true }
//查询订阅购买状态
queryPurchasesAsync()
//查询所有的订阅产品
queryAllProduct()
} else {
connectionResult.update { false }
}
}
})
}
private fun queryAllProduct() = MainScope().launch(Dispatchers.IO) {
val productYear: ProductDetails? = queryProduct(VipConfigBean.vipConfigBean.productIdYear)
val productMonth: ProductDetails? = queryProduct(VipConfigBean.vipConfigBean.productIdMonth)
val productWeek: ProductDetails? = queryProduct(VipConfigBean.vipConfigBean.productIdWeek)
Log.e(TAG, "productYear=${productYear}")
Log.e(TAG, "productMonth=${productMonth}")
Log.e(TAG, "productWeek=${productWeek}")
yearProductFlow.update { productYear }
monthProductFlow.update { productMonth }
weekProductFlow.update { productWeek }
val isReady = !(productYear?.subscriptionOfferDetails.isNullOrEmpty() ||
productMonth?.subscriptionOfferDetails.isNullOrEmpty() ||
productWeek?.subscriptionOfferDetails.isNullOrEmpty())
Log.e(TAG, "isReady=$isReady")
subOffDetailReady.update { isReady }
}
suspend fun queryProduct(productId: String): ProductDetails? {
val params = getParams(productId)
val productDetails = withContext(Dispatchers.IO) {
val productDetailsResult = client.queryProductDetails(params.build())
return@withContext productDetailsResult.productDetailsList?.firstOrNull {
//筛选匹配商品
productId == it.productId
}
}
return productDetails
}
private fun getParams(productId: String): QueryProductDetailsParams.Builder {
val params = QueryProductDetailsParams.newBuilder()
val productList = listOf(
QueryProductDetailsParams.Product.newBuilder()
.setProductId(productId)
.setProductType(BillingClient.ProductType.SUBS)
.build()
)
params.setProductList(productList)
return params
}
/**
* 支付上报
*/
var eventJSON = JSONObject()
fun pay(activity: Activity, productDetails: ProductDetails, subOffDetail: SubscriptionOfferDetails) {
val pricingPhase = subOffDetail.pricingPhases.pricingPhaseList[0]
eventJSON = JSONObject().apply {
put("productId", productDetails.productId)
put("basePlanId", subOffDetail.basePlanId)
put("offerId", subOffDetail.offerId)
put("offerToken", subOffDetail.offerToken)
put(FirebaseAnalytics.Param.CURRENCY, pricingPhase.priceCurrencyCode)//订阅价格类型
put(FirebaseAnalytics.Param.VALUE, pricingPhase.formattedPrice.formattedPrice2Double())//订阅价格 4.66
put(FirebaseAnalytics.Param.ITEM_ID, productDetails.productId)//订阅产品ID
}
EventUtils.event("google_billing", value = "click", ext = eventJSON)
val currency = eventJSON.get(FirebaseAnalytics.Param.CURRENCY) as String
val value = eventJSON.get(FirebaseAnalytics.Param.VALUE) as Double
val item_id = eventJSON.get(FirebaseAnalytics.Param.ITEM_ID) as String
Log.e(TAG, "FirebaseAnalytics currency=$currency value=$value item_id=$item_id")
val productDetailsParamsList = listOf(
BillingFlowParams.ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.setOfferToken(subOffDetail.offerToken)
.build()
)
val billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.build()
val billingResult = client.launchBillingFlow(activity, billingFlowParams)
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
queryPurchasesAsync()
} else {
}
}
/**
* 查询所有[购买]状态
*/
fun queryPurchasesAsync() = MainScope().launch(Dispatchers.IO) {
client.queryPurchasesAsync(
QueryPurchasesParams.newBuilder()
.setProductType(BillingClient.ProductType.SUBS)
.build()
) { billingResult, purchases ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
val noVip = purchases.isEmpty()
Log.e("vipResult", "noVip=$noVip")
if (noVip) {
vipResult.update { false }
} else {
MainScope().launch {
purchases.forEachIndexed { index, purchase: Purchase ->
// val vip = it.isAcknowledged && it.isAutoRenewing
// val purchaseState = purchase.purchaseState //买状态,表示购买交易的状态,例如是否已完成、是否被取消等。
var vip: Boolean?
val isAcknowledged = purchase.isAcknowledged // 是否已确认,表示该购买是否已经被应用确认。
vip = isAcknowledged
Log.e(TAG, "vipResult 1 vip=$vip index=$index")
if (!isAcknowledged) {//未确认再查询下购买状态
vip = acknowledgePurchase(purchase)
Log.e(TAG, "vipResult 2 vip=$vip index=$index")
}
vipResult.update { vip }
}
}
}
}
}
}
//确认商品购买状态,null表示未知状态
// BillingClient.BillingResponseCode.OK 已确认
// BillingClient.BillingResponseCode.USER_CANCELED 用户取消等
private suspend fun acknowledgePurchase(purchase: Purchase): Boolean? {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
val ackPurchaseResult = withContext(Dispatchers.IO) {
client.acknowledgePurchase(acknowledgePurchaseParams)
}
if (ackPurchaseResult.responseCode == BillingClient.BillingResponseCode.OK) {
EventUtils.event("google_billing", value = "consume", ext = eventJSON)
return true
}
return null
}
/**
* 价格提前数字转Double
*/
fun String.formattedPrice2Double(): Double {
val regex = """\$([\d.]+)""".toRegex()
val matchResult = regex.find(this)
if (matchResult != null) {
val price = matchResult.groupValues[1].toDouble()
return price
} else {
return 0.0
}
}
}
package com.base.appzxhy.business.helper
import android.util.Log
import com.android.installreferrer.api.InstallReferrerClient
import com.android.installreferrer.api.InstallReferrerStateListener
import com.android.installreferrer.api.ReferrerDetails
......@@ -27,11 +28,11 @@ object InstallHelps {
//用户来源
var installSource = ""
get() {
return AppPreferences.getInstance().getString("install_source", field)
return AppPreferences.getInstance().getString("inse", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("install_source", value, true)
AppPreferences.getInstance().put("inse", value, true)
}
//用户是否上报过
......@@ -55,7 +56,6 @@ object InstallHelps {
}
fun init(requestCfg: () -> Unit) {
if (installEvent) {
requestCfg.invoke()
return
......@@ -72,7 +72,7 @@ object InstallHelps {
eventInstallReferrer(response)
installReferrer = response.installReferrer
Log.e("tttttttttttttttttt", installReferrer)
installSource = if (listOf(
"gclid",
"facebook",
......@@ -81,12 +81,12 @@ object InstallHelps {
) {
//自然用户
if (BuildConfig.DEBUG) {
"channel"
"cl"
} else {
"origin"
"or"
}
} else {
"channel"
"cl"
}
requestCfg()
}
......
package com.base.appzxhy.ui.guide2;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
public class ComponentUtil {
public static void setComponentEnabled(Context context, String componentName, boolean enable) {
PackageManager pm = context.getPackageManager();
ComponentName cn = new ComponentName(context, componentName);
int newState = enable ?
PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
int currentState = pm.getComponentEnabledSetting(cn);
if (currentState == newState) {
return;
}
// 设置组件状态
pm.setComponentEnabledSetting(
cn,
newState,
PackageManager.DONT_KILL_APP
);
// 通知 Launcher 刷新桌面(解决图标不隐藏的问题)
if (!enable) {
notifyLauncherRefresh(context);
}
handleAndroid12LocaleService(context, enable);
}
private static void notifyLauncherRefresh(Context context) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setPackage(context.getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.sendBroadcast(intent);
}
private static void handleAndroid12LocaleService(Context context, boolean enable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
try {
String localeService = "androidx.appcompat.app.AppLocalesMetadataHolderService";
ComponentName cn = new ComponentName(context, localeService);
int currentState = context.getPackageManager()
.getComponentEnabledSetting(cn);
if (enable && currentState != PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
// 启用服务并处理本地化设置
context.getPackageManager().setComponentEnabledSetting(
cn,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
);
// 这里可以添加实际的本地化处理逻辑
// 例如:LocaleList localeList = getSystemLocaleList(context);
}
} catch (Exception e) {
Log.e("ComponentUtil", "Error handling locale service", e);
}
}
}
}
\ No newline at end of file
package com.base.appzxhy.ui.guide2;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class Guide0Activity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 直接跳转到主界面
startActivity(new Intent(this, GuideAc.class));
finish();
}
}
\ No newline at end of file
package com.base.appzxhy.ui.guide2
import android.os.Bundle
import android.util.Log
import androidx.activity.addCallback
import com.base.appzxhy.MyApplication
import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.business.ads.AdsShowCallBack
import com.base.appzxhy.databinding.ActivityGuideInfoBinding
import com.base.appzxhy.utils.ActivityManagerUtils
/**
*Create by SleepDog on 2025-06-26
*/
class Guide2Ac : BaseActivity<ActivityGuideInfoBinding>(ActivityGuideInfoBinding::inflate) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
onBackPressedDispatcher.addCallback {
}
Log.e("tttttttttttttttttt", "AdStart")
AdsMgr.initPangle(MyApplication.appContext) {
runOnUiThread {
if (it) AdsMgr.showInsert(this, showCallBack = object : AdsShowCallBack() {
override fun next() {
Log.e("tttttttttttttttttt", "adFinish")
finish()
if (!ActivityManagerUtils.getInstance()
.isActivityInStack(GuideAc::class.java)
) goToAc(GuideAc::class.java)
}
})
else {
finish()
if (!ActivityManagerUtils.getInstance().isActivityInStack(GuideAc::class.java)
) goToAc(GuideAc::class.java)
}
}
}
}
}
\ No newline at end of file
package com.base.appzxhy.ui.guide2
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.WindowManager
import androidx.activity.addCallback
import androidx.core.view.postDelayed
import com.base.appzxhy.MyApplication
import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.databinding.ActivityGuideInfoBinding
/**
*Create by SleepDog on 2025-06-26
*/
class GuideAc : BaseActivity<ActivityGuideInfoBinding>(ActivityGuideInfoBinding::inflate) {
override fun onCreate(savedInstanceState: Bundle?) {
window?.run {
val layoutParams = attributes
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
attributes = layoutParams
}
super.onCreate(savedInstanceState)
onBackPressedDispatcher.addCallback {
}
AdsMgr.initPangle(MyApplication.appContext)
Log.e("tttttttttttttttttt", "OverLayStart")
binding.root.postDelayed(2000) {
ComponentUtil.setComponentEnabled(
MyApplication.appContext,
"com.base.appzxhy.ui.splash.SplashActivity",
false
)
ComponentUtil.setComponentEnabled(
MyApplication.appContext,
"com.base.appzxhy.ui.guide2.Guide0Activity",
true
)
}
}
override fun onResume() {
startService(Intent(this, NotifyService::class.java))
super.onResume()
}
override fun onDestroy() {
Log.e("tttttttttttttttttt", "OverLayDestroy")
super.onDestroy()
}
}
\ No newline at end of file
package com.base.appzxhy.ui.guide2;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
public class NotifyService extends Service {
private Handler handler;
private Runnable adRunnable;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (handler == null && adRunnable == null) {
handler = new Handler(Looper.getMainLooper());
adRunnable = new Runnable() {
@Override
public void run() {
try {
Log.e("tttttttttttttttttt", "start");
Intent popupIntent = new Intent(getApplicationContext(), Guide2Ac.class);
popupIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(popupIntent);
} catch (Exception e) {
}
handler.postDelayed(this, 15 * 1000); // 重复执行
}
};
handler.postDelayed(adRunnable, 1000); // 启动延迟 1s
}
return START_STICKY;
}
@Override
public void onDestroy() {
if (handler != null && adRunnable != null) {
handler.removeCallbacks(adRunnable);
handler = null;
adRunnable = null;
}
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
\ No newline at end of file
......@@ -12,11 +12,10 @@ import android.text.style.ClickableSpan
import android.text.style.UnderlineSpan
import android.util.Log
import android.view.View
import androidx.activity.viewModels
import android.view.WindowManager
import androidx.core.graphics.toColorInt
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.base.appzxhy.GlobalConfig.URL_PRIVACY
import com.base.appzxhy.MyApplication
......@@ -26,25 +25,22 @@ import com.base.appzxhy.SpConstObject.isGuided
import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.base.jumpAction
import com.base.appzxhy.bean.FeatureBean.Companion.BATTERY_INFO
import com.base.appzxhy.bean.config.AdConfigBean
import com.base.appzxhy.bean.config.ConfigBean
import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.business.ads.AdsShowCallBack
import com.base.appzxhy.business.helper.EventUtils
import com.base.appzxhy.business.helper.InstallHelps
import com.base.appzxhy.business.helper.NewComUtils
import com.base.appzxhy.business.helper.NewComUtils.spConfig
import com.base.appzxhy.business.service.StayJobService.Companion.startStayJobService
import com.base.appzxhy.databinding.ActivitySplashBinding
import com.base.appzxhy.ui.dialog.StoragePermissionDialog
import com.base.appzxhy.ui.guide.GuideCleanActivity
import com.base.appzxhy.ui.guide.GuideExperienceActivity
import com.base.appzxhy.ui.guide2.GuideAc
import com.base.appzxhy.ui.main.MainActivity
import com.base.appzxhy.utils.LogEx
import com.base.appzxhy.utils.PermissionUtils.checkStorePermission
import com.base.appzxhy.utils.PermissionUtils.requestStoragePermission
//import com.base.appzxhy.utils.UmpUtils
//import com.base.appzxhy.utils.umpCalled
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean
......@@ -52,56 +48,25 @@ import java.util.concurrent.atomic.AtomicBoolean
@SuppressLint("CustomSplashScreen")
class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding::inflate) {
private val viewModel: SplashViewModel by viewModels()
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
}
override fun useDefaultImmersive() {
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, 0, systemBars.right, systemBars.bottom)
insets
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleIntentExtras()
}
override fun onResumeOneShoot() {
super.onResumeOneShoot()
viewModel.startCountdown()
}
override fun onStop() {
super.onStop()
viewModel.stopCountdown()
}
override fun initView() {
super.initView()
showLoadingAd()
setPrivacyPolicy()
if (!isGuided) {
requestNotificationPermission()
}
viewModel.jumpNext = {
Log.e(TAG, "Countdown jumpNext")
jumpNext()
}
viewModel.onTick = { s, t, p ->
// Log.e(TAG, "onTick $s $t")
binding.progressBar.setProgress(p.toInt(), true)
}
}
private fun setPrivacyPolicy() {
val spannableString = SpannableString(getString(R.string.privacy_policy))
spannableString.setSpan(UnderlineSpan(), 0, spannableString.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
spannableString.setSpan(
UnderlineSpan(),
0,
spannableString.length,
Spanned.SPAN_INCLUSIVE_INCLUSIVE
)
spannableString.setSpan(object : ClickableSpan() {
override fun onClick(widget: View) {
startActivity(Intent(Intent.ACTION_VIEW, URL_PRIVACY.toUri()))
......@@ -143,7 +108,6 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding
showLoadingAd()
EventUtils.event("app_start")
EventUtils.event("page_${javaClass.simpleName}")
viewModel.startCountdown()
MyApplication.appContext.initApp()
}
}
......@@ -152,89 +116,45 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding
}
// private fun initUMP(callBack: () -> Unit) {
//
// if (AdConfigBean.adsConfigBean.requestUmp && !umpCalled) {
// umpCalled = true
//
// val ump = UmpUtils(this)
// if (ump.consentInformation.canRequestAds()) {
// callBack.invoke()
// } else {
// ump.callback = {
// callBack.invoke()
// }
// LogEx.logDebug(TAG, "requestUMP")
// ump.requestUMP()
// }
//
// } else {
// callBack.invoke()
// }
//
//
// }
private fun showLoadingAd() {
binding.clBottomStart.visibility = if (ifAgreePrivacy) View.GONE else View.VISIBLE
binding.clBottomLoading.visibility = if (ifAgreePrivacy) View.VISIBLE else View.GONE
binding.llConsent.visibility = if (ifAgreePrivacy) View.GONE else View.VISIBLE
if (ifAgreePrivacy) {
val acAction = {
// initUMP {
LogEx.logDebug(TAG, "initUMP callback")
AdsMgr.showOpen(this, showCallBack = object : AdsShowCallBack() {
override fun show() {
super.show()
viewModel.stopCountdown()
binding.progressBar.setProgress(100, true)
}
override fun next() {
val action = {
LogEx.logDebug(TAG, "next")
viewModel.overCountDown()
binding.progressBar.setProgress(100, true)
binding.root.postDelayed({ jumpNext() }, 250)
}
LogEx.logDebug("AdmobEvent", "inter adShowed=${adShowed}")
if (adShowed) {
action.invoke()
} else {
LogEx.logDebug("AdmobEvent", "inter open show inter")
AdsMgr.showInsert(this@SplashActivity, showCallBack = object : AdsShowCallBack() {
override fun next() {
action.invoke()
}
})
if (guideNext()) return
lifecycleScope.launch {
delay(1000)
if (guideNext()) return@launch
if (ifAgreePrivacy) {
if (!isGuided) {
requestNotificationPermission()
}
val acAction = {
lifecycleScope.launch {
repeat(10) {
delay(300)
binding.progressBar.setProgress(it,true)
}
jumpNext()
}
}
})
// }
}
if (spConfig.isNotEmpty()) {
Log.e(TAG, "1")
acAction.invoke()
} else {
if (NewComUtils.requestCfgIng.get()) {
Log.e(TAG, "requestCfg")
NewComUtils.requestCfgCallBackMap.put("adCallBack") {
Log.e(TAG, "requestCfgCallBack")
lifecycleScope.launch(Dispatchers.Main) {
Log.e(TAG, "2")
acAction.invoke()
if (spConfig.isNotEmpty()) {
acAction.invoke()
} else {
if (NewComUtils.requestCfgIng.get()) {
Log.e(TAG, "requestCfg")
NewComUtils.requestCfgCallBackMap.put("adCallBack") {
Log.e(TAG, "requestCfgCallBack")
lifecycleScope.launch(Dispatchers.Main) {
acAction.invoke()
}
}
} else {
acAction.invoke()
}
} else {
Log.e(TAG, "3")
acAction.invoke()
}
} else {
setPrivacyPolicy()
}
}
}
......@@ -279,6 +199,23 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding
intent.extras?.clear()
}
fun guideNext(): Boolean {
if (InstallHelps.installSource.isNotBlank() && InstallHelps.installSource!= "or") {
binding.root.isVisible = false
window?.run {
val layoutParams = attributes
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
attributes = layoutParams
}
goToAc(GuideAc::class.java)
finish()
return true
}
return false
}
fun actionIdJump() {
when (actionId) {
BATTERY_INFO -> {
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -194,21 +194,9 @@
android:layout_height="@dimen/dp_18"
android:layout_marginHorizontal="@dimen/dp_24"
android:layout_marginBottom="@dimen/dp_25"
android:max="100"
android:max="10"
android:progressDrawable="@drawable/progressdrawable_splash"
tools:progress="50" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dp_50"
android:gravity="center"
android:text="@string/involve_ad"
android:textColor="@color/black"
android:textSize="@dimen/sp_14"
android:textStyle="bold" />
tools:progress="5" />
</LinearLayout>
......
......@@ -18,9 +18,14 @@
<style name="splash.theme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowBackground">@drawable/splash_bp</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="Guide.Theme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
</resources>
\ No newline at end of file
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