Skip to content

Commit

Permalink
Updated Ads implementation for avoiding application force close when …
Browse files Browse the repository at this point in the history
…not available
  • Loading branch information
Javinator9889 committed Jun 30, 2020
1 parent d752e11 commit 35604f9
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 31 deletions.
Expand Up @@ -33,7 +33,6 @@ import com.google.android.gms.ads.*
import com.google.android.gms.ads.formats.NativeAdOptions
import com.google.android.gms.ads.formats.UnifiedNativeAd
import com.google.android.gms.ads.formats.UnifiedNativeAdView
import com.google.android.play.core.splitcompat.SplitCompat
import com.javinator9889.handwashingreminder.gms.ads.AdLoader
import com.javinator9889.handwashingreminder.utils.isConnected
import com.javinator9889.handwashingreminder.utils.isDebuggable
Expand Down Expand Up @@ -62,8 +61,7 @@ class AdLoaderImpl private constructor(context: Context?) : AdLoader {
"the first instance"
)
moduleContext = context
SplitCompat.install(moduleContext)
MobileAds.initialize(moduleContext)
MobileAds.initialize(moduleContext.applicationContext)
val videoOptions = VideoOptions.Builder()
.setStartMuted(true)
.build()
Expand All @@ -79,39 +77,42 @@ class AdLoaderImpl private constructor(context: Context?) : AdLoader {
override fun instance(context: Context?): AdLoader {
instance.get()?.let { return it }
synchronized(this) {
val instance = AdLoaderImpl(context?.applicationContext)
val instance = AdLoaderImpl(context)
this.instance = WeakReference(instance)
return instance
}
}
}

@SuppressLint("InflateParams")
override fun loadAdForViewGroup(view: ViewGroup, removeAllViews: Boolean) {
override fun loadAdForViewGroup(view: ViewGroup, removeAllViews: Boolean) = runCatching {
if (!isVideoEnded || !isConnected())
return
throw IllegalStateException("Phone is not connected or the video didn't finished")
val adLoader = AdBase.Builder(moduleContext, ADMOB_APP_NATIVE_ID)
.forUnifiedNativeAd { ad: UnifiedNativeAd ->
val adView = LayoutInflater.from(moduleContext)
.inflate(R.layout.native_ad_view, null) as CardView
populateUnifiedNativeAdView(ad, adView)
if (removeAllViews)
view.removeAllViews()
view.addView(adView)
try {
val adView = LayoutInflater.from(moduleContext)
.inflate(R.layout.native_ad_view, null) as CardView
populateUnifiedNativeAdView(ad, adView)
if (removeAllViews)
view.removeAllViews()
view.addView(adView)
} catch (e: Throwable) {
Timber.w(e, "Cannot load ad in view")
}
}
.withNativeAdOptions(adOptions)
.withAdListener(object : AdListener() {
override fun onAdFailedToLoad(errorCode: Int) {
when (errorCode) {
AdRequest.ERROR_CODE_INVALID_REQUEST,
AdRequest.ERROR_CODE_NO_FILL ->
Timber.e("Error while loading the ad: $errorCode")
AdRequest.ERROR_CODE_NO_FILL -> throw IllegalAccessError(errorCode.toString())
else -> return
}
}
}).build()
adLoader.loadAd(AdRequest.Builder().build())
}
}.exceptionOrNull()

override fun destroy() {
currentNativeAd?.destroy()
Expand Down
Expand Up @@ -81,14 +81,14 @@ class LauncherActivity : AppCompatActivity() {
}
whenStarted {
progressBar.show()
val welcomeScreenDeferred = showWelcomeScreenAsync()
val welcomeScreenJob = showWelcomeScreenAsync()
deferreds.add(installRequiredModulesAsync())
activityIntentDeferred.await().run {
Timber.d("Activity Init is now completed!")
Timber.d("Activity Init is now completed! - $this")
if (launchFromNotification)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TASK
welcomeScreenDeferred.join()
welcomeScreenJob.join()
startActivity(this)
overridePendingTransition(0, android.R.anim.fade_out)
finish()
Expand Down Expand Up @@ -153,9 +153,8 @@ class LauncherActivity : AppCompatActivity() {
Activity.RESULT_OK -> {
createPackageContext(packageName, 0).also {
SplitCompat.install(it)
}.also {
initAds(it)
}
initAds()
}
Activity.RESULT_CANCELED -> app.adLoader = null
}
Expand Down Expand Up @@ -237,14 +236,17 @@ class LauncherActivity : AppCompatActivity() {
splitInstallManager.installedModules
}

private fun initAds(context: Context) {
val className = "${Ads.PACKAGE_NAME}.${Ads
.CLASS_NAME}\$${Ads.PROVIDER_NAME}"
val adProvider = Class.forName(className).kotlin
.objectInstance as AdLoader.Provider
app.adLoader = adProvider.instance(app)
val adsEnabler = AdsEnabler(app)
adsEnabler.enableAds()
private fun initAds(context: Context = app) {
if (Ads.MODULE_NAME in splitInstallManager.installedModules &&
sharedPreferences.getBoolean(ADS_ENABLED, true)) {
val className = "${Ads.PACKAGE_NAME}.${Ads
.CLASS_NAME}\$${Ads.PROVIDER_NAME}"
val adProvider = Class.forName(className).kotlin
.objectInstance as AdLoader.Provider
app.adLoader = adProvider.instance(context)
val adsEnabler = AdsEnabler(app)
adsEnabler.enableAds()
}
}

private fun createDynamicFeatureActivityIntent(
Expand Down Expand Up @@ -283,6 +285,8 @@ class LauncherActivity : AppCompatActivity() {
with(AlarmHandler(this)) {
scheduleAllAlarms()
}
Timber.d("Initializing Ads Provider")
initAds()
Timber.d("Adding periodic notifications if not enqueued yet")
Timber.d("Setting-up Firebase custom properties")
setupFirebasePropertiesAsync().join()
Expand Down
Expand Up @@ -25,6 +25,7 @@ import com.javinator9889.handwashingreminder.application.HandwashingApplication
import com.javinator9889.handwashingreminder.utils.notNull
import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.items.AbstractItem
import timber.log.Timber

class Ads : AbstractItem<Ads.ViewHolder>() {
override val layoutRes: Int = R.layout.simple_frame_view
Expand All @@ -38,7 +39,9 @@ class Ads : AbstractItem<Ads.ViewHolder>() {

override fun bindView(item: Ads, payloads: List<Any>) {
ads.notNull {
it.loadAdForViewGroup(container, false)
it.loadAdForViewGroup(container, false)?.let { e ->
Timber.w(e, "Ads cannot be loaded")
}
}
}

Expand Down
Expand Up @@ -28,5 +28,5 @@ interface AdLoader {

fun destroy()

fun loadAdForViewGroup(view: ViewGroup, removeAllViews: Boolean = true)
fun loadAdForViewGroup(view: ViewGroup, removeAllViews: Boolean = true): Throwable?
}
Expand Up @@ -26,7 +26,7 @@ import com.javinator9889.handwashingreminder.application.HandwashingApplication
const val PACKAGE_NAME = "com.google.android.gms.ads"
const val CLASS_NAME = "MobileAdsInitProvider"

class AdsEnabler(private val app: HandwashingApplication) {
class AdsEnabler(app: HandwashingApplication) {
private val packageManager = app.packageManager
private val componentName =
ComponentName(app, "${PACKAGE_NAME}.${CLASS_NAME}")
Expand Down

0 comments on commit 35604f9

Please sign in to comment.