7

I'm using Product Variants in gradle/android studio to achieve the following project setup:

  1. Two apps, that are 80% similar in one android studio project.
  2. Each app should have its own manifest package path (they should basically behave like two independent apps - with it's own google api and push keys)

I've followed multiple tutorials in my attempt to achieve this (placeholders, multiple manifests) but nothing works.

Following this tutorial I did the following: http://www.kevinrschultz.com/blog/2014/03/23/using-android-content-providers-with-multiple-package-names/

My build.gradle:

android {
compileSdkVersion 19
buildToolsVersion '20'

defaultConfig {
    minSdkVersion 10
    targetSdkVersion 19
    versionCode 1
    versionName "1.0"
}

buildTypes {
    release {
        runProguard false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
    }
}

productFlavors {
    app1 {
        packageName "com.test.app1"
        //applicationId "com.test.app1"
    }

    app2 {
        packageName "com.test.app2"
        //applicationId "com.test.app2"
    }
}}

And here my manifest files.

src/main/manifest:

<?xml version="1.0" encoding="utf-8"?>

<application>
</application>

src/app1/manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:name="com.test.app1”
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name="com.test.app1.MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:screenOrientation="portrait" >
        </activity>
    </application>
</manifest>

src/app2/manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:name="com.test.app2”
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name="com.test.app2.MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:screenOrientation="portrait" >
        </activity>
    </application>
</manifest>

This gives me the following error message:

Manifest merger failed : Main AndroidManifest.xml at AndroidManifest.xml manifest:package attribute is not declared

Unfortunately I can't set a package to each individual manifest tag as my app requires different package paths. If I do it anyway, the merger is not able to merge the manifest files because of different package values. Besides packageName I also tried setting "applicationId" but this doesn't work, either. Using a placeholder like this package="${applicationId}" doesn't work because it doesn't resolve the variable value.

Any ideas how to solve this problem? I'm using Android Studio 0.8.2 with gradle 0.12.2

Opal
  • 81,889
  • 28
  • 189
  • 210
Dominik Schreiber
  • 769
  • 2
  • 15
  • 25

4 Answers4

4

You can safely add

<manifest xmlns:android="..."
  package="com.test.app">
</manifest>

in your main manifest.

But you have to use applicationId and not packageName in your build.gradle. The applicationId of the build.gradle will overwrite this value during your different builds.

A better way of doing this would be to use applicationIdSuffix instead of applicationId for your different product flavors.

The field have to be present in your main manifest.

pdegand59
  • 12,776
  • 8
  • 51
  • 58
  • This is what I get if I add package="com.test.app" and switch to applicationId. /src/app1/AndroidManifest.xml:0:0 Error: Overlay manifest:package attribute declared at AndroidManifest.xml:2:70 value=(com.test.app1) has a different value=(com.flatiron) declared in main manifest at AndroidManifest.xml:2:70 Suggestion : remove the overlay declaration at AndroidManifest.xml and place it in the build.gradle: flavorName { applicationId = "com.test.app1" } FAILED FAILURE: Build failed with an exception. – Dominik Schreiber Aug 12 '14 at 13:09
  • What if you remove the `package=""` in your main Manifest but you keep the applicationId instead of packageName in your build.gradle. What is the exact error ? – pdegand59 Aug 12 '14 at 13:13
  • src/main/AndroidManifest.xml:0:0 Error: Main AndroidManifest.xml at AndroidManifest.xml manifest:package attribute is not declared FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:processApp1DebugManifest'. > Manifest merger failed : Main AndroidManifest.xml at AndroidManifest.xml manifest:package attribute is not declared – Dominik Schreiber Aug 12 '14 at 13:16
  • I tried the following: only in src/main/manifest set to package="" (the other untouched). -> gives me the Overlay manifest error. all manifests set to package="" gives me the following error: /Users/ds/AndroidstudioProjects/TestApp/app/build/generated/source/r/app1/debug/Manifest.java:8: error: expected package ; ^ Gradle doesn't seem to replace anything in the manifest file? – Dominik Schreiber Aug 12 '14 at 13:23
  • Can you try to use the old manifest merger ? In your build.gradle, add `useOldManifestMerger true` in the android plugin bloc. I remember reading that the new one is still buggy. – pdegand59 Aug 12 '14 at 13:30
  • This is what I get if I activate the old merger and set the main package to "com.test.app", app1 to "com.test.app1" and app2 to "com.test.app2": FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:mergePassengerDebugManifests'. > Manifest merging failed. See console for more info. Unfortunately I don't see any further information in the Gradle Console, neither the ADB Logs/Logcat other than "15:37:08 Gradle build finished with 1 error(s) in 2 sec" – Dominik Schreiber Aug 12 '14 at 13:41
  • try to remove it on app1 and app2, just leave the default one. – pdegand59 Aug 12 '14 at 14:56
  • I think that pdegand59 is talking about this https://developer.android.com/studio/build/manifest-build-variables – murt Nov 02 '18 at 18:27
3

In addition to your src/app1/AndroidManifest.xml and src/app2/AndroidManifest.xml you will have a src/main/AndroidManifest.xml which can contain elements both apps share.

In your flavor-specific manifests, you do not have to specify a package attribute, since that is already defined in your build.gradle.

In your main manifest however, you need to define a package attribute, to specify the package name used for your shared resources:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.test.app">
</manifest>

Make sure that you do not have any dependent libraries, which is also using that name, or you will get another build error.

Furthermore, you will want to specify applicationId instead of packageName in you build.gradle to decouple the package name used for identification of your app from the package name used for internal resource access.

Check this link for further information: http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename

Nappy
  • 3,016
  • 27
  • 39
0

I resolved same issue putting the same package="com.ex.app" in every flavor's manifest and putting applicationId and useOldManifestMerger true into build.gradle file

android {
    useOldManifestMerger true

    productFlavors{
        app1{
            applicationId = "com.ex.app1"
        }
        app2{
            applicationId = "com.ex.app2"
        }
    }
}
ar-g
  • 3,417
  • 2
  • 28
  • 39
0

I started over fresh but this time Android Studio generated the Variant configuration for me (under project settings there's a tab for flavors, variants, etc.)

I also decided to change the package name of all three variants to the same name as the identification of each app (variant) is done by the applicationId (which has nothing to do with the actual package names of the variants).

Thanks to pdegand59 for his help!

Dominik Schreiber
  • 769
  • 2
  • 15
  • 25