はじめに
最近ionic3を触る機会があり、その中でWebViewを実装することがありました。
が、基本的にionicのドキュメントは英語のみ、問題が起こってもほとんどstackoverflowとかgithubのissueを見て解決しなければならない…といった具合になかなか思うように進まず苦しい思いをしました
そこで今回は、実際にionicでWebViewを実装する際に調べたことを共有していこうと思います。
注意事項
ionicがどういったもの?、Cordova、WebViewって?といったことは省略させていただきます💦
またNode.js, ionic, cordova等のインストールが済んでいる前提で進めていきます。
InAppBrowserとは
Launches in app Browser
ionicのアプリ内でwebページを開くための機能になります。(そのまんま)
インストール
$ ionic cordova plugin add cordova-plugin-inappbrowser
$ npm install --save @ionic-native/in-app-browser
プラグインとモジュール両方のインストールが必要です!
ちなみに僕は上記コマンドのどちらかでいいんだろうなと勝手に判断してnpm install npm install --save @ionic-native/in-app-browser
のほうだけやったら一応webページが表示されるのですが、後に出てくるtarget
に_blank
を設定しても意図した動きをしてくれませんでした
後にプラグインのインストールが必要とわかり入れたところ、うまく動くようになりました。
(cordovaがベースとあるんですから当然ですね…)
初期設定
以下のようにapp.module.tsに追加していきます。
import { InAppBrowser } from "@ionic-native/in-app-browser"; // ← 追加!
@NgModule({
(省略)
providers: [
StatusBar,
SplashScreen,
{ provide: ErrorHandler, useClass: IonicErrorHandler },
InAppBrowser // ← 追加!
]
})
使い方
表示させたいコンポーネントファイルに以下のように実装していきます。
※今回の例ではngOnInitに実装してますが、イベント発火時でも実装できます。そこはよしなに
import { Component, OnInit } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { InAppBrowser } from "@ionic-native/in-app-browser"; // ← 追加!
@IonicPage()
@Component({
selector: 'page-hoge',
templateUrl: 'hoge.html',
})
export class hogePage implements OnInit {
constructor(
public navCtrl: NavController,
public navParams: NavParams,
private inAppBrowser: InAppBrowser // ← 追加!
) { }
ngOnInit() {
const browser = this.inAppBrowser.create('https://hogehoge.com', '_blank', { location: "no", zoom: "no"});
}
}
では順に実際に処理を見ていきましょう
InAppBrowser.create( url, target, options)
このメソッドで実際にInAppBrowserのインスタンスを生成し同時にwebページの表示まで行います。
引数は以下の通り
引数 | 型 | 詳細 |
---|---|---|
url | string | 表示するページのURL |
target | string | URLを表示させるブラウザを指定できる。ターゲットに関しては後述。デフォルトでは_self
|
options | InAppBrowserOptions | InAppBrowserのオプション。デフォルトはlocation= "yes"
|
options のInAppBrowserOptions 型に関して、オプションを直接引数に渡すのであれば例のように{location: "yes"} で問題ないのですが、例えば変数に切り出して実装したいというときに型の指定で必要になります。 |
// InAppBrowserOptionsを追加!
import { InAppBrowser, InAppBrowserOptions } from "@ionic-native/in-app-browser";
(省略)
const url: string = 'https://hogehoge.com';
const target: string = '_blank';
const options: object = { ... }; // ← コンパイルエラー
const options: InAppBrowserOptions = { ... }; // ← OK
const browser = this.inAppBrowser.create(url, target, options);
targetについて
webページを表示するターゲットは3種類あります。
ターゲット | 詳細 |
---|---|
_self | URLがホワイトリストに追加されている場合はcordova browserで、それ以外ではInAppBrowserのブラウザで開く |
_blank | InAppBrowserのブラウザで開く |
_system | システム標準のブラウザを開く(chrome, safari等) |
例えばAndroidでwebページをchromeを立ち上げずにアプリ内で開きたいという場合には_blank
を使用します。
また後で説明しますがexecuteScript()
は**_blank
でしか実行することができません。
※_self
でもできました💦
(すみません、insertCSSは未確認です…。💦確認次第反映させます。)
InAppBrowserのメソッド
create(url , target, options)
先ほども説明しましたが、URL
、target
、options
を設定して実際にwebページを表示させます。
show()
InAppBrowserウィンドウを表示させます。既に表示されている場合は表示されません。
close()
現在表示されているInAppBrowserを非表示にします。既に非表示の場合は何もしません。
executeScript(script)
戻り値:Promise< any >
InAppBrowserに実行するJavascriptのコードを注入します。
引数はobject型で渡します。コードを直接書けますし、外部ファイルを読み込ませることも可能です。
※executeScript()
を使用する場合はcreate(url, target, options)
のtarget
が_blank
である必要があります。
※_self
でもできました💦
executeScript({code: "alert('Hello Ionic!');"});
insertCSS(css)
戻り値:Promise< any >
InAppBrowserウィンドウにCSSを注入します。
executeScriptのCSS版と思っていただいて大丈夫です。こちらも同じようにコードまたは外部ファイルを使用することができます。
on(event)
戻り値:Observable< InAppBrowserEvent >
InAppBrowserのイベントによって処理のタイミングを設定します。
イベントは4種類用意されています。
Param | Details |
---|---|
loadstart | ページの読み込みが始まったら |
loadstop | ページの読み込みが終わったら |
loaderror | ページの読み込み中にエラーが起きたら |
exit | ブラウザを閉じたら |
InAppBrowserOptions
InAppBrowser.createのoptionsに設定できるプロパティです。
が、長いのでゆっくり更新していきます
Ionic InAppBrowser Options
※一部は直訳していたり適当に書いている部分もありますが許してください!なんでもしますから!
Param | Type | Details | OS |
---|---|---|---|
location | 'yes' or 'no' | InAppBrowserのロケーションバーの表示、非表示を設定する。(任意設定) | |
hidden | 'yes' or 'no' | (任意設定) | |
clearcache | 'yes' |
yes を設定すると新しいウィンドウを開くときにクッキーとキャッシュをクリアする。 |
|
clearsessioncache | 'yes' | (任意設定) | |
closebuttoncaption | string | (任意設定) | |
closebuttoncolor | string | (任意設定) | |
zoom | 'yes' or 'no' | ブラウザのズームコントロールの表示非表示を設定する。デフォルトはyes
|
Android |
hardwareback | 'yes' or 'no' | (任意設定) | |
mediaPlaybackRequiresUserAction | 'yes' or 'no' |
yes に設定するとHTML5オーディオまたはビデオが自動再生されなくなる。デフォルトはno
|
|
hidenavigationbuttons | 'yes' or 'no' | (任意設定) | |
hideurlbar | 'yes' or 'no' | (任意設定) | |
navigationbuttoncolor | string | (任意設定) | |
toolbarcolor | string | (任意設定) | |
shouldPauseOnSuspend | 'yes' or 'no' | InAppBrowser WebViewでバックグラウンドオーディオを停止するためにアプリを一時停止/再開させるにはyes に設定する。 ※GooglePlayで利用規約違反になる問題があるため。 |
Android |
footer | 'yes' or 'no' |
yes に設定すると、iOSの完了ボタンと同様にフッターに閉じるボタンが表示される。そのためclosebuttoncaption とclosebuttoncolor を使用してプロパティを設定する。 |
Android |
footercolor | 'string' |
# 00ff00 などの有効な16進数の文字列に設定するとフッターの色がデフォルトから変更される。footer をyes に設定している場合のみ適用される。 |
Android |
disallowoverscroll | 'yes' or 'no' | UIWebViewBounce(rubber-band)を使用するか設定する。 | iOS |
toolbar | 'yes' or 'no' | InAppBrowserのツールバーの表示、非表示を設定する。デフォルトはyes
|
iOS |
toolvartranslucent | 'yes' or 'no' | ツールバーを半透明にするかしないかを設定する。ツールバーが設定されているときのみ。デフォルトはyes
|
iOS |
enableViewportScale | 'yes' or 'no' | メタタグによるビューポートの拡大縮小を防止する。 | iOS |
allowInlineMediaPlayback | 'yes' or 'no' | (任意設定) | - |
keyboardDisplayRequiresUserAction | 'yes' or 'no' | Javascriptのfocus()呼び出しでフォーカスが当たったときにキーボードを開くにはyes を設定する。 |
iOS |
suppressesIncrementalRendering | 'yes' or 'no' | レンダリングする前に全ての表示内容が受信されるまで待機する。デフォルトはno
|
iOS |
presntationstyle | 'pagesheet' or 'formsheet' or 'fullscreen' | プレゼンテーションスタイルを設定する。デフォルトはフルスクリーン | iOS |
transitionstyle | 'fliphorizontal' or 'crossdissolve' or 'coververtical' | トランジションスタイルを設定する。デフォルトはcoververtical ここわかりやすい
|
iOS |
toolbarposition | 'top' or 'bottom' | ツールバーの位置を設定する。デフォルトは下 | iOS |
hidespinner | 'yes' or 'no' | ローディングインジケーターの表示、非表示を設定する。 | iOS |
fullscreen | 'yes' | (任意設定) | |
useWideViewPort | 'yes' or 'no' |
viewport HTMLメタタグのサポートの有効無効を設定する。yes でページにビューポートメタタグが含まれる場合、指定された幅の値が適用される。ページにメタタグが無いか、幅が指定されていない場合はワイドビューポートが適用される。デフォルトはyes
|
Android |
ユースケース
ネイティブ側でCognitoを利用しサインインまでを行い、サインイン完了後以降はCloudFrontにあるページをWebviewで表示したい。
この時、サインインで取得したトークンをWebViewのページに渡すにはどうしたらよいでしょうか?
このケースのようにネイティブからWebviewへ値を渡したいときは**executeScript()
**を利用します
実装例はこちら
const browser = this.inAppbrowser.create(url, target, options);
browser.on('loadstop').subscribe(event => {
browser.executeScript({ code: "sessionStorage.setItem('hoge', 'piyopiyo');"});
});
まず基本であるcreate
をします。繰り返しますがtarget
は_blank
で設定してください。
次にイベントを設定します。表示先webページの読み込みが完了したら指定したJavascript、ここではSessionStorageに値を入れる処理をしていますが、これを実行します。
こうすることで、ネイティブ側で保持している値をWebview側に渡すことが出来ます。
※ちなみにon().subscribe()
は**Android端末またはiOS端末でしか動作しません。**ブラウザで動作を確認しようとするとエラーが出ます。
余談ですが僕は実装当初
browser.executeScript({ code: `SessionStorage.setItem('hoge, ${this.hoge}');`});
このようなことをしていましたがうまく値渡しができませんでした。いろいろ調べてはみたのですがどれも解決に至らず…。
約1日ほど悩みました。が、なんと
browser.executeScript({ code: `SessionStorage.setItem('hoge', '${this.hoge}');`});
このように${}
をシングルクォーテーション囲んでいなかったのが原因でした。
こんなのにハマって1日無駄にしたのが情けない情けない…。
もしかしたら僕以外にハマる方がいらっしゃるかもしれないので一応これも共有しておきます…。
さいごに
エンジニアが学ぶべき言語は英語(確信)
参考リンク
Ionic native InAppBrowser
apache/cordova-plugin-inappbrowser github
※あとから追記していきます。