Open TetsuFe opened 4 years ago
<script type="text/javascript">
var nend_params = {"media":66283,"site":338979,"spot":1003266,"type":1,"oriented":1};
</script>
<script type="text/javascript" src="https://js1.nend.net/js/nendAdLoader.js"></script>
<script src="main.dart.js" type="application/javascript"></script>
</body>
このように記述したが、何も表示されなかった
https://pub.dev/packages/nend_plugin#-example-tab-
場所は指定できない
nend公式(ファンコミュニケーションズ)のプラグインがあるっぽいので採用してみる=>ダメっぽい(後述。apiKeyが使えないとこのプラグインが使えないようだが、ios/androidしか対応していないようなので)
apiKeyというのが必要らしいが、表示されていない・・ 申請が承認される必要がある?
apiKeyは、多分ios/androidでしか使えない https://github.com/fan-ADN/nendSDK-Flutter/blob/master/example/lib/banner.dart#L218
String get apiKey {
print('apiKey selection : $_selection');
switch (_selection) {
case BannerSize.type728x90:
return (Platform.isAndroid
? "02e6e186bf0183105fba7ce310dafe68ac83fb1c"
: "2e0b9e0b3f40d952e6000f1a8c4d455fffc4ca3a");
case BannerSize.type320x100:
return (Platform.isAndroid
? "8932b68d22d1d32f5d7251f9897a6aa64117995e"
: "eb5ca11fa8e46315c2df1b8e283149049e8d235e");
case BannerSize.type300x100:
return (Platform.isAndroid
? "1e36d1183d1ab66539998df4170a591c13028416"
: "25eb32adddc4f7311c3ec7b28eac3b72bbca5656");
case BannerSize.type300x250:
return (Platform.isAndroid
? "499f011dbec5d37cfa388b749aed2bfff440a794"
: "88d88a288fdea5c01d17ea8e494168e834860fd6");
case BannerSize.type320x50:
default:
return (Platform.isAndroid
? "c5cb8bc474345961c6e7a9778c947957ed8e1e4f"
: "a6eca9dd074372c898dd1df549301f277c53f2b9");
}
}
https://affiliate150.com/nend-ad-setting
ここの「ステータス」という部分が「承認中」となっている間は審査中なので広告は表示されません。しばらくするとメールが来てこのステータスが「アクティブ」に変わります。「アクティブ」になっていれば広告は表示されているハズです。
なので、「nendの広告が表示されない」「広告が出ない」という場合にはこの点を確認して下さい。またWordPressの場合にはプラグインとの相性で広告が表示されない場合もありますので、一度プラグインを停止して確認しましょう。
https://japanese-photographer.com/information_technology/nend_no-display/
ステータスがアクティブになっても、数時間は広告が表示されません。
https://japanese-photographer.com/information_technology/nend_no-display/
Googleアドセンスと大きくことなる点ですが、うっかり忘れがちなのが「nendの広告はPCサイトには表示されない」という点です。
特定のページだけで表示するには、ページにscriptタグをしこむしかない。逆に、index.htmlにしこむと全ページで広告が有効になってしまう。
ノベルゲームページでは広告が邪魔になってしまうことが考えられるので、特定のページだけに表示したいというわけ。
とりあえず、StoryListPageにこんな感じで挿入してみた
import 'dart:html';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter_state_management/story/story.dart';
import 'package:flutter_state_management/story/story_api.dart';
import 'package:flutter_state_management/story/story_details_page.dart';
import 'package:flutter_state_management/story/story_state_notifier.dart';
import 'package:flutter_state_notifier/flutter_state_notifier.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
class StoryListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory('add_nend_script_1',
(int viewId) {
final element = ScriptElement()
..src = 'https://js1.nend.net/js/nendAdLoader.js'
..type = 'text/javascript';
return element;
});
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory('add_nend_script_2',
(int viewId) {
final element = ScriptElement()
..text = 'var nend_params = {"media":66283,'
'"site":338979,"spot":1003266,"type":1,"oriented":1};'
..type = 'text/javascript';
return element;
});
return Scaffold(
appBar: AppBar(
title: const Text('ストーリー選択'),
),
body: SingleChildScrollView(
child: Column(
children: [
const SizedBox(
width: 0,
height: 0,
child: HtmlElementView(viewType: 'add_nend_script_1'),
),
const SizedBox(
width: 0,
height: 0,
child: HtmlElementView(viewType: 'add_nend_script_2'),
),
],
),
),
);
}
}
https://aloerina01.github.io/javascript/2016/10/14/1.html
デバッグの際の注意点:非同期に読み込まれるので、待たないとエラーが表示されない
index.htmlのbodyにscriptを仕込む方法
ui.platformViewRegistry.registerViewFactory('add_nend_script_2',
(int viewId) {
final element = DivElement()
..appendHtml(
'<script>var nend_params = {\'media\':66283,\'site\':338979,\'spot\':1003266,\'type\':1,\'oriented\':1};</script><script src=\'https://js1.nend.net/js/nendAdLoader.js\'></script>',
validator: NodeValidatorBuilder.common()
..allowTextElements()
..allowElement('script', attributes: ['src']))
..id = 'plotly_div_id_';
//..innerHtml =
// '<script>var nend_params = {\'media\':66283,\'site\':338979,\'spot\':1003266,\'type\':1,\'oriented\':1};</script><script src=\'https://js1.nend.net/js/nendAdLoader.js\'></script>';
return element;
/* 省略 */
const SizedBox(
width: 0,
height: 0,
child: HtmlElementView(viewType: 'add_nend_script_2'),
),
普通にやると、Removing disallowed attribute・・となってしまうので、以下のようにして許可する https://stackoverflow.com/questions/18867266/dart-removing-disallowed-attribute-after-editor-upgraded
final NodeValidatorBuilder _htmlValidator=new NodeValidatorBuilder.common()
..allowElement('a', attributes: ['data-target', 'data-toggle'])
..allowElement('button', attributes: ['data-target', 'data-toggle']);
'に対してのエスケープが必要なことに注意すればよい。
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:html';
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
ui.platformViewRegistry.registerViewFactory("add_script", (int viewId) {
ScriptElement element = ScriptElement()
..src = "https://js1.nend.net/js/nendAdLoader.js"
..type = "text/javascript";
return element;
});
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Directionality(
textDirection: TextDirection.ltr,
child: SizedBox(
width: 640,
height: 360,
child: HtmlElementView(viewType: 'add_script'),
),
),
],
),
);
}
}
ただし、Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened. とエラーが出て動かない。
これは、以下を意味している
https://aloerina01.github.io/javascript/2016/10/14/1.html
こちらの方法でもやってみたが、flutterがつくるcanvasに上書きされてしまうっぽい。実際に、buildメソッド上でエラーが出て止まった時などにはcanvasが作成されないため、広告が表示された。一番惜しい方法だったかもしれないが、これ以上進展がなさそうなものでもあった
Scaffoldに包まずにMaterialApp直下に高さ0、幅0のWidgetをおくと、広告が表示された。
コード
import 'dart:html';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
class StoryListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory('add_nend_script_2',
(int viewId) {
final element = ScriptElement()
..async = true
..text = '(function() {'
'var iframe = document.createElement("iframe");'
'var body = document.getElementsByTagName("body")[0];'
'body.appendChild(iframe);'
'var html = "<body><script>var nend_params = {\'media\':66283,\'site\':338979,\'spot\':1003266,\'type\':1,\'oriented\':1};</script><script src=\'https://js1.nend.net/js/nendAdLoader.js\'></script></body>";'
'var iframeDocument = iframe.contentWindow.document;'
'iframeDocument.open();'
'iframeDocument.write(html);'
'iframeDocument.close();'
'})();'
..type = 'text/javascript';
return element;
});
return const SizedBox(
width: 0,
height: 0,
child: HtmlElementView(viewType: 'add_nend_script_2'),
);
}
}
しかし、実際にはwidgetの裏のiframeが表示されている状態。 Widgetを追加すると、以下のように隠れる。
iframeとposition:absoluteの合わせ技を使うとflutterのwidgetの前面にiframeを表示できることがわかった。
ui.platformViewRegistry.registerViewFactory('add_nend_script_2',
(int viewId) {
final element = ScriptElement()
..async = true
..text = '(function() {'
'var iframe = document.createElement("iframe");'
'iframe.style=\'position:absolute;\';'
'var body = document.getElementsByTagName("body")[0];'
'body.appendChild(iframe);'
'var html = "<body><flt><script>var nend_params = {\'media\':66283,\'site\':338979,\'spot\':1003266,\'type\':1,\'oriented\':1};</script><script src=\'https://js1.nend.net/js/nendAdLoader.js\'></script></flt></body>";'
'var iframeDocument = iframe.contentWindow.document;'
'iframeDocument.open();'
'iframeDocument.write(html);'
'iframeDocument.close();'
'})();'
..type = 'text/javascript';
return element;
});
return SingleChildScrollView(
child: Column(
children: [
// StoryList(),
const SizedBox(
width: 0,
height: 0,
child: HtmlElementView(viewType: 'add_nend_script_2'),
),
IgnorePointer(
child: Container(
width: 300,
height: 300,
color: Colors.lightGreen,
)),
Container(
width: 300,
height: 300,
color: Colors.red,
),
],
),
);
}
}
ちなみに、scaffoldでラップしてもちゃんと前面に出てくれる。
return Scaffold(
appBar: AppBar(
title: const Text('ストーリー選択'),
),
body: SingleChildScrollView(
child: Column(
children: [
// StoryList(),
const SizedBox(
width: 0,
height: 0,
child: HtmlElementView(viewType: 'add_nend_script_2'),
),
IgnorePointer(
child: Container(
width: 300,
height: 300,
color: Colors.lightGreen,
)),
Container(
width: 300,
height: 300,
color: Colors.red,
),
],
),
),
現状実用性がなさそうなのでclose
ストーリーを読んだ後に広告を表示したい
Adsenseのライブラリはないのでplatform channelを使う https://stackoverflow.com/questions/57909791/is-it-possible-to-insert-google-adsense-at-flutter-web-application
参考
Admob
Can we implement admob Or other ads in flutter website?
admob_flutterのサンプル