JRebel for Android enables live Android development by skipping the time consuming build and install steps each time you make a change. Early access for JRebel for Android has been available for nearly a month. Now is a good time to look under the hood and understand how JRebel for Android works it magic.
Android Studio plugin
The plugin is available directly from the JetBrains repositories. The plugin performs automatic configuration for Gradle based projects and allows running the application with JRebel for Android.
It adds the commands for Run, Debug and Apply changes with JRebel for Android. The JRebel for Android console displays all relevant messages.
In addition, we have made it super easy to send feedback and issue bug reports via Tools > JRebel for Android > Send feedback.
Once you hit Run with JRebel for Android for the first time, we check whether the Gradle scripts include the JRebel for Android Gradle plugin. The plugin then creates new JRebel for Android tasks within the build. These let JRebel understand the project structure as well as enable the IDE plugin to trigger the right Gradle tasks when applying changes.
It is important to note that JRebel for Android only adds these tasks to build variants with debuggable build types. Production builds intended for Google Play are not affected. JRebel for Android supports all Android phones and tablets running Android version 4.0 or newer.
Installing an application with JRebel for Android
To allow updating the application code during runtime, we need to process the classes and add our agent to the APK. The agent will be used to receive changed classes and resources. In order to reduce the startup time, we have made changes to how our APK gets built.
Our Gradle plugin adds the new
jrebelPrepareDebug task that builds an APK, but skips dexing! Therefore, the APK built does not include any .dex files. It still includes all the relevant APK files: the manifest, resources, .so libraries, and so on.
We can now prepare this shell APK (with no application .dex files, hence the name), install it and start it on the device while still processing application code. This is when the Droid takes off on the JRebel for Android rocket ship!
Once the shell APK is installed, all previously processed application code is dexed and sent to the agent. As the very last step, the application is started.
- The shell APK is created (containing the JRebel for Android agent, without application .dex files, but with everything else relevant to the APK).
- The shell APK is installed.
- The processed application code is dexed and sent to the agent.
- Application is started.
The application is now running with full functionality and is ready to receive changes from the IDE.
Once you have made some changes to your code or resources, hit the Apply changes with JRebel for Android button. This invokes the
jrebelCompileDebug Gradle task. It does everything a normal Gradle build would, all the way to Java compilation. This includes rebuilding any libraries in the project and reprocessing the resources.
All the changes are packaged and forwarded to the agent via adb (Android Debug Bridge). The agent applies these changes. To make sure that the app is using the latest resources, the agent will call Activity.recreate for the top-most activity in the activity stack. This will make the activity go through the song and dance it usually does when the device configuration changes (for instance when you rotate the device). This also means that the most important code in an activity gets called again (the
So for example, while making your UI look pixel perfect, there is no need to build a new APK each time you would like to see change. Also, the application and activity states are preserved so there is no need for re-navigation. Just make sure you handle your
onSaveInstance states the way they are meant to be!
JRebel for Android supports applying most Java and resource changes to a running app. There are still gaps like updating the manifest or changing a superclass. Sometimes you just want to test your startup logic or rerun the app after a crash. In these cases, the app needs to be restarted and possibly re-installed. Since processing all the classes again and sending them to the device takes a while, we have implemented a way to make development faster in these cases by using incremental installs.
Incremental installs follow the same logic as applying changes during runtime. We only send the changed classes and resources to the device. If the manifest has changed, we will install the shell APK again — the app still has the classes on the device so it is faster than a clean install. Once again, our agent will apply the changes sent, but instead of an activity restart we will restart the entire application with the latest code present on the device.
To sum up
JRebel for Android has come a long way since its inception about a year ago. During this time, we have matured the product from a shaky proof of concept to a solid, professional tool. The interest in JRebel for Android has been incredible, from the beta, to the early access phase and beyond. We expect JRebel for Android to become a permanent addition to any Android developer toolset. Want to see it in action for yourself?