-
-
Save ConAlgorithm/421ccdebf99b77d29ed78c2111c3a4c3 to your computer and use it in GitHub Desktop.
SignalWatcher extends code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.net.ConnectivityManager; | |
import android.net.NetworkInfo; | |
import android.os.Build; | |
import android.telephony.PhoneStateListener; | |
import android.telephony.TelephonyManager; | |
import permissions.dispatcher.PermissionUtils; | |
/* | |
base is | |
http://kamoland.com/wiki/wiki.cgi?Android%A4%C7%C5%C5%C7%C8%B7%F7%B3%B0%A4%F2%C8%BD%C4%EA%A4%B9%A4%EB | |
*/ | |
public class SignalWatcher { | |
private static SignalWatcher instance; | |
public static SignalWatcher getInstance(Context context) { | |
if(instance == null){ | |
instance = new SignalWatcher(context); | |
} | |
return instance; | |
} | |
private Context mContext; | |
private ConnectivityManager conMan | |
private boolean stateConnected; | |
private TelephonyManager telManager; | |
public SignalWatcher(Context context){ | |
mContext = context; | |
conMan = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); | |
mTelManager = (TelephonyManager)_context.getSystemService(Context.TELEPHONY_SERVICE); | |
} | |
public boolean isSignalOn() { | |
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(); | |
} | |
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; | |
} | |
private static final String[] PERMISSION_PHONE_STATE = new String[] {"android.permission.READ_PHONE_STATE"}; | |
private static final String[] PERMISSION_BINDLOCATIONACTION = new String[] {"android.permission.ACCESS_FINE_LOCATION"}; | |
public void start() { | |
int events =PhoneStateListener.LISTEN_SIGNAL_STRENGTHS| | |
PhoneStateListener.LISTEN_SERVICE_STATE; | |
if(PermissionUtils.hasSelfPermissions(mContext, PERMISSION_PHONE_STATE) || | |
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ | |
events = PhoneStateListener.LISTEN_DATA_CONNECTION_STATE| //TODO: LOLLIPOP以降であれば READ_PHONE_STATE いらない | |
PhoneStateListener.LISTEN_SIGNAL_STRENGTHS| | |
PhoneStateListener.LISTEN_SERVICE_STATE; | |
} | |
if (PermissionUtils.hasSelfPermissions(mContext, PERMISSION_BINDLOCATIONACTION)) { | |
events |= PhoneStateListener.LISTEN_CELL_LOCATION; //ACCESS_COARSE_LOCATION がないとクラッシュする | |
} | |
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){ | |
// LISTEN_CELL_INFOは4.2以降でのみ有効なのでそれ以下の場合は取得しない。 | |
events |= PhoneStateListener.LISTEN_CELL_INFO; | |
} | |
try { | |
mTelManager.listen(_listener,events); | |
}catch(Exception e) { | |
Log.e(TAG, "SecurityException", e); | |
// 一部端末(GALAXY)でREAD_PHONE_STATEのパーミッションが要求されるので | |
// その場合はLISTEN_CELL_INFOを取得しない。 | |
} | |
} | |
//========================================= | |
// PhoneStateListener の設定 | |
private SignalStrength _signalStrength; | |
private ServiceState _serviceState; | |
private CellLocation _cellLocation; | |
private PhoneStateListener _listener = new PhoneStateListener() { | |
// LISTEN_DATA_CONNECTION_STATE | |
@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); | |
} | |
// LISTEN_SERVICE_STATE | |
@Override | |
public void onServiceStateChanged(ServiceState serviceState) { | |
_serviceState = serviceState; | |
if(getPictBar() <= 0){ | |
stateConnected = false; | |
} | |
else{ | |
stateConnected = true; | |
} | |
super.onServiceStateChanged(serviceState); | |
} | |
//LISTEN_SIGNAL_STRENGTHS | |
@Override | |
public void onSignalStrengthsChanged(SignalStrength signalStrength) { | |
//ここで情報取得 | |
_signalStrength = signalStrength; | |
if(getPictBar() <= 0){ | |
stateConnected = false; | |
} | |
else{ | |
stateConnected = true; | |
} | |
super.onSignalStrengthsChanged(signalStrength); | |
} | |
//LISTEN_CELL_LOCATION | |
@Override | |
public void onCellLocationChanged(CellLocation location) { | |
_cellLocation = location; | |
super.onCellLocationChanged(location); | |
} | |
}; | |
public void stop() { | |
try { | |
mTelManager.listen(_listener, PhoneStateListener.LISTEN_NONE); | |
} catch (Exception e) { | |
} | |
} | |
//========================================= | |
// アンテナ表示ピクトバーの処理の記載 | |
// see http://relog.xii.jp/mt5r/2011/04/androidtelephonymanager.html | |
public static final int INITIAL_VALUE = Integer.MAX_VALUE; | |
public static final int INVAILD_VALUE = -1; | |
public static final int PICTBAR_UNKNOW = 99; | |
public int getPictBar() { | |
if(_signalStrength == null) { | |
return INITIAL_VALUE; | |
} | |
if(!isNetworkConnected(_context)) { | |
return PICTBAR_UNKNOW; | |
} | |
int level = getPictBarBySignalStrengthGetLevel(); | |
if (level != INITIAL_VALUE) { | |
return level; | |
} | |
if (!isCdma()) { | |
int asu = _signalStrength.getGsmSignalStrength(); | |
if (asu == 99) return 99; | |
if (asu <= 2) return 0; | |
if (asu >= 12) return 4; | |
if (asu >= 8) return 3; | |
if (asu >= 5) return 2; | |
return 1; | |
} | |
if (isEvdo()) { | |
return getEvdoLevel(); | |
} | |
return getCdmaLevel(); | |
} | |
private int getEvdoLevel() { | |
int evdoDbm = _signalStrength.getEvdoDbm(); | |
int evdoSnr = _signalStrength.getEvdoSnr(); | |
int levelEvdoDbm = 0; | |
int levelEvdoSnr = 0; | |
if (evdoDbm >= -65) levelEvdoDbm = 4; | |
else if (evdoDbm >= -75) levelEvdoDbm = 3; | |
else if (evdoDbm >= -90) levelEvdoDbm = 2; | |
else if (evdoDbm >= -105) levelEvdoDbm = 1; | |
else levelEvdoDbm = 0; | |
if (evdoSnr >= 7) levelEvdoSnr = 4; | |
else if (evdoSnr >= 5) levelEvdoSnr = 3; | |
else if (evdoSnr >= 3) levelEvdoSnr = 2; | |
else if (evdoSnr >= 1) levelEvdoSnr = 1; | |
else levelEvdoSnr = 0; | |
return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr; | |
} | |
private int getCdmaLevel() { | |
final int cdmaDbm = _signalStrength.getCdmaDbm(); | |
final int cdmaEcio = _signalStrength.getCdmaEcio(); | |
int levelDbm = 0; | |
int levelEcio = 0; | |
if (cdmaDbm >= -75) levelDbm = 4; | |
else if (cdmaDbm >= -85) levelDbm = 3; | |
else if (cdmaDbm >= -95) levelDbm = 2; | |
else if (cdmaDbm >= -100) levelDbm = 1; | |
else levelDbm = 0; | |
if (cdmaEcio >= -90) levelEcio = 4; | |
else if (cdmaEcio >= -110) levelEcio = 3; | |
else if (cdmaEcio >= -130) levelEcio = 2; | |
else if (cdmaEcio >= -150) levelEcio = 1; | |
else levelEcio = 0; | |
return (levelDbm < levelEcio) ? levelDbm : levelEcio; | |
} | |
public boolean isNetworkConnected(Context context) { | |
final NetworkInfo networkInfo = | |
((ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo(); | |
return (networkInfo != null) && networkInfo.isConnected(); | |
} | |
public boolean isGsm() { | |
return (_signalStrength != null) && _signalStrength.isGsm(); | |
} | |
public boolean isCdma() { | |
return (_signalStrength != null) && !_signalStrength.isGsm(); | |
} | |
public static final int RADIO_TECHNOLOGY_EVDO_0 = 7; | |
public static final int RADIO_TECHNOLOGY_EVDO_A = 8; | |
public static final int RADIO_TECHNOLOGY_EVDO_B = 12; | |
private boolean isEvdo() { | |
return ( (_serviceState != null) | |
&& ((getRadioTechnology() | |
== RADIO_TECHNOLOGY_EVDO_0) | |
|| (getRadioTechnology() | |
== RADIO_TECHNOLOGY_EVDO_A) | |
|| (getRadioTechnology() | |
== RADIO_TECHNOLOGY_EVDO_B))); | |
} | |
public int getRadioTechnology() { | |
int radioTechnology = 0; | |
Method[] wmMethods = _serviceState.getClass().getDeclaredMethods(); | |
for (Method method : wmMethods) { | |
if (method.getName().equals("getRadioTechnology")) { | |
try { | |
radioTechnology = (Integer) method.invoke(_serviceState); | |
} catch (Exception e) { | |
Log.e(TAG, "Failed to invoke getRadioTechnology.", e); | |
} | |
break; | |
} | |
} | |
return radioTechnology; | |
} | |
public int getPictBarBySignalStrengthGetLevel() { | |
int level = INITIAL_VALUE; | |
Method[] wmMethods = _signalStrength.getClass().getDeclaredMethods(); | |
for (Method method : wmMethods) { | |
if ("getLevel".equals(method.getName())) { | |
try { | |
level = (Integer) method.invoke(_signalStrength); | |
} catch (Exception e) { | |
Log.e(TAG, "Failed to invoke getLevel.", e); | |
} | |
break; | |
} | |
} | |
return level; | |
} | |
//============================================================== | |
// _cellLocation から得られる情報(基地局のID/座標) | |
// TODO:とりあえず基地局につながればOKにしてしまってるけど、そこから通信できるかは後で要検証 | |
public int getBaseStationID() { | |
if (_cellLocation == null || (_cellLocation instanceof GsmCellLocation)) { | |
return INITIAL_VALUE; | |
} | |
CdmaCellLocation cdma = (CdmaCellLocation) _cellLocation; | |
return cdma.getBaseStationId(); | |
} | |
public int getBaseStationLat() { | |
if (_cellLocation == null || (_cellLocation instanceof GsmCellLocation)) { | |
return INITIAL_VALUE; | |
} | |
CdmaCellLocation cdma = (CdmaCellLocation) _cellLocation; | |
return cdma.getBaseStationLatitude(); | |
} | |
public int getBaseStationLon() { | |
if (_cellLocation == null || (_cellLocation instanceof GsmCellLocation)) { | |
return INITIAL_VALUE; | |
} | |
CdmaCellLocation cdma = (CdmaCellLocation) _cellLocation; | |
return cdma.getBaseStationLongitude(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment