Android N(7)からのhttp(s)接続のこと

なんか変わったぽいので、情報をつまみ食いしてみる。

ネットワーク セキュリティ構成  |  Android Developers


こちらとかも。

developer.android.com




なんでも、Android7から、ネットワークセキュリティ構成機能(network-security-config)てのが追加されたぽい。
証明書まわりとかで、セキュリティの向上を図っている感じかな。
いろいろあるだろうが、ここでは
 ・HTTPでの接続は原則、怒られるようになり、回避するには仕込みが必要。
てところを確認してみたい。

(前略。適当にonCreateなり何なり好きなとこに)
(UIスレッドで通信処理すると怒られるので、適当やっつけThreadで書いている。
ほんとはしかるべき非同期処理の記述を選択すべきだろう。)

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection con = null;
                URL url = null;

                //これは特に問題なく接続。(ステータスコード200返却)
                String urlSt = "https://www.yahoo.co.jp";

                //こっち(http)は、network-security-configの仕込み必要となる。
                //String urlSt = "http://www.yahoo.co.jp";
                //※なお接続成功するとステータスコード301返却される。
                // 301なのはyahoo側でhttp→httpsにリダイレクトしてるからだろうから、
                // 200が返らないのは当然で、また当記事の本質とは関係ないので気にしない。


                try {
                    // URLの作成
                    url = new URL(urlSt);
                    // 接続用HttpURLConnectionオブジェクト作成
                    con = (HttpURLConnection)url.openConnection();
                    // リクエストメソッドの設定
                    con.setRequestMethod("GET");
                    // リダイレクトを自動で許可しない設定
                    con.setInstanceFollowRedirects(false);
                    // URL接続からデータを読み取る場合はtrue
                    con.setDoInput(true);
                    // URL接続にデータを書き込む場合はtrue
                    con.setDoOutput(true);

                    // 接続
                    con.connect();

                    // 本文の取得
                    InputStream in = con.getInputStream();
                    byte bodyByte[] = new byte[1024];
                    in.read(bodyByte);
                    in.close();

                    System.out.println(con.getResponseCode());
                    System.out.println(bodyByte);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        });
        thread.start();

インターネット接続なので。マニフェストにはいつもの。

<uses-permission android:name="android.permission.INTERNET"/>

ヤフーに接続(GET)してるだけ。
URLがhttps~ならここまでで十分で、今まで通りの感覚。

さて、httpの場合、network-security-configという機構の仕込みが必要になった模様。
マニフェストには

    <application
        (省略)
        android:networkSecurityConfig="@xml/network_security_config"
        >

と書いてやり、そのxmlを用意(~res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <!-- ここに書いたドメインには、httpで接続しても怒られなくなる、みたいな感じぽい。 -->
        <domain includeSubdomains="true">yahoo.co.jp</domain>
    </domain-config>
</network-security-config>

http接続だと、上記をちゃんとしてないと、
NetworkSecurityConfig: No Network Security Config specified, using platform default
とか
java.io.IOException: Cleartext HTTP traffic to www.yahoo.co.jp not permitted
とか
怒られてしまうようだ。


まあ今日びはhttpsでつなぎなさいよ、てことか。みんな常時SSLとか言ってるしなあ。
証明書の管理とかめんどくさいイメージ(個人の感想です)。
まあ開発環境とかでhttp使うなら役立つかも、てとこかなあ。

脱線するけれど、開発環境といえば、https~で立てるときにオレオレ証明書だとナニな感じなので
無理やり信用しちゃう(エラーを無視する)、みたいなことをやった記憶。
こちらとか参考になるかも。
ishiitakeru-programing-memo.blogspot.com
うっかりこういう設定のままリリースしないように気をつけなきゃ、ですね。