Commit 415b15ef authored by wanglei's avatar wanglei

[迭代]广告和多语言字符串

parent 8714dc91
......@@ -176,19 +176,26 @@ dependencies {
//广告
//admob渠道
implementation(libs.vungle)
implementation(libs.facebook)
implementation(libs.mintegral)
implementation(libs.pangle)
//applovin sdk
implementation(libs.applovin)
//applovin渠道
implementation(libs.applovin.google)
implementation(libs.applovin.admob)
implementation(libs.applovin.facebook) //meta
implementation(libs.applovin.mintegral)//mintegral
implementation(libs.applovin.pangle) //pangle
implementation(libs.applovin.vungle) //vungle
// implementation(libs.vungle)
// implementation(libs.facebook)
// implementation(libs.mintegral)
// implementation(libs.pangle)
// //applovin sdk
// implementation(libs.applovin)
// //applovin渠道
// implementation(libs.applovin.google)
// implementation(libs.applovin.admob)
// implementation(libs.applovin.facebook) //meta
// implementation(libs.applovin.mintegral)//mintegral
// implementation(libs.applovin.pangle) //pangle
// implementation(libs.applovin.vungle) //vungle
implementation("com.google.android.gms:play-services-ads:23.5.0")
implementation("com.google.ads.mediation:applovin:13.0.1.0")
implementation("com.google.ads.mediation:facebook:6.18.0.0")
implementation("com.google.ads.mediation:mintegral:16.8.61.0")
implementation("com.google.ads.mediation:pangle:6.3.0.4.0")
implementation("com.google.ads.mediation:vungle:7.4.2.0")
val work_version = "2.8.1"
implementation("androidx.work:work-runtime-ktx:$work_version")
......
......@@ -195,7 +195,7 @@ class MyApplication : Application() {
private var lastTimePause = 0L
private var lastTimeResume = 0L
private fun isHotLaunch(): Boolean {
if ((lastTimeResume - lastTimePause) > 5000) {
if ((lastTimeResume - lastTimePause) > 3500) {
return true
}
return false
......
......@@ -4,7 +4,6 @@ package com.simplecleaner.app.bean.config
class AdConfigBean(
var isAdShow: Boolean = true,//广告开关
var adSwitch: Boolean = true,//true 走admob,false走max
var taichiAdValue: Int = 1,//价值上报阀值
var adRatio: Int = 100,//价值上报随机控制
......@@ -12,6 +11,7 @@ class AdConfigBean(
var numRequestLimit: Int = -1,//请求次数限制
var numClickLimit: Int = -1,//点击次数限制
var timeInterval: Int = 10,//广告间隔秒
var timeIntervalOpen: Int = 0,//开屏广告间隔
var openAdLoading: Int = 15,//开屏广告拉取时间
var numNativeDisplayLimit: Int = -1,//原生展示次数限制
......
......@@ -3,6 +3,9 @@ package com.simplecleaner.app.business.ads
import com.simplecleaner.app.MyApplication
import com.simplecleaner.app.business.helper.EventUtils
import com.simplecleaner.app.utils.LogEx
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import org.json.JSONObject
import java.util.UUID
......@@ -25,7 +28,7 @@ abstract class AdEvent {
var from: String = ""
var reqId = UUID.randomUUID().toString()
var isUnLimit: Boolean = false
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
fun adPrepareShow() {
val obj1 = JSONObject()
......@@ -49,8 +52,8 @@ abstract class AdEvent {
fun adShowError(reason: Any) {
val obj = JSONObject()
obj.put("ad_unit", adUnit)
obj.put("req_id", reqId)
obj.put("from", from)
obj.put("req_id", reqId)
obj.put("reason", reason.toString())
EventUtils.event("ad_show_error", ext = obj)
LogEx.logDebug(TAG, "ad_show_error_$adUnit $obj")
......@@ -59,11 +62,10 @@ abstract class AdEvent {
fun adLimited(value: String) {
val obj = JSONObject()
obj.put("ad_unit", adUnit)
obj.put("req_id", reqId)
obj.put("from", from)
obj.put("req_id", reqId)
EventUtils.event("ad_limit", value, obj)
LogEx.logDebug(TAG, "ad_limit_$adUnit $obj")
}
}
\ No newline at end of file
package com.simplecleaner.app.business.ads
import android.app.Dialog
import com.simplecleaner.app.business.ads.LimitUtils.openInterLastShowTime
import com.simplecleaner.app.business.ads.LimitUtils.interLastShowTime
import com.simplecleaner.app.business.ads.LimitUtils.openLastShowTime
class AdState<T>() {
var adDialog: Dialog? = null
......@@ -24,41 +26,41 @@ class AdState<T>() {
*/
var loadingAd: Boolean = false
/**
* 用于保存引用现有页面,在此页面显示广告(因为要等待广告加载完毕)
*/
// var activityRef: WeakReference<Activity>? = null
/**
* 上一次的缓存成功时间
*/
var lastLoadTime: Long = 0
/**
* 上次展示时间
*/
// var lastShowTime: Long = 0
/**
* 广告已经展示
*/
fun onAdDisplayed() {
fun onAdDisplayed(adsType: AdsType) {
currentAd = null
currentAdEvent = null
// activityRef = null
adDialog?.dismiss()
adDialog = null
openInterLastShowTime = System.currentTimeMillis()
if (adsType == AdsType.OPEN) {
openLastShowTime = System.currentTimeMillis()
}
if (adsType == AdsType.INSERT) {
interLastShowTime = System.currentTimeMillis()
}
}
fun onAdHidden() {
fun onAdHidden(adsType: AdsType) {
//重置下上次展示的时间,避免看广告的时间算入间隔
openInterLastShowTime = System.currentTimeMillis()
if (adsType == AdsType.OPEN) {
openLastShowTime = System.currentTimeMillis()
}
if (adsType == AdsType.INSERT) {
interLastShowTime = System.currentTimeMillis()
}
}
......@@ -68,17 +70,16 @@ class AdState<T>() {
currentAd = null
currentAdEvent = null
// activityRef = null
}
fun onAdLoaded(ad: T?, adEvent: AdEvent?) {
//这里可能提前设置,所有可以不设置,max回调的类型可能不同
if (ad != null) {
currentAd = ad
}
if (adEvent != null) {
currentAdEvent = adEvent
}
fun loadStart(adEvent: AdEvent) {
loadingAd = true
currentAdEvent = adEvent
}
fun onAdLoaded(ad: T?) {
currentAd = ad
loadingAd = false
lastLoadTime = System.currentTimeMillis()
}
......@@ -90,7 +91,7 @@ class AdState<T>() {
}
fun adAvailable() =
currentAd != null || ((System.currentTimeMillis() - lastLoadTime) / 1000 / 60).toInt() < 30
fun needLoad() = currentAd == null || ((System.currentTimeMillis() - lastLoadTime) / 1000 / 60).toInt() > 30
}
......@@ -5,11 +5,6 @@ import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import com.applovin.sdk.AppLovinMediationProvider
import com.applovin.sdk.AppLovinSdk
import com.applovin.sdk.AppLovinSdkInitializationConfiguration
import com.simplecleaner.app.BuildConfig
import com.simplecleaner.app.GlobalConfig
import com.simplecleaner.app.bean.config.AdConfigBean.Companion.adsConfigBean
import com.simplecleaner.app.bean.config.ConfigBean.Companion.configBean
import com.simplecleaner.app.business.ads.admob.AdBannerMgr
......@@ -17,19 +12,9 @@ import com.simplecleaner.app.business.ads.admob.AdInterMgr
import com.simplecleaner.app.business.ads.admob.AdNativeMgr
import com.simplecleaner.app.business.ads.admob.AdOpenMgr
import com.simplecleaner.app.business.ads.admob.AdmobEvent
import com.simplecleaner.app.business.ads.applovin.AdMaxEvent
import com.simplecleaner.app.business.ads.applovin.MaxInsertMgr
import com.simplecleaner.app.business.ads.applovin.MaxNativeMgr
import com.simplecleaner.app.business.ads.applovin.MaxOpenMgr
import com.simplecleaner.app.business.helper.EventUtils
import com.simplecleaner.app.utils.AppPreferences
import com.simplecleaner.app.utils.LogEx
import com.simplecleaner.app.utils.ToastUtils.toast
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import com.google.android.gms.ads.initialization.AdapterStatus
import java.util.Collections
import java.util.concurrent.Executors
/**
* 广告管理类
......@@ -49,27 +34,12 @@ object AdsMgr {
AdBannerMgr()
}
private val maxOpenMgr by lazy {
MaxOpenMgr()
}
private val maxInsertMgr by lazy {
MaxInsertMgr()
}
private val maxNativeMgr by lazy {
MaxNativeMgr()
}
/**
* 是否初始化
*/
var isAdmobInit = false
private set
/**
* 是否初始化
*/
var isMaxInit = false
private set
var isAdUtEvent = false
......@@ -86,14 +56,7 @@ object AdsMgr {
* @param context 这里最好是appContext,因为是耗时操作,等它初始化完毕马上加载开屏和插屏广告
*/
fun init(context: Context) {
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", value = "isInBlackList=${configBean.isInBlackList}")
return
}
initAdmob(context)
initMax(context)
}
private fun initAdmob(context: Context) {
......@@ -106,7 +69,7 @@ object AdsMgr {
EventUtils.event("AdmobInit", "AdmobInit=$isAdmobInit")
// context.toast("admob init")
if (adsConfigBean.adSwitch) {
if (true) {
admobInitCallBack?.invoke()
admobInitCallBack = null
adNativeMgr.loadAd(context, AdmobEvent("nativeAd", context::class.java.simpleName))
......@@ -114,44 +77,9 @@ object AdsMgr {
adInterMgr.loadAd(context, AdmobEvent("interAd", context::class.java.simpleName))
}
}
}
private fun initMax(context: Context) = kotlin.runCatching {
if (isMaxInit) return@runCatching
val executor = Executors.newSingleThreadExecutor()
executor.execute {
val currentGaid = AdvertisingIdClient.getAdvertisingIdInfo(context).id
AppPreferences.getInstance().getString("gid", currentGaid)
val build = AppLovinSdkInitializationConfiguration
.builder(GlobalConfig.KEY_MAX, context)
build.mediationProvider = AppLovinMediationProvider.MAX
if (BuildConfig.DEBUG) {
build.testDeviceAdvertisingIds = Collections.singletonList(currentGaid)
}
val initConfig = build.build()
runCatching {
AppLovinSdk.getInstance(context).initialize(initConfig) {
isMaxInit = true
// maxOpenMgr.loadAd(context)
if (!adsConfigBean.adSwitch) {
maxInsertMgr.loadAd(context, AdMaxEvent("interAd", context::class.java.simpleName))
context.toast("max init")
maxInitCallBack?.invoke()
maxInitCallBack = null
}
}
}
}
}
var admobInitCallBack: (() -> Unit)? = null
var maxInitCallBack: (() -> Unit)? = null
/**
......@@ -172,14 +100,9 @@ object AdsMgr {
return
}
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", "isInBlackList=${configBean.isInBlackList}")
showCallBack?.failed()
return
}
val from = activity::class.java.simpleName
if (adsConfigBean.adSwitch) {
if (true) {
val admobEvent = AdmobEvent("openAd", from).apply { this.isUnLimit = isUnLimit }
if (isAdmobInit) {
adOpenMgr.show(activity, admobEvent, showCallBack)
......@@ -189,13 +112,6 @@ object AdsMgr {
adOpenMgr.show(activity, admobEvent, showCallBack)
}
} else {
if (isMaxInit) {
maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
} else {
maxInitCallBack = {
maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
}
}
}
}
......@@ -218,18 +134,10 @@ object AdsMgr {
showCallBack?.failed()
return
}
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
showCallBack?.failed()
return
}
LogEx.logDebug("showAd", "adSwitch=${adsConfigBean.adSwitch}")
val from = activity::class.java.simpleName
if (adsConfigBean.adSwitch) {
if (true) {
adInterMgr.show(activity, AdmobEvent("interAd", from).apply { this.isUnLimit = isUnLimit }, showCallBack)
} else {
maxInsertMgr.show(activity, isUnLimit, AdMaxEvent("interAd", from), showCallBack)
}
}
......@@ -237,29 +145,24 @@ object AdsMgr {
* 展示原生广告
*
* @param nativeView 需要展示广告的布局容器
* @param layout 原生广告布局 ,这里传入的layout要和com.example.mydemo.strategy.ads.admob.NativeView里的id一致
* @param layout 原生广告布局
*/
fun showNative(
nativeView: NativeParentView,
@LayoutRes layout: Int,
nativeCallBack: ((Any?) -> Unit)? = null
) {
if (!adsConfigBean.isAdShow) {
if (!adsConfigBean.isAdShow || !LimitUtils.isShowNative(AdsType.NATIVE, null)) {
nativeView.visibility = View.GONE
nativeCallBack?.invoke(null)
return
}
nativeView.visibility = View.VISIBLE
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return
}
val showNative = {
if (adsConfigBean.adSwitch) {
if (true) {
adNativeMgr.show(AdmobEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
} else {
maxNativeMgr.show(AdMaxEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
}
}
......@@ -282,12 +185,10 @@ object AdsMgr {
return
}
parent.visibility = View.VISIBLE
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return
}
if (adsConfigBean.adSwitch) {
if (true) {
adBannerMgr.show(parent, collapsible, adClose)
}
}
}
\ No newline at end of file
}
package com.simplecleaner.app.business.ads
import android.util.Log
import com.simplecleaner.app.BuildConfig
import com.simplecleaner.app.bean.config.AdConfigBean
import com.simplecleaner.app.utils.AppPreferences
import com.simplecleaner.app.utils.KotlinExt.toFormatTime4
import com.simplecleaner.app.utils.LogEx
/**
......@@ -95,16 +97,15 @@ object LimitUtils {
AppPreferences.getInstance().put(NUM_REQUEST, 0)
AppPreferences.getInstance().put(NUM_CLICK, 0)
}
val flag1 = isDisplayLimited
if (flag1) {
if (isDisplayLimited) {
val value = "current${getAdEventMsg(adsType)} " +
"show=${AppPreferences.getInstance().getInt(NUM_DISPLAY, 0)} " +
"${getAdEventMsg(adsType).lowercase()}_" + "max_show=${AdConfigBean.adsConfigBean.numDisplayLimit}"
adEvent?.adLimited(value)
}
val flag2 = isClickLimited
if (flag2) {
if (isClickLimited) {
val value =
"current${getAdEventMsg(adsType)}Click=${AppPreferences.getInstance().getInt(NUM_CLICK, 0)} "
"${getAdEventMsg(adsType).lowercase()}_max_click=${AdConfigBean.adsConfigBean.numClickLimit}"
......@@ -112,15 +113,14 @@ object LimitUtils {
adEvent?.adLimited(value)
}
val flag3 = isRequestLimited
if (flag3) {
if (isRequestLimited) {
val value = "current${getAdEventMsg(adsType)}Request=${AppPreferences.getInstance().getInt(NUM_REQUEST, 0)} " +
"${getAdEventMsg(adsType).lowercase()}_max_request=${AdConfigBean.adsConfigBean.numRequestLimit}"
adEvent?.adLimited(value)
}
return !(flag1 || flag2 || flag3)
return !(isDisplayLimited || isClickLimited || isRequestLimited)
}
private fun addNum(key: String) {
......@@ -151,27 +151,59 @@ object LimitUtils {
addNum(NUM_NATIVE_DISPLAY)
}
/**
* 开屏限制
*/
fun isIntervalOpenLimit(adEvent: AdEvent): Boolean {
val passTime = ((System.currentTimeMillis() - openLastShowTime) / 1000).toInt()
val interval = AdConfigBean.adsConfigBean.timeIntervalOpen
val flag = passTime < interval
Log.e(adEvent.TAG, "open isIntervalOpenLimit=$flag passTime=$passTime interval=$interval")
if (flag) {
adEvent.adShowError("ad in timeInterval")
}
return flag
}
/**
* 开屏和插页广告的显示间隔限制
* 插屏限制
*/
fun isIntervalLimited(adEvent: AdEvent?): Boolean {
val flag = ((System.currentTimeMillis() - openInterLastShowTime) / 1000).toInt() < (AdConfigBean.adsConfigBean.timeInterval)
fun isIntervalInterLimit(adEvent: AdEvent): Boolean {
val passTime = ((System.currentTimeMillis() - interLastShowTime) / 1000).toInt()
val interval = AdConfigBean.adsConfigBean.timeInterval
val flag = passTime < interval
Log.e(
adEvent.TAG,
"inter isIntervalInterLimit=$flag interLastShowTime=$interLastShowTime passTime=$passTime interval=$interval"
)
if (flag) {
adEvent?.adLimited("ad in timeInterval")
adEvent.adShowError("ad in timeInterval")
}
return flag
}
//开屏和插页上一次展示时间共用,避免开屏插页连弹
var openInterLastShowTime = 0L
//开屏上次展示时间
var openLastShowTime = 0L
get() {
return AppPreferences.getInstance().getLong("openLastShowTime", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("openLastShowTime", value, true)
}
//插屏上次展示时间
var interLastShowTime = 0L
get() {
return AppPreferences.getInstance().getLong("openInterLastShowTime", field)
return AppPreferences.getInstance().getLong("interLastShowTime", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("openInterLastShowTime", value, true)
AppPreferences.getInstance().put("interLastShowTime", value, true)
}
/**
* 原生广告是否到达限制
*/
......@@ -190,12 +222,19 @@ object LimitUtils {
AppPreferences.getInstance().put(NUM_NATIVE_DISPLAY, 0)
}
val flag = isNativeLimited
val todayNumber = AppPreferences.getInstance().getInt(NUM_NATIVE_DISPLAY, 0)
val max = AdConfigBean.adsConfigBean.numNativeDisplayLimit
LogEx.logDebug(adEvent?.TAG ?: "", "native todayNumber=$todayNumber max=$max ")
if (flag) {
val value = "current${getAdEventMsg(adsType)} " +
"show=${AppPreferences.getInstance().getInt(NUM_NATIVE_DISPLAY, 0)} " +
"${getAdEventMsg(adsType).lowercase()}_" + "max_show=${AdConfigBean.adsConfigBean.numNativeDisplayLimit}"
"show=${todayNumber} " +
"${getAdEventMsg(adsType).lowercase()}_" + "max_show=${max}"
adEvent?.adLimited(value)
}
return !flag
}
}
\ No newline at end of file
}
......@@ -13,6 +13,7 @@ import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdSize
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.LoadAdError
import com.simplecleaner.app.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
import java.util.UUID
/**
......@@ -25,7 +26,7 @@ class AdBannerMgr {
fun show(parent: ViewGroup, collapsible: Boolean, adClose: (() -> Unit)? = null) {
if (!AdConfigBean.adsConfigBean.adSwitch) {
if (!AdConfigBean.adsConfigBean.isAdShow) {
return
}
val admobEvent = AdmobEvent("banner", "banner")
......
......@@ -19,6 +19,7 @@ import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
import com.simplecleaner.app.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
/**
......@@ -26,12 +27,12 @@ import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
*/
class AdInterMgr {
private val TAG = "AdInterMgr"
private var adState = AdState<InterstitialAd>()
private var showCallBack: AdsShowCallBack? = null
//正在加载回调
private var loadingCallBack: (() -> Unit)? = null
private var loadingCallBack: ((flag: Boolean) -> Unit)? = null
fun show(
activity: Activity,
......@@ -43,24 +44,22 @@ class AdInterMgr {
return
}
val nowAdEvent = adEvent
//currentAdEvent!=null 表示有缓存广告,关联reqId
adState.currentAdEvent?.let { nowAdEvent.reqId = it.reqId }
adState.currentAdEvent?.let { adEvent.reqId = it.reqId }
if (!nowAdEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, nowAdEvent)) {
if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
showCallBack?.failed(2)
return
}
if (LimitUtils.isIntervalLimited(nowAdEvent)) {
if (LimitUtils.isIntervalInterLimit(adEvent)) {
showCallBack?.failed(3)
return
}
}
val needLoad = !adState.adAvailable()
// adState.activityRef = WeakReference(activity)
val needLoad = adState.needLoad()
this.showCallBack = showCallBack
if (adState.adDialog == null) {
......@@ -69,24 +68,29 @@ class AdInterMgr {
adState.adDialog?.dismiss()
}
nowAdEvent.adPrepareShow()
adEvent.adPrepareShow()
LogEx.logDebug(adEvent.TAG, "needLoad=$needLoad")
if (needLoad) {
if (!adState.loadingAd) {
LogEx.logDebug(adEvent.TAG, "inter adState !loadingAd")
loadAd(activity, nowAdEvent) {
showReadyAd(activity, nowAdEvent)
loadAd(activity, adEvent) {
if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
}
} else {
LogEx.logDebug(adEvent.TAG, "inter adState is loadingAd")
loadingCallBack = {
showReadyAd(activity, nowAdEvent)
showReadyAd(activity, adEvent)
}
}
} else {
LogEx.logDebug(adEvent.TAG, "inter ad ready")
showReadyAd(activity, nowAdEvent)
showReadyAd(activity, adEvent)
}
}
......@@ -94,13 +98,12 @@ class AdInterMgr {
private fun showReadyAd(ac: Activity, adEvent: AdEvent) {
// val ac = adState.activityRef?.get()
val admobEvent = (adEvent as AdmobEvent)
val tag = adEvent.TAG
LogEx.logDebug(tag, "showReadyAd ac=$ac currentAd=${adState.currentAd}")
LogEx.logDebug(tag, "inter showReadyAd ac=${ac.javaClass.simpleName} currentAd=${adState.currentAd}")
if (ac.isFinishing || ac.isDestroyed || adState.currentAd == null) {
LogEx.logDebug(tag, "showReadyAd ac=null isFinishing isDestroyed")
LogEx.logDebug(tag, "inter showReadyAd ac=null isFinishing isDestroyed")
showCallBack?.failed()
adState.onAdDisplayFailed()
return
......@@ -112,12 +115,12 @@ class AdInterMgr {
override fun onAdShowedFullScreenContent() {
super.onAdShowedFullScreenContent()
admobEvent.showAd(responseInfo, ac)
adState.onAdDisplayed()
adState.onAdDisplayed(AdsType.INSERT)
showCallBack?.show()
LimitUtils.addDisplayNum()
admobEvent.showAd(responseInfo, ac)
}
override fun onAdFailedToShowFullScreenContent(adError: AdError) {
......@@ -133,10 +136,11 @@ class AdInterMgr {
override fun onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent()
adState.onAdHidden()
adState.onAdHidden(AdsType.INSERT)
showCallBack?.close()
showCallBack = null
loadAd(MyApplication.appContext, AdmobEvent("interAd", "preload"))
}
......@@ -147,7 +151,6 @@ class AdInterMgr {
LimitUtils.addClickNum()
}
}
// val activity = adState.activityRef?.get()
if (AdConfigBean.adsConfigBean.showCountdown) {
createUICountdownTimer(adState.adDialog) {
show(ac)
......@@ -158,10 +161,11 @@ class AdInterMgr {
}
}
fun loadAd(
context: Context,
adEvent: AdEvent,
loadCallBack: (() -> Unit)? = null
loadCallBack: ((flag: Boolean) -> Unit)? = null
) {
if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
......@@ -173,14 +177,12 @@ class AdInterMgr {
}
//避免无效预加载
if (adState.loadingAd && loadCallBack == null && loadingCallBack == null) {
//容错机制
adState.loadingAd = false
if (adState.loadingAd) {
return
}
adState.loadingAd = true
adEvent.adPulStart()
adState.loadStart(adEvent)
InterstitialAd.load(
context, GlobalConfig.ID_ADMOB_INTER, AdRequest.Builder().build(),
......@@ -188,10 +190,10 @@ class AdInterMgr {
override fun onAdLoaded(ad: InterstitialAd) {
val event = (adEvent as AdmobEvent)
ad.onPaidEventListener = AdmobOnPaidEventListener(ad, adEvent.scope)
adState.onAdLoaded(ad, adEvent)
adState.onAdLoaded(ad)
loadCallBack?.invoke()
loadingCallBack?.invoke()
loadCallBack?.invoke(true)
loadingCallBack?.invoke(true)
loadingCallBack = null
LimitUtils.addRequestNum()
......@@ -200,11 +202,14 @@ class AdInterMgr {
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
adState.onAdLoadFailed()
if (loadCallBack != null) {
adState.onAdDisplayFailed()
}
showCallBack?.adFailed()
showCallBack = null
loadCallBack?.invoke(false)
loadingCallBack?.invoke(false)
loadingCallBack = null
(adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError)
}
......@@ -214,4 +219,4 @@ class AdInterMgr {
}
}
\ No newline at end of file
}
......@@ -13,6 +13,7 @@ import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdOptions
import com.simplecleaner.app.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
import java.util.concurrent.ConcurrentLinkedDeque
/**
......@@ -91,8 +92,6 @@ class AdNativeMgr {
nativeCallBack: ((Any?) -> Unit)? = null
) {
admobEvent.adPrepareShow()
if (!LimitUtils.isAdShow(AdsType.NATIVE, admobEvent)) {
Log.e(TAG, "!isAdShow")
cacheItems.clear()
......@@ -102,6 +101,8 @@ class AdNativeMgr {
return
}
admobEvent.adPrepareShow()
Log.e(TAG, "adNative can show")
if (!adAvailable()) {
......@@ -139,4 +140,5 @@ class AdNativeMgr {
private fun adAvailable(): Boolean {
return (lastTime == 0L) || ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
}
}
\ No newline at end of file
}
......@@ -15,6 +15,7 @@ import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.appopen.AppOpenAd
import com.simplecleaner.app.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
/**
......@@ -22,12 +23,11 @@ import com.google.android.gms.ads.appopen.AppOpenAd
*/
class AdOpenMgr {
private val TAG = "AdOpenMgr"
private val adState = AdState<AppOpenAd>()
private var showCallBack: AdsShowCallBack? = null
//正在加载回调
private var loadingCallBack: (() -> Unit)? = null
private var loadingCallBack: ((flag: Boolean) -> Unit)? = null
fun show(
activity: Activity,
......@@ -38,65 +38,70 @@ class AdOpenMgr {
return
}
val nowAdEvent = adEvent
adState.currentAdEvent?.let { nowAdEvent.reqId = it.reqId }
adState.currentAdEvent?.let { adEvent.reqId = it.reqId }
if (!nowAdEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, nowAdEvent)) {
if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(nowAdEvent)) {
if (LimitUtils.isIntervalOpenLimit(adEvent)) {
showCallBack?.failed()
return
}
}
val needLoad = !adState.adAvailable()
val needLoad = adState.needLoad()
this.showCallBack = showCallBack
nowAdEvent.adPrepareShow()
adEvent.adPrepareShow()
if (needLoad) {
if (!adState.loadingAd) {
LogEx.logDebug(adEvent.TAG, "open adState !loadingAd")
loadAd(activity, adEvent) {
showReadyAd(activity)
if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
}
} else {
LogEx.logDebug(adEvent.TAG, "open adState is loadingAd")
loadingCallBack = {
showReadyAd(activity)
if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
}
}
} else {
LogEx.logDebug(adEvent.TAG, "open ad ready")
showReadyAd(activity)
showReadyAd(activity, adEvent)
}
}
private fun showReadyAd(ac: Activity) {
private fun showReadyAd(ac: Activity, adEvent: AdEvent) {
val admobEvent = (adEvent as AdmobEvent)
// val ac = adState.activityRef?.get()
if (ac.isFinishing || ac.isDestroyed || adState.currentAd == null) {
LogEx.logDebug(TAG, "showReadyAd ac=null isFinishing isDestroyed")
LogEx.logDebug(adEvent.TAG, "open showReadyAd ac=null isFinishing isDestroyed")
return
}
adState.currentAd?.run {
val adEvent = adState.currentAdEvent as AdmobEvent?
fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() {
adEvent?.showAd(this@run.responseInfo, ac)
adState.onAdDisplayed(AdsType.OPEN)
showCallBack?.show()
adState.onAdDisplayed()
//计数
LimitUtils.addDisplayNum()
admobEvent.showAd(this@run.responseInfo, ac)
}
override fun onAdFailedToShowFullScreenContent(adError: AdError) {
......@@ -106,25 +111,24 @@ class AdOpenMgr {
showCallBack = null
adState.onAdDisplayFailed()
adEvent?.adShowError(adError)
admobEvent.adShowError(adError)
}
override fun onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent()
adState.onAdHidden(AdsType.OPEN)
showCallBack?.close()
showCallBack = null
adState.onAdHidden()
//预加载,“Timeout for show call succeed.”预加载的广告大概率,
loadAd(MyApplication.appContext, AdmobEvent("openAd", "preload"))
}
override fun onAdClicked() {
adEvent?.clickAd(this@run.responseInfo)
admobEvent.clickAd(this@run.responseInfo)
//计数
LimitUtils.addClickNum()
}
......@@ -136,7 +140,7 @@ class AdOpenMgr {
fun loadAd(
context: Context,
adEvent: AdEvent,
loadCallBack: (() -> Unit)? = null
loadCallBack: ((flag: Boolean) -> Unit)? = null
) {
if (!adEvent.isUnLimit) {
......@@ -149,14 +153,12 @@ class AdOpenMgr {
}
//避免无效预加载
if (adState.loadingAd && loadCallBack == null && loadingCallBack == null) {
//容错机制
adState.loadingAd = false
if (adState.loadingAd) {
return
}
adState.loadingAd = true
adEvent.adPulStart()
adState.loadStart(adEvent)
AppOpenAd.load(
context,
......@@ -164,25 +166,31 @@ class AdOpenMgr {
AdRequest.Builder().build(),
object : AppOpenAd.AppOpenAdLoadCallback() {
override fun onAdLoaded(appOpenAd: AppOpenAd) {
adState.onAdLoaded(appOpenAd, adEvent)
LogEx.logDebug(adEvent.TAG, "open onAdLoaded loadAd")
appOpenAd.onPaidEventListener = AdmobOnPaidEventListener(appOpenAd, adEvent.scope)
adState.onAdLoaded(appOpenAd)
loadCallBack?.invoke()
loadingCallBack?.invoke()
loadCallBack?.invoke(true)
loadingCallBack?.invoke(true)
loadingCallBack = null
(adEvent as AdmobEvent).pullAd(appOpenAd.responseInfo)
appOpenAd.onPaidEventListener = AdmobOnPaidEventListener(appOpenAd, adEvent.scope)
LimitUtils.addRequestNum()
(adEvent as AdmobEvent).pullAd(appOpenAd.responseInfo)
}
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
showCallBack?.adFailed()
showCallBack = null
LogEx.logDebug(adEvent.TAG, "open onAdFailedToLoad loadAd")
adState.onAdLoadFailed()
loadCallBack?.invoke(false)
loadingCallBack?.invoke(false)
loadingCallBack = null
(adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError)
}
}
)
}
}
\ No newline at end of file
}
package com.simplecleaner.app.business.ads.applovin
import androidx.annotation.LayoutRes
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxError
import com.applovin.mediation.nativeAds.MaxNativeAdListener
import com.applovin.mediation.nativeAds.MaxNativeAdLoader
import com.applovin.mediation.nativeAds.MaxNativeAdView
import com.simplecleaner.app.GlobalConfig
import com.simplecleaner.app.business.ads.AdsType
import com.simplecleaner.app.business.ads.LimitUtils
import com.simplecleaner.app.business.ads.NativeParentView
import com.simplecleaner.app.business.helper.EventUtils
import org.json.JSONObject
import java.util.UUID
/**
*原生广告加载显示管理类
*/
class MaxNativeMgr {
/**
* 上一次的缓存成功时间
*/
protected var lastTime: Long = 0
/**
* 原生广告
*/
private var currentAd: MaxAd? = null
private var currentLoader: MaxNativeAdLoader? = null
private fun loadAd(
adMaxEvent: AdMaxEvent,
parent: NativeParentView,
@LayoutRes layout: Int
) {
if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) return
val reqId = UUID.randomUUID().toString()
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("ad_type", "nativeAd")
val nativeAdLoader = MaxNativeAdLoader(GlobalConfig.ID_MAX_NATIVE, parent.context)
nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() {
override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
currentLoader = nativeAdLoader
currentAd = ad
lastTime = System.currentTimeMillis()
adMaxEvent.pullAd(ad)
nativeAdLoader.setRevenueListener(AdMaxEvent.EventOnPaidEventListener())
show(adMaxEvent, parent, layout)
}
override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError) {
adMaxEvent.pullAd(null, error)
}
override fun onNativeAdClicked(ad: MaxAd) {
}
})
nativeAdLoader.loadAd()
}
fun show(
adMaxEvent: AdMaxEvent,
parent: NativeParentView,
@LayoutRes layout: Int,
nativeCallBack: ((Any?) -> Unit)? = null
) {
if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) {
currentLoader = null
currentAd = null
return
}
val nativeAd = currentAd
val nativeLoader = currentLoader
if ((nativeAd == null || nativeLoader == null).also {
if (it) {
val obj2 = JSONObject()
obj2.put("reason", "no_ad")
obj2.put("ad_unit", "nativeAd")
EventUtils.event("ad_show_error", ext = obj2)
}
} || (!adAvailable()).also {
if (it) {
val obj2 = JSONObject()
obj2.put("ad_unit", "nativeAd")
EventUtils.event("ad_expire", ext = obj2)
}
}) {
//缓存过期了就清空
currentLoader = null
currentAd = null
loadAd(AdMaxEvent("nativeAd", "preload"), parent, layout)
return
}
val obj = JSONObject()
obj.put("ad_unit", "nativeAd")
EventUtils.event("ad_prepare_show", ext = obj)
parent.setNativeAd(nativeLoader!!, nativeAd!!, layout)
nativeCallBack?.invoke(nativeAd)
}
private fun adAvailable(): Boolean {
return ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
}
}
\ No newline at end of file
//package com.simplecleaner.app.business.ads.applovin
//
//import androidx.annotation.LayoutRes
//import com.applovin.mediation.MaxAd
//import com.applovin.mediation.MaxError
//import com.applovin.mediation.nativeAds.MaxNativeAdListener
//import com.applovin.mediation.nativeAds.MaxNativeAdLoader
//import com.applovin.mediation.nativeAds.MaxNativeAdView
//import com.simplecleaner.app.GlobalConfig
//import com.simplecleaner.app.business.ads.AdsType
//import com.simplecleaner.app.business.ads.LimitUtils
//import com.simplecleaner.app.business.ads.NativeParentView
//import com.simplecleaner.app.business.helper.EventUtils
//import org.json.JSONObject
//import java.util.UUID
//
///**
// *原生广告加载显示管理类
// */
//class MaxNativeMgr {
//
// /**
// * 上一次的缓存成功时间
// */
// protected var lastTime: Long = 0
//
// /**
// * 原生广告
// */
// private var currentAd: MaxAd? = null
// private var currentLoader: MaxNativeAdLoader? = null
//
//
// private fun loadAd(
// adMaxEvent: AdMaxEvent,
// parent: NativeParentView,
// @LayoutRes layout: Int
// ) {
//
// if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) return
//
// val reqId = UUID.randomUUID().toString()
// val obj = JSONObject()
// obj.put("req_id", reqId)
// obj.put("ad_type", "nativeAd")
//
// val nativeAdLoader = MaxNativeAdLoader(GlobalConfig.ID_MAX_NATIVE, parent.context)
//
// nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() {
//
// override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
// currentLoader = nativeAdLoader
// currentAd = ad
// lastTime = System.currentTimeMillis()
// adMaxEvent.pullAd(ad)
// nativeAdLoader.setRevenueListener(AdMaxEvent.EventOnPaidEventListener())
// show(adMaxEvent, parent, layout)
// }
//
// override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError) {
// adMaxEvent.pullAd(null, error)
// }
//
// override fun onNativeAdClicked(ad: MaxAd) {
//
// }
//
// })
// nativeAdLoader.loadAd()
// }
//
// fun show(
// adMaxEvent: AdMaxEvent,
// parent: NativeParentView,
// @LayoutRes layout: Int,
// nativeCallBack: ((Any?) -> Unit)? = null
// ) {
// if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) {
// currentLoader = null
// currentAd = null
// return
// }
// val nativeAd = currentAd
// val nativeLoader = currentLoader
// if ((nativeAd == null || nativeLoader == null).also {
// if (it) {
// val obj2 = JSONObject()
// obj2.put("reason", "no_ad")
// obj2.put("ad_unit", "nativeAd")
// EventUtils.event("ad_show_error", ext = obj2)
// }
// } || (!adAvailable()).also {
// if (it) {
// val obj2 = JSONObject()
// obj2.put("ad_unit", "nativeAd")
// EventUtils.event("ad_expire", ext = obj2)
// }
// }) {
// //缓存过期了就清空
// currentLoader = null
// currentAd = null
// loadAd(AdMaxEvent("nativeAd", "preload"), parent, layout)
// return
// }
// val obj = JSONObject()
// obj.put("ad_unit", "nativeAd")
// EventUtils.event("ad_prepare_show", ext = obj)
// parent.setNativeAd(nativeLoader!!, nativeAd!!, layout)
// nativeCallBack?.invoke(nativeAd)
// }
//
// private fun adAvailable(): Boolean {
// return ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
// }
//}
\ No newline at end of file
......@@ -12,8 +12,10 @@ import com.simplecleaner.app.bean.FeatureBean.Companion.SCREENSHOT_CLEAN
import com.simplecleaner.app.bean.FeatureBean.Companion.SIMILAR_PHOTOS
import com.simplecleaner.app.bean.FeatureBean.Companion.UNINSTALL_APP
import com.simplecleaner.app.business.ads.AdsMgr
import com.simplecleaner.app.business.ads.AdsShowCallBack
import com.simplecleaner.app.databinding.ActivityGuideExperienceBinding
import com.simplecleaner.app.ui.dialog.StoragePermissionDialog
import com.simplecleaner.app.ui.main.MainActivity
import com.simplecleaner.app.utils.PermissionUtils.requestStoragePermission
class GuideExperienceActivity : BaseActivity<ActivityGuideExperienceBinding>(
......@@ -29,7 +31,11 @@ class GuideExperienceActivity : BaseActivity<ActivityGuideExperienceBinding>(
}
override fun handleBackCallBack() {
AdsMgr.showInsert(this, false, object : AdsShowCallBack() {
override fun next() {
goToAc(MainActivity::class.java)
}
})
}
override fun initListener() {
......
//package com.base.appzxhy.ui.malware
//
//import com.base.appzxhy.MyApplication
//import com.trustlook.sdk.cloudscan.CloudScanClient
//import com.trustlook.sdk.data.Region
//
///**
// *Create by SleepDog on 2025-01-24
// */
//object CloudScan {
// val scanClient by lazy(LazyThreadSafetyMode.NONE) {
// CloudScanClient.Builder(MyApplication.appContext)
// // 设置服务地区,
//// 海外地区设置:Region.INTL,百度用户设置:Region.BAIDU
// .setRegion(Region.INTL)
// // 设置连接超时时长,单位为毫秒
// .setConnectionTimeout(30000)
// //设置传输超时时长,单位为毫秒
// .setSocketTimeout(30000)
// .build()
// }
//}
\ No newline at end of file
//package com.base.appzxhy.ui.malware
//
//import android.app.Activity
//import android.view.LayoutInflater
//import androidx.appcompat.app.AlertDialog
//import androidx.constraintlayout.widget.ConstraintLayout
//import com.base.appzxhy.R
//import com.base.appzxhy.business.ads.AdsMgr
//import com.base.appzxhy.databinding.DialogErrBinding
//
//class ErrorScanDialog(
// val activity: Activity
//) {
// val dialog = AlertDialog.Builder(activity).create()
// val binding = DialogErrBinding.inflate(LayoutInflater.from(activity))
//
// var action: (() -> Unit)? = null
//
// fun showDialog() {
// dialog.setView(binding.root)
// dialog.setCanceledOnTouchOutside(false)
// dialog.show()
//
// val params = dialog.window?.attributes
//// params?.width = ConstraintLayout.LayoutParams.MATCH_PARENT
// params?.width = activity.resources.getDimensionPixelSize(R.dimen.dp_295)
// params?.height = ConstraintLayout.LayoutParams.WRAP_CONTENT
//// params?.gravity = Gravity.BOTTOM
// dialog.window?.attributes = params
// dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
//
// AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
// binding.tvSure.setOnClickListener {
// dialog.dismiss()
// action?.invoke()
// }
// }
//}
\ No newline at end of file
//package com.base.appzxhy.ui.malware
//
//import android.app.Activity
//import android.view.LayoutInflater
//import androidx.appcompat.app.AlertDialog
//import com.base.appzxhy.databinding.DialogMalwareTipBinding
//import com.base.appzxhy.utils.AppPreferences
//
////是否已经同意
//var malwareTipAgree = false
// get() {
// return AppPreferences.getInstance().getBoolean("malwareTipAgree", field)
// }
// set(value) {
// field = value
// AppPreferences.getInstance().put("malwareTipAgree", value, true)
// }
//
//class MalwareDialog(
// val activity: Activity
//) {
//
// val dialog = AlertDialog.Builder(activity).create()
// val binding = DialogMalwareTipBinding.inflate(LayoutInflater.from(activity))
//
// var action: ((flag: Boolean) -> Unit)? = null
//
// fun showDialog() {
//
// if (malwareTipAgree) {
// action?.invoke(true)
// return
// }
//
// dialog.setView(binding.root)
// dialog.setCanceledOnTouchOutside(false)
// dialog.show()
//
// val params = dialog.window?.attributes
//// params?.width = ConstraintLayout.LayoutParams.MATCH_PARENT
//// params?.width = activity.resources.getDimensionPixelSize(R.dimen.dp_295)
//// params?.height = ConstraintLayout.LayoutParams.WRAP_CONTENT
//// params?.gravity = Gravity.BOTTOM
// dialog.window?.attributes = params
// dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
//
// var flag = false
//
// binding.tvCancel.setOnClickListener {
// dialog.dismiss()
// }
// binding.tvSure.setOnClickListener {
// dialog.dismiss()
// flag = true
// malwareTipAgree = true
// action?.invoke(true)
// }
//
// dialog.setOnDismissListener {
// action?.invoke(flag)
// }
// }
//}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ExtraTranslation">
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="which_type_do_you_want_to_clean">Welchen Typ möchten Sie bereinigen?</string>
<string name="consent">
Während der Nutzung dieser App benötigen wir folgende Informationen: Handymodell, Hersteller, Android-Version, App-Versionsnummer, App-Versionsname, Paketname, Google-Werbe-ID, Zeitzone, Handy-Fotoalbum, leere Ordner, APK-Dateien, temporäre Dateien, Protokolldateien, Akkustand, Standby-Zeit, Akkutemperatur, Akkuspannung, Akkutechnologie, Akkukapazität, Akkustrom, durchschnittlicher Akkustrom.
Wir behandeln Ihre Daten streng nach geltenden Gesetzen. Alle gesammelten Daten werden zweckgebunden verwendet, um App-Funktionen zu gewährleisten und Services zu verbessern. Wir ergreifen alle notwendigen Maßnahmen zum Schutz Ihrer Daten. Ihr Datenschutz hat für uns höchste Priorität.
</string>
<string name="consent">Während der Nutzung dieser App benötigen wir folgende Informationen: Handymodell, Hersteller, Android-Version, App-Versionsnummer, App-Versionsname, Paketname, Google-Werbe-ID, Zeitzone, Handy-Fotoalbum, leere Ordner, APK-Dateien, temporäre Dateien, Protokolldateien, Akkustand, Standby-Zeit, Akkutemperatur, Akkuspannung, Akkutechnologie, Akkukapazität, Akkustrom, durchschnittlicher Akkustrom. Wir behandeln Ihre Daten streng nach geltenden Gesetzen. Alle gesammelten Daten werden zweckgebunden verwendet, um App-Funktionen zu gewährleisten und Services zu verbessern. Wir ergreifen alle notwendigen Maßnahmen zum Schutz Ihrer Daten. Ihr Datenschutz hat für uns höchste Priorität.</string>
<string name="junk_clean">Junk-Bereinigung</string>
<string name="battery_info">Akkustatus</string>
<string name="screenshot_clean">Screenshot-Bereinigung</string>
......@@ -15,7 +10,6 @@
<string name="similar_photos">Doppelte Fotos</string>
<string name="home">Start</string>
<string name="settings">Einstellungen</string>
<string name="battery_status">Akkustatus</string>
<string name="temperature">Temperatur</string>
<string name="voltage">Spannung</string>
......@@ -24,11 +18,9 @@
<string name="normal">Normal</string>
<string name="battery_type">Akkutyp</string>
<string name="battery_capacity">Akkukapazität</string>
<string name="please_wait">Bitte warten</string>
<string name="power">Ladestand</string>
<string name="charging">Wird geladen</string>
<string name="found">Gefunden</string>
<string name="clean_tips">Bereinigung löscht keine persönlichen Daten</string>
<string name="clean">Bereinigen</string>
<string name="go_it">Verstanden</string>
......@@ -46,7 +38,6 @@
<string name="image">Bild</string>
<string name="apk">APK</string>
<string name="other_types">Andere Typen</string>
<string name="all_time">Gesamter Zeitraum</string>
<string name="week_1">1 Woche</string>
<string name="month_1">1 Monat</string>
......@@ -74,19 +65,9 @@
<string name="version">Version</string>
<string name="thank_you_for_using_app">Danke für die Nutzung von %s!</string>
<string name="submit">ABSENDEN</string>
<string name="guide_tip_1">
Junk entfernen, Geschwindigkeit steigern. Mit einem Klick Speicher freigeben.
</string>
<string name="guide_tip_2">
Fotos, Videos und Audiodateien bereinigen für mehr Platz und Ordnung.
</string>
<string name="guide_tip_3">
Leistungsstarke Scanfunktion für umfassenden Schutz. Sicherheit für Ihr Gerät.
</string>
<string name="guide_tip_1">Junk entfernen, Geschwindigkeit steigern. Mit einem Klick Speicher freigeben.</string>
<string name="guide_tip_2">Fotos, Videos und Audiodateien bereinigen für mehr Platz und Ordnung.</string>
<string name="guide_tip_3">Leistungsstarke Scanfunktion für umfassenden Schutz. Sicherheit für Ihr Gerät.</string>
<string name="next">Weiter</string>
<string name="sure">Bestätigen</string>
<string name="exit_junk_clean">Junk-Bereinigung beenden?</string>
......@@ -110,10 +91,8 @@
<string name="powered_by_trustlook">Powered by Trustlook</string>
<string name="malware_recommended">Für genauere Ergebnisse Internetverbindung empfohlen</string>
<string name="notification_tips">Aktivieren Sie Benachrichtigungen für wichtige Hinweise.</string>
<string name="don_t_miss_important_tips">Wichtige Hinweise nicht verpassen</string>
<string name="select_a_language">Sprache wählen</string>
<string name="get_started">Loslegen</string>
<string name="loading">Wird geladen...</string>
<string name="battery">Akku</string>
<string name="estimated_battery">Voraussichtliche Akkulaufzeit</string>
<string name="electric_current">Stromstärke</string>
......@@ -126,4 +105,39 @@
<string name="notify_screenshot">Screenshots bereinigen für mehr Platz!</string>
<string name="notify_photo_compression">Fotos komprimieren für mehr Speicherplatz!</string>
<string name="ads_are_about_to_be_shown_s">Werbung wird in (%1$s Sek.) angezeigt</string>
<string name="by_continuing_">Durch Fortfahren stimmen Sie den\u0020</string>
<string name="thank_you_very_much">Vielen Dank, dass Sie sich die Zeit genommen haben, uns zu bewerten.</string>
<string name="view">Anzeigen</string>
<string name="content_not_found">Inhalt nicht gefunden</string>
<string name="uninstall_app">App deinstallieren</string>
<string name="ok">OK</string>
<string name="size">Größe</string>
<string name="install_time">Installationszeit</string>
<string name="app_function_experience_tip">%s ist ein fortschrittlicher Reiniger für Android-Geräte, um Mobiltelefone zu bereinigen. Die Reinigungs-App kann leere Dateien, Protokolldateien, veraltete APKs, temporäre Dateien, ähnliche Bilder und große Dateien bereinigen. Sie kann auch Batterieinformationen anzeigen, Apps deinstallieren und Bilder komprimieren.</string>
<string name="experience_it_immediately">Sofort ausprobieren</string>
<string name="screenshot">Screenshot</string>
<string name="exit_uninstall_app_content">App-Deinstallation beenden? Ungenutzte Anwendungen können Speicherplatz belegen.</string>
<string name="notify_uninstall_app">Entfernen Sie ungenutzte Apps, um Speicherplatz freizugeben.</string>
<string name="quick_clean">Schnellbereinigung</string>
<string name="scan_completed">Scan abgeschlossen</string>
<string name="turn_on_notification">Benachrichtigung aktivieren</string>
<string name="redundant_files_found">Überflüssige Dateien gefunden</string>
<string name="found_f">Gefunden: %1$s</string>
<string name="involve_ad">Dieser Vorgang kann Werbung enthalten.</string>
<string name="consent_required">Zustimmung erforderlich</string>
<string name="start">Start</string>
<string name="privacy_policy">Datenschutzrichtlinie</string>
<string name="photo">Foto</string>
<string name="audio">Audio</string>
<string name="document">Dokument</string>
<string name="video">Video</string>
<string name="continue_">Fortfahren</string>
<string name="open_settings">Einstellungen öffnen</string>
<string name="storage_permission_title">Speicherberechtigungen benötigt</string>
<string name="storage_permission_content">Zulassen, dass %s auf die Berechtigung „Zugriff auf alle Dateien“ zugreift, um Dateien auf Ihrem Gerät zu verwalten?</string>
<string name="large_file">Große Dateien</string>
<string name="exit_uninstall_app">App-Deinstallation beenden</string>
</resources>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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