0

I am creating Flutter plugin that displays banner and interstitial ads in Flutter UI using Kotlin and Swift. When trying to show interstitial ad using Kotlin, I need to use Activity for that, which I am trying to get using onAttachedToActivity, but my activity variable is always null.

I checked other questions related to this, but they are either using configureFlutterEngine or have only one class.

I am using init method instead of FlutterEngine to add a layout in Flutter UI using Kotlin, which is later used to display banner (and banner works without any problems, so I removed that code part). I am adding all three Kotlin classes used for displaying ads.

Plugin class:

class SecondPluginAttemptPlugin: FlutterPlugin {

  private var Tag: String = "MyTag"
  override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    Log.d(Tag, "SecondPluginAttemptPlugin attached to Flutter engine")
    try {
      binding.platformViewRegistry.registerViewFactory(
        "plugins.example/second_attempt", MyViewFactory(binding.binaryMessenger)
      )
      Log.d(Tag, "MyViewFactory registered")
    } catch (e: Exception) {
      Log.e(Tag, "Error during registration: ${e.message}")
    }
  }
  
  override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    Log.d(Tag, "SecondPluginAttemptPlugin detached from Flutter engine")
  }
}

Factory class:

class MyViewFactory (private val messenger: BinaryMessenger): PlatformViewFactory(StandardMessageCodec.INSTANCE){
        override fun create(context: Context, id: Int, o: Any?) : PlatformView {
            return MyView(context, messenger, id)
        }
}

And my view class

class MyView internal constructor(context: Context, messenger: BinaryMessenger, id: Int) :
    PlatformView, MethodCallHandler, ActivityAware {
    private var applicationContext: Context = context
    private var messageLayout: ViewGroup?
    private val channel = MethodChannel(messenger, "plugins.example/second_attempt_$id")

    private var mAdManagerInterstitialAd: AdManagerInterstitialAd? = null
    private lateinit var myActivity: Activity
    private val Tag = "MyTag"

    init {
        try {
            Log.d(Tag, "init")
            channel.setMethodCallHandler(this)

        } catch (e: Exception) {
            Log.e(Tag, "Error setting method call handler: $e")
        }
        messageLayout = FrameLayout(applicationContext)
        messageLayout?.setBackgroundColor(Color.BLUE)
        val params = FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.WRAP_CONTENT,
            FrameLayout.LayoutParams.WRAP_CONTENT
        )
        params.gravity = Gravity.BOTTOM
    }

    override fun getView(): View? {
        Log.d(Tag, "View")
        return messageLayout
    }

    override fun dispose() {
        Log.d(Tag, "Dispose")
        messageLayout = null
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        Log.d(Tag, "onMethodCall " )
        when (call.method) {
            "setParams" -> settingParameters(call)
            else -> result.notImplemented()
        }
    }

    private fun settingParameters(call: MethodCall) {
        val arguments = call.arguments as? Map<*, *>
        val accountId = arguments?.get("prebidAccountId") as? String ?: ""
        val adUnitId = arguments?.get("adUnitId") as? String ?: ""
        val configId = arguments?.get("configId") as? String ?: ""
        val width = arguments?.get("width") as? Int ?: 0
        val height = arguments?.get("height") as? Int ?: 0

        messageLayout?.removeAllViews()

        val textView = TextView(applicationContext)
        textView.setTextColor(Color.RED)
        textView.gravity = Gravity.CENTER

        //Skipped some code used to check if variables are not empty and if they are - a message is displayed inside messageLayout

        createInterstitial(adUnitId)
    }

    private fun createInterstitial(AD_UNIT_ID: String) {
        val adRequest = AdManagerAdRequest.Builder().build()

        AdManagerInterstitialAd.load(applicationContext, AD_UNIT_ID, adRequest,
            object : AdManagerInterstitialAdLoadCallback() {
                override fun onAdLoaded(interstitialAd: AdManagerInterstitialAd) {
                    mAdManagerInterstitialAd = interstitialAd
                    Log.i(Tag, "onAdLoaded")
                    showInterstitial()
                }

                override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                    Log.d(Tag, loadAdError.toString())
                    mAdManagerInterstitialAd = null
                }
            })
    }

    private fun showInterstitial() {
        if (mAdManagerInterstitialAd != null) {
            mAdManagerInterstitialAd?.show(myActivity)
        } else {
            Log.d("TAG", "The interstitial ad wasn't ready yet.")
        }
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        myActivity = binding.activity
    }

    override fun onDetachedFromActivityForConfigChanges() {
        TODO("Not yet implemented")
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        TODO("Not yet implemented")
    }

    override fun onDetachedFromActivity() {
        TODO("Not yet implemented")
    }
}

Edit: so it seems my problem was adding ActivityAware inside MyView class instead of SecondPluginAttemptPlugin. As for passing activity value to MyView class, I used lateinit and CompletableFuture<Activity>().

1 Answer 1

1

Use ActivityAware

import io.flutter.embedding.engine.plugins.activity.ActivityAware



class SecondPluginAttemptPlugin : FlutterPlugin, ActivityAware {
    private var activity: Activity? = null

    //* * *

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.activity
    }
    override fun onReattachedToActivityForConfigChanges(binding:ActivityPluginBinding) {
        activity = binding.activity
    }

    override fun onDetachedFromActivityForConfigChanges() {}

    override fun onDetachedFromActivity() {}
}
Sign up to request clarification or add additional context in comments.

1 Comment

Ah, so I should use it here and then pass to MyView class, yes? I did try to use ActivityAware, but in MyView class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.