Android Emulator 上で React Native のアプリを動かしてホストに HTTPS でアクセスする

Ruby on Rails の勉強をしていて、やっぱり動かせるクライアントが欲しいなと思って React Native でアプリを作り始めた。Networking · React Native を読んでただ fetch したらデータが取得できたけど、

On Android, as of API Level 28, clear text traffic is also blocked by default.

と書いてあったので HTTPS でアクセスできた方がいいのかなと思ってアクセスできるようにした。

やり方

  • android/app/src/main/AndroidManifest.xmlandroid:networkSecurityConfig="@xml/network_security_config" を追記する
  • android/app/src/main/res/xml/network_security_config.xml に下記の内容を設定する
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="false">localhost</domain>
        <domain includeSubdomains="false">10.0.2.2</domain>
        <domain includeSubdomains="false">10.0.3.2</domain>
    </domain-config>
    <debug-overrides>
        <trust-anchors>
            <certificates src="@raw/localhost"/>
        </trust-anchors>
    </debug-overrides>
</network-security-config>
  • サーバーで使用している証明書を android/app/src/main/res/raw/localhost にコピーする
  • Android Emulator 上の React Native のアプリから https://10.0.2.2/ にアクセスする

動くようになるまで

最終的にはこの設定だけで動くようになったが、こうなるまでにいろいろと調べた。最初はホストにアクセスする方法がわからなかったのでそこから。調べたら Android Emulator 上からは 10.0.2.2 でホストにアクセスできるとのことだった1。さっそくアクセスしてみたら React Native で動かしてるアプリからアクセスしようとしてもエラーが出るが、Android Emulator 上の Chrome からはアクセスできるという状態になった。証明書をインストールする必要があるのかなと思って adb でファイルを渡してインストールしてみたが、変わらずアプリからはアクセスできないままだった23

エラーでググってみる

TypeError: Network request failed というエラーが出ていたのでそれでいろいろとググっていたら証明書に関するエラーかも知れないという話があったので見てみた4Security with HTTPS and SSL | Android DevelopersNetwork security configuration | Android Developers を読んだら設定で証明書を指定することで動くようになりそうだということがわかった5android/app/src/main/AndroidManifest.xmlapplicationandroid:networkSecurityConfig="@xml/network_security_config" を追記して、android/app/src/main/res/xml/network_security_config.xml ファイルを作成し、例を参考に下記のように設定して、証明書をコピーした。

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config>
        <trust-anchors>
            <certificates src="@raw/localhost"/>
            <certificates src="system"/>
        </trust-anchors>
    </base-config>
</network-security-config>

設定したら違うエラーが出た

今度は Metro に接続できないというエラーが発生した。調べたら、おそらく、何も設定しなかったら React Native の設定が使われて HTTP でアクセスできるようになっていたものが、自分の設定ファイルを作成したことで設定が上書きされるようになったのだと思われる6。なので、Metro は HTTP でアクセスできるようにするために設定を追加し、ついでに debug-overrides という設定を見つけたのでそれを使用して、最初に提示したような設定の内容となった7

設定は合ってるはずなのに動かない

設定は合ってるはずなのに動かなかった。おかしいと思ってログをちゃんと見てみようと思って npx react-native log-android を実行してみた8910。そうしたら表示されるエラーが明らかにおかしくて、どこか間違ってるのかなと思って fetch しているコードを見てみたら、なにかの操作ミスで URL が指定されるべき場所に全然関係ない文字列が指定されていた。そこを https://10.0.2.2/ から始まる URL にしたらちゃんと動いた。

React Native よさそう

React Native はまだ触り始めたばかりで全然わかっていないが、よさそうな感じがする。React のような感じのコードがアプリになるのすごい。とりあえず手持ちの Android と iPad にアプリをインストールしてみたが、実機でアプリが動くのは楽しい。これから開発を進めていく予定。