Posts tagged with kotlin

I have a singleton class for loading and displaying ads

object AdmobProvider {     var countLoadAds = 0     lateinit var mInterstitialAd: InterstitialAd     private val adRequest = AdRequest.Builder().build()     fun init(activity: Activity) {         MobileAds.initialize(activity)         initInterstitial(activity)     }     private fun initInterstitial(context: Activity) {         mInterstitialAd = InterstitialAd(context)         if (!SubscriptionProvider.hasSubscription()) {             mInterstitialAd.adUnitId = context.getString(R.string.interstitial_video)             mInterstitialAd.loadAd(adRequest)             mInterstitialAd.adListener = object : AdListener() {                 override fun onAdClosed() {                     super.onAdClosed()                     Log.i("AdmobProvider", "onAdClosed: ")                 }                 override fun onAdFailedToLoad(p0: Int) {                     super.onAdFailedToLoad(p0)                     countLoadAds++                     Log.i("AdmobProvider", "onAdFailedToLoad: $countLoadAds")                     if (countLoadAds <= 3) {                         initInterstitial(context)                     } else {                         callback?.Failed(true)                     }                 }                 override fun onAdOpened() {                     super.onAdOpened()                     Log.i("AdmobProvider", "onAdOpened: ")                 }                 override fun onAdLoaded() {                     super.onAdLoaded()                     Log.i("AdmobProvider", "onAdLoaded: ")                     if (mInterstitialAd.isLoaded) {                         callback?.Success(true)                     }                 }             }         }     }     fun showInterstitial() {         if (mInterstitialAd.isLoaded) {             mInterstitialAd.show()         }     } } 

I load ads via

ActivityA in onCreate()

AdmobProvider.init(this) override fun Success(state: Boolean) {         Handler().postDelayed({             val intent = Intent(this@ActivityA, ActivityB::class.java)             intent.putExtra("ActivityB", 1)             startActivity(intent)             finish()         }, 200)     } 

and show in ActivityB in onCreate()

if (intent.getIntExtra("ActivityB", 0) == 1) {     AdmobProvider.showInterstitial() } 

While I tested it on the phone and emulators everything was fine, but from users, a crash began to arrive in the ActivityB, mainly on Android 8+

java.lang.RuntimeException: Unable to start activity ComponentInfo{MainActivity}: d.m: lateinit property mInterstitialAd has not been initialized     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3455)     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3598)     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2164)     at android.os.Handler.dispatchMessage(Handler.java:107)     at android.os.Looper.loop(Looper.java:241)     at android.app.ActivityThread.main(ActivityThread.java:7582)     at java.lang.reflect.Method.invoke(Native Method)     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941) Caused by: d.m: lateinit property mInterstitialAd has not been initialized     at .b.i(Unknown Source)     at .MainActivity.onCreate(Unknown Source)     at android.app.Activity.performCreate(Activity.java:7822)     at android.app.Activity.performCreate(Activity.java:7811)     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1328)     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3430) 

I understand what the error is, but I can't figure out how to fix it correctly, because if I initialize an advertisement in the second activity, I will need to load it there, but it doesn't suit me. According to statistics, 88% of cases crash in background. Please tell me how to fix it correctly?

I added a single Native ad to my application, but on different devices, ads, especially videos, come with a delay, on the emulator the video is not shown at all. I know that you can somehow preload ads, but I don’t know how to do it, please explain to me.

Here is my code:

class Fragment(private var index: Int, private var adsId: String) : Fragment() {     var currentNativeAd: UnifiedNativeAd? = null     lateinit var adLoader: AdLoader     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {         val view = inflater.inflate(R.layout.fragment, container, false)         return view     }     override fun onActivityCreated(savedInstanceState: Bundle?) {         super.onActivityCreated(savedInstanceState)         val unifiedNativeAdView = layoutInflater.inflate(R.layout.native_ad_layout, null) as UnifiedNativeAdView         val nativeAdLayout = view!!.findViewById<FrameLayout>(R.id.id_native_ad)         val adLoader = AdLoader.Builder(activity, adsId).forUnifiedNativeAd { unifiedNativeAd -> (unifiedNativeAd)             mapUnifiedNativeAdToLayout(unifiedNativeAd, unifiedNativeAdView)             nativeAdLayout.removeAllViews()         }.withAdListener(object : AdListener() {             // Code to be executed when an ad request fails.             override fun onAdLoaded() {                 super.onAdLoaded()                 if (!adLoader.isLoading) {                   nativeAdLayout.addView(unifiedNativeAdView)                 }             }             override fun onAdFailedToLoad(errorCode: Int) {                Toast.makeText(applicationContext, "Ad failed to load! error code: $errorCode", Toast.LENGTH_SHORT).show()             }             override fun onAdClosed() {                 nativeAdLayout.removeAllViews()             }         }).build()         adLoader.loadAd(AdRequest.Builder().build())         }     fun mapUnifiedNativeAdToLayout(adFromGoogle: UnifiedNativeAd, myAdView: UnifiedNativeAdView) {         currentNativeAd?.destroy()         currentNativeAd = adFromGoogle         val mediaView: MediaView = myAdView.findViewById(R.id.ad_media)         myAdView.mediaView = mediaView         myAdView.bodyView = myAdView.findViewById(R.id.ad_body)         if (adFromGoogle.body == null) {             myAdView.bodyView.visibility = View.GONE         } else {             (myAdView.bodyView as TextView).text = adFromGoogle.body         }         myAdView.setNativeAd(adFromGoogle)         val vc = adFromGoogle.videoController         if (vc.hasVideoContent()) {             vc.videoLifecycleCallbacks = object : VideoController.VideoLifecycleCallbacks() {                 override fun onVideoEnd() {                     super.onVideoEnd()                 }             }         }      }     override fun onDestroy() {         currentNativeAd?.destroy()         super.onDestroy()     } } 

native_ad_layout.xml

<?xml version="1.0" encoding="utf-8"?> <com.google.android.gms.ads.formats.UnifiedNativeAdView xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:layout_gravity="bottom">     <LinearLayout         android:layout_width="match_parent"         android:layout_height="match_parent"         android:layout_gravity="center"         android:orientation="vertical">         <RelativeLayout             android:layout_width="match_parent"             android:layout_height="match_parent">             <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:weightSum="2"                 android:orientation="vertical">                 <com.google.android.gms.ads.formats.MediaView                     android:id="@+id/ad_media"                     android:layout_width="match_parent"                     android:layout_height="0dp"                     android:padding="@dimen/_8sdp"                     android:layout_gravity="center"                     android:layout_weight="2"                     android:background="#fff" />                 <TextView                     android:id="@+id/ad_body"                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:fontFamily="@font/sf_pro_display_regular"                     android:gravity="center"                     android:text="body of ad"                     android:textSize="14sp" />             </LinearLayout>         </RelativeLayout>          </LinearLayout> </com.google.android.gms.ads.formats.UnifiedNativeAdView> 

In a fragment.xml, just a FrameView for the ad.

I use the library 'com.google.android.gms: play-services-ads: 19.1.0' for advertising, I create a banner as follows: https://developers.google.com/admob/android/banner/adaptive so that it always turned out to be the full width of the screen and everything works well, but sometimes black lines appear enter image description here

please tell me how can I remove them? I tried transparent styles and setting the background color,

android: theme = "@ style / TranslucentTheme" android: background = "@ color / transparent"

In xml and through the code, and nothing helps.

I am developing library and using that library as aar to my app as below sample project.

Library Project:

public class UserDevice {     private static final String TAG = "UserDevice";     private static Context mContext;     public UserDevice(final Context context) {         mContext = context.getApplicationContext();     }     private static String getAdvertisementId(Context context) {         String _myads = null;         try {             String id = com.google.android.gms.ads.identifier.AdvertisingIdClient.getAdvertisingIdInfo(context).getId();             if (id != null) {                 _myads = id;             }         } catch (Exception e) {             Log.e(TAG, "Could not get det ID.", e);         }         return _myads;     } } //build.gradle android {     compileSdkVersion 29     buildToolsVersion "29.0.3"     defaultConfig {         minSdkVersion 16         targetSdkVersion 29         versionCode 1         versionName "1.0"         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"         consumerProguardFiles 'consumer-rules.pro'     } ... } dependencies {     // default dependencies     // ...     implementation 'com.google.android.gms:play-services-base:17.2.1'     implementation 'com.google.android.gms:play-services-ads:19.0.1' } 

App Project:

class MainActivity : AppCompatActivity() {     override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         val device = UserDevice(this) //         btn_show_ads.setOnClickListener {             label_ads_id.text = device.myads             Log.d("App", "Device Ads id is: ${device.myads}")         }     } } /// build.gradle dependencies {     // default dependencies     // ...     compile(name: 'adslibrary', ext: 'aar')     // compile project(path: ':adslibrary') } 

But what happened here is that it giving error

2020-05-11 10:11:32.489 21925-21991/com.bhavdip.myadstest E/AndroidRuntime: FATAL EXCEPTION: Thread-2     Process: com.bhavdip.myadstest, PID: 21925     java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/ads/identifier/AdvertisingIdClient;         at com.bhavdip.adslibrary.CRDevice.getAdvertisementId(Unknown Source:2)         at com.bhavdip.adslibrary.CRDevice$1.run(Unknown Source:4)         at java.lang.Thread.run(Thread.java:764)      Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.ads.identifier.AdvertisingIdClient" on path: DexPathList[[zip file "/data/app/com.bhavdip.myadstest-fP-f0WbH8_ErVLG3QBcgkQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.bhavdip.myadstest-fP-f0WbH8_ErVLG3QBcgkQ==/lib/arm, /system/lib, /vendor/lib]]         at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)         at java.lang.ClassLoader.loadClass(ClassLoader.java:379)

I already added and am using gms:play-services-ads dependency in library. The app again asks me to add those dependency forcefully.

If I will add the dependency to the app it works fine, but I don't want to add that dependency again. I don't want to expose my library dependency to end user or developer. Adds below dependency to my-library.

//For advertisement ID implementation 'com.google.android.gms:play-services-ads:19.1.0' implementation 'com.google.android.gms:play-services-base:17.2.1' 

Reference links: I tried this and this too. I also checked all answers in reference links.

I have tried multidex, transitive and also changed implementation to api or compile. in app project like this.

// Use transitive compile(name: 'adslibrary', ext: 'aar') {     transitive = true } 

----- EDIT for Questions -----

  • What is transitive? How it works?
  • How multidex works in library?

I might miss something to change. Please help me out of this problem.