I am developing an SMS app and want to check for network (cellular) connection. With API level 29, checking for connection requires use of ConnectivityManager.NetworkCallback. What I have managed is to get 'onAvailable()` to inform me when a network becomes available. However, that will also inform me if it connects to WiFi (so I could have no service to send an SMS but if WiFI connects then onAvailable() will fire).
I tried onCapabilitiesChanged() and .hasTransport(TRANSPORT_CELLULAR) but that reports false if I am connected to WiFi.
I also thought to try hasCapability(NET_CAPABILITY_MMS) but that informs if MMS is possible. It's not clear to me if there is a scenario/network where SMS is possible but MMS is not? So could I get this reporting false because network does not support MMS but can still send SMS?
What is the correct method for checking if cellular network is available?
Maybe you can try the following
Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
boolean cellular = caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
if(cellular){
// do your stuff
}
Late to the pary, and I'm not sure about 29... and I guess it is quite lame... but this is how I did it:
public boolean isCellularAvailable()
{
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
String opetarorName = telephonyManager.getNetworkOperatorName();
Log.i(LOG_TAG, "#### isCellularAvailable(): NetworkOperatorName is: " + opetarorName );
if (opetarorName .compareTo("") == 0)
{
Log.i(LOG_TAG, "#### isCellularAvailable(): NOPE");
Toast.makeText(context, "Turn off airplane mode and try again :)", Toast.LENGTH_LONG).show();
return false;
}
else
{
Log.i(LOG_TAG, "#### isCellularAvailable(): YES!");
return true;
}
}
The idea here is that if you are connected to a cellular network you should be able to get the name of your network provider.
If you get the name of one, then you are connected to that network, and should will be able to use it.
If you are in e.g. airplane mode, you will not be connected to a network, and will not get a name.
Noted that documentation says “Result may be unreliable on CDMA networks”… whatever that means.
But the “telephonyManager” offers a few similar functions, e.g. “getNetworkType()” might be another way to go if you know you´re favorable network types:
public boolean isCellularAvailable()
{
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
int networkType = telephonyManager.getNetworkType();// .getNetworkOperatorName();
Log.i(LOG_TAG, "#### isCellularAvailable(): Network type is: " + networkType);
switch (networkType)
{
// Return true for networks that suits your purpose
case TelephonyManager.NETWORK_TYPE_1xRTT: return true;
case TelephonyManager.NETWORK_TYPE_CDMA: return true;
case TelephonyManager.NETWORK_TYPE_EDGE: return true;
case TelephonyManager.NETWORK_TYPE_EHRPD: return true;
case TelephonyManager.NETWORK_TYPE_EVDO_0: return true;
case TelephonyManager.NETWORK_TYPE_EVDO_A: return true;
case TelephonyManager.NETWORK_TYPE_EVDO_B: return true;
case TelephonyManager.NETWORK_TYPE_GPRS: return true;
case TelephonyManager.NETWORK_TYPE_GSM: return true;
case TelephonyManager.NETWORK_TYPE_HSDPA: return true;
case TelephonyManager.NETWORK_TYPE_HSPA: return true;
case TelephonyManager.NETWORK_TYPE_HSPAP: return true;
case TelephonyManager.NETWORK_TYPE_HSUPA: return true;
case TelephonyManager.NETWORK_TYPE_IDEN: return true;
case TelephonyManager.NETWORK_TYPE_IWLAN: return true;
case TelephonyManager.NETWORK_TYPE_LTE: return true;
//case TelephonyManager.NETWORK_TYPE_NR: return true; // Not supported by my API
case TelephonyManager.NETWORK_TYPE_TD_SCDMA: return true;
case TelephonyManager.NETWORK_TYPE_UMTS: return true;
// Return false for unacceptable networks, UNKNOWN id no network e.g. airplane mode.
case TelephonyManager.NETWORK_TYPE_UNKNOWN: return false;
// Future unknown network types, handle as you please.
default: return false;
}
Try using following code to check if device is connected to internet or not.
ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conMgr.getActiveNetworkInfo();
if (netInfo == null) {
Toast.makeText(this, "Please turn on Internet ", Toast.LENGTH_SHORT).show();
} else {
//do what you want
}
You need to use Network Callback.
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();
connectivityManager.registerNetworkCallback(builder.build(),new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Variables.isNetworkConnected = true; // Global Static Variable
}
#Override
public void onLost(Network network) {
Variables.isNetworkConnected = false; // Global Static Variable
}
}
);
Variables.isNetworkConnected = false;
}catch (Exception e){
Variables.isNetworkConnected = false;
}
Variables.isNetworkConnected - Here I used a Global Static Variable, So I can use it to access the network state in anyware of the application.
Please refer this gist for full code implementation.
I trying to save their phone numbers after checking permissions and USIM state.
In onCreate() methods, Initialized global variable TelephonyManager.
mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
TelephonyManager initialized, but checked Null on a specific device(Galaxy S3).
// Null value confirmed here even though initialized
if(mTelephonyManager != null) {
if (mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_ABSENT
|| mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_UNKNOWN) {
// not USIM
numFlag = false;
finish();
} else if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
//Permission Check
numFlag = false;
finish();
} else {
// For security reasons, test in the following ways
if (TextUtils.isEmpty(SharedUtil.getInstance().getString(this, "phoneNumber"))) {
// PhoneNumber Init...
} else {
// Data Saved...
}
}
}else{
Toast.makeText(SmartIdActivity.this, "Unable to save phone number.", Toast.LENGTH_LONG).show();
finish();
}
Am I wrong or is this a special issue?
Some devices will return null when the sim card is not installed on the devices. Some devices will raise an exception when you're trying to call the following code:
TelephonyManager telMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
So, you need to handle both of them. Something like this:
private boolean isSimCardAvailable() {
try {
TelephonyManager telMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (telMgr == null) return false;
int simState = telMgr.getSimState();
switch (simState) {
case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
case TelephonyManager.SIM_STATE_PIN_REQUIRED:
case TelephonyManager.SIM_STATE_PUK_REQUIRED:
case TelephonyManager.SIM_STATE_READY:
case TelephonyManager.SIM_STATE_NOT_READY:
return true;
case TelephonyManager.SIM_STATE_UNKNOWN:
case TelephonyManager.SIM_STATE_ABSENT:
//SIM card state: SIM Card Error, permanently disabled
case TelephonyManager.SIM_STATE_PERM_DISABLED:
// SIM card state: SIM Card Error, present but faulty
case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
// SIM card state: SIM Card restricted, present but not usable due to
//carrier restrictions.
case TelephonyManager.SIM_STATE_CARD_RESTRICTED:
return false;
default:
return false;
}
} catch (Exception e) {
Log.e("TAG", "Exception e = " + e.toString());
return false;
}
}
I have an app that I want to be able to use to get a connection status report from a remote query.
I want to know if WiFi is connected, and if data access is enabled over mobile network.
If the WiFi goes out of range I want to know if I can rely on the mobile network.
The problem is that data enabled is always returned as true when I am connected by WiFi, and I can only properly query the mobile network when not connected by WiFi.
all the answers I have seen suggest polling to see what the current connection is, but I want to know if mobile network is available should I need it, even though I might be connected by WiFi at present.
Is there anyway of telling whether mobile network data is enabled without polling to see if is connected?
EDIT
So when connected by WiFi If I go to settings and deselect 'Data Enabled' and then in my app I do this:
boolean mob_avail =
conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isAvailable();
mob_avail is returned as 'true', but I have disabled Mobile Network Data, so I would expect it to be 'false'
If I turn off the WiFi, there is (rightly) no connection as I have disabled mobile network data.
so how do I check if mobile network data is enabled when I am connected by WiFi?
UPDATE
I took a look at getAllNetworkInfo() as suggested in the comments by ss1271
I outputted the info returned about the mobile network under the following 3 conditions
WiFi Off - Mobile Data on
WiFi On - Mobile Data off
WiFi On - Mobile Data on
and got the following results:
With WiFi OFF:
mobile[HSUPA], state: CONNECTED/CONNECTED, reason: unknown, extra:
internet, roaming: false, failover: false, isAvailable: true,
featureId: -1, userDefault: false
With WiFi On / Mobile OFF
NetworkInfo: type: mobile[HSUPA], state: DISCONNECTED/DISCONNECTED,
reason: connectionDisabled, extra: (none), roaming: false,
failover: false, isAvailable: true, featureId: -1, userDefault:
false
With WiFi On / Mobile On
NetworkInfo: type: mobile[HSPA], state: DISCONNECTED/DISCONNECTED,
reason: connectionDisabled, extra: (none), roaming: false,
failover: false, isAvailable: true, featureId: -1, userDefault:
false
So as you can see isAvailable returned true each time, and state only showed as Disconnected when WiFi was in affect.
CLARIFICATION
I am NOT looking to see if my phone is currently connected by Mobile Network. I AM trying to establish whether or not the user has enabled / disabled Data access over mobile network. They can turn this on and off by going to Settings -> Wireless and Network Settings ->Mobile Network Settings -> Data enabled
The following code will tell you if "mobile data" is enabled or not, regardless of whether or not there is a mobile data connection active at the moment or whether or not wifi is enabled/active or not. This code only works on Android 2.3 (Gingerbread) and later. Actually this code also works on earlier versions of Android as well ;-)
boolean mobileDataEnabled = false; // Assume disabled
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
try {
Class cmClass = Class.forName(cm.getClass().getName());
Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
method.setAccessible(true); // Make the method callable
// get the setting for "mobile data"
mobileDataEnabled = (Boolean)method.invoke(cm);
} catch (Exception e) {
// Some problem accessible private API
// TODO do whatever error handling you want here
}
Note: you will need to have permission android.permission.ACCESS_NETWORK_STATE to be able to use this code.
I've upgraded Allesio's answer. Settings.Secure's mobile_data int has moved to Settings.Global since 4.2.2.
Try This code when you want to know if mobile network is enabled even when wifi is enabled and connected.
Updated to check if SIM Card is available. Thanks for pointing out murat.
boolean mobileYN = false;
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1)
{
mobileYN = Settings.Global.getInt(context.getContentResolver(), "mobile_data", 1) == 1;
}
else{
mobileYN = Settings.Secure.getInt(context.getContentResolver(), "mobile_data", 1) == 1;
}
}
One way is to check whether the user has mobile data activated in the Settings, which most likely will be used if wifi goes off.
This works (tested), and it doesn't use reflection, although it uses an hidden value in the API:
boolean mobileDataAllowed = Settings.Secure.getInt(getContentResolver(), "mobile_data", 1) == 1;
Depending on the API, you need to check Settings.Global instead of Settings.Secure, as pointed out by #user1444325.
Source:
Android API call to determine user setting "Data Enabled"
Since ConnectivityManager.allNetworkInfo is deprecated, Android suggested using getNetworkCapabilities
fun isOnMobileData(): Boolean {
val connectivityManager =
context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
val all = connectivityManager.allNetworks
return all.any {
val capabilities = connectivityManager.getNetworkCapabilities(it)
capabilities?.hasTransport(TRANSPORT_CELLULAR) == true
}
}
#sNash's function works great. But in few devices I found it returns true even if data is disabled.
So I found one alternate solution which is in Android API.
getDataState() method of TelephonyManager will be very useful.
I updated #snash's function with the above function used. Below function returns false when cellular data is disabled otherwise true.
private boolean checkMobileDataIsEnabled(Context context){
boolean mobileYN = false;
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
// if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1)
// {
// mobileYN = Settings.Global.getInt(context.getContentResolver(), "mobile_data", 0) == 1;
// }
// else{
// mobileYN = Settings.Secure.getInt(context.getContentResolver(), "mobile_data", 0) == 1;
// }
int dataState = tm.getDataState();
Log.v(TAG,"tm.getDataState() : "+ dataState);
if(dataState != TelephonyManager.DATA_DISCONNECTED){
mobileYN = true;
}
}
return mobileYN;
}
You can try something like that:
ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//mobile
State mobile = conMan.getNetworkInfo(0).getState();
//wifi
State wifi = conMan.getNetworkInfo(1).getState();
if (mobile == NetworkInfo.State.CONNECTED || mobile == NetworkInfo.State.CONNECTING)
{
//mobile
}
else if (wifi == NetworkInfo.State.CONNECTED || wifi == NetworkInfo.State.CONNECTING)
{
//wifi
}
If you are interested if you are realy connected, use
NetworkInfo.State.CONNECTED
only, instead of
NetworkInfo.State.CONNECTED || NetworkInfo.State.CONNECTING
use TelephonyManager
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
tm.isDataEnabled()
According to android documentation
https://developer.android.com/reference/android/telephony/TelephonyManager.html#isDataEnabled()
I think using NetworkInfo class and isConnected should work:
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
return info != NULL || info.isConnected();
And to check mobile data is connected perhaps. I can not be sure until I test it. Which I cannot do until tommorrow.
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if(tm .getDataState() == tm .DATA_CONNECTED)
return true;
Here is a xamarin solution to this problem:
public static bool IsMobileDataEnabled()
{
bool result = false;
try
{
Context context = //get your context here or pass it as a param
if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr1)
{
//Settings comes from the namespace Android.Provider
result = Settings.Global.GetInt(context.ContentResolver, "mobile_data", 1) == 1;
}
else
{
result = Settings.Secure.GetInt(context.ContentResolver, "mobile_data", 1) == 1;
}
}
catch (Exception ex)
{
//handle exception
}
return result;
}
PS: Make sure you have all the permissions for this code.
Here is a simple solution from two other answers:
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return tm.isDataEnabled();
} else {
return tm.getSimState() == TelephonyManager.SIM_STATE_READY && tm.getDataState() != TelephonyManager.DATA_DISCONNECTED;
}
You must use the ConnectivityManager, and NetworkInfo details can be found here
To identify which SIM or slot is making data connection active in mobile, we need to register action android:name="android.net.conn.CONNECTIVITY_CHANGE" with permission
uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" & uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"
public void onReceive(Context context, Intent intent)
if (android.net.conn.CONNECTIVITY_CHANGE.equalsIgnoreCase(intent
.getAction())) {
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
NetworkState[] states = service.getAllNetworkState();
for (NetworkState state : states) {
if (state.networkInfo.getType() == ConnectivityManager.TYPE_MOBILE
&& state.networkInfo.isConnected()) {
TelephonyManager mTelephonyManager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
int slotList = { 0, 1 };
int[] subId = SubscriptionManager.getSubId(slotList[0]);
if(mTelephonyManager.getDataEnabled(subId[0])) {
// this means data connection is active for SIM1 similary you
//can chekc for SIM2 by slotList[1]
.................
}
}
}
ConnectivityManager cm = (ConnectivityManager) activity
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
String networkType = "";
if (info.getType() == ConnectivityManager.TYPE_WIFI) {
networkType = "WIFI";
}
else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
networkType = "mobile";
}
According to android documentation https://developer.android.com/training/monitoring-device-state/connectivity-monitoring#java
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
Well there is a workaround to check if the data connection is on. But I am not sure whether it will work on every device. You need to check that. (It worked on Android one device)
long data = TrafficStats.getMobileRxBytes();
if(data > 0){
//Data is On
}
else{
//Data is Off
}
If you are not aware about this method, it returns the total of bytes recieved through mobile network since the device boot up. When you turn off the mobile data connection, it will return Zero (0). When you turn on, it will return the total of bytes again. But you need to aware that there is a problem which can happen when using this workaround.
This method will also return 0 when you reboot the phone because the calculation starts from 0 bytes.
private boolean haveMobileNetworkConnection() {
boolean haveConnectedMobile = false;
ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
if (ni.isConnected())
haveConnectedMobile = true;
}
return haveConnectedMobile;
}
Note: you will need to have permission android.permission.ACCESS_NETWORK_STATE to be able to use this code
There is simple API that seems to be working
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.isDataEnabled();
My Android app can only function with WiFi connected to the Internet. Thus, I use the following code to check if the device is connected:
ConnectivityManager conMgr = (ConnectivityManager)getSystemService(Activity.CONNECTIVITY_SERVICE);
boolean wifi = conMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected();
However, very often when the application is launched and WiFi connected to the Internet, I get the notification that is only shown when wifi = false. Have I missed something, or the check is not that accurate?
My project also relies on Wifi (although I use a private network). The following is my code for setting up a Wifi connection on start up:
private void initWIFI (WifiManager wifiMgr, String SSID, String key)
{
WifiInfo curr;
if (null == (curr = wifiMgr.getConnectionInfo())) // Get current wifi state
{
joinNetwork (wifiMgr, SSID, key);
}
else switch (curr.getSupplicantState())
{
case DISCONNECTED:
case DORMANT:
case INACTIVE:
case SCANNING:
joinNetwork (wifiMgr, SSID, key);
break;
default:
if (!curr.getSSID().equals (SSID))
joinNetwork (wifiMgr, SSID, key);
}
while (wifiMgr.getConnectionInfo().getIpAddress() == 0)
{
try
{
Thread.sleep (1000);
}
catch (Exception e)
{ }
}
}
/**This method is used to join the proper WiFi network when necessary. Normally,
* the Android retains network configuration and it is not necessary to manually
* re-join the desired network on software startup. However, when it is determined
* that the Android is not currently attached to the proper network, this function
* is used to correct that situation. */
private void joinNetwork (WifiManager wifiMgr, String SSID, String key)
{
try
{
WifiConfiguration wc = new WifiConfiguration();
wc.allowedAuthAlgorithms.set (WifiConfiguration.AuthAlgorithm.OPEN);
wc.allowedAuthAlgorithms.set (WifiConfiguration.AuthAlgorithm.SHARED);
wc.allowedGroupCiphers.set (WifiConfiguration.GroupCipher.WEP40);
wc.allowedGroupCiphers.set (WifiConfiguration.GroupCipher.WEP104);
wc.allowedKeyManagement.set (WifiConfiguration.KeyMgmt.NONE);
wc.allowedPairwiseCiphers.set (WifiConfiguration.PairwiseCipher.TKIP);
wc.allowedPairwiseCiphers.set (WifiConfiguration.PairwiseCipher.CCMP);
wc.allowedProtocols.set (WifiConfiguration.Protocol.WPA);
wc.allowedProtocols.set (WifiConfiguration.Protocol.RSN);
wc.hiddenSSID = false;
wc.priority = 32;
wc.SSID = "\"" + SSID + "\"";
wc.status = WifiConfiguration.Status.ENABLED;
wc.wepKeys[0] = key;
wc.wepTxKeyIndex = 0;
int netID;
if (-1 == (netID = wifiMgr.addNetwork (wc)))
{
listener.lostConnection (true);
}
else
{
wifiMgr.enableNetwork (netID, true);
Thread.sleep (5000); // Delay to allow the DHCP process to work
}
}
catch (Exception e)
{
listener.lostConnection (true);
}
}
It should be pointed out that I always use the same wireless access point, and the code in joinNetwork() is specifically configured for it, so if your configuration needs to be more flexible, then your solution may be more complex. Sadly, I do not remember the web site where I found the starting point for this code, but it didn't take a ton of Googling to find it. Finally, I'm pretty sure your application needs to have the ACCESS_WIFI_STATE and CHANGE_WIFI_STATE permissions.
I use code like this:
public static String getCurrentSsid(Context context) {
final WifiInfo wifiInfo = getCurrentWifiInfo(context);
if (wifiInfo != null && !StringUtil.isBlank(wifiInfo.getSSID())) {
return wifiInfo.getSSID();
}
return null;
}
public static WifiInfo getCurrentWifiInfo(Context context) {
final ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (networkInfo != null && networkInfo.isConnected()) {
final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
return wifiManager.getConnectionInfo();
}
return null;
}
At the same time be aware of this two issues 19078 and 3641.
I need help checking whether a device has a sim card programatically. Please provide sample code.
Use TelephonyManager.
http://developer.android.com/reference/android/telephony/TelephonyManager.html
As Falmarri notes, you will want to use getPhoneType FIRST of all, to see if you are even dealing with a GSM phone. If you are, then you can also get the SIM state.
TelephonyManager telMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
int simState = telMgr.getSimState();
switch (simState) {
case TelephonyManager.SIM_STATE_ABSENT:
// do something
break;
case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
// do something
break;
case TelephonyManager.SIM_STATE_PIN_REQUIRED:
// do something
break;
case TelephonyManager.SIM_STATE_PUK_REQUIRED:
// do something
break;
case TelephonyManager.SIM_STATE_READY:
// do something
break;
case TelephonyManager.SIM_STATE_UNKNOWN:
// do something
break;
}
EDIT:
Starting at API 26 (Android O Preview) you can query the SimState for individual sim slots by using getSimState(int slotIndex) ie:
int simStateMain = telMgr.getSimState(0);
int simStateSecond = telMgr.getSimState(1);
official documentation
If you're developing with and older api, you can use TelephonyManager's
String getDeviceId (int slotIndex)
//returns null if device ID is not available. ie. query slotIndex 1 in a single sim device
int devIdSecond = telMgr.getDeviceId(1);
//if(devIdSecond == null)
// no second sim slot available
which was added in API 23 - docs here
You can check with the below code :
public static boolean isSimSupport(Context context)
{
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); //gets the current TelephonyManager
return !(tm.getSimState() == TelephonyManager.SIM_STATE_ABSENT);
}
Found another way to do this.
public static boolean isSimStateReadyorNotReady() {
int simSlotCount = sSlotCount;
String simStates = SystemProperties.get("gsm.sim.state", "");
if (simStates != null) {
String[] slotState = simStates.split(",");
int simSlot = 0;
while (simSlot < simSlotCount && slotState.length > simSlot) {
String simSlotState = slotState[simSlot];
Log.d("MultiSimUtils", "isSimStateReadyorNotReady() : simSlot = " + simSlot + ", simState = " + simSlotState);
if (simSlotState.equalsIgnoreCase("READY") || simSlotState.equalsIgnoreCase("NOT_READY")) {
return true;
}
simSlot++;
}
}
return false;
}
Thanks #Arun kumar answer, kotlin version as below
fun isSIMInserted(context: Context): Boolean {
return TelephonyManager.SIM_STATE_ABSENT != (context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).simState
}