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.
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 was modifying the libcore on Andorid for debugging purpose.
It took a lot of time to build even for a variable change.
Is it possible to pass the data to libcore of android?
(so I can change the data in the running time).
I tried System.getProperty() but the data could not cross process.
I also tried SystemProperties.get() but it seems it can not be used in libcore (it could not find the package and symbol).
Does anyone know how to pass data to the libcore on Android?
Thanks Nativ.
JNI is doable but a little complicated for me.
Finally, I used a simple, easy but stupid way to do that.
I created a file and saved my parameter in this file, and get the data from libcore.
It is a stupid way but worked for me for debugging.
Now I don't need to rebuild libcore and It saved much for me.
You can use reflection on class android.os.SystemProperties to get System Properties at runtime.
Code example:
public static String getSystemProperty(String key) {
String value = "";
try {
Class clazz = Class.forName("android.os.SystemProperties");
if (clazz != null) {
Object object = clazz.newInstance();
value = (String) (clazz.getMethod("get", String.class).invoke(object, key));
} else {
System.err.println(TAG + ", getSystemProperty: Class is null.");
}
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
Recently I complied the source code of adw-launcher, some of the class of this project use protected variable of android classes.
Below is a code snippet:
#Override
protected boolean setFrame(int left, int top, int right, int bottom) {
if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
mBackgroundSizeChanged = true;
}
return super.setFrame(left, top, right, bottom);
}
mLeft, mRight are all protected.
How to go about this ?
I am totally noob in this, need your guidance.
I went through this link: How do I build the Android SDK with hidden and internal APIs available?
If I replace new jar file, hope it will access these new files, will I have to alter these files ? I just don't have any idea.
Thanks
You can't access protected members outside their packages - this is by design of Java.
You might be able to access it using Java reflection, but this isn't advisable.
Field[] f = ClassName.getClass().getDeclaredFields();
Then, simply f[i].setAccessible(true) to allow yourself to read from them. But this definitely isn't advisable unless truly needed.
Android SDK hidden classes are only available to framework level apps/code. You need to link framework.jar and framework2.jar with your code to access hidden APIs. But then also your app might raise a Security Exception at runtime.
As suggested in link you provided you will have to build source to obtain those jars. Those protected variables must be coming from base class. If i understand your question correctly that base class might be coming from framework jars.
You may use powerful (and dangerous) Reflection API of Java at your own risk!
try {
Field field = TargetClass.class.getDeclaredField(fieldName);
field.setAccessible(true);
result = field.get(targetObject);
field.setAccessible(false);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
to get result as int :
int result = field.getInt(targetObject);
Background
I've noticed a weird column for MediaStore.Images.ImageColumns called "MINI_THUMB_MAGIC" .
the documentation says just that :
The mini thumb id.
Type: INTEGER
Constant Value: "mini_thumb_magic"
The question
my guess is that this field is related to MediaStore.Images.Thumbnails .
Is it correct ? if not, what is this and how do you use it?
if it is correct , i have other questions related to it:
Is it a mini sized image of the original one? does it use the same aspect ratio or does it do center-cropping on it?
how come the size of "MICRO" is square (96 x 96) and the size of "MINI" is a non-square rectangle ( 512 x 384 ) ?
How do you use it? My guess is that it's done by using "THUMB_DATA", which is a blob, so you use it like this, but then what is the purpose of using "getThumbnail" if you already have this field?
does it get a rotated thumbnail in case the orientation value is not 0 ? meaning that if I wish to show it, I won't need to rotate the image?
Is it possible to do a query of the images together with their thumbnails? maybe using inner join?
Is it available for all Android devices and versions?
Why is it even called "magic" ? Is it because it's also available for videos (and for some reason doesn't exist for music, as it could be the album's cover photo, for example) ?
Check this file: https://github.com/android/platform_packages_providers_mediaprovider/blob/master/src/com/android/providers/media/MediaThumbRequest.java in the Android source code. This value is some magic number which allows to determine if the thumbnail is still valid. I didn't investigate that file further, but it should be no bit issue to dive deeper.
To your questions:
No, no mini-sized image
Well, I guess it's a definition by Google who want to have a square thumbnail for some lists, where only very small previews should be visible and where many items should fit on the screen and there's another thumbnail format where the images are bigger...
I don't know that, but according to Google's doc, one (THUMB_DATA) is only some raw byte array of the thumbnail (dunno in which format) and the other one (getThumbnail) retrieves a full-fledged bitmap object...
don't know
don't know
I guess so, as it's part of AOSP source code.
The word "magic" is often used for some kind of identifier. There are "magic packets" who can wake up a computer from sleep or shutdown over the network, there are magic numbers on hard disks, where some sectors (e.g. the MBR) has the hexadecimal values AA 55 on its last two byte positions, there are also magic numbers in image files which help software packages determine the image type (e.g. GIF files begin with GIF89a or GIF87a (ASCII), JPEG files begin with FF D8 hexadecimal) and there are many, many more examples. So, magic numbers are a very common term here :-)
According to the source code at the following URL, the Magic Number is the Id of the original image * a constant. That value is then used to check for a long int. If the int isn't as expected, it's considered out of sync with the image media.
http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/4.4_r1-robolectric-0/android/media/MiniThumbFile.java#MiniThumbFile.getMagic%28long%29
// Get the magic number for the specified id in the mini-thumb file.
// Returns 0 if the magic is not available.
public synchronized long getMagic(long id) {
// check the mini thumb file for the right data. Right is
// defined as having the right magic number at the offset
// reserved for this "id".
RandomAccessFile r = miniThumbDataFile();
if (r != null) {
long pos = id * BYTES_PER_MINTHUMB;
FileLock lock = null;
try {
mBuffer.clear();
mBuffer.limit(1 + 8);
lock = mChannel.lock(pos, 1 + 8, true);
// check that we can read the following 9 bytes
// (1 for the "status" and 8 for the long)
if (mChannel.read(mBuffer, pos) == 9) {
mBuffer.position(0);
if (mBuffer.get() == 1) {
return mBuffer.getLong();
}
}
} catch (IOException ex) {
Log.v(TAG, "Got exception checking file magic: ", ex);
} catch (RuntimeException ex) {
// Other NIO related exception like disk full, read only channel..etc
Log.e(TAG, "Got exception when reading magic, id = " + id +
", disk full or mount read-only? " + ex.getClass());
} finally {
try {
if (lock != null) lock.release();
}
catch (IOException ex) {
// ignore it.
}
}
}
return 0;
}
I got the runtime exception when trying to get the original Id of a thumbnail by looking up the thumbnail's path. (BTW, the disk isn't full and it's not read-only.)
It's a bit strange parameter...
While exploring the Gallery source code,
noticed that the value is being read from the cursor, but then is Never used:
#Override
protected BaseImage loadImageFromCursor(Cursor cursor) {
long id = cursor.getLong(INDEX_ID);
String dataPath = cursor.getString(INDEX_DATA_PATH);
long dateTaken = cursor.getLong(INDEX_DATE_TAKEN);
if (dateTaken == 0) {
dateTaken = cursor.getLong(INDEX_DATE_MODIFIED) * 1000;
}
// here they read it ====>>
long miniThumbMagic = cursor.getLong(INDEX_MINI_THUMB_MAGIC);
int orientation = cursor.getInt(INDEX_ORIENTATION);
String title = cursor.getString(INDEX_TITLE);
String mimeType = cursor.getString(INDEX_MIME_TYPE);
if (title == null || title.length() == 0) {
title = dataPath;
}
// and not use at all ==>>>
return new Image(this, mContentResolver, id, cursor.getPosition(),
contentUri(id), dataPath, mimeType, dateTaken, title,
orientation);
}
Maybe it was used on the previous APIs.
ref: https://android.googlesource.com/platform/packages/apps/Gallery/+/android-8.0.0_r12/src/com/android/camera/gallery/ImageList.java?autodive=0%2F%2F.
and videos list:
https://android.googlesource.com/platform/packages/apps/Gallery/+/android-8.0.0_r12/src/com/android/camera/gallery/VideoList.java?autodive=0%2F%2F
I'm trying to determine if a String represents a Double. I expect the following code to throw a NumberFormatException:
String s = "type1234";
try {
Double val = Double.parseDouble(s);
} catch (NumberFormatException e) {
// Handle exception
e.printStackTrace();
}
Instead, val ends up with Infinity. I ran the code in a standard JVM and it does, indeed, throw NumberFormatException
It looks like Android is ignoring the leading characters 'typ' and then parsing it as e^1234, which is out of Double's range.
Is this the expected behavior? If so, what is a more reliable way to determine if a String can be parsed as a Double?
Use a regular expression to validate yourself if you don't trust the framework. Here's an example of one way to do this.
// You can get much fancier than this to handle all cases, but this should handle most
String regexDouble = "^-?\\d*(\\.\\d+)?$";
boolean isDouble = val.matches(regexDouble);
Fastest way to check if a String can be parsed to Double in Java
The answer on this post works on android. I have tested it on ICS.