Ionic 3 でリンクを外部ブラウザで開く

Ionic 3 を使ってAndroid / iOS アプリを実装していたのですが、
リンクタップ時にアプリ外のブラウザを開けずハマりました。
なのでその備忘録を兼ねて、対応方法を書いていきたいと思います。

なお、Advent Calendar 初挑戦です。
なにかお気づきの点がありましたら、ご指摘いただけるとうれしいです。



## ことのほったん
実装するためにググったところ、下記のコードが見つかりました。

``` js
window.open("https://qiita.com/", "_system");
```

なのでこれを使って下記のような実装をしたら、なぜかiOS では動きませんでした……。

**HTML**

``` html
<ion-content padding>
  <button ion-button color="danger" (click)="openLink('tel:00012345678')">
    <ion-icon name="call"></ion-icon>
    Call
  </button>
  <button ion-button color="secondary" (click)="openLink('mailto:')">
    <ion-icon name="mail"></ion-icon>
    Mail
  </button>
  <button ion-button color="primary" (click)="openLink('https://ionicframework.com/')">
    <ion-icon name="search"></ion-icon>
    Web
  </button>
</ion-content>
```

**TypeScript**

``` ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  constructor(public navCtrl: NavController) {
  }

  openLink(uri: string) {
    window.open(uri, "_system");
  }
}
```



## 正しい実装
改めてググったところ、Ionic Native プラグインの[In App Browser](https://ionicframework.com/docs/native/in-app-browser/) を使うといいと出てきました。
なので、下記手順で実装を修正していきました。

### 1. インストール
下記コマンドをターミナルで入力し、Cordova プラグインと、Node パッケージをインストールします。

```
$ ionic cordova plugin add cordova-plugin-inappbrowser
$ npm install --save @ionic-native/in-app-browser
```

### 2. モジュールの追加
src/app/app.module.ts に手順１で追加したものを追記します。

``` ts
(省略)

import { InAppBrowser } from "@ionic-native/in-app-browser";

(省略)

@NgModule({
  (省略)
  providers: [
    (省略)
    InAppBrowser
  ]
})
export class AppModule {}
```

### 3. ```windows.open()``` を書き換える
InAppBrowser モジュールを使って書き直していきます。
さきほどのコードを例にすると下記のようになります。

``` ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { InAppBrowser } from '@ionic-native/in-app-browser';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  constructor(
    public navCtrl: NavController,
    private ipb: InAppBrowser) {
  }

  openLink(uri: string) {
    this.ipb.create(uri, "_system");
  }
}
```



## まとめ
Ionic アプリ内にあるリンクを外部ブラウザで開きたい場合は、
Ionic Native プラグインの[In App Browser](https://ionicframework.com/docs/native/in-app-browser/) を使った実装にすることで、
Android, iOS, WEB で同じ挙動を達成できる。



## 備考
### URI スキーム別の挙動
#### ```windows.open(url, "_system")```
URI スキーム | Android | iOS | Chrome(macOS)
--- | --- | --- | ---
http/https | アプリ外のブラウザが起動 | 動作しない | 別タブ起動
mailto | メーラーが起動 | 動作しない | メーラーが起動
tel | 電話が起動 | 動作しない | FaceTime 起動

#### InAppBrowser モジュール
URI スキーム | Android | iOS | Chrome(macOS)
--- | --- | --- | ---
http/https | アプリ外のブラウザが起動 | アプリ外のブラウザが起動 | 別タブ起動
mailto | メーラーが起動 | メーラーが起動 | メーラーが起動
tel | 電話が起動 | 発信前ダイアログが起動 | FaceTime 起動

### 開発環境
* Ionic
    * Ionic CLI: 4.4.0
    * Ionic Framework: ionic-angular 3.9.2
    * @ionic/app-scripts: 3.2.0
* Cordova
    * Cordova CLI: 8.0.0
* System
    * ios-deploy: 1.9.2
    * NodeJS: v8.11.3
    * npm: 6.4.1
    * OS: macOS High Sierra
* IDE
    * Android Studio: 3.2.1
    * Xcode: 10.1

### 検証端末
* Nexus 5X(Android OS: 8.1.0)
* iPhone 7(iOS: 12.1)
* MacBook Pro(macOS: High Sierra)
    * Chrome(version: 70.0.3538.102, 64bit)



## 参考資料
1. [Launch External URLs with Ionic Framework](https://www.thepolyglotdeveloper.com/2014/07/launch-external-urls-ionicframework/) (2018/12/05)  
→ 「ことのほったん」で触れた実装の例。おそらくこういうのを見たと思われる
2. [Ionic Native - In App Browser](https://ionicframework.com/docs/native/in-app-browser/) (2018/12/05)  
3. [Xcode10＆iPhoneiOS12にアップデートしたら実機テストできなくなった話](http://worja.wp.xdomain.jp/?p=725) (2018/12/05)  
→ Xcode 10, iOS 12 でアプリインストールができなかったので、この方法で回避しました