How to check telephony and camera availability for SDK version < 5 - android

Standard way of checking camera and telephony hardware availability works only since SDK >= 5:
PackageManager pm = this.getPackageManager();
boolean hasTelephony=pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
boolean hasCamera=pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
My problem that I need to runtime define availability of telephony and camera in SDK 3 (Android 1.5)
Any ideas?
P.S. I understand that Android 1.5 is very outdated, but still I do have bunch of customers running these devices, so I have to keep compatibility with them.

Well, I have found solution - very odd but it's working.
Basically method tries to get telephony service if it's null - it returns false, if it's not null (e.g. for HTC Flyer TelephonyManager is not null) method tries to run PackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) using reflection, since this method is not available for old versions of SDK.
Here is a code:
private Boolean hasTelephony;
public boolean hasTelephony()
{
if(hasTelephony==null)
{
TelephonyManager tm=(TelephonyManager )this.getSystemService(Context.TELEPHONY_SERVICE);
if(tm==null)
{
hasTelephony=new Boolean(false);
return hasTelephony.booleanValue();
}
if(this.getSDKVersion() < 5)
{
hasTelephony=new Boolean(true);
return hasTelephony;
}
PackageManager pm = this.getPackageManager();
Method method=null;
if(pm==null)
return hasCamera=new Boolean(false);
else
{
try
{
Class[] parameters=new Class[1];
parameters[0]=String.class;
method=pm.getClass().getMethod("hasSystemFeature", parameters);
Object[] parm=new Object[1];
parm[0]=new String(PackageManager.FEATURE_TELEPHONY);
Object retValue=method.invoke(pm, parm);
if(retValue instanceof Boolean)
hasTelephony=new Boolean(((Boolean )retValue).booleanValue());
else
hasTelephony=new Boolean(false);
}
catch(Exception e)
{
hasTelephony=new Boolean(false);
}
}
}
return hasTelephony;
}
More or less the same approach is workable for checking of camera availability

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/

Reliable method to check if device can send SMS with current connectivity

I have an application that send SMS automatically to a remote server. I want to check if the phone is connected to a network capable to send SMS before calling the SMSManager.send() method.
I tried the following method :
TelephonyManager tlm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
boolean hasNetwork = tlm.getNetworkType() != android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
Unfortunately, this method works on some phones like Acer or Nexus but not on others like some Sony Xperia.
I then tried an other approach :check if the phone is connected to antennas (and I assume that there is network when connected to an antenna)
private static boolean isSmsNetworkAvailable(Context context) {
TelephonyManager tlm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
boolean hasNetwork = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// new API
List<CellInfo> listCellInfo = tlm.getAllCellInfo();
if (listCellInfo != null && !listCellInfo.isEmpty()) {
for (CellInfo cellInfo : listCellInfo) {
if (cellInfo.isRegistered()) {
hasNetwork = true;
break;
}
}
}
} else {
// old API
List<NeighboringCellInfo> listNeighboringCellInfo = tlm.getNeighboringCellInfo();
if (listNeighboringCellInfo != null && !listNeighboringCellInfo.isEmpty()) {
hasNetwork = true;
}
}
return hasNetwork;
}
This method is also unreliable , it works on Nexus, Xperia, but not on Acer phones (for example)...
So the question is : Is there a reliable method to check if a phone is really capable to send SMS with the current connectivity?

How to find out whether android device has cellular radio module?

How can I find out for sure that device really has gsm, cdma or other cellular network equipment (not just WiFi)?
I don't want to check current connected network state, because device can be offline in the moment.
And I don't want to check device id via ((TelephonyManager) act.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId() because some devices would just give you polymorphic or dummy device ID.
Actualy, I need to check cell equipment exactly for skipping TelephonyManager.getDeviceId and performing Settings.Secure.ANDROID_ID check on those devices that don't have cellular radio. I have at least one tablet (Storage Options Scroll Excel 7") which returns different IMEIs every time you ask it, although it should return null as it has no cell radio (the same situation here: Android: getDeviceId() returns an IMEI, adb shell dumpsys iphonesubinfo returns Device ID=NULL). But I need to have reliable device id that is the same every time I ask.
I'd be glad to hear your thoughts!
If you're publishing in the store, and you want to limit your application only being visible to actual phones, you could add a <uses-feature> into your manifest that asks for android.hardware.telephony. Check out if that works for you from the documentation.
Just in case somebody needs complete solution for this:
Reflection is used because some things may not exist on some firmware versions.
MainContext - main activity context.
static public int getSDKVersion()
{
Class<?> build_versionClass = null;
try
{
build_versionClass = android.os.Build.VERSION.class;
}
catch (Exception e)
{
}
int retval = -1;
try
{
retval = (Integer) build_versionClass.getField("SDK_INT").get(build_versionClass);
}
catch (Exception e)
{
}
if (retval == -1)
retval = 3; //default 1.5
return retval;
}
static public boolean hasTelephony()
{
TelephonyManager tm = (TelephonyManager) Hub.MainContext.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null)
return false;
//devices below are phones only
if (Utils.getSDKVersion() < 5)
return true;
PackageManager pm = MainContext.getPackageManager();
if (pm == null)
return false;
boolean retval = false;
try
{
Class<?> [] parameters = new Class[1];
parameters[0] = String.class;
Method method = pm.getClass().getMethod("hasSystemFeature", parameters);
Object [] parm = new Object[1];
parm[0] = "android.hardware.telephony";
Object retValue = method.invoke(pm, parm);
if (retValue instanceof Boolean)
retval = ((Boolean) retValue).booleanValue();
else
retval = false;
}
catch (Exception e)
{
retval = false;
}
return retval;
}

Does every android phone has streetview application by default?

Does every android phone with 2.3 and above has streetview by default or one have to download the streetview and install it. The reason I am asking is that I am using streetview in my application and I use
private boolean isIntentAvailable(Intent intent) {
final PackageManager packageManager = mapView.getContext().getPackageManager();
List<ResolveInfo> list =
packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
to see if streetview application is available in the device. The problem is that in one of mobile with android 4.1.1 streetview is available but still this method throws false for that. But it works in most of the devices that I have tested like in all Samsung , HTC and sony mobiles.
Not all android devices have Google apps. It depends of the constructor
[EDIT :]
to check if an app is installed, you may use :
appInstalledOrNot("com.google.android.apps.maps")
using the method:
private boolean appInstalledOrNot(String uri) {
PackageManager pm = getPackageManager();
boolean app_installed = false;
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
app_installed = true;
} catch (PackageManager.NameNotFoundException e) {
app_installed = false;
}
return app_installed ;
}
I read somewhere that all version of Maps have Street View, but I really can not confirm this, I am not sure.

Categories

Resources