Androidでモバイルネットワークが使えるかどうかを判定する方法の実装例.

Androidで電波圏外を判定する

拙作のAndroidアプリ 山旅ロガー では,GPSで取得した移動中の位置を記録するのですが,それと同時に携帯電波の圏外かどうかを記録する機能があります.
# 余談ですが,記録した電波情報を共有できるサイトを公開しています.→山の電波地図

この機能で行っている実装について書きます.

ソース

AndroidManifest.xmlに追加する権限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
※なお,6.0以降では今回の用途にREAD_PHONE_STATEはいらないらしく,maxSdkVersionを指定して
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="22" />
という書き方もありうるようです.(私は使ってませんが)

SignalWatcher.java

package com.kamoland.signaltest;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public class SignalWatcher {
    private boolean stateConnected;

    public boolean isSignalOn(Context context) {
        ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo network = null;

        for (NetworkInfo ni: conMan.getAllNetworkInfo()) {
            if (ni.getType() == ConnectivityManager.TYPE_MOBILE) {
                network = ni;
                break;
            }
        }

        if (network == null) {
            return false;
        }

        // Android 5.0未満では,圏外でisAvailable()がfalseになるので使える
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            return network.isAvailable();

        } else {
            if (!network.isAvailable()) {
                return false;
            }
            // Xperia Z5 Compact(Android 5.1.1)では,圏外でも
            // TelephonyManager.DATA_DISCONNECTEDが発生しないのでこれが必要
            if (!network.isConnected()) {
                return false;
            }
            if (!stateConnected) {
                return false;
            }
            return true;
        }
    }

    public void start(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // Zenfone2 Laser(Android 5.0)では,
            // 圏外でもnetwork.isConnected()がfalseにならないので必要
            TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
            tm.listen(stateListener, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
        }
    }

    private PhoneStateListener stateListener = new PhoneStateListener() {
        @Override
        public void onDataConnectionStateChanged(int state) {
            switch (state) {
                case TelephonyManager.DATA_CONNECTED:
                    stateConnected = true;
                    break;
                case TelephonyManager.DATA_DISCONNECTED:
                    stateConnected = false;
                    break;
            }
            super.onDataConnectionStateChanged(state);
        }
    };

    public void stop(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
            tm.listen(stateListener, PhoneStateListener.LISTEN_NONE);
        }
    }
}

使い方

SignalWatcher signalWatcher = new SignalWatcher();
signalWatcher.start(context);
 ・・・
// 必要なときに呼びだす
boolean signalOn = signalWatcher.isSignalOn(context);

 ・・・
signalWatcher.stop(context);

全ての機種に対応している保証はありませんので,あしからず.

結局,3種類の方法を組み合わせているわけで,もっと簡単な方法があるかも知れません...

★注意
ASUSの機種では,画面オフ状態では上記の方法でも最新の状態を取得できないことが判明しています. 画面をオンにすれば,最新の状態を取得できます.
ASUSの機種では画面オンの状態でしか使えないという状況ですので,ご注意ください.

他にも同様の機種があるかも知れません.

参考


© 2024 KMIソフトウェア