質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • Android

    6401questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Androidで、機内モードをキャンセルし、ネットワークが使用できるようになった事を検知したい

解決済

回答 3

投稿

  • 評価
  • クリップ 2
  • VIEW 1,738

usugita_san

score 218

Androidアプリで、機内モードから元に戻った時に、処理を再開する、というようなアプリを作ろうとしています。

BroadcastReceiverのサブクラスを生成し、onReceiveメソッドを使って接続状態の変化は取得できたのです。
こんな感じのメソッドです。

@Override
public void onReceive(Context context, Intent intent) {
    //Broadcast intentを受信
    ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    synchronized (isDisConnect) {
        NetworkInfo info = manager.getActiveNetworkInfo();
        if (info == null) {
            //接続していない。WIFIやLTEなど、何かしら接続がされていればNetworkInfoは必ず取得できるはず。NetworkInfoがnullであるという事は、全ての回線が切断された事を意味している
            isDisConnect = true;
            Log.i(TAG,"通信が完全に切断されました。");
        } else {
            Log.d(TAG,"回線は切断されてないです。でもどういう状態か不明");
            //接続している時。
            //一度完全にコネクションが切断された後に、接続が取得できたという事は、通信が回復したと判断できる。通信回復時の処理を実行する
            if(isDisConnect){
                //通信が回復した時の処理
                Log.i(TAG,"通信回復時の処理を実行します");
                //何か処理を行う
                isDisConnect = false;
            }
        }
    }
}

しかしこれだけでは不十分でした。
回線が復旧したとしても、すぐにネットがつながるわけではありません。
試しに、ネットに接続するような処理を書いてみても、接続ができずにエラーが帰ってきてしまいます。
どうもIPアドレスの取得とか、ネットワークの準備ができていないようなのです。

私の希望としては、ネットが使えるようになったという事を検知したいのですが、どうにかして実現できないでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

check解決した方法

+1

どうもonReceiveは、ネットワークの状態が変わるたびに呼ばれるらしく、IPアドレスを取得した後にも呼び出されているようです。
というわけで実現できました。
まず、こんな感じのメソッドを作ります。

    /** ネットワークがアクティブかを判断する */
    public static boolean isNetworkActive(Context context){
        String nowAddress = getActiveIpAddress(context);
        Log.d(TAG,"現在のIPアドレス" + nowAddress);
        if("0.0.0.0".equals(nowAddress)){
            return false;
        }else if("127.0.0.1".equals(nowAddress)){
            return false;
        }else
            return true;
    }
    /**
     * 3GとWifiのうちアクティブなIPアドレスを取得する
     *
     * @param context
     * @return String IPAddress
     */
    public static String getActiveIpAddress(Context context) {
        // 接続方法取得
        String status = getActiveNetwork(context);
        if ("3G".equals(status)) {
            return getIPAddress();

        } else if ("WIFI".equals(status)) {
            return getWifiIPAddress(context);
        }

        return "127.0.0.1";
    }

    /**
     * その瞬間アクティブなネットワークを取得する
     * @param context
     * @return 3G / WIFI
     */
    public static String getActiveNetwork(Context context) {

        // 3Gの状態を取得する
        ConnectivityManager cm = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        // ネットワーク情報を全て取得
        NetworkInfo[] networkInfos = cm.getAllNetworkInfo();
        for (NetworkInfo ni : networkInfos) {
            if (ni.getType() == ConnectivityManager.TYPE_MOBILE
                    && ni.isConnected()) {

                return "3G";
            } else if (ni.getType() == ConnectivityManager.TYPE_WIFI
                    && ni.isConnected()) {

                return "WIFI";
            }
        }
        return "";
    }
    /**
     * 3G回線のIPアドレスを取得する
     *
     * @return
     */
    private static String getIPAddress() {
        try {
            Enumeration<NetworkInterface> interfaces = NetworkInterface
                    .getNetworkInterfaces();

            while (interfaces.hasMoreElements()) {
                NetworkInterface network = interfaces.nextElement();
                Enumeration<InetAddress> addresses = network.getInetAddresses();

                while (addresses.hasMoreElements()) {
                    String address = addresses.nextElement().getHostAddress();
                    if (address.matches(ipShape)) {
                        return address;
                    }
                    // 127.0.0.1と0.0.0.0以外のアドレスが見つかったらそれを返す
                    // if (!"127.0.0.1".equals(address)
                    // && !"0.0.0.0".equals(address)) {
                    // return address;
                    // }
                }
            }
        } catch (IOException e) {
            return "127.0.0.1";
        } catch (Exception e) {
            return "127.0.0.1";
        }

        return "127.0.0.1";
    }

    /**
     * WifiのIPアドレスを取得する
     *
     * @param context
     * @return
     */
    private static String getWifiIPAddress(Context context) {
        WifiManager wifiManager = (WifiManager) context
                .getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        int ipAddress = wifiInfo.getIpAddress();
        String strIPAddess = ((ipAddress >> 0) & 0xFF) + "."
                + ((ipAddress >> 8) & 0xFF) + "." + ((ipAddress >> 16) & 0xFF)
                + "." + ((ipAddress >> 24) & 0xFF);
        if (!"".equals(strIPAddess)) {
            return strIPAddess;
        }
        return "127.0.0.1";
    }

あとは、onReceiveからIPアドレスの取得をチェックできるので、こんな感じで実装すれば、ネットワークが使えるようになったかを確認できます。

@Override
public void onReceive(Context context, Intent intent) {
    //Broadcast intentを受信
    ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    synchronized (isDisConnect) {
        NetworkInfo info = manager.getActiveNetworkInfo();
        if (info == null) {
            //接続していない。WIFIやLTEなど、何かしら接続がされていればNetworkInfoは必ず取得できるはず。NetworkInfoがnullであるという事は、全ての回線が切断された事を意味している
            isDisConnect = true;
            Log.i(TAG,"通信が完全に切断されました。");
        } else {
            Log.d(TAG,"回線は切断されてないです。でもどういう状態か不明");
            //接続している時。
            //一度完全にコネクションが切断された後に、接続が取得できたという事は、通信が回復したと判断できる。通信回復時の処理を実行する
            if(isDisConnect){
                    //通信が回復した時の処理
                    if(isNetworkActive(context)) {
                        Log.i(TAG, "通信回復時の処理を実行します");
                        isDisConnect = false;
                        mNetworkStateListener.onConnect();
                    }
            }
        }
    }
}

無事解決しました。
ありがとうございました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/02/26 11:52

    この方法については、このソースコードを参考にさせて頂きました。
    https://github.com/cyber-z/pinco/blob/master/src/jp/tokyo/shibuya/pinco/util/DeviceUtil.java
    この場を借りてお礼を申し上げます。

    キャンセル

+1

おっしゃる通り機内モードになってからすぐはネットワークの接続にできないので
ネットワーク接続に失敗したら時間をおいてリトライするようにしてはいかがでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

NetworkInfoを使って、通信接続が可能状態か知る

これを、回線復旧後つながるかタイムアウトするまでループすると言うのはいかがでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/02/25 12:20

    やってみたんですが、ループの管理が大変なので、もうちょい違う方法で実現しました。後ほど投稿します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Android

    6401questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。