Flutter Android端如何获取Activity?插屏广告加载遇空指针问题
问题:Flutter插件Kotlin侧获取Activity为空,插屏广告无法正常展示
我正在使用Kotlin和Swift开发一款Flutter插件,用于在Flutter界面中展示横幅广告和插屏广告。但在Kotlin侧展示插屏广告时,需要用到Activity,尝试通过onAttachedToActivity方法获取,却发现activity变量始终为空。
我没有使用FlutterEngine,而是通过init方法在Flutter界面中添加布局(该布局用于展示横幅广告,且运行正常,相关代码已移除)。以下是用于展示广告的三个Kotlin类:
插件类
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") } }
工厂类
class MyViewFactory (private val messenger: BinaryMessenger): PlatformViewFactory(StandardMessageCodec.INSTANCE){ override fun create(context: Context, id: Int, o: Any?) : PlatformView { return MyView(context, messenger, id) } }
视图类
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") } }
问题解决说明
后来定位到问题根源:ActivityAware接口被错误地实现在了MyView类中,正确的做法应该是在插件主类SecondPluginAttemptPlugin中实现该接口。
将Activity传递给MyView类的实现方式:结合使用lateinit和CompletableFuture<Activity>来完成Activity实例的传递。
内容的提问来源于stack exchange,提问作者T1D
相关产品推荐
相关产品推荐

