Product Variants: Multiple Activities

9.1k Views Asked by At

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

4

There are 4 best solutions below

8
On

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.

0
On

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"
        }
    }
}
0
On

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!

0
On

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