How to use the new manifest merger (of Android Studio and Gradle)?
Asked Answered
D

2

24

Background

In the past, when Eclipse&ADT were the official tools to develop for Android, you could simply use "manifestmerger.enabled=true" inside the "project.properties" of the app's project, and you got it merging all of the libraries' manifests automatically (and I've posted about it here).

This worked, sometimes. It had a lot of weird issues, and I always preferred to just avoid using it, and put what is needed into the main manifest file manually.

The problem

Somewhere on 2014, Google announced that the new Android-Studio (0.1 I think), together with Gradle, will allow you to choose exactly how to perform merging of libraries' components.

However, the new instructions (link here) are very complex and I really (really) tried to understand how to use them, and also didn't find samples of how to use them.

It's not that I didn't understand anything, but I'm not sure if I understood well.

What I've found

On the bright side, I've found out that merging is done completely automatically, so if you have a BroadcastReceiver on the library's manifest (and as a class, of course), it will be added to the app's project that uses it.

The question

I can't simply ask everything to be explained. I think it will be enough to ask those questions:

  1. How can I choose which app components (permissions, activities,...) to be ignored from being auto-merged?

  2. How can I point override app components (of the library) attributes (on the app's project) ? for example the theme of the activities?

  3. Is there a way to completely disable the auto-merger for the manifest files?

  4. What happens with manifests of dependencies that are inside repositories? Are they merged too?

  5. Are there any tutorials/samples/videos regarding this new (well new for me) feature?

  6. Are there any things I should be aware of when using the auto-merger?

I hope those questions are representative enough, informative enough, yet not too hard to answer for people who know.

Doublespace answered 6/1, 2015 at 0:21 Comment(0)
A
46

1. Disabling elements

You can always explicitly disable permissions and features in your app's manifest and override any library values. And i found that you can disable elements from library.

Example

Consider the following code from the above link:

<activity-alias android:name="foo.bar.alias">
    <meta-data 
        android:name="zoo"
        tools:node="remove" />
</activity-alias>

By having this code inside your manifest you ensure that the merger finds any <activity-alias> elements with android:name="foo.bar.alias" attribute and removes a <meta-data> element if it has the android:name="zoo" attribute. It removes just the "zoo" meta data. Not the activity alias. If you specify this in your main manifest it will be effective on anything that has been merged so far (elements from libraries).

Example #2

Since you requested an example with activities, this is what I've come up with:

<activity android:name="com.example.ui.MyActivity" tools:node="remove" />

This line will make the merger remove any activities with android:name="com.example.ui.MyActivity" attribute that have been merged so far. So if you specify this in your main manifest it will effectively remove any com.example.ui.MyActivity entries that might have been merged from libraries.

2. Overriding attributes from library

The order in which the values are merged are described here. Basically, it goes like this: libraries, then main manifest, then flavors and build types manifests if you use those.

What are build types?

The default are "debug" and "release". You can define your own and override settings like signing or proguard. For your purposes you could say it's the equivalent of run configurations.

It works like this: you put your default and shared values inside the main manifest. Then in flavor manifests you override the values you need. Google "gradle flavors" for more info.

The following example is taken from a previous version of manifest merger documentation.

Override an attribute coming from a library

Using tools:replace="x, y, z" will override x,y,z attributes from the imported library’s activity XML declarations.

Higher Priority declaration

<activity
    android:name="com.foo.bar.ActivityOne"
    android:screenOrientation="portrait"
    android:theme="@theme1"
    tools:replace="theme"/>

with a lower priority declaration :

<activity
    android:name="com.foo.bar.ActivityOne"
    android:theme="@olddogtheme"
    android:windowSoftInputMode="stateUnchanged"
    android:exported="true">

will result in :

<activity
    android:name="com.foo.bar.ActivityOne"
    android:screenOrientation="portrait"
    android:theme="@theme1"
    android:windowSoftInputMode="stateUnchanged"
    android:exported="true"/>

3. Disabling manifest merger altogether

See Disable Manifest Merger in Android Gradle Build.

android.applicationVariants.all { variant ->
    variant.processResources.manifestFile = file('src/main/AndroidManifest.xml')
    variant.processManifest.enabled=false
}

In what file do you put this?

At the end of your module's (not root project) build.gradle.

4. Are manifests from dependencies merged?

Yes they are (they're libraries).

Is there a way to block merging certain library manifests?

Not that I know of, sorry.

5. Any tutorials?

Depends on what are you trying to achive. So far it always worked for me out-of-the-box.

I don't know about any videos.

6. Anything I should be aware of?

You can check the generated manifest if you get suspicious about extra permissions etc. It's located in project/module/build/intermediates/manifests/full/[flavor]/build-type/AndroidManifest.xml.

Source: https://developer.android.com/studio/build/manifest-merge

Airliah answered 6/1, 2015 at 1:22 Comment(10)
1. What's the "zoo" for ? 2. What are the "built types"? Is it the equivalent to run-configurations as used on Eclipse? For each of them I can choose even what to merge? 3. in which file do you put what the answer wrote (Here: https://mcmap.net/q/582533/-disable-manifest-merger-in-android-gradle-build) ? 4. is there a way to block merging manifests of certain libraries? or at least be notified when anything is added there? 5. I don't understand. I mean tutorials/videos regarding the manifest merging. 6. where? Is it on "\app\build\outputs\apk\manifest-merger-debug-report" ? Seems quite messy. Doesn't it show via the UI?Doublespace
1. The "zoo" is on the link you've provided: android:name=”zoo” . 2-6. OK. Thank you. BTW, you have a typo "sauce" instead of "source".Doublespace
Oh, right, it's an example name. In the first example the metadata with name "zoo" of activity "foo.bar.alias" will be removed. In the second example the value will be changed. Ad the typo: It's intentional, notice the pronunciation is the same :)Airliah
An example name of what? Why does it need a name, if it's removed? The examples show only activity-aliases, but isn't it more common to remove activities? I don't understand what is going on there.Doublespace
Ok, another example: You want to remove activity with name "com.example.ui.MyActivity". You write <activity android:name="com.example.ui.MyActivity" tools:node="remove"/>. Is it clear now? It needs name because the merger needs to know what to remove. You can apply these operations on any element in the manifest root element.Airliah
Yes, but for some reason, they got just "zoo", and also a metadata that has it. Why is there a metadata, and what is the "zoo" inside of it? Why can't it be as short as you've written? There isn't even an example on the section you've pointed to, that looks like what you've written. Perhaps it would be better to put here the answers?Doublespace
I've added some code examples to the answer #1 with clear explanation of how to use them and what they do. Please understand that it's an example. Don't ask "why is this piece of code there", ask "what does this piece of code do". Both examples do something completely different.Airliah
Oh, so the example there was for removing metadata ? Odd, I was expecting more commonly used things first.Doublespace
Can I also override manifest XML declarations like 'uses-permission' -> #27963289 ?Fencer
You should be able to modify any child of the root element manifest.Airliah
E
0

Some of the links in this thread are obsolete. Here's the main one that is updated related to auto merger of manifests, by gradle, for Android AARs.

https://developer.android.com/studio/build/manifest-merge

Enkindle answered 22/10, 2018 at 15:44 Comment(2)
I've updated the links in my answer. Please note that Stack Overflow is not a classic forum and this is not a thread. If instead you had left a comment on my post, I'd have got a notification and could have fixed the problem two years earlier. Thanks anywayAirliah
Thanks for updating your answer Eugen. And for explaining the advantages of using comments. 👍Enkindle

© 2022 - 2024 — McMap. All rights reserved.