新しいHTML5 APPプラットフォーム「Capacitor」を試してみた

**Capacitorは現在、1.0.0-beta.11でまだリリースされていません。**

Capacitorの概略は[「新しいHTML5 APPプラットフォーム「Capacitor」の概要説明」](https://www.rdlabo.jp/article/973)をご覧ください。何がどういう考え方でできるようになったかをざっとまとめております。

ということで、Capacitorの試し方です（[公式ドキュメント](https://capacitor.ionicframework.jp)）。また、Ionic CLIでも設定したらCapacitor使えるんですが、これ自体もまだbeta版機能なので紹介を割愛しています。興味ある方は[Help Wanted: Test Capacitor #3129](https://github.com/ionic-team/ionic-cli/issues/3129)をご覧ください。

前提として、Node, Git, Ionic, Xcode, Android Studioなどのインストールは済んでる方を対象にします。Ionicはインストールしてないぜ！って方は、`$npm i ionic -g` だけ先に叩いておいてください。

## 準備：依存性解決
まず、先にいくつかの依存性を解決しなければなりません。CocoaPodsというiOSアプリをコマンドラインから操作することができるライブラリなどを入れる必要があります。

### iOS開発
```bash
$ sudo gem install cocoapods
$ xcode-select --install
$ pod repo update
```

### Android開発
Java 8 JDKをインストールしてデフォルトに設定する必要があります。Java 9は現時点では動作しません。`/usr/libexec/java_home -v` でバージョンを確認することができます。
8系でなかった場合は `export JAVA_HOME='/usr/libexec/java_home -v 1.8'` でデフォルトを指定するようにしてください。

https://stackoverflow.com/questions/21964709/how-to-set-or-change-the-default-java-jdk-version-on-os-x/24657630#24657630

あたりが詳しいです。
また、Capacitorのターゲットが現行では

> CapacitorのAndroidバージョンのサポートは、iOSよりも複雑です。現在、Android 5.0（Lollipop）以上のAPIレベル21以上をターゲットにしています。

となっておりますので、古いAndroidを対象にしてサービスする場合はいろいろと厳しくなりそうです。

## 準備：プロジェクトをつくる
Ionicでプロジェクトをつくります。Cordovaを追加するか聞かれますので`N`を入力して、追加せずに進めてください。

```bash
$ ionic start myApp tabs
$ cd myApp
```

次に、CordovaのSplashscreen Pluginを削除します。これは、Capacitorと競合するためです。

```bash
$ npm uninstall --save cordova-plugin-splashscreen
```

これで準備は完了です。いつも通り `$ ionic serve` したらライブローディングつきで開発できるプロジェクトを作成することができました。

## Capacitorのインストール
Capacitorをインストールします。Capacitorはプロジェクト毎にバージョン管理することを前提としているため、globalにCLIを入れることはしません。以下のコマンドを実行してローカルにインストールしてください。

```bash
$ npm install --save @capacitor/cli @capacitor/core
```

初期設定として、アプリ名とアプリIDの設定を行います。ここでは、アプリ名は`example`、アプリIDは`com.example.app`とします。

```bash
$ npx cap init example com.example.app
```

npxコマンドは、ローカルでいろいろとやってくれるnpmコマンドを拡張した感じのものです。詳しくは https://qiita.com/vvakame/items/23b02e950ca307b9e674 あたりをご参照ください。

続いて、プラットフォームの追加を行い、IDEを開きます。わざわざIDEからどのフォルダを開くか探さなくていいので個人的に `npx cap open` コマンドは気に入っていますｗ

```bash
$ npx cap add ios
$ npx cap add android

$ npx cap open ios
$ npx cap open android
```

これでCapacitorのインストールが完了しました。

## プロジェクトをCapacitorにコピー
Capacitorというガワはできたので、そこにプロジェクトをビルドして同期させます。`ionic build` で、`www/`フォルダにビルドして、それを `npx cap copy` でCapacitor側にコピーしています。

```bash
$ ionic build
$ npx cap copy
```

これで、Caacitorを動かす用意は完了です。アプリIDEで実行ボタンをクリックして、動かしてみてください。

![スクリーンショット 2018-08-04 15.59.40.png](https://qiita-image-store.s3.amazonaws.com/0/100460/3d58b3ed-c98d-c35c-34e7-af634004ae1a.png)

うまくいってるとこのような画面が表示されます。ただ、基本、Emulatorは遅いので、実機でお試しすることをおすすめします。なお、LiveReloadは現在実装中なので、将来的にはサポートされます。

それでは、また。

## おまけ：Native UI Shellを試してみる
わかる方向けですが、以下をお試しいただけますとNative UI Shellを楽しむことができます。おー！こんなに簡単にNative呼び出しできるのか！！って楽しんでください。

```home.html
<ion-header>
  <ion-navbar>
    <ion-title>Home</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <h2>Welcome to Ionic!</h2>
  <p>
    This starter project comes with simple tabs-based layout for apps
    that are going to primarily use a Tabbed UI.
  </p>
  <p>
    Take a look at the <code>src/pages/</code> directory to add or change tabs,
    update any existing page or create new pages.
  </p>
  <button ion-button (click)="toast()">Toast</button>

  <button ion-button (click)="showAlert()">showAlert</button>
  <button ion-button (click)="showConfirm()">showConfirm</button>
  <button ion-button (click)="showPrompt()">showPrompt</button>
  <button ion-button (click)="showActions()">showActions</button>
</ion-content>
```

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

import { Plugins } from '@capacitor/core';
const { Toast } = Plugins;
const { Modals } = Plugins;

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

  constructor(public navCtrl: NavController) {

  }

  async toast() {
    await Toast.show({
      text: 'Toastを立ち上げました'
    });
  }

  async showAlert() {
    let alertRet = await Modals.alert({
      title: 'Stop',
      message: 'this is an error'
    });
  }

  async showConfirm() {
    let confirmRet = await Modals.confirm({
      title: 'Confirm',
      message: 'Are you sure you\'d like to press the red button?'
    });
    console.log('Confirm ret', confirmRet);
  }

  async showPrompt() {
    let promptRet = await Modals.prompt({
      title: 'Hello',
      message: 'What\'s your name?'
    });
    console.log('Prompt ret', promptRet);
  }

  async showActions() {
    let promptRet = await Modals.showActions({
      title: 'Photo Options',
      message: 'Select an option to perform',
      options: [
        {
          title: 'Upload'
        },
        {
          title: 'Share'
        },
        {
          title: 'Remove',
        }
      ]
    })
    console.log('You selected', promptRet);
  }
}

```