Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you read/amend/replace AndroidManifest.xml file with a Custom Annotation Processor

I am investigating custom annotation processors for Android applications.

I have a use case where I would like to be able to use an annotation processor to read/amend the AndroidManifest.xml and add the following intent section for all Activities mentioned there in?

        <intent-filter>
            <action android:name="com.my.package.name.my_activity.open"/>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

Is this possible?

like image 857
Hector Avatar asked Oct 25 '25 07:10

Hector


2 Answers

It is a very interesting question but I don't think you could achieve such a task with an annotation processor since those work at Kotlin/Java code generation level.

How would you annotate XML @Something and have it still be valid XML?

Take a look at this:

KoltinConf18 - Annotation processing in Kotlin

Screenshot from the recorded talk on youtube

At 7:18 Zack goes over annotation processing in Java and it basically says:

  • Happens at compile time
  • And you cannot modify code, just generate more

So by using barebones annotation processing you can't really modify the already existing AndroidManifest.xml.

An alternative would be writing a Gradle plugin that generates those bits of XML and merges it with the current XML file that already exists within the project.

Something from the top of my head could be:

  1. Create an annotation and mark all activities that you want to introduce that bit of code
  2. On the plugin side; when you are writing the Gradle task; you may use reflection and figure out which classes are annotated by such extension. Or just make the programmer put those activities in a specific directory inside the source folder, which would be way easier
  3. With the fully qualified class names, you may look at the <activity> nodes in the AndroidManifest.xml, filter out the class names that don't match the list of annotated class names
  4. Modify those nodes with the piece of code you would like to inject.

To get started on how to write a Gradle plugin take a look here

A simple example to get you started could be:

Step 1

You create a separate module to write your plugin if it gets too cumbersome but for this simple example I decided to stick it right in the build.gradle.kts. It doesn't need to be a kotlin Gradle file, but I am more proficient in Kotlin than in Groovy :)

step 1

As you can see I have created a text testFile.txt in the root of the project.

In code I just navigate to it and read it; print it's content and then modify it.

You could do the very same thing with your AndroidManifes.xml. Then you would need to recursively iterate over the source files from your srcDir looking for all of those activities annotated by your special annotation and store all of the fully qualified class names inside a List<String>. Then do the necessary replacements inside the AndroidManifest

Note that with this basic configuration the Gradle task appears in the Gradle tab inside the others category, to change that is a little bit off of the scope of annotation processing.

Step 2, profit

step 2

It works, as you can see the file has been updated and the println statements show the previous content of the file before modifying it

like image 152
Some random IT boy Avatar answered Oct 26 '25 21:10

Some random IT boy


You could have a template AndroidManifest_template.xml then using a gradle task go through the AndroidManifest_template.xml and generate the real AndroidManifest.xml which would be used to build the app.

In other words, AndroidManest.xml would be a transient part of the build and you could use any XML preprocessor you want to take the template and turn it into the real file.

like image 36
user2199860 Avatar answered Oct 26 '25 23:10

user2199860