suが使える環境が前提であるが、
setprop net.change `getprop net.change`
これだけでよい。ただし、HttpURLConnectionを使う場合、少なくとも
static {
System.setProperty("networkaddress.cache.ttl", "0");
System.setProperty("networkaddress.cache.negative.ttl", "0");
}
をやっている前提であること。
DNSのキャッシュはlibcの低レベルレイヤとDalvik上のINetAddressのレイヤの両方で行っており、INetAddress用の設定をSystem.setPropertyで行ってもlibcでキャッシュしているため、setprop net.changeを行う必要がある。(libcでnet.changeの変更時間とキャッシュを管理している)
プロセス単位でキャッシュされているようなので、そのプロセスが一旦死ねばキャッシュも当然ながら破棄される。
##調査の経緯
通信が不安定なモバイルルーターに接続されているAndroid端末があり、通信が復帰してもアプリから通信ができない問題があった。原因としては、
- Androidから外にアクセスする際に、DNSの問い合わせを行う
- モバイルルーターが適当なIPアドレスを返す
- AndroidがそのURLに対して正しくないIPアドレスをキャッシュする
- そのIPに対してAndroidからHTTPリクエストを送る
- モバイルルータが「インターネッツに接続できないよ」的なページを200 OKで返す
- モバイルルーターがそのうち接続できるようになる
- AndroidからはずっとWIFIで接続できている状態であり、ネットワークの接続状態は変化なし
- Androidは正しくないIPアドレスを使用してインターネットに接続してしまう
- DNSレコードのTTLが何故か無視されている
という状態であった。setprop net.changeを実行して、やっと正しいIPアドレスで接続できるようになった。