我尝试重新加载激励视频广告,当我打电话给RewardedVideoAd.instance.load(adUnitId: "xxx", targetingInfo: xyz);
时,我发现以下错误:
W/MessageQueue(13672): Handler (android.os.Handler) {1a13e8a} 向死线程上的处理程序发送消息 W/MessageQueue(13672): java.lang.IllegalStateException: Handler (android.os.Handler) {1a13e8a} 将消息发送到死线程上的处理程序 W/MessageQueue(13672): at android.os.MessageQueue.enqueueMessage(MessageQueue.java:543) W/MessageQueue(13672): at android.os.Handler.enqueueMessage(Handler.java:643) W/MessageQueue(13672): at android.os.Handler.sendMessageAtTime(Handler.java:612) W/MessageQueue(13672): at android.os.Handler.sendMessageDelayed(Handler.java:582) W/MessageQueue(13672): at android.os.Handler.sendEmptyMessageDelayed(Handler.java:546) W/MessageQueue(13672): at android.os.Handler.sendEmptyMessage(Handler.java:531) W/MessageQueue(13672): at com.google.android.gms.ads.exoplayer1.h.c(:com.google.android.gms.policy_ads_fdr_dynamite@20300003@20300003.251657827.251657827:2) W/MessageQueue(13672): at com.google.android.gms.ads.internal.video.exoplayer1.f.b(:com.google.android.gms.policy_ads_fdr_dynamite@20300003@20300003.251657827.251657827:1) W/MessageQueue(13672): at com.google.android.gms.ads.internal.webview.t.E(:com.google.android.gms.policy_ads_fdr_dynamite@20300003@20300003.251657827.251657827:5) W/MessageQueue(13672): at com.google.android.gms.ads.internal.webview.j.onPageDone(:com.google.android.gms.policy_ads_fdr_dynamite@20300003@20300003.251657827.251657827:2) W/MessageQueue(13672): at uU.d(PG:307) W/MessageQueue(13672): at aIV.handleMessage(PG:73) W/MessageQueue(13672): at android.os.Handler.dispatchMessage(Handler.java:102) W/MessageQueue(13672): at android.os.Looper.loop(Looper.java:154) W/MessageQueue(13672): at android.app.ActivityThread.main(ActivityThread.java:6780) W/MessageQueue(13672): at java.lang.reflect.Method.invoke(Native Method) W/MessageQueue(13672): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496) W/MessageQueue(13672): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386) W/ExoPlayerImplInternal(13672):发布后发送消息(1)。消息已忽略。 D/Graph (13672): removeVertex() : insertDummyVertex,因为没有祖先。 D/ViewRootImpl@b8db50eAdActivity: mHardwareRenderer.destroy()#4 D/ViewRootImpl@b8db50eAdActivity: dispatchDetachedFromWindow
我把听众放在屏幕的initState()
。 在这个屏幕中,我有一个button
,如果我们点击它,它应该显示Rewarded Video Ads
.
此外,在重新加载Rewarded Ads
时出现错误后,点击按钮显示广告后出现以下错误(因为广告实例为空):
E/颤振 (13672): [错误:颤振/lib/ui/ui_dart_state.cc(148)] 未处理的异常:平台异常(ad_not_loaded,激励视频显示失败,未加载广告,空)E/颤振 (13672):#0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:564:7) E/flutter (13672): #1 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:316:33) E/颤振 (13672): E/颤振 (13672): #2 _invokeBooleanMethod (包:firebase_admob/firebase_admob.dart:518:61) E/颤振 (13672): E/颤振 (13672): #3 奖励视频广告 (包:firebase_admob/firebase_admob.dart:392:12)
我把Rewarded Video Ads Listener
放在initState()
,以下是代码:
@override
void initState() {
super.initState();
...
RewardedVideoAd.instance.listener =
(RewardedVideoAdEvent event, {String rewardType, int rewardAmount}) {
if (event == RewardedVideoAdEvent.completed) {
setState(() {
print ("::debug:: ads should be reloaded");
RewardedVideoAd.instance.load(adUnitId: "ca-app-pub-3940256099942544/5224354917", targetingInfo: targetingInfos);
});
}
};
...
但是,如果我像下面这样将代码放在按钮的onPressed
,视频广告将在点击 2-3 次后显示(调试时显示ads = null
)
RaisedButton(
onPressed: () {
RewardedVideoAd.instance.show().whenComplete(() {
RewardedVideoAd.instance.load(adUnitId: "ca-app-pub-3940256099942544/5224354917", targetingInfo: targetingInfos);
})
},
...
任何想法 ?
提前致谢...
似乎问题出在事件completed
上。查看此代码。
MobileAdTargetingInfo targetingInfo = MobileAdTargetingInfo(
keywords: <String>['flutterio', 'beautiful apps'],
contentUrl: 'https://flutter.io',
childDirected: false,
testDevices: <String>[], // Android emulators are considered test devices
);
bool _loaded = false;
@override
void initState() {
super.initState();
// load ad in the beginning
RewardedVideoAd.instance
.load(adUnitId: RewardedVideoAd.testAdUnitId, targetingInfo: targetingInfo)
.catchError((e) => print("error in loading 1st time"))
.then((v) => setState(() => _loaded = v));
// ad listener
RewardedVideoAd.instance.listener = (RewardedVideoAdEvent event, {String rewardType, int rewardAmount}) {
if (event == RewardedVideoAdEvent.closed) {
RewardedVideoAd.instance
.load(adUnitId: RewardedVideoAd.testAdUnitId, targetingInfo: targetingInfo)
.catchError((e) => print("error in loading again"))
.then((v) => setState(() => _loaded = v));
}
};
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(
"Loaded = ${_loaded}",
style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
),
),
floatingActionButton: FloatingActionButton(
// show ad on FAB click
onPressed: () async {
await RewardedVideoAd.instance.show().catchError((e) => print("error in showing ad: ${e.toString()}"));
setState(() => _loaded = false);
},
),
);
}
无需调用 set 状态,因为它很昂贵并且会导致完全重建。
可以通过以下方式轻松解决此问题:
import 'package:flutter/material.dart';
import 'package:firebase_admob/firebase_admob.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage());
}
}
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//The targeting info required for Rewarded Videos Ads
MobileAdTargetingInfo targetingInfo = MobileAdTargetingInfo(
keywords: <String>['flutterio', 'beautiful apps'],
contentUrl: 'https://flutter.io',
childDirected: false,
testDevices: <String>[], // Android emulators are considered test devices
);
//An instance to be called in the init state
RewardedVideoAd _videoAd = RewardedVideoAd.instance;
@override
void initState() {
//---------------------------------------//
//Initialise the listener with the values.
_videoAd.listener =
(RewardedVideoAdEvent event, {String rewardType, int rewardAmount}) {
if (event == RewardedVideoAdEvent.completed) {
//When the video ad gets completed load a new video ad
_videoAd
.load(
adUnitId: RewardedVideoAd.testAdUnitId,
targetingInfo: targetingInfo)
.catchError((e) => print('Error in loading.'));
}
//On every other event change pass the values to the _handleEvent Method.
_handleEvent(event, rewardType, 'Reward', rewardAmount);
};
//------------------------------------------------------------------//
//This will load the video when the widget is built for the first time.
_videoAd
.load(
adUnitId: RewardedVideoAd.testAdUnitId,
targetingInfo: targetingInfo)
.catchError((e) => print('Error in loading.'));
//-----------------------------------------------------//
super.initState();
}
//---- Useful function to know exactly what is being done ----//
void _handleEvent(RewardedVideoAdEvent event, String rewardType,
String adType, int rewardAmount) {
switch (event) {
case RewardedVideoAdEvent.loaded:
_showSnackBar('New Admob $adType Ad loaded!', 1500);
break;
case RewardedVideoAdEvent.opened:
_showSnackBar('Admob $adType Ad opened!', 1500);
break;
//
//The way we are fixing the issue is here.
//This is by calling the video to be loaded when the other rewarded video is closed.
case RewardedVideoAdEvent.closed:
_showSnackBar('Admob $adType Ad closed!', 1500);
_videoAd
.load(
adUnitId: RewardedVideoAd.testAdUnitId,
targetingInfo: targetingInfo)
.catchError((e) => print('Error in loading.'));
break;
case RewardedVideoAdEvent.failedToLoad:
_showSnackBar('Admob $adType failed to load.', 1500);
break;
case RewardedVideoAdEvent.rewarded:
_showSnackBar('Rewarded $rewardAmount', 3000);
break;
default:
}
}
//Snackbar shown with ad status
void _showSnackBar(String content, int duration) {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(content),
duration: Duration(milliseconds: duration),
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FlatButton(
child: Text('Play AD'),
onPressed: () {
_videoAd.show().catchError(
(e) => print("error in showing ad: ${e.toString()}"));
},
),
),
);
}
}
您可以简单地捕获异常,如下所示:
myRewardVideoAd.show()
.catchError((e) => print("error in showing ad: ${e.toString()}"));
嗨,我认为最好的解决方案是使用 try catch,如果有问题,我们可以尝试再次显示它。这是我的代码;
MobileAdTargetingInfo targetingInfo = MobileAdTargetingInfo(
keywords: <String>['flutterio', 'beautiful apps'],
contentUrl: 'https://flutter.io',
childDirected: false,
testDevices: <String>[],
);
String adUnit = "ca-app-pub-6288831324909345/9733176442";
bool tryAgain = false;
await RewardedVideoAd.instance
.load(adUnitId: adUnit, targetingInfo: targetingInfo);
try {
await RewardedVideoAd.instance.show();
} on PlatformException catch (e) {
tryAgain = true;
print(e.message);
}
RewardedVideoAd.instance.listener =
(RewardedVideoAdEvent event, {String rewardType, int rewardAmount}) {
switch (event) {
case RewardedVideoAdEvent.rewarded:
setState(() {
// Here, apps should update state to reflect the reward.
print("_goldCoins += rewardAmount");
});
break;
case RewardedVideoAdEvent.loaded:
if (tryAgain) RewardedVideoAd.instance.show();
break;
default:
print(event.toString());
break;
}
};
请检查您是否在 adMob 帐号中添加了付款信息。在未向 Google 提供这些信息的情况下,系统禁止查看广告。 广告支付
另一个问题可能是您的帐户尚未获得批准。这意味着您的帐户是新的,您必须等待 24 小时到 2 周。