Access protected variable of android class - android

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);

Related

Crawling Android File System gets stuck in possible SymLink loop

I'm trying to crawl the entire file system of an android device, both directories and files, without the benefit of NIO, to build a tree of it. If I had NIO then I could use WalkTree or similar, but I don't.
The problem I am having (on the Nexus 5 API 23 x86 emulator) is in /sys/bus/pci/devices and possibly other directories (eg /proc/self) - it doesn't complete before the app times out/quits/crashes (unknown which), possibly getting into some kind of loop or something (the path may change in a repetitive fashion but the canonical path varies little or not at all) .
However if I rule out Symbolic links then that problem goes away but I get what is only some of the files on the device rather than all - for example lacking files under /data (or /data/media/0) and those files not showing up elsewhere - not to mention it looks completely different from the file system that most file managers show. The former is strange as I'd understood Symbolic Links pointed to files and folders that were still present in the file system, but just made them look as if they were elsewhere.
What's the solution? Do I have to code exceptions or special handling for /sys/bus/pci/devices, /proc/self and others? I'd prefer to keep Symbolic Links being followed if I can, and I'd prefer to crawl as many files and folders as I can (so starting in a sub-folder is not preferred).
And a few related questions that might affect the approach I eventually take - if I DO keep SymLinks then does that mean that some things will be crawled twice or more? Is there a way to avoid that? Is there a way to detect when something is the TARGET of a SymLink, other than following the SymLink and checking the CanonicalPath?
Here's my code:
I get the root (I understand that in Android, the first and likely only root is the valid one):
File[] roots = File.listRoots();
String rootPath = "";
try {
rootPath = roots[0].getCanonicalPath();
} catch (IOException e) {
// do something
}
Then I start the crawl (note the boolean to choose whether to ignore simlinks or not):
try {
// check if the rootPath is null or empty, and then...
File rootFile = new File(rootPath);
rootNode = new FileFolderNode(rootFile, null, true, false); // last param may be true to ignore sim links
//FileFolderNode(String filePath, FileFolderNode parent, boolean addChildren, boolean ignoreSimLinks)
} catch (Exception e) {
// do something
}
That uses the FileFolderNode, which has constructor:
public FileFolderNode(File file, FileFolderNode parent, boolean addChildren, boolean ignoreSimLinks) throws IOException {
if (file == null)
throw new IOException("File is null in new FileFolderNode");
if (!file.exists())
throw new IOException("File '" + file.getName() + "' does not exist in new FileFolderNode");
// for now this uses isSymLink() from https://svn.apache.org/repos/asf/commons/_moved_to_git/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java adjusted a bit to remove Java 7 and Windows mentions
if (!ignoreSimLinks)
if (FileUtils.isSymlink(file))
return;
this.name = file.getName();
if (this.name.equals("") && ! file.getCanonicalPath().equals("/"))
throw new IOException("Name is empty in new FileFolderNode");
this.isDirectory = file.isDirectory();
if (this.isDirectory) {
this.children = new ArrayList<FileFolderNode>();
if (addChildren) {
File[] files = file.listFiles();
if (files == null) {
// do something
} else {
// add in children
for (File f : files) {
FileFolderNode child = null;
try {
child = new FileFolderNode(f, this, addChildren, ignoreSimLinks);
} catch (Exception e) {
child = null;
}
if (child != null)
children.add(child);
}
}
}
}
}
Given the lack of answers here, I've broken this question down into areas needing clarification, and am trying to get answers to those - please do see if you can help with those:
Get Android Filing System root
Android SymLinks to hidden or separate locations or partitions
Avoiding Android Symbolic Link loop

How to turn on the torch/flashlight with GooglePlay Services Vision API Xamarin Android

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#.

How can I pass data to libcore on Android?

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;
}

Is it possible to TextView#getMaxLines() on pre api-16 devices?

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.

Android & calling methods that current API doesnt have

If i want to get the external path like this, and device has Android 2.1 (api 7)
File f;
int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
if (sdkVersion >= 8) {
System.out.println(">=8");
f = getApplicationContext().getExternalFilesDir(null);
} else {
System.out.println("<=7");
f = Environment.getExternalStorageDirectory();
}
LogCat will display:
05-25 15:44:08.355: W/dalvikvm(16688): VFY: unable to resolve virtual method 12: Landroid/content/Context;.getExternalFilesDir (Ljava/lang/String;)Ljava/io/File;
, but app will not crush. I want to know what is VFY? Is there something in the virtual machine dalvik that checks if code inside a called method is valid? Because current proj was compiled agains Android 2.2 so Eclipse didn't complained.. but at runtime, i get LogCat entry
PS: i dont use method like this in really, i have Helper class which initialises a class for API<=7 or another for API>=8.. but still please answer!
Yes, VFY errors are logged from dex verifier in dalvik.
You are facing this issue because you are performing runtime checks for the SDK version and calling the API methods. The problem is even if the method call is inside the if(){} block which may never be executed in lower API levels, the symbolic information is present in the generated bytecode. If you need to perform platform specific function calls, you need to use reflection.
File f;
int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
if (sdkVersion >= 8) {
System.out.println(">=8");
try {
Method getExternalFilesDir = Context.class.getMethod("getExternalFilesDir", new Class[] { String.class } );
f = (File)getExternalFilesDir.invoke(getApplicationContext(), new Object[]{null});
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("<=7");
f = Environment.getExternalStorageDirectory();
}

Categories

Resources