Skip to content

Instantly share code, notes, and snippets.

@kimukou
Created August 28, 2017 14:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kimukou/c88be73088b25f1b766a5b6186a25ffc to your computer and use it in GitHub Desktop.
Save kimukou/c88be73088b25f1b766a5b6186a25ffc to your computer and use it in GitHub Desktop.
SignalWatcher extends code
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