Alternate to hasPermanentMenuKey() for Android 2.3.3 - android

I am building my App with API level 10. But it can be installed and used in later versions. I need to show Action Bar only if the device does not have menu button. For Example, Tablets, Google Galaxy Nexus Phone, etc. People suggest to use hasPermanentMenuKey() function. But it is available only after API level 14 I guess. Can anyone suggest me how to get around this issue?
Thanks,
Karthik

Use Below code :
ViewConfiguration.get(context).hasPermanentMenuKey();
First set your build target to API level 14 or UP that will stop Eclipse from getting Any Error while Using above code.
Now Check your API Level
Case 1. if your API level : 10 and less
the device does have hardware menu button.
Case 2. if your API level : 11 to 13(HoneyComb)
the device doesn't have HW MENU button, because tablets with Honeycomb
doesn't have MENU.
Case 3. if your API level : 14 or Higher
If the API level is 14 or higher, you can use hasPermanentMenuKey().
Hope it will some how help you.

This should work for all devices on the market:
public static boolean hasPermanentKeys(Activity activity) {
//
int height=0;
int realHeight=0;
WindowManager w = activity.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
// since SDK_INT = 1;
height = metrics.heightPixels;
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
try {
realHeight = (Integer) Display.class.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 17)
try {
Point realSize = new Point();
Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
realHeight = realSize.y;
} catch (Exception ignored) {
}
if(height == realHeight){
return true;
}
else{
return false;
}
}

although its an old post but if anyone comes across this here is a solution that could be used from support-v4 library (from library version 24.2.0 it will support upto API-9):
ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(context))
https://developer.android.com/topic/libraries/support-library/index.html

Related

Android: PackageManager.getSystemAvailableFeatures() is not working as expected on Nexus9

I am trying to get all the available system features on my Nexus9 device using PackageManager.getSystemAvailableFeatures().
From Android 5.0 Lollipop, Google introduced new camera APIs (camera2). I think Nexus9 is using Camera2 APIs.
When I am running this API on Nexus9 device it is not listing camera2 APIs features like:
android.hardware.camera.level.full
android.hardware.camera.capability.manual_post_processing
android.hardware.camera.capability.manual_sensor
android.hardware.camera.capability.raw
I am using below code to get all the available features:
public final static boolean isFeatureAvailable(Context context, String feature) {
final PackageManager packageManager = context.getPackageManager();
final FeatureInfo[] featuresList = packageManager.getSystemAvailableFeatures();
for (FeatureInfo f : featuresList) {
if (f.name != null && f.name.equals(feature)) {
return true;
}
}
return false;
}
Questions:
Is Nexus9 using & having camera2 API features?
If answer is yes for above question, then Why it is not listing these system level features? I am doing something wrong?
Thanks for your comments in advance!
Is Nexus9 using & having camera2 API features?
Yes. All Android Lollipop devices and newer have the camera2 APIs.
If answer is yes for above question, then Why it is not listing these system level features?
Supported APIs are usually not included in the system features list. Most system features are related to things that can vary from device to device and are usually related to hardware features (e.g. sensors, bluetooth, NFC, etc) or system-wide software support (e.g. backup, device management, multi-user, etc). There's a list of all supported capabilities here.
I am doing something wrong?
According to the docs, the recommended way to check if the camera2 APIs exist is by requesting the camera service via:
CameraManager cameraManager = (CameraManager) getSystemService("camera");
Basically this method returns null if the camera2 APIs aren't available, either because the version of Android is too old (sdkVersion < 21) or because they've been removed from the system (e.g. via a custom ROM).
Finally I was able to get answers to my questions.
Is Nexus9 using & having camera2 API features?
Ans: Yes Nexus9 is having and using Camera2 APIs. It has LIMITED supported hardware level and has capabilities: BACKWARD_COMPATIBLE and MANUAL_SENSOR
If answer is yes for above question, then Why it is not listing these system level features? I am doing something wrong?
Ans: Because using above code I am listing features not capabilities. To list down the capabilities I used below code:
Activity activity = getActivity();
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
if (characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) {
Log.d("Camera2 SUPPORTED_HARDWARE_LEVEL: ", "FULL");
} else if (characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
Log.d("Camera2 SUPPORTED_HARDWARE_LEVEL: ", "LEGACY");
} else if(characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
Log.d("Camera2 SUPPORTED_HARDWARE_LEVEL: ", "LIMITED");
}
StringBuilder stringBuilder = new StringBuilder();
for (int i=0; i<characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES).length; i++) {
if(characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)[i] ==CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
stringBuilder.append("BACKWARD_COMPATIBLE" + " ");
} else if (characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)[i] ==CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING) {
stringBuilder.append("MANUAL_POST_PROCESSING" + " ");
} else if(characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)[i] ==CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) {
stringBuilder.append("MANUAL_SENSOR" + " ");
} else if (characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)[i] ==CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW) {
stringBuilder.append("RAW" + " ");
}
}
Log.d("Camera2: ", stringBuilder.toString());

How to know a process of an app is 32-bit or 64-bit programmatically in Android lollipop?

As we all know from Android 5.0.64bit support is there. I have very simple question. Can we check programmatically in what mode any application is running i.e. 32bit or 64bit? For example: I have Facebook app running on my Nexus 9, so can I check using my android app if Facebook app's process is running in 32bit mode or 64bit mode?
In Nexus 5x
String arch = System.getProperty("os.arch");
returns
armv8l
it is not aarch64 and my code broke. However,
root#bullhead:/ # uname -m
aarch64
root#bullhead:/ # getprop ro.product.cpu.abilist
arm64-v8a,armeabi-v7a,armeabi
Wired. So I changed my code to
boolean is64 = (android.os.Build.VERSION.SDK_INT >= 21) && System.getProperty("ro.product.cpu.abilist").contains("64");
Updated on 2016-02-11
In Samsung Samsung Galaxy S5 Neo, Android 5.1.1
String arch = System.getProperty("os.arch");
returns aarch64 but it is not 64-bit device!!!
ro.product.cpu.abilist returns armeabi-v7a,armeabi
bool is64Bit = System.getProperty("ro.product.cpu.abilist").contains("64");
check is the only way to check.
Try System.getProperty("os.arch").
I haven't tried it on 64-bit android, but it must return something like 'aarch64' in case of 64 bit device.
http://developer.android.com/reference/java/lang/System.html#getProperty(java.lang.String)
public static boolean is64Bit() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Added in API level 23
return Process.is64Bit();
}
try {
Class cls = Class.forName("dalvik.system.VMRuntime");
Method getRuntimeMethod = cls.getDeclaredMethod("getRuntime");
Object vmRuntime = getRuntimeMethod.invoke(null);
Method is64BitMethod = cls.getDeclaredMethod("is64Bit");
Object is64Bit = is64BitMethod.invoke(vmRuntime);
if (is64Bit instanceof Boolean) {
return (boolean) is64Bit;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
IMO, you can use reflect to get the result of is64Bit. Android 6.0 began to provide this api to check your process.
android.os.Process.is64Bit()
In my experience (if your minSdkVersion is >= 21) the best way is to check the size of the array Build.SUPPORTED_64_BIT_ABIS.
(see https://developer.android.com/reference/android/os/Build#SUPPORTED_64_BIT_ABIS)
Something like this:
public static boolean is64Bit() {
return (Build.SUPPORTED_64_BIT_ABIS!= null && Build.SUPPORTED_64_BIT_ABIS.length >0);
}
What makes you think your device isn't 64-bit? The specs for the phone indicate it uses an Exynos 7 Octa 7580 which is arm8 and 64-bit.
boolean is64Arch = Build.CPU_ABI.equalsIgnoreCase("x86_64") || Build.CPU_ABI.equalsIgnoreCase("arm64-v8a");

Get GridView horizontal spacing on Android 4.0

Is there any way to determine the horizontal spacing used by a GridView on Android 4.0.3 (API level 15)?
I have some working code targeting 4.1.x that uses GridView.GetRequestedHorizontalSpacing(), but this doesn't exist prior to API 16. Is there an equivalent to this, or a way to calculate it, on API level 15?
you can get it using Reflection API.
GridView gridView = (GridView) findViewById(R.id.gridView);
try {
Field field = gridView.getClass().getDeclaredField("mHorizontalSpacing");
field.setAccessible(true);
int hSpacing = field.getInt(gridView);
field = gridView.getClass().getDeclaredField("mRequestedHorizontalSpacing");
field.setAccessible(true);
int reqHSpacing = field.getInt(gridView);
} catch (Exception e) {
// TODO: handle exception
}

To get android os version at run time [duplicate]

Does anyone know how can I check the system version (e.g. 1.0, 2.2, etc.) programatically?
Example how to use it:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
// only for gingerbread and newer versions
}
Check android.os.Build.VERSION.
CODENAME: The current development codename, or the string "REL" if this is a release build.
INCREMENTAL: The internal value used by the underlying source control to represent this build.
RELEASE: The user-visible version string.
Build.Version is the place go to for this data. Here is a code snippet for how to format it.
public String getAndroidVersion() {
String release = Build.VERSION.RELEASE;
int sdkVersion = Build.VERSION.SDK_INT;
return "Android SDK: " + sdkVersion + " (" + release +")";
}
Looks like this "Android SDK: 19 (4.4.4)"
For checking device version which is greater than or equal to Marshmallow ,use this code.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
}
for ckecking others just change the VERSION_CODES like,
K for kitkat,
L for loolipop
N for Nougat and so on...
Build.VERSION.RELEASE;
That will give you the actual numbers of your version; aka 2.3.3 or 2.2.
The problem with using Build.VERSION.SDK_INT is if you have a rooted phone or custom rom, you could have a none standard OS (aka my android is running 2.3.5) and that will return a null when using Build.VERSION.SDK_INT so Build.VERSION.RELEASE will work no matter what!
You can find out the Android version looking at Build.VERSION.
The documentation recommends you check Build.VERSION.SDK_INT against the values in Build.VERSION_CODES.
This is fine as long as you realise that Build.VERSION.SDK_INT was only introduced in API Level 4, which is to say Android 1.6 (Donut). So this won't affect you, but if you did want your app to run on Android 1.5 or earlier then you would have to use the deprecated Build.VERSION.SDK instead.
I can't comment on the answers, but there is a huge mistake in Kaushik's answer:
SDK_INT is not the same as system version but actually refers to API Level.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH){
//this code will be executed on devices running ICS or later
}
The value Build.VERSION_CODES.ICE_CREAM_SANDWICH equals 14.
14 is the API level of Ice Cream Sandwich, while the system version is 4.0. So if you write 4.0, your code will be executed on all devices starting from Donut, because 4 is the API level of Donut (Build.VERSION_CODES.DONUT equals 4).
if(Build.VERSION.SDK_INT >= 4.0){
//this code will be executed on devices running on DONUT (NOT ICS) or later
}
This example is a reason why using 'magic number' is a bad habit.
Be aware that Build.VERSION.SDK_INT isn't reliable, it's mentioned by #Falcon165o and recently I ran into that one too.
So to get the String data (based on Android version list) of currently installed android, I made a code like this:
Java
//Current Android version data
public static String currentVersion(){
double release=Double.parseDouble(Build.VERSION.RELEASE.replaceAll("(\\d+[.]\\d+)(.*)","$1"));
String codeName="Unsupported";//below Jelly Bean
if(release >= 4.1 && release < 4.4) codeName = "Jelly Bean";
else if(release < 5) codeName="Kit Kat";
else if(release < 6) codeName="Lollipop";
else if(release < 7) codeName="Marshmallow";
else if(release < 8) codeName="Nougat";
else if(release < 9) codeName="Oreo";
else if(release < 10) codeName="Pie";
else if(release >= 10) codeName="Android "+((int)release);//since API 29 no more candy code names
return codeName+" v"+release+", API Level: "+Build.VERSION.SDK_INT;
}
Kotlin
fun currentVersion(): String {
val release = java.lang.Double.parseDouble(java.lang.String(Build.VERSION.RELEASE).replaceAll("(\\d+[.]\\d+)(.*)", "$1"))
var codeName = "Unsupported"//below Jelly Bean
if (release >= 4.1 && release < 4.4) codeName = "Jelly Bean"
else if (release < 5) codeName = "Kit Kat"
else if (release < 6) codeName = "Lollipop"
else if (release < 7) codeName = "Marshmallow"
else if (release < 8) codeName = "Nougat"
else if (release < 9) codeName = "Oreo"
else if (release < 10) codeName = "Pie"
else if (release >= 10) codeName = "Android "+(release.toInt())//since API 29 no more candy code names
return codeName + " v" + release + ", API Level: " + Build.VERSION.SDK_INT
}
Example of an output it produce:
Marshmallow v6.0, API Level: 23
For example, a feature only works for api21 up the following we fix bugs in api21 down
if(Build.VERSION.SDK_INT >= 21) {
//only api 21 above
}else{
//only api 21 down
}
if (Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.HONEYCOMB_MR2) {
//do anything you like.
}
Use This method:
public static String getAndroidVersion() {
String versionName = "";
try {
versionName = String.valueOf(Build.VERSION.RELEASE);
} catch (Exception e) {
e.printStackTrace();
}
return versionName;
}
use this class
import android.os.Build;
/**
* Created by MOMANI on 2016/04/14.
*/
public class AndroidVersionUtil {
public static int getApiVersion() {
return android.os.Build.VERSION.SDK_INT;
}
public static boolean isApiVersionGraterOrEqual(int thisVersion) {
return android.os.Build.VERSION.SDK_INT >= thisVersion;
}
}
Given you have bash on your android device, you can use this bash function :
function androidCodeName {
androidRelease=$(getprop ro.build.version.release)
androidCodeName=$(getprop ro.build.version.codename)
# Time "androidRelease" x10 to test it as an integer
case $androidRelease in
[0-9].[0-9]|[0-9].[0-9].|[0-9].[0-9].[0-9]) androidRelease=$(echo $androidRelease | cut -d. -f1-2 | tr -d .);;
[0-9].) androidRelease=$(echo $androidRelease | sed 's/\./0/');;
[0-9]) androidRelease+="0";;
esac
[ -n "$androidRelease" ] && [ $androidCodeName = REL ] && {
# Do not use "androidCodeName" when it equals to "REL" but infer it from "androidRelease"
androidCodeName=""
case $androidRelease in
10) androidCodeName+=NoCodename;;
11) androidCodeName+="Petit Four";;
15) androidCodeName+=Cupcake;;
20|21) androidCodeName+=Eclair;;
22) androidCodeName+=FroYo;;
23) androidCodeName+=Gingerbread;;
30|31|32) androidCodeName+=Honeycomb;;
40) androidCodeName+="Ice Cream Sandwich";;
41|42|43) androidCodeName+="Jelly Bean";;
44) androidCodeName+=KitKat;;
50|51) androidCodeName+=Lollipop;;
60) androidCodeName+=Marshmallow;;
70|71) androidCodeName+=Nougat;;
80|81) androidCodeName+=Oreo;;
90) androidCodeName+=Pie;;
100) androidCodeName+=ToBeReleased;;
*) androidCodeName=unknown;;
esac
}
echo $androidCodeName
}
According to Android documentation:
Build.VERSION.RELEASE – "The user-visible version string. E.g., "1.0"
or "3.4b5" or "bananas""
In order to get a plain Android version (2.3, 5.1, 12.0, etc) I use this function:
private fun getVersion(): Float {
val release = Build.VERSION.RELEASE
val parsedVersion = "\\d+(\\.\\d+)?".toRegex()
.find(release)?.value
if (parsedVersion.isNullOrBlank()) return 0f
return try {
parsedVersion.toFloat()
} catch (e: Exception) {
0f
}
}

Retrieving Android API version programmatically

Is there any way to get the API version that the phone is currently running?
As described in the Android documentation, the SDK level (integer) the phone is running is available in:
android.os.Build.VERSION.SDK_INT
The class corresponding to this int is in the android.os.Build.VERSION_CODES class.
Code example:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
// Do something for lollipop and above versions
} else{
// do something for phones running an SDK before lollipop
}
Edit: This SDK_INT is available since Donut (android 1.6 / API4) so make sure your application is not retro-compatible with Cupcake (android 1.5 / API3) when you use it or your application will crash (thanks to Programmer Bruce for the precision).
Corresponding android documentation is here and here
Very easy:
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
int version = Build.VERSION.SDK_INT;
String versionRelease = Build.VERSION.RELEASE;
Log.e("MyActivity", "manufacturer " + manufacturer
+ " \n model " + model
+ " \n version " + version
+ " \n versionRelease " + versionRelease
);
Output:
E/MyActivity: manufacturer ManufacturerX
model SM-T310
version 19
versionRelease 4.4.2
Build.VERSION.RELEASE;
That will give you the actual numbers of your version; aka 2.3.3 or 2.2.
The problem with using Build.VERSION.SDK_INT is if you have a rooted phone or custom rom, you could have a non standard OS (aka my android is running 2.3.5) and that will return a null when using Build.VERSION.SDK_INT so Build.VERSION.RELEASE will work no matter using standard Android version or not !
To use it, you could just do this;
String androidOS = Build.VERSION.RELEASE;
try this:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
// only for gingerbread and newer versions
}
Taking into account all said, here is the code I use for detecting if device has Froyo or newer Android OS (2.2+):
public static boolean froyoOrNewer() {
// SDK_INT is introduced in 1.6 (API Level 4) so code referencing that would fail
// Also we can't use SDK_INT since some modified ROMs play around with this value, RELEASE is most versatile variable
if (android.os.Build.VERSION.RELEASE.startsWith("1.") ||
android.os.Build.VERSION.RELEASE.startsWith("2.0") ||
android.os.Build.VERSION.RELEASE.startsWith("2.1"))
return false;
return true;
}
Obviously, you can modify that if condition to take into account 1.0 & 1.5 versions of Android in case you need generic checker. You will probably end up with something like this:
// returns true if current Android OS on device is >= verCode
public static boolean androidMinimum(int verCode) {
if (android.os.Build.VERSION.RELEASE.startsWith("1.0"))
return verCode == 1;
else if (android.os.Build.VERSION.RELEASE.startsWith("1.1")) {
return verCode <= 2;
} else if (android.os.Build.VERSION.RELEASE.startsWith("1.5")) {
return verCode <= 3;
} else {
return android.os.Build.VERSION.SDK_INT >= verCode;
}
}
Let me know if code is not working for you.
android.os.Build.VERSION.SDK should give you the value of the API Level. You can easily find the mapping from api level to android version in the android documentation. I believe, 8 is for 2.2, 7 for 2.1, and so on.
SDK.INT is supported for Android 1.6 and up
SDK is supported for all versions
So I do:
String sdk_version_number = android.os.Build.VERSION.SDK;
Credits to: CommonsWare over this answer
Got it. Its using the getApplicationInfo() method of the Context class.
I generally prefer to add these codes in a function to get the Android version:
int whichAndroidVersion;
whichAndroidVersion= Build.VERSION.SDK_INT;
textView.setText("" + whichAndroidVersion); //If you don't use "" then app crashes.
For example, that code above will set the text into my textView as "29" now.
i prefer have the version as number to be handeled more easyway than i wrote this:
public static float getAPIVerison() {
Float f = null;
try {
StringBuilder strBuild = new StringBuilder();
strBuild.append(android.os.Build.VERSION.RELEASE.substring(0, 2));
f = new Float(strBuild.toString());
} catch (NumberFormatException e) {
Log.e("", "error retriving api version" + e.getMessage());
}
return f.floatValue();
}
I improved code i used
public static float getAPIVerison() {
float f=1f;
try {
StringBuilder strBuild = new StringBuilder();
strBuild.append(android.os.Build.VERSION.RELEASE.substring(0, 2));
f= Float.valueOf(strBuild.toString());
} catch (NumberFormatException e) {
Log.e("myApp", "error retriving api version" + e.getMessage());
}
return f;
}
Like this:
String versionRelease = BuildConfig.VERSION_NAME;
versionRelease :- 2.1.17
Please make sure your import package is correct ( import package your_application_package_name, otherwise it will not work properly).

Categories

Resources