FlutterFragment で admob が表示されない問題
問題
FutterFragment で admob を表示しようとしたところ表示されず、ログを見ると下記エラーが発生していました。
2024-03-11 19:39:43.207 17033-17180 flutter
E [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method create on channel flutter/platform_views)
#0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:313:7)
<asynchronous suspension>
#1 SurfaceAndroidViewController._sendCreateMessage (package:flutter/src/services/platform_views.dart:1045:9)
<asynchronous suspension>
#2 AndroidViewController.create (package:flutter/src/services/platform_views.dart:818:5)
<asynchronous suspension>
原因
admob では PlatformView の機能を利用しているが、これを登録するための処理が内部で実行されていない様子。
登録処理は FlutterEngineConnectionRegistry.attachToActivityInternal(Activity, Lifecycle) で実行されているがFlutterFragment でこの処理がスキップされている。
ちなみにこのエラーに関するコメントが実装に記されている。
// Activate the PlatformViewsController. This must happen before any plugins attempt
// to use it, otherwise an error stack trace will appear that says there is no
// flutter/platform_views channel.
flutterEngine
.getPlatformViewsController()
.attach(activity, flutterEngine.getRenderer(), flutterEngine.getDartExecutor());
この処理が実行されるかどうかは shouldAttachEngineToActivity
というフラグを見ている。
/**
* See {@link NewEngineFragmentBuilder#shouldAttachEngineToActivity()} and {@link
* CachedEngineFragmentBuilder#shouldAttachEngineToActivity()}.
*
* <p>Used by this {@code FlutterFragment}'s {@link FlutterActivityAndFragmentDelegate}
*/
@Override
public boolean shouldAttachEngineToActivity() {
return getArguments().getBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY);
}
このフラグがやや曲者で NewEngineFragmentBuilder や CachedEngineFragmentBuilder を利用して FlutterFragment インスタンスを生成した場合のデフォルト値は true になるが、それ以外の場合は false になる。
builder 以外の生成方法では ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY
のフラグが設定されないことで getBoolean(String) がフォールバックされて false が返されてしまう。
なので本来的にはこのような処理が正しいのでは。(shouldAttachEngineToActivity は FlutterFragment のメンバ変数で true を設定しているので、それをフォールバックとして設定)
@Override
public boolean shouldAttachEngineToActivity() {
return getArguments().getBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY, shouldAttachEngineToActivity);
}
いずれにしてもここを true で返せば問題なさそう。
対応
FlutterFragment に shouldAttachEngineToActivity() を継承して true を返すようにしました。
override fun shouldAttachEngineToActivity(): Boolean {
return true
}
HogeFragment : FlutterFragment() のような実装だったのでこのような対応をしましたが、それ以外の場合は NewEngineFragmentBuilder や CachedEngineFragmentBuilder を利用して FlutterFragment を生成する方法にすればいいと思います。
Discussion