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
}
Related
I have been trying to implement the flashlight/torch feature of the camera using the GooglePlay Services Vision API (using Nuget from Visual Studio) for the past few days without success. I have noticed that there is a GitHub implementation of this API which has such functionality but that is only available to Java users.
I was wondering if there is anything related to C# Xamarin users.
The Camera object is not made available on this API therefore I am not able to alter the Camera parameters needed to activate the flashlight.
I would like to be sure if that functionality is not available so I don't waste more time over this. It just might be the case that the Xamarin developers have not attended to this functionality and they might in a near future.
UPDATE
https://github.com/googlesamples/android-vision/blob/master/visionSamples/barcode-reader/app/src/main/java/com/google/android/gms/samples/vision/barcodereader/BarcodeCaptureActivity.java
In there you can see that on line 214 we have such method call:
mCameraSource = builder.setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null).build();
SetFlashMode is not a method of the CameraSource in Nuget, but it is on the GitHub (open source version).
Xamarin Vision Library Didn't expose the method to set Flash Mode.
WorkAround.
Using Reflection. You can get the Camera Object from CameraSouce and add the flash parameter then set the updated parameters to the camera.
This should be called after surfaceview has been created
Code
public Camera getCameraObject (CameraSource _camSource)
{
Field [] cFields = _camSource.Class.GetDeclaredFields ();
Camera _cam = null;
try {
foreach (Field item in cFields) {
if (item.Name.Equals ("zzbNN")) {
Console.WriteLine ("Camera");
item.Accessible = true;
try {
_cam = (Camera)item.Get (_camSource);
} catch (Exception e) {
Logger.LogException (this, e);
}
}
}
} catch (Exception e) {
Logger.LogException (this, e);
}
return _cam;
}
public void setFlash (bool isEnable)
{
try {
isTorch = !isEnable;
var _cam = getCameraObject (mCameraSource);
if (_cam == null) return;
var _pareMeters = _cam.GetParameters ();
var _listOfSuppo = _cam.GetParameters ().SupportedFlashModes;
_pareMeters.FlashMode = isTorch ? _listOfSuppo [0] : _listOfSuppo [3];
_cam.SetParameters (_pareMeters);
} catch (Exception e) {
Logger.LogException (this, e);
}
}
Basically, anything you can do with Android can be done with Xamarin.Android. All the underlying APIs area available.
Since you have existing Java code, you can create a binding project that enables you to call the code from your Xamarin.Android project. Here's a good article on how to get started: Binding a Java Library
On the other hand, I don't think you need a library to do what you want to. If you only want torch/flashlight functionality, you just need to adapt the Java code from this answer to work in Xamarin.Android with C#.
I used TextView#getMaxLines() in my application for a few weeks without incident.
Lint is now informing me that it's only available in API 16+ (#setMaxLines() is API 1+...), though (to the best of my knowledge) I haven't modified anything that would cause this sudden flag - my min-sdk has been 8 for a while, and I have files in my source control to prove it.
1) Why could lint be flagging this error randomly? (To be clear, I mean to say that it should have caught it initially - I'm not implying this is something that it shouldn't have flagged at all).
2) Is there any way to retrieve the maxLines for a TextView on pre-api 16 devices? I checked the source but couldn't devise a way to retrieve this value using the exposed methods on a 2.2 device.
A simpler solution was added to the support lib v4 inTextViewCompat
int maxLines = TextViewCompat.getMaxLines(yourtextView);
Check out this answer for some more informations.
You can use Reflection:
Field mMaximumField = null;
Field mMaxModeField = null;
try {
mMaximumField = text.getClass().getDeclaredField("mMaximum");
mMaxModeField = text.getClass().getDeclaredField("mMaxMode");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
if (mMaximumField != null && mMaxModeField != null) {
mMaximumField.setAccessible(true);
mMaxModeField.setAccessible(true);
try {
final int mMaximum = mMaximumField.getInt(text); // Maximum value
final int mMaxMode = mMaxModeField.getInt(text); // Maximum mode value
if (mMaxMode == 1) { // LINES is 1
text.setText(Integer.toString(mMaximum));
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
OR:
Maybe, the best way is keep maxLine value at values and set it value in xml, and get as int resource in code.
The code for that method simply doesn't exist on 2.2, so you can't use it directly of course.
On the other hand, I've run a diff on the two files and it seems as though the new 4.2.2 TextView isn't using any new APIs internally (this is based solely on its imports). You may be able to add it as a class in your project and use it instead of the inbuilt TextView across all version of 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
I know listview can set scrollbar thumb in XML like this Android:scrollbarThumbVertical etc.
But I'm creating a listview instance in the java code and I maybe need to set different scrollbar thumb. Is there a method can set scrollbar thumb programmatically?
You can achieve that via reflection:
try
{
Field mScrollCacheField = View.class.getDeclaredField("mScrollCache");
mScrollCacheField.setAccessible(true);
Object mScrollCache = mScrollCacheField.get(listview);
Field scrollBarField = mScrollCache.getClass().getDeclaredField("scrollBar");
scrollBarField.setAccessible(true);
Object scrollBar = scrollBarField.get(mScrollCache);
Method method = scrollBar.getClass().getDeclaredMethod("setVerticalThumbDrawable", Drawable.class);
method.setAccessible(true);
method.invoke(scrollBar, getResources().getDrawable(R.drawable.scrollbar_style));
}
catch(Exception e)
{
e.printStackTrace();
}
The above code executes as:
listview.mScrollCache.scrollBar.setVerticalThumbDrawable(getResources().getDrawable(R.drawable.scrollbar_style));
I modified the answer to make it a method 100% programmatically
public static void ChangeColorScrollBar(View Scroll, int Color, Context cxt){
try
{
Field mScrollCacheField = View.class.getDeclaredField("mScrollCache");
mScrollCacheField.setAccessible(true);
Object mScrollCache = mScrollCacheField.get(Scroll);
Field scrollBarField = mScrollCache.getClass().getDeclaredField("scrollBar");
scrollBarField.setAccessible(true);
Object scrollBar = scrollBarField.get(mScrollCache);
Method method = scrollBar.getClass().getDeclaredMethod("setVerticalThumbDrawable", Drawable.class);
method.setAccessible(true);
Drawable[] layers = new Drawable[1];
ShapeDrawable sd1 = new ShapeDrawable(new RectShape());
sd1.getPaint().setColor(cxt.getResources().getColor(Color));
sd1.setIntrinsicWidth(Math.round(cxt.getResources().getDimension(R.dimen.dp_3)));
layers[0] = sd1;
method.invoke(scrollBar, layers);
}
catch(Exception e)
{
e.printStackTrace();
}
}
I didn't know the answer to this, but after a bit of digging around I don't think it's possible without a load of hassle.
This xml attribute is actually associated with a View, not a ListView - In the Android View source code, it seems that the only place that it is setting the vertical thumb drawable is the 'initializeScrollbars' method. Now this method isn't private, so we can extend any child of View and override this method, but the issue is that a crucial component needed to set the thumb drawable, the ScrollabilityCache, is private without any getter methods.
So without rewriting a lot of the code I don't think there's any easy way to do this - sorry!
Starting from Android Q (API level 29), you can use setVerticalScrollbarThumbDrawable() & setHorizontalScrollbarThumbDrawable():
scrollView.verticalScrollbarThumbDrawable =
ResourcesCompat.getDrawable(resources,
R.drawable.scrollview_thumb, null)
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).