package com.telephony; import android.annotation.TargetApi; import android.app.Activity; import android.app.Application; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.telephony.CellIdentityCdma; import android.telephony.CellIdentityGsm; import android.telephony.CellIdentityLte; import android.telephony.CellIdentityWcdma; import android.telephony.CellInfo; import android.telephony.CellInfoCdma; import android.telephony.CellInfoGsm; import android.telephony.CellInfoLte; import android.telephony.CellInfoWcdma; import android.telephony.CellLocation; import android.telephony.CellSignalStrengthCdma; import android.telephony.CellSignalStrengthGsm; import android.telephony.CellSignalStrengthLte; import android.telephony.CellSignalStrengthWcdma; import android.telephony.PhoneStateListener; import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.core.DeviceEventManagerModule; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by Rafael on 03/07/17. */ public class TelephonyModule extends ReactContextBaseJavaModule implements TelephonyListener.PhoneCallStateUpdate, LifecycleEventListener { private ReactApplicationContext mReactContext; private TelephonyManager telephonyManager; private TelephonyListener telephonyPhoneStateListener; private String PHONE_STATE_LISTENER = "Telephony-PhoneStateListener"; private String LISTEN_CALL_FORWARDING_INDICATOR = "LISTEN_CALL_FORWARDING_INDICATOR"; private String LISTEN_CALL_STATE = "LISTEN_CALL_STATE"; private String LISTEN_CELL_INFO = "LISTEN_CELL_INFO"; private String LISTEN_CELL_LOCATION = "LISTEN_CELL_LOCATION"; private String LISTEN_DATA_ACTIVITY = "LISTEN_DATA_ACTIVITY"; private String LISTEN_DATA_CONNECTION_STATE = "LISTEN_DATA_CONNECTION_STATE"; private String LISTEN_MESSAGE_WAITING_INDICATOR = "LISTEN_MESSAGE_WAITING_INDICATOR"; private String LISTEN_SERVICE_STATE = "LISTEN_SERVICE_STATE"; private String LISTEN_SIGNAL_STRENGTHS = "LISTEN_SIGNAL_STRENGTHS"; private int DATA_ACTIVITY_NONE = 0; private int DATA_ACTIVITY_IN = 1; private int DATA_ACTIVITY_OUT = 2; private int DATA_ACTIVITY_INOUT = 3; private int DATA_ACTIVITY_DORMANT = 4; private int DATA_DISCONNECTED = 0; private int DATA_CONNECTING = 1; private int DATA_CONNECTED = 2; private int DATA_SUSPENDED = 3; private int CALL_STATE_IDLE = 0; private int CALL_STATE_RINGING = 1; private int CALL_STATE_OFFHOOK = 2; public TelephonyModule(ReactApplicationContext reactContext) { super(reactContext); mReactContext = reactContext; mReactContext.addLifecycleEventListener(this); telephonyManager = (TelephonyManager) mReactContext.getSystemService( Context.TELEPHONY_SERVICE); } private void sendEvent(String eventName, Object params) { mReactContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit(eventName, params); } @ReactMethod public void startListener(int events) { telephonyPhoneStateListener = new TelephonyListener(this); telephonyManager.listen(telephonyPhoneStateListener, events); } @ReactMethod public void stopListener() { if (telephonyManager == null || telephonyPhoneStateListener == null) { return; } telephonyManager.listen(telephonyPhoneStateListener, PhoneStateListener.LISTEN_NONE); telephonyManager = null; telephonyPhoneStateListener = null; } @ReactMethod public void isNetworkRoaming(Callback successCallback) { successCallback.invoke(telephonyManager.isNetworkRoaming()); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) @ReactMethod public void getCellInfo(Callback successCallback) { WritableArray mapArray = Arguments.createArray(); List<CellInfo> cellInfo = telephonyManager.getAllCellInfo(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || cellInfo == null) { successCallback.invoke(mapArray); return; } int i = 0; for (CellInfo info : cellInfo) { WritableMap mapCellIdentity = Arguments.createMap(); WritableMap mapCellSignalStrength = Arguments.createMap(); WritableMap map = Arguments.createMap(); map.putInt("key", i); if (info instanceof CellInfoGsm) { CellIdentityGsm cellIdentity = ((CellInfoGsm) info).getCellIdentity(); map.putString("connectionType", "GSM"); mapCellIdentity.putInt("cid", cellIdentity.getCid()); mapCellIdentity.putInt("lac", cellIdentity.getLac()); mapCellIdentity.putInt("mcc", cellIdentity.getMcc()); mapCellIdentity.putInt("mnc", cellIdentity.getMnc()); mapCellIdentity.putInt("psc", cellIdentity.getPsc()); CellSignalStrengthGsm cellSignalStrengthGsm = ((CellInfoGsm) info).getCellSignalStrength(); mapCellSignalStrength.putInt("asuLevel", cellSignalStrengthGsm.getAsuLevel()); mapCellSignalStrength.putInt("dBm", cellSignalStrengthGsm.getDbm()); mapCellSignalStrength.putInt("level", cellSignalStrengthGsm.getLevel()); } else if (info instanceof CellInfoWcdma && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { CellIdentityWcdma cellIdentity = ((CellInfoWcdma) info).getCellIdentity(); map.putString("connectionType", "WCDMA"); mapCellIdentity.putInt("cid", cellIdentity.getCid()); mapCellIdentity.putInt("lac", cellIdentity.getLac()); mapCellIdentity.putInt("mcc", cellIdentity.getMcc()); mapCellIdentity.putInt("mnc", cellIdentity.getMnc()); mapCellIdentity.putInt("psc", cellIdentity.getPsc()); CellSignalStrengthWcdma cellSignalStrengthWcdma = ((CellInfoWcdma) info).getCellSignalStrength(); mapCellSignalStrength.putInt("asuLevel", cellSignalStrengthWcdma.getAsuLevel()); mapCellSignalStrength.putInt("dBm", cellSignalStrengthWcdma.getDbm()); mapCellSignalStrength.putInt("level", cellSignalStrengthWcdma.getLevel()); } else if (info instanceof CellInfoLte) { if(info.isRegistered()) { mapCellIdentity.putBoolean("servingCellFlag", info.isRegistered()); } else { mapCellIdentity.putBoolean("servingCellFlag", info.isRegistered()); } CellIdentityLte cellIdentity = ((CellInfoLte) info).getCellIdentity(); map.putString("connectionType", "LTE"); mapCellIdentity.putInt("cid", cellIdentity.getCi()); mapCellIdentity.putInt("tac", cellIdentity.getTac()); mapCellIdentity.putInt("mcc", cellIdentity.getMcc()); mapCellIdentity.putInt("mnc", cellIdentity.getMnc()); mapCellIdentity.putInt("pci", cellIdentity.getPci()); getEarfcn(mapCellIdentity, cellIdentity); String cellIdHex = decToHex(cellIdentity.getCi()); boolean cellIdHexIsEmpty = cellIdHex == null || cellIdHex.isEmpty() || cellIdHex.length() < 2; String eNodeBHex = cellIdHexIsEmpty ? "0" : cellIdHex.substring(0, cellIdHex.length() - 2); mapCellIdentity.putInt("eNodeB", hexToDec(eNodeBHex)); String localCellIdHex = cellIdHexIsEmpty ? "0" : cellIdHex.substring(cellIdHex.length() - 2, cellIdHex.length()); mapCellIdentity.putInt("localCellId", hexToDec(localCellIdHex)); CellSignalStrengthLte cellSignalStrengthLte = ((CellInfoLte) info).getCellSignalStrength(); mapCellSignalStrength.putInt("asuLevel", cellSignalStrengthLte.getAsuLevel()); mapCellSignalStrength.putInt("dBm", cellSignalStrengthLte.getDbm()); mapCellSignalStrength.putInt("level", cellSignalStrengthLte.getLevel()); mapCellSignalStrength.putInt("timingAdvance", cellSignalStrengthLte.getTimingAdvance()); } else if (info instanceof CellInfoCdma) { CellIdentityCdma cellIdentity = ((CellInfoCdma) info).getCellIdentity(); map.putString("connectionType", "CDMA"); mapCellIdentity.putInt("basestationId", cellIdentity.getBasestationId()); mapCellIdentity.putInt("latitude", cellIdentity.getLatitude()); mapCellIdentity.putInt("longitude", cellIdentity.getLongitude()); mapCellIdentity.putInt("networkId", cellIdentity.getNetworkId()); mapCellIdentity.putInt("systemId", cellIdentity.getSystemId()); CellSignalStrengthCdma cellSignalStrengthCdma = ((CellInfoCdma) info).getCellSignalStrength(); mapCellSignalStrength.putInt("asuLevel", cellSignalStrengthCdma.getAsuLevel()); mapCellSignalStrength.putInt("cmdaDbm", cellSignalStrengthCdma.getCdmaDbm()); mapCellSignalStrength.putInt("cmdaEcio", cellSignalStrengthCdma.getCdmaEcio()); mapCellSignalStrength.putInt("cmdaLevl", cellSignalStrengthCdma.getCdmaLevel()); mapCellSignalStrength.putInt("dBm", cellSignalStrengthCdma.getDbm()); mapCellSignalStrength.putInt("evdoDbm", cellSignalStrengthCdma.getEvdoDbm()); mapCellSignalStrength.putInt("evdoEcio", cellSignalStrengthCdma.getEvdoEcio()); mapCellSignalStrength.putInt("evdoLevel", cellSignalStrengthCdma.getEvdoLevel()); mapCellSignalStrength.putInt("evdoSnr", cellSignalStrengthCdma.getEvdoSnr()); mapCellSignalStrength.putInt("level", cellSignalStrengthCdma.getLevel()); } map.putMap("cellIdentity", mapCellIdentity); map.putMap("cellSignalStrength", mapCellSignalStrength); mapArray.pushMap(map); i++; } successCallback.invoke(mapArray); } @TargetApi(24) public void getEarfcn(WritableMap mapCellIdentity, CellIdentityLte cellIdentity) { if (android.os.Build.VERSION.SDK_INT >= 24){ // Do something for nougat and above versions mapCellIdentity.putInt("earfcn", cellIdentity.getEarfcn()); } else{ // do something for phones running an SDK before lollipop mapCellIdentity.putInt("earfcn", 0); } } @ReactMethod public void getPhoneInfo(Callback successCallBack) { WritableMap mapPhoneInfo = Arguments.createMap(); mapPhoneInfo.putString("imsi", telephonyManager.getSubscriberId().toString()); mapPhoneInfo.putString("imei", telephonyManager.getDeviceId()); mapPhoneInfo.putString("mdn", telephonyManager.getLine1Number()); mapPhoneInfo.putString("model", Build.MANUFACTURER + " " + Build.MODEL + " " + Build.VERSION.RELEASE + " " + Build.VERSION_CODES.class.getFields()[Build.VERSION.SDK_INT].getName()); successCallBack.invoke(mapPhoneInfo); } @ReactMethod public void getNetworkClass(Callback successCallback) { int networkType = telephonyManager.getNetworkType(); String network; switch (networkType) { case TelephonyManager.NETWORK_TYPE_GPRS: case TelephonyManager.NETWORK_TYPE_EDGE: case TelephonyManager.NETWORK_TYPE_CDMA: case TelephonyManager.NETWORK_TYPE_1xRTT: case TelephonyManager.NETWORK_TYPE_IDEN: network = "2G"; break; case TelephonyManager.NETWORK_TYPE_UMTS: case TelephonyManager.NETWORK_TYPE_EVDO_0: case TelephonyManager.NETWORK_TYPE_EVDO_A: case TelephonyManager.NETWORK_TYPE_HSDPA: case TelephonyManager.NETWORK_TYPE_HSUPA: case TelephonyManager.NETWORK_TYPE_HSPA: case TelephonyManager.NETWORK_TYPE_EVDO_B: case TelephonyManager.NETWORK_TYPE_EHRPD: case TelephonyManager.NETWORK_TYPE_HSPAP: network = "3G"; break; case TelephonyManager.NETWORK_TYPE_LTE: network = "4G"; break; default: network = "Unknown"; break; } successCallback.invoke(network); } @Override public String getName() { return "Telephony"; } @Override public Map<String, Object> getConstants() { final Map<String, Object> constants = new HashMap<>(); constants.put(LISTEN_CALL_FORWARDING_INDICATOR, PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR); constants.put(LISTEN_CALL_STATE, PhoneStateListener.LISTEN_CALL_STATE); constants.put(LISTEN_CELL_INFO, PhoneStateListener.LISTEN_CELL_INFO); constants.put(LISTEN_CELL_LOCATION, PhoneStateListener.LISTEN_CELL_LOCATION); constants.put(LISTEN_DATA_ACTIVITY, PhoneStateListener.LISTEN_DATA_ACTIVITY); constants.put(LISTEN_DATA_CONNECTION_STATE, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); constants.put(LISTEN_MESSAGE_WAITING_INDICATOR, PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR); constants.put(LISTEN_SERVICE_STATE, PhoneStateListener.LISTEN_SERVICE_STATE); constants.put(LISTEN_SIGNAL_STRENGTHS, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); constants.put("DATA_ACTIVITY_NONE", DATA_ACTIVITY_NONE); constants.put("DATA_ACTIVITY_IN", DATA_ACTIVITY_IN); constants.put("DATA_ACTIVITY_OUT", DATA_ACTIVITY_OUT); constants.put("DATA_ACTIVITY_INOUT", DATA_ACTIVITY_INOUT); constants.put("DATA_ACTIVITY_DORMANT", DATA_ACTIVITY_DORMANT); constants.put("DATA_DISCONNECTED", DATA_DISCONNECTED); constants.put("DATA_CONNECTING", DATA_CONNECTING); constants.put("DATA_CONNECTED", DATA_CONNECTED); constants.put("DATA_SUSPENDED", DATA_SUSPENDED); constants.put("CALL_STATE_IDLE", CALL_STATE_IDLE); constants.put("CALL_STATE_RINGING", CALL_STATE_RINGING); constants.put("CALL_STATE_OFFHOOK", CALL_STATE_OFFHOOK); return constants; } @Override public void phoneCallStateUpdated(int state, String incomingNumber) { WritableMap map = Arguments.createMap(); map.putInt("state", state); map.putString("incomingNumber", incomingNumber); WritableMap result = Arguments.createMap(); result.putString("type", "LISTEN_CALL_STATE"); result.putMap("data", map); sendEvent(PHONE_STATE_LISTENER, result); } @Override public void phoneCallForwardingIndicatorUpdated(boolean cfi) { WritableMap map = Arguments.createMap(); map.putBoolean("cfi", cfi); WritableMap result = Arguments.createMap(); result.putString("type", "LISTEN_CALL_FORWARDING_INDICATOR"); result.putMap("data", map); sendEvent(PHONE_STATE_LISTENER, result); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) @Override public void phoneCellInfoUpdated(List<CellInfo> cellInfo) { WritableArray mapArray = Arguments.createArray(); if (cellInfo == null) { return; } int i = 0; for (CellInfo info : cellInfo) { WritableMap mapCellIdentity = Arguments.createMap(); WritableMap mapCellSignalStrength = Arguments.createMap(); WritableMap map = Arguments.createMap(); map.putInt("key", i); if (info instanceof CellInfoGsm) { CellIdentityGsm cellIdentity = ((CellInfoGsm) info).getCellIdentity(); map.putString("connectionType", "GSM"); mapCellIdentity.putInt("cid", cellIdentity.getCid()); mapCellIdentity.putInt("lac", cellIdentity.getLac()); mapCellIdentity.putInt("mcc", cellIdentity.getMcc()); mapCellIdentity.putInt("mnc", cellIdentity.getMnc()); mapCellIdentity.putInt("psc", cellIdentity.getPsc()); CellSignalStrengthGsm cellSignalStrengthGsm = ((CellInfoGsm) info).getCellSignalStrength(); mapCellSignalStrength.putInt("asuLevel", cellSignalStrengthGsm.getAsuLevel()); mapCellSignalStrength.putInt("dBm", cellSignalStrengthGsm.getDbm()); mapCellSignalStrength.putInt("level", cellSignalStrengthGsm.getLevel()); } else if (info instanceof CellInfoWcdma && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { CellIdentityWcdma cellIdentity = ((CellInfoWcdma) info).getCellIdentity(); map.putString("connectionType", "WCDMA"); mapCellIdentity.putInt("cid", cellIdentity.getCid()); mapCellIdentity.putInt("lac", cellIdentity.getLac()); mapCellIdentity.putInt("mcc", cellIdentity.getMcc()); mapCellIdentity.putInt("mnc", cellIdentity.getMnc()); mapCellIdentity.putInt("psc", cellIdentity.getPsc()); CellSignalStrengthWcdma cellSignalStrengthWcdma = ((CellInfoWcdma) info).getCellSignalStrength(); mapCellSignalStrength.putInt("asuLevel", cellSignalStrengthWcdma.getAsuLevel()); mapCellSignalStrength.putInt("dBm", cellSignalStrengthWcdma.getDbm()); mapCellSignalStrength.putInt("level", cellSignalStrengthWcdma.getLevel()); } else if (info instanceof CellInfoLte) { CellIdentityLte cellIdentity = ((CellInfoLte) info).getCellIdentity(); map.putString("connectionType", "LTE"); mapCellIdentity.putInt("ci", cellIdentity.getCi()); mapCellIdentity.putInt("tac", cellIdentity.getTac()); mapCellIdentity.putInt("mcc", cellIdentity.getMcc()); mapCellIdentity.putInt("mnc", cellIdentity.getMnc()); mapCellIdentity.putInt("pci", cellIdentity.getPci()); CellSignalStrengthLte cellSignalStrengthLte = ((CellInfoLte) info).getCellSignalStrength(); mapCellSignalStrength.putInt("asuLevel", cellSignalStrengthLte.getAsuLevel()); mapCellSignalStrength.putInt("dBm", cellSignalStrengthLte.getDbm()); mapCellSignalStrength.putInt("level", cellSignalStrengthLte.getLevel()); mapCellSignalStrength.putInt("timingAdvance", cellSignalStrengthLte.getTimingAdvance()); } else if (info instanceof CellInfoCdma) { CellIdentityCdma cellIdentity = ((CellInfoCdma) info).getCellIdentity(); map.putString("connectionType", "CDMA"); mapCellIdentity.putInt("basestationId", cellIdentity.getBasestationId()); mapCellIdentity.putInt("latitude", cellIdentity.getLatitude()); mapCellIdentity.putInt("longitude", cellIdentity.getLongitude()); mapCellIdentity.putInt("networkId", cellIdentity.getNetworkId()); mapCellIdentity.putInt("systemId", cellIdentity.getSystemId()); CellSignalStrengthCdma cellSignalStrengthCdma = ((CellInfoCdma) info).getCellSignalStrength(); mapCellSignalStrength.putInt("asuLevel", cellSignalStrengthCdma.getAsuLevel()); mapCellSignalStrength.putInt("cmdaDbm", cellSignalStrengthCdma.getCdmaDbm()); mapCellSignalStrength.putInt("cmdaEcio", cellSignalStrengthCdma.getCdmaEcio()); mapCellSignalStrength.putInt("cmdaLevl", cellSignalStrengthCdma.getCdmaLevel()); mapCellSignalStrength.putInt("dBm", cellSignalStrengthCdma.getDbm()); mapCellSignalStrength.putInt("evdoDbm", cellSignalStrengthCdma.getEvdoDbm()); mapCellSignalStrength.putInt("evdoEcio", cellSignalStrengthCdma.getEvdoEcio()); mapCellSignalStrength.putInt("evdoLevel", cellSignalStrengthCdma.getEvdoLevel()); mapCellSignalStrength.putInt("evdoSnr", cellSignalStrengthCdma.getEvdoSnr()); mapCellSignalStrength.putInt("level", cellSignalStrengthCdma.getLevel()); } map.putMap("cellIdentity", mapCellIdentity); map.putMap("cellSignalStrength", mapCellSignalStrength); mapArray.pushMap(map); i++; } WritableMap result = Arguments.createMap(); result.putString("type", "LISTEN_CELL_INFO"); result.putArray("data", mapArray); sendEvent(PHONE_STATE_LISTENER, result); } @Override public void phoneDataActivityUpdated(int direction) { WritableMap map = Arguments.createMap(); map.putInt("direction", direction); WritableMap result = Arguments.createMap(); result.putString("type", "LISTEN_DATA_ACTIVITY"); result.putMap("data", map); sendEvent(PHONE_STATE_LISTENER, result); } @Override public void phoneDataConnectionStateUpdated(int direction) { WritableMap map = Arguments.createMap(); map.putInt("direction", direction); WritableMap result = Arguments.createMap(); result.putString("type", "LISTEN_DATA_CONNECTION_STATE"); result.putMap("data", map); sendEvent(PHONE_STATE_LISTENER, result); } @Override public void phoneSignalStrengthsUpdated(SignalStrength signalStrength) { WritableMap map = Arguments.createMap(); map.putInt("cdmaDbm", signalStrength.getCdmaDbm()); map.putInt("cdmaEcio()", signalStrength.getCdmaEcio()); map.putInt("evdoDbm", signalStrength.getEvdoDbm()); map.putInt("evdoEcio", signalStrength.getEvdoEcio()); map.putInt("evdoSnr", signalStrength.getEvdoSnr()); map.putInt("gsmBitErrorRate", signalStrength.getGsmBitErrorRate()); map.putInt("gsmSignalStrength", signalStrength.getGsmSignalStrength()); map.putBoolean("gsm", signalStrength.isGsm()); WritableMap result = Arguments.createMap(); result.putString("type", "LISTEN_SIGNAL_STRENGTHS"); result.putMap("data", map); sendEvent(PHONE_STATE_LISTENER, result); } @Override public void onHostResume() { // Activity `onResume` } @Override public void onHostPause() { // Activity `onPause` } @Override public void onHostDestroy() { stopListener(); } public String decToHex(int dec) { return String.format("%x", dec); } public int hexToDec(String hex) { return Integer.parseInt(hex, 16); } }