Search code examples
androidkotlinandroid-jetpack-composeandroid-jetpack-compose-preview

Multi-module Jetpack Compose UI Previews


I have the issue that whenever I have a multi-module project, all Jetpack Compose UI previews except for the ones in the app module display an additional TopAppBar with the text androidx.compose.ui.tooling.PreviewActivity when being executed on a device. You can see the result here:

Non app module preview in multi module project

When only looking at a preview without executing it, the TopAppBar does not show. The issue appears in the simplest multi-module project, where both modules only contain a single preview composable, too. This leads me to believe it's not caused by a complex setup. I already tried removing and adding various things in the build.gradle file and the manifest but nothing seems to help.

App module:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            ComposePreviewWithAdMobTheme {

            }
        }
    }
}

@Preview
@Composable
fun Preview() {
    Text("Preview!")
}

Core module:

@Preview
@Composable
fun CorePreview() {
    Text("CorePreview!")
}

As mentioned before, the app module preview works fine whilst the other shows the additional TopAppBar. Has anybody faced similar difficulties and can help me?

Thank you.


Solution

  • That is a expected behavior.

    Jetpack Compose previews run in an instrumented context and it uses the application info found in the module's AndroidManifest.xml or its androidTest source set.

    When the preview runs from the :app module it uses the main AndroidManifest.xml which contains the right android:label and android:name in the <application> tag. When it runs from a module, if it does not contain a manifest file, it uses a default one in which android:label is set to the instrumented activity full-qualified name hosting the preview. This is the one you are seeing.

    To change behavior you could just create a manifest in the androidTest source set of the module such as:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <application
            android:name=".MyInstrumetedApp"
            android:label="My app's name" />
    </manifest>
    

    The preview toolbar title will be My app's name and the application instantiated will be MyInstrumetedApp.

    Do also notice that the Application instance in the :app module won't be used either when running preview from a module.