- Learn Java for Android Development: Reflection Basics
- What You’ll Need
- Why Use Reflection?
- Inspecting Classes
- Inspecting the Constructors Available Within a Class
- Inspecting the Fields Available Within a Class
- Inspecting the Methods Available Within a Class
- Inspecting Inner Classes
- Inspecting Member Modifiers
- Inspecting Class Metadata
- Reflection: Handy for Debugging
- Why Not To Use Reflection
- Wrapping Up
- Mirror: Easy Reflection for Java and Android
- What is Mirror?
- Example: Using the method doCoolStuff() from class PrivateCoolClass
- Download
- What’s next?
- Notes:
- Is reflection useful for Android?
- 4 Answers 4
- How is an Android activity instantiated (using reflection)?
- 4 Answers 4
Learn Java for Android Development: Reflection Basics
In this tutorial, you’ll become familiar with the concept of Java reflection: the ability of a class or object to examine details about its own implementation programmatically.
Android applications are written in the Java, a programming language that supports reflection—the ability of an object to examine itself. In this tutorial, you’ll learn the basics of Java reflection, including how to inspect the methods and fields of a given class, check for the availability of specific methods, and other practical tasks you may need to use when developing for different versions of the Android SDK.
What You’ll Need
Technically, you don’t need any tools to complete this tutorial but you will certainly need them to develop Android applications.
To develop Android applications (or any Java applications, for that matter), you need a development environment to write and build applications. Eclipse is a very popular development environment (IDE) for Java and the preferred IDE for Android development. It’s freely available for Windows, Mac, and Linux operating systems.
For complete instructions on how to install Eclipse (including which versions are supported) and the Android SDK, see the Android developer website.
Why Use Reflection?
Reflection gives developers the flexibility to inspect and determine API characteristics at runtime, instead of compile time. Within the security constraints imposed by Java (e.g. use of public, protected, private), you can then construct objects, access fields, and invoke methods dynamically. The Java Reflection APIs are available as part of the java.lang.reflect package, which is included within the Android SDK for developers to use.
So what does this have to do with Android development? Well, with each new version of the Android SDK, classes, interfaces, methods, etc. are added, updated, and (less frequently) removed. However, Android developers often want to target devices running different versions of Android with a simple application package. To do this, Android developers may use reflection techniques to determine, at runtime, if a specific class or method is available before trying to use it. This allows the developer to leverage new APIs where available while still supporting the older devices—all in the same application.
Inspecting Classes
Java classes are represented at runtime using the Class (java.lang.Class) class. This class provides the starting point for all reflection APIs. Within this class, you’ll find many methods for inspecting different aspects of a class, such as its fields, constructors, methods, permissions, and more. You can also use the Class method called forName() to load a non-primitive class (e.g. not int, but Integer) by name dynamically at runtime, instead of at compile time:
The class (in this case, NotificationManager) need not have the corresponding import statement in your code; you are not compiling in this class into your application. Instead, the class loader will load the class dynamically at runtime, if possible. You can then inspect this Class object and use the reflection techniques described in the rest of this tutorial.
Inspecting the Constructors Available Within a Class
You can inspect the constructors available within a given Class. To get just the constructors that are publicly available, use getConstructors(). However, if you want to inspect those methods specifically declared within the class, whether they are public or not, use getDeclaredConstructors() instead. Both methods return an array of Constructor (java.lang.reflect.Constructor) objects.
For example, the following code iterates through the declared constructors of a class:
Once you have a valid Constructor object, you can inspect its parameters and even declare a new instance of the class using that constructor with the newInstance() method.
Inspecting the Fields Available Within a Class
You can inspect the fields (or attributes) available within a given Class. To get just the methods that are publicly available, including inherited fields, use getFields(). However, if you want to inspect those fields specifically declared within the class (and not inherited ones), whether they are public or not, use getDeclaredFields() instead. Both methods return an array of Field (java.lang.reflect.Field) objects.
For example, the following code iterates through the declared fields of a class:
You can also check for a specific public field by name using the getField() method. For example, to check for the EXTRA_CHANGED_PACKAGE_LIST field of the Intent class (which was added in API Level 8, or Android 2.2), you could use:
Once you have a valid Field object, you can get its name using the toGenericString() method. If you have the appropriate permissions, you can also access the value of that class field using the appropriate get() and set() methods.
Inspecting the Methods Available Within a Class
You can inspect the methods available within a given Class. To get just the methods that are publicly available, including inherited methods, use getMethods(). However, if you want to inspect those methods specifically declared within the class (without inherited ones), whether they are public or not, use getDeclaredMethods() instead. Both methods return an array of Method (java.lang.reflect.Method) objects.
For example, the following code iterates through the declared methods of a class:
Once you have a valid Method object, you can get its name using the toGenericString() method. You can also examine the parameters used by the method and the exceptions it can throw. Finally, if you have the appropriate permissions, you can also call the method using the invoke() method.
Inspecting Inner Classes
You can inspect the inner classes defined within a Class using getDeclaredClasses() method. This method will return an array of Class (java.lang.class) objects declared within the parent class. These classes can then be inspected like any other.
Inspecting Member Modifiers
You can also inspect the flags and security settings—called modifiers—associated with a given Class, Field, or Method using the getModifiers() method. Interesting modifiers include whether the component is public, private, protected, abstract, final, or static (amongst others).
For example, the following code checks the security modifiers of a class:
Keep in mind that you cannot dynamically access or invoke any class, method, or field using reflection that you would not normally be able to access at compile-time. In other words, regular class security is still applied at runtime.
Inspecting Class Metadata
You can also inspect the metadata—called annotations—associated with a given class, field or method using the getAnnotations() method. Interesting metadata associated with a class might include information about deprecation, warnings, and overrides, among other things.
For example, the following code checks the metadata available for the AbsoluteLayout class. Since this class was deprecated in Android 1.5, one of the annotations returned is @java.lang.Deprecated() when this code is run on Android 2.2:
Similarly, you could simply check for the existence of a specific annotation, such as deprecation, by its type:
Reflection: Handy for Debugging
You can also use reflection to assist with debugging. For example, you might want to use the class keyword to access the underlying class data for a given type:
You can also get class information from a variable instance using the getClass() method of the Object class (which is therefore inherited by all classes in Java):
If you want to check the class of a variable, using instanceof is more appropriate. See the previous tutorial on instanceof for more details.
Similarly, you might want to use the getClass() method with the this keyword to check the name of the class you’re currently in and include this information as part of your debug logging to LogCat:
Why Not To Use Reflection
As you’ve seen, reflection can be used to great effect, especially when you are unsure if a specific class or method is available at compile time. Reflection does, however, have some drawbacks, including reduced performance and the loss of the strong typing and safe coding practices enforced at compile time. It’s best to use reflection sparingly, but do use it when needed.
Wrapping Up
Reflection is a powerful tool that Java developers can use to explore packages and APIs programmatically at runtime. While reflection operations come at a cost, they give the developer the flexibility that is sometimes essential for getting the job done. Android developers frequently use these simple reflection techniques to test for the availability of specific classes, interfaces, methods, and fields at runtime, enabling them to support different versions.
Источник
Mirror: Easy Reflection for Java and Android
I’ve been working on Android for a while, and it’s been many years that I must do some tweaking and hacking to call private APIs (using Java Reflection, for good and bad reasons). I got fed up of writing the same twenty lines of code to call one single method. So, during a hackathon organized by Genymobile, my buddy Florent Noël and I decided to try fixing this issue over a weekend. We came up with a solution called Mirror.
What is Mirror?
Mirror is a Java library allowing you to write interfaces with annotations — à la Retrofit — to avoid the pain of the reflection API.
- Simplicity → Only annotations: no painful API to learn or remember.
- Readability → Separate the reflection from the code using it.
- Auto Wrapping → Mirror object methods can return mirror objects.
- Lightweight → only 12 ko.
Example: Using the method doCoolStuff() from class PrivateCoolClass
Here’s a piece of code using the Java Reflection API:
All exceptions could be caught in one statement but you get the idea. It’s barely readable, all the reflection gets in the way of what you are trying to achieve and you have to remember how to use it every time.
With Mirror , the reflection API is totally invisible. First, we need to declare an interface that will represent the Java class we want to use:
Some explanations here:
- The private class is specified by the @Class annotation.
- As we need to retrieve an instance of the private class at some point, we need a method annotated with @Constructor and the same signature as an existing constructor.
- Other methods are declared with the exact same signature as the private class.
Once this is done, we are able to do the exact same things as the code above with only a few lines of code:
If you’d like more information on feature and capabilities, please check the README.
Download
Mirror is available on Jcenter! If you are using Gradle add this line to the dependencies of your module:
What’s next?
We coded that 2 years ago and just open-sourced it today. We are using it from time to time to debug, prototype or hack things. There is still some work to be done to cover 100% of what is possible to do with reflection and performances can probably be improved greatly. Maybe a 2.0 with code generation or other fancy stuff, we’ll see…
Anyway, feel free to give it a try and let me know if you encounter any issues. Cheers!
Notes:
- As an alternative you can also have a look at FEST-Reflect
- Save sharks!
Liked what you saw? Hit that ❤ and follow me 🤓
Источник
Is reflection useful for Android?
I learnt a bit about reflection after reading about it in some tpics here. From what I understands, it is used to check the avaibility of a certain class/method/field at runtime. But is it really useful in Android ? Android provide us with the api version at runtime and we can know if a particular class/method or field is available by reading the Android doc (or with error message with Android Studio).
I understand how it can be useful with Java in general, but is there any meaning to use it in Android?
4 Answers 4
Reflection (in every languages) is very powerful.
In Android most of time reflection is not needed, because you can find Security Exceptions, problems. It depends on what You do.
If you use undocumented classes, libs, you can use it, and it’s very useful.
Sometimes, to do particular things, like turn on/off 3g on old device, change device language, you need rooted device to use reflection.
Finally, depends always on what You do.
Sometimes it works , and some times it does’t work .
E.T work example : You can reflect the method to hang off a phone call (there are a lot example codes on Internet so I won’t copy the code.).
Doesn’t work example: If you want to switch data connect status , use reflection works on 4.4 but will not work on 5.0 because it’s a binder connection, the BN will check Permission the app granted , but this permission only granted to system app . So if your app is a third part app,on 5.0 you can’t use reflection to switch data connect status.
Источник
How is an Android activity instantiated (using reflection)?
Got asked this today in an Android interview. I answered the usual, you know, intent + startActivity, etc. Interviewer then asked more pointedly,
«Yes, but where is it actually instantiated? You don’t call new Activity anywhere».
Which now that I think about it, I don’t really know. He hinted that it used Java reflection, but I dont have a lot of experience with that, and I’ve only used it to access some variables in the Android SDK.
Can someone explain how Activities are instantiated using reflection, and why? Bonus points for insight into what value the interviewer saw in knowing this.
4 Answers 4
When an app’s launcher icon is clicked on homescreen, following event happens under the android system :
- Homescreen/Launcher app sends an intent to start an activity using startActivity()(startActivity() is binder call to ActivityManager)
- Activity Manager sends a process fork request using a socket to Zygote.
- Zygote forks a new VM instance that loads ActivityThread(Activity thread manages the execution of the main thread in an application process, scheduling and executing activities, broadcasts, and other operations on it as the activity manager requests.).
- ActivityThread has real main() for an app.
- ActivityThread calls the app’s onCreate().
Hence ActivityThread is responsible for instantiating Activity(inside performLaunchActivity method)
Источник