Roaming detection on OnePlus One/Two/Three - android

I'm willing to detect if roaming switch on a telephone is turned off.
if (Build.VERSION.SDK_INT < 17) {
isDataRoamingDisabled =
(Settings.System.getInt(context.getContentResolver(), Settings.Secure.DATA_ROAMING, 0)
== 0);
} else {
isDataRoamingDisabled =
(Settings.Global.getInt(context.getContentResolver(), Settings.Global.DATA_ROAMING, 0)
== 0);
}
Unfortunately only for OnePlus One/Two/Three the setting is always false (0).
On rest devices that i tested - Nexus 6P, LG G5, Samsung S5 all is working fine...
telephonyManager.isNetworkRoaming(), is not really the solution here since it detects if a user in roaming and not switch in settings.
Thanks for help! :)

I found some solution regarding this issue..
It seems like it caused by the using of Dual SIM on these devices, which adopted the newer API for this functionality. (I found it on the source code of Oxygen)
This solution requires READ_PHONE_STATE permission
Accessing the roaming of each subscription:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
List<SubscriptionInfo> subscriptions = SubscriptionManager.from(context).getActiveSubscriptionInfoList();
for (SubscriptionInfo subscriptionInfo:subscriptions) {
if (subscriptionInfo.getDataRoaming() == SubscriptionManager.DATA_ROAMING_ENABLE) {
return true;
}
}
return false;
}
For the rest of the devices you may use the solution you specified above.

Related

How to detect Samsung S10 5G is running on 5G network?

Android Q added a new network type, NETWORK_TYPE_NR for 5G which is
not available for Android Pie. Recently released Samsung S10 fully supports 5G. It can show 5G icon on the status bar when it is on the 5G network.
Is it possible for a third-party app to know if Android Pie device on a 5G network or not?
Any help will be appreciated.
The following link is the definition for the new network type. It is not available on the Android Pie branch.
Source code for Pie release
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/pie-release-2/telephony/java/android/telephony/TelephonyManager.java
The latest source code that has NETWORK_TYPE_NR
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/telephony/java/android/telephony/TelephonyManager.java#2375
I believe they backported the code from Q to Pie as the logic for 5G was implemented at the end of last year in Q (alpha).
So when using
TelephonyManager.getNetworkType()
you will likely get
20 (5G)
EDIT
As per comment below: The network type will be 13 so it doesn't solve the thing.
EDIT
Try using reflection
static boolean isNRConnected(TelephonyManager telephonyManager) {
try {
Object obj = Class.forName(telephonyManager.getClass().getName())
.getDeclaredMethod("getServiceState", new Class[0]).invoke(telephonyManager, new Object[0]);
Method[] methods = Class.forName(obj.getClass().getName()).getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("getNrStatus") || method.getName().equals("getNrState")) {
method.setAccessible(true);
return ((Integer) method.invoke(obj, new Object[0])).intValue() == 3;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
There is an official documentation to detect 5G on Android 11.
https://developer.android.com/about/versions/11/features/5g#detection
Call TelephonyManager.listen(), passing in LISTEN_DISPLAY_INFO_CHANGED, to determine if the user has a 5G network connection.
as #Hunter suggested you need to use "listen" from telephony manager but if it's api 30+ you need to have READ_PHONE permission granted and listen for LISTEN_DISPLAY_INFO_CHANGED and override onDisplayInfoChanged from PhoneStateListener
(context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).listen(customPhoneStateListener,PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
The listener should be something like this:
private class CustomPhoneStateListener : PhoneStateListener() {
override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
super.onDisplayInfoChanged(telephonyDisplayInfo)
when (telephonyDisplayInfo.overrideNetworkType) {
//5G
OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO,
OVERRIDE_NETWORK_TYPE_NR_NSA,
OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> setNetworkChange(NETWORK_TYPE_NR)
OVERRIDE_NETWORK_TYPE_LTE_CA -> {
setNetworkChange(19) //LTE+
}
else -> setNetworkChange(telephonyDisplayInfo.networkType)
}
} else {
setNetworkChange(telephonyDisplayInfo.networkType)
}
}
}
Link: https://developer.android.com/about/versions/11/features/5g#detection
Couldn't add this as a comment, but as #Pavel Machala said, looking at the ServiceState class in the AOSP yields the following:
/**
* Get the NR 5G status of the mobile data network.
* #return the NR 5G status.
* #hide
*/
public #NRStatus int getNrStatus() {
final NetworkRegistrationState regState = getNetworkRegistrationState(
NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState == null) return NetworkRegistrationState.NR_STATUS_NONE;
return regState.getNrStatus();
}
I have extracted the ServiceState.java from SM-G977N firmware and it confirms that they have added
ServiceState.getNrStatus()
5G(NR) is active is if NetworkRegistrationState.NR_STATUS_CONNECTED = 3;

Detecting if device is from Samsung Galaxy family

Is there a reliable way of detecting if device is one from Samsung Galaxy phones? Currently, I do it in this way:
private static boolean isSamsungGalaxyN() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
try {
PackageInfo info = getContext().getPackageManager().getPackageInfo("com.samsung.android.app.galaxyfinder", 0);
if (info != null) {
return true;
}
} catch (PackageManager.NameNotFoundException e) {
// ignored
}
}
return false;
}
So, I just check if there is such apk (which is S Finder, actually):
com.samsung.android.app.galaxyfinder
But is this method reliable and is there some better method?
Use Build.MANUFACTURER and Build.MODEL.
With Model you can get device family. For Galaxy S7 it will be SM-G903x. You need to have list of known Galaxy model names.
https://www.techwalls.com/samsung-galaxy-s7-edge-model-numbers-differences/

Android; detect if the Vibrate setting in the device is on or off, esp for the case when it rings but does not vibrate

App requirement: To detect when a phone is on Ringing mode with the Vibrate Setting being OFF
so the problem comes down to : detect whether the Vibrate Setting is OFF or ON
Relevant information:
To start with,
Vibrator has no method like isVibratorModeOn() and the
Flags related to Vibrate and EXTRA_VIBRATE_... are all marked deprecated with:
This constant was deprecated in API level 16. Applications should
maintain their own vibrate policy based on current ringer mode that
can be queried via getRingerMode().
But under getRingerMode(), we won't exactly know if the vibrate setting is off or not with RINGER_MODE_NORMAL;
It will vibrate if the vibrate setting is on.
Now the getVibrateSetting() is also deprecated.
Code which works for detecting the RINGER_MODE on *most devices and o.s. versions including Android M on Nexus 6:
if(audioManager.getRingerMode()!=AudioManager.RINGER_MODE_SILENT){
if (audioManager.getStreamVolume(AudioManager.STREAM_RING) != 0) {
*Exception: Nexus 5 - 5.1.1, probably for all Lollipop versions
I feel its very surprising if this has been missed or i've made the big(gest) silly mistake by missing something obvious. Hopefully, this isn't a waste of your time.
Here's more to explain the problem:
RINGER_MODE_SILENTscenario covered:
RINGER_MODE_VIBRATE scenario covered:
DETECTING THIS IS THE PROBLEM:
Screenshot crops from Android M, Nexus 6
Update:
the solution is a bit twisted, using a deprecated method in one of the loops, it has worked on all devices i have tested; those of brands; motorola, samsung, htc, lg, xiaomi, micromax, sony
audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getRingerMode() != AudioManager.RINGER_MODE_SILENT) {
//ensuring it is not on silent
if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) {
// if it is on vibrate mode , esp for api 23
} else if (audioManager.getStreamVolume(AudioManager.STREAM_RING) != 0) {
// else check whether the volume is not 0
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
if (audioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER) == AudioManager.VIBRATE_SETTING_ON
|| audioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER) == AudioManager.VIBRATE_SETTING_ONLY_SILENT) { //need to add this to detect a specific scenario in xiaomi device
// if the device o.s version is not 23 this part works
}
}
if ((1 == Settings.System.getInt(ApplicationController.getInstance().getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0))) {
// the constant VIBRATE_WHEN_RINGING was added in api 23
}
}
Modified solution to the one given:
Even for API < 23 and API 23 this works fine. It seems fine if you do not use deprecated methods for previous APIs. Tested on Samsung, Motorola, OnePlus, Google Pixel, Google Nexus
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int mode = am.getRingerMode();
switch (mode) {
case AudioManager.RINGER_MODE_NORMAL:
if ((1 == Settings.System.getInt(getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0))) {
// code here
Toast.makeText(getApplicationContext(), "=== ring + vibrate mode ===", Toast.LENGTH_LONG).show();
} else {
// code here
Toast.makeText(getApplicationContext(), "=== ring + no vibrate mode ===", Toast.LENGTH_LONG).show();
}
break;
case AudioManager.RINGER_MODE_SILENT:
// code here
Toast.makeText(getApplicationContext(), "=== in silent mode ===", Toast.LENGTH_LONG).show();
break;
case AudioManager.RINGER_MODE_VIBRATE:
// code here
Toast.makeText(getApplicationContext(), "=== in vibrate mode ===", Toast.LENGTH_LONG).show();
break;
}
Parath's solution written in Kotlin with some updates:
private fun shouldVibrateOnCall(): Boolean {
val audioManager = applicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
// Ensuring it is not on silent
if (audioManager.ringerMode != RINGER_MODE_SILENT) {
// If it is on vibrate mode
if (audioManager.ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
return true
// Else check whether the volume is not 0
} else if (audioManager.getStreamVolume(AudioManager.STREAM_RING) != 0) {
if ((1 == Settings.System.getInt(contentResolver, Settings.System.VIBRATE_WHEN_RINGING, 0))) {
return true
}
}
}
return false
}
Hope it saves you some time.

How to check "Automatic date and time" is enabled or not?

I need to check whether "Automatic date and time" in the android device is enabled or not. If it is not enabled I need to display the popup that it is not enabled.
Is it possible to achieve. If possible, how to check enabled or not ?
Link for API 17 and above
android.provider.Settings.Global.getInt(getContentResolver(), android.provider.Settings.Global.AUTO_TIME, 0);
Link for API 16 and below
android.provider.Settings.System.getInt(getContentResolver(), android.provider.Settings.System.AUTO_TIME, 0);
public static boolean isTimeAutomatic(Context c) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return Settings.Global.getInt(c.getContentResolver(), Settings.Global.AUTO_TIME, 0) == 1;
} else {
return android.provider.Settings.System.getInt(c.getContentResolver(), android.provider.Settings.System.AUTO_TIME, 0) == 1;
}
}
I would just like to point out that it is possible to cheat (I just did it on a Samsung Galaxy S4, Android 5.0.1):
Disable auto time
Disconnect from the internets (airplane mode, no wifi etc...)
reboot phone (otherwise the real time is retrieved)
set auto time on
Done today:
Unix time: 1129294173
Date: 14102005024933
is automatic? 1 (using android.provider.Settings.Global.getInt(getActivity().getContentResolver(), android.provider.Settings.Global.AUTO_TIME, 0))
And today definitely isn't Oct 14, 2005
if(Settings.Global.getInt(getContentResolver(), Global.AUTO_TIME) == 1)
{
// Enabled
}
else
{
// Disabed
}
Check is Auto Time or Zone is Enabled ? (Kotlin)
fun isAutoTimeEnabled(activity: Activity) =
Settings.Global.getInt(activity.contentResolver, Settings.Global.AUTO_TIME) == 1
fun isAutoTimeZoneEnabled(activity: Activity) =
Settings.Global.getInt(activity.contentResolver, Settings.Global.AUTO_TIME_ZONE) == 1
in kotlin you can use
fun isTimeAutomatic(c: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Settings.Global.getInt(c.contentResolver, Settings.Global.AUTO_TIME, 0) == 1
} else {
Settings.System.getInt(c.contentResolver, Settings.System.AUTO_TIME, 0) == 1
}}

How to find out from code if my Android app runs on emulator or real device?

I have read this stackoverflow thread already and I tried using the code given in that answer to find out if I run my code on the emulator or on a real device:
import android.content.ContentResolver;
import android.provider.Settings.Secure;
...
mTextView.setText(Secure.getString(getContentResolver(), Secure.ANDROID_ID));
On my real device it returns "2bccce3...", however on the emulator it does not return null, but also a string "bd9f8..."
Ideas how to find out if emulator or real device from code would be highly appreciated
This should do it:
boolean inEmulator = false;
String brand = Build.BRAND;
if (brand.compareTo("generic") == 0)
{
inEmulator = true;
}
EDIT:
boolean inEmulator = "generic".equals(Build.BRAND.toLowerCase());
With the advent of the new Intel native emulator the above mentioned methods did not work any longer. Now I am using this code snippet which works on both Intel and ARM emulators:
if (Build.MODEL.contains("google_sdk") ||
Build.MODEL.contains("Emulator") ||
Build.MODEL.contains("Android SDK")) {
RunsInEmulator = true;
}
There's a rather old thread on Android Developers group that suggests checking the number of sensors on the device. Something like this might work:
SensorManager manager = (SensorManager) getSystemService(SENSOR_SERVICE);
if (manager.getSensorList(Sensor.TYPE_ALL).isEmpty()) {
// running on an emulator
} else {
// running on a device
}
I haven't tried this, so I have no idea how reliable the suggestion is. (Perhaps some emulators now report some sensors; perhaps some devices report no sensors. [Is there an Android toothbrush yet?]) But it can't be worse than checking for a null ANDROID_ID (which doesn't work as of 2.2).
P.S. Another thread claims that as of 2.2, the ANDROID_ID for the emulator is always "9774D56D682E549C". However, you are apparently getting some other hex string, so I don't think this is right, either.
P.P.S. Other suggestions I haven't tried are here. One that seems particularly nice (if it works) is:
if (android.os.Build.MODEL.equals(“google_sdk”)) {
// emulator
} else {
//not emulator
}
I think that the best answer is to decide why you actually care to know - and then check for whatever specific characteristic of the emulator you believe requires that your app behave differently than it would on a device.
How about this solution:
public static boolean isRunningOnEmulator()
{
boolean result=//
Build.FINGERPRINT.startsWith("generic")//
||Build.FINGERPRINT.startsWith("unknown")//
||Build.MODEL.contains("google_sdk")//
||Build.MODEL.contains("Emulator")//
||Build.MODEL.contains("Android SDK built for x86");
if(result)
return true;
result|=Build.BRAND.startsWith("generic")&&Build.DEVICE.startsWith("generic");
if(result)
return true;
result|="google_sdk".equals(Build.PRODUCT);
return result;
}
EDIT: seems I've answered this already, here:
https://stackoverflow.com/a/21505193/878126
As stated in this post, IMEI and IMSI are harcoded on the emulator:
2325 { "+CIMI", OPERATOR_HOME_MCCMNC "000000000", NULL }, /* request internation subscriber identification number */
2326 { "+CGSN", "000000000000000", NULL }, /* request model version */
You can easily get the value using
adb shell dumpsys iphonesubinfo
So checking the device's IMEI using TelephonyManager.getDeviceId() should be sufficient to find out, whether you're on an emulator or a real device.To be absolutely sure, you might combine it with checking the model name as stated by various other posts.
public static boolean isRunningOnEmulator(final Context inContext) {
final TelephonyManager theTelephonyManager = (TelephonyManager)inContext.getSystemService(Context.TELEPHONY_SERVICE);
final boolean hasEmulatorImei = theTelephonyManager.getDeviceId().equals("000000000000000");
final boolean hasEmulatorModelName = Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK");
return hasEmulatorImei || hasEmulatorModelName;
}
The downside to this approach is that you need a context to access this information and instantiating a TelephonyManager for every check.
This is the standard google flutter emulator check :
public boolean isEmulator() {
return (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
|| Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.HARDWARE.contains("goldfish")
|| Build.HARDWARE.contains("ranchu")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| Build.PRODUCT.contains("sdk_google")
|| Build.PRODUCT.contains("google_sdk")
|| Build.PRODUCT.contains("sdk")
|| Build.PRODUCT.contains("sdk_x86")
|| Build.PRODUCT.contains("vbox86p")
|| Build.PRODUCT.contains("emulator")
|| Build.PRODUCT.contains("simulator");
}
Following one is correctly detect my emulator
if (Build.BRAND.equalsIgnoreCase("generic")) {
//"YES, I am an emulator"
} else {
//"NO, I am NOT an emulator"
}
As of writing this, nothing in this thread worked for the Bluestacks 4 emulator except trying to check for sensors. And so I checked the battery temperature using this gist. It should return 0.0 which means it does not have a battery temperature (and therefore it's an emulator).
public float getCpuTemp() {
Process process;
try {
process = Runtime.getRuntime().exec("cat sys/class/thermal/thermal_zone0/temp");
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = reader.readLine();
float temp = Float.parseFloat(line) / 1000.0f;
return temp;
} catch (Exception e) {
e.printStackTrace();
return 0.0f;
}
}

Categories

Resources