avatarRick Buiten

Summary

The article outlines a seven-step process for developing a Google Instant app using Hilt for dependency injection, emphasizing the importance of user value and proper server and module configuration.

Abstract

The article, titled "This is how to develop a Google Instant app in 7 steps with Hilt," provides a detailed guide for developers looking to implement Instant app functionality. It begins by explaining the purpose of Instant apps, which allow users to access app features without installation, and references a previous article for foundational knowledge. The author shares their experience integrating an Instant app into the existing EcoScan app, highlighting the added user value by enabling quick waste sorting advice through QR code scanning. The steps include server configuration with Digital Asset Links, creating feature modules, Gradle configuration with Hilt integration, customizing the Android manifest, and testing the app. The article also discusses the importance of considering the necessity of an Instant app for user experience, the use of separate modules for Instant app logic, and the manual initialization of Hilt due to compatibility issues. The process concludes with building the app bundle and deploying it to the Google Play Store, with additional resources provided for further guidance.

Opinions

  • The author believes that the primary consideration for developing an Instant app should be the added value for the user, as it may not be worth the investment if it does not enhance user experience.
  • They suggest that using separate modules for Instant app functionality is necessary due to size limitations and to maintain clear logic separation.
  • The author emphasizes the importance of proper server configuration with Digital Asset Links to ensure Google recognizes the Instant app.
  • They note that while there are various tutorials available, the development process for Instant apps has evolved, necessitating updated guidance.
  • The article conveys that manual initialization of Hilt is required for Instant apps due to limitations with annotations like @AndroidEntryPoint.
  • The author encourages developers to test the Instant app thoroughly and to expect and resolve issues that may arise during development.
  • They recommend deploying the app bundle to the Google Play Store only after extensive testing and ensuring functionality.
  • The author offers additional help and suggests following them and considering Medium membership for access to more resources and support.

This is how to develop a Google Instant app in 7 steps with Hilt

Google Instants app — How to implement it

An instant app is a functionality that allows users to use your app without having to install it. This is part 2 of the Instant app series. Do you want more information about Instant apps? Then read the article here.

How do you start? That’s the question we asked ourselves last year when we decided to add an Instant app to our existing EcoScan app (www.EcoScanApp.eu). This is an app that helps users to sort waste their waste. Users simply take a photo or scan the barcode and we will tell them in which container it belongs based on their location.

Do I need an Instant app?

The most important thing is that you should first ask yourself whether it has added value for the user, otherwise it is better not to invest time in it. For EcoScan there was added value for the user. We enable manufacturers to provide location-based advice for their customers. Their customers could scan a QR code, which then opens the Instant app. The user can therefore quickly see in which container the waste belongs without having to download the app first.

There are already various tutorials that you can use for developing an Instant app, but things have been modified in recent years in terms of development, so that it often worked differently now.

This are the steps I took to get it working on production.

  1. Server configuration

Before you start modifying the code, make sure that Google knows that an instant app is present. You do this by adding the Digital Asset Links JSON file to your website. The location is <>/. well-known/assetlinks.json. The file looks like this:

[
  {
    "relation": [
      "delegate_permission/common.handle_all_urls"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "<<your app package name>>",
      "sha256_cert_fingerprints": [
        "<<your certificated fingerprint>>"
      ]
    }
  }
]

2. Add modules (feature module)

After you have added the configuration file to your server, you could go on with creating the Instant app. Due to the size limitation of the app bundle, it is necessary to put the Instant functionality in a separate module. In addition, it is wise to make a separate module for the logic that is necessary in both modules, for example the style of your app.

You create an Instant module by going to File > New > New module in Android Studio. In the screen that now appears, select the template “Instant Dynamic Feature”. Adjust the information in the screen and click Finish.

If you would like to have a seperate module you could add it as well.

3. Gradle configuration

After creating the module(s) some adjustments are still needed in the gradle file. Add the following in the Instant module:

plugin {
  id id 'kotlin-kapt'
}
android {
  dataBinding {
    enabled true
  }
/* if you have compileoptions / kotlinOptions / productflavors add them here as well */
}
dependencies {
  implementation project(":app")
  implementation "javax.inject:javax.inject:1"
  implementation "com.google.android.gms:play-services-instantapps:$instant_version"
  implementation "com.google.dagger:hilt-android:$hilt_version"
  implementation "androidx.appcompat:appcompat:$appcompat_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

4. Configuration Hilt

In our project we use Hilt as a dependency injection framework. In the app module it is therefore necessary to add all references that we need in our Instant app. This way you can use them in your Instant app. The class look like this:

@EntryPoint
@InstallIn(SingletonComponent::class)
interface FeatureValidateBarcodeModuleDependencies {
    fun hasUserInfo(): HasUserInfo
    fun registerAnonymous(): RegisterAnonymous
}

This should be places within the app module.

5. Add or move Instant Functionality

This depends on the app you are going to develop. I have chosen to use a separate Activity. The view could be like this but probably you would a more complex view. This is just for demo purpose.

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

    <data>

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">
        
        <TextView
            android:id="@+id/hello_world"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
</layout>

This screen looks like this:

class ValidateBarcodeActivity : AppCompatActivity() {

    private lateinit var binding: ActivityValidateBarcodeBinding

    @Inject
    lateinit var hasUserInfo: HasUserInfo

    @Inject
    lateinit var registerAnonymous: RegisterAnonymous

    override fun onCreate(savedInstanceState: Bundle?) {
        handleInject()
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_validate_barcode)

        if (hasUserInfo()) {
            handleFeature()
        } else {
            registerAnonymous().observe(this, {
                if (it.status == Result.Status.SUCCESS) {
                    handleFeature()
                }
            })
        }
    }

    private fun handleFeature() {
        if (InstantApps.getPackageManagerCompat(this).isInstantApp) {
            intent.data?.let {
                // TODO handle url for instant
                binding.helloWorld.text = "Hello Instant world"
            }
        } else {
            intent.data?.let {
                // TODO handle url for normal app
                binding.helloWorld.text = "Hello App world"
            }
        }
    }

    private fun handleInject() {
        DaggerValidateBarcodeComponent.builder()
            .context(this)
            .appDependencies(
                EntryPointAccessors.fromApplication(
                    applicationContext,
                    FeatureValidateBarcodeModuleDependencies::class.java
                )
            )
            .build()
            .inject(this)
    }
}

The most important code is InstantApps.getPackageManagerCompat(this).isInstantApp.

This check could be used to check if the app is an instant app or the normal app as the activity could also be used within the app itself.

As you can see we have to init Hilt manually. This is because we couldn’t use the @AndroidEntryPoint within the Instant app.

@Component(
    dependencies = [FeatureValidateBarcodeModuleDependencies::class]
)
interface ValidateBarcodeComponent {

    fun inject(activity: ValidateBarcodeActivity)

    @Component.Builder
    interface Builder {
        fun context(@BindsInstance context: Context): Builder
        fun appDependencies(featureValidateBarcodeModuleDependencies: FeatureValidateBarcodeModuleDependencies): Builder
        fun build(): ValidateBarcodeComponent
    }
}

6. Customize Android manifest

To open an Instant app you need to edit the Android Manifest file. Here you enter the URL and the Activity that should be started. In addition, it is necessary to add a default URL as meta data as well. This URL will be used as URL when the user clicks on the “Try Now” button in the details screen of your app in the Google play store. The Instant module AndroidManifest.xml looks like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:dist="http://schemas.android.com/apk/distribution"
    package="<<package name feature>>"
    android:targetSandboxVersion="2">

    <dist:module
        dist:instant="true"
        dist:onDemand="false"
        dist:title="@string/app_name">
        <dist:fusing dist:include="true" />
    </dist:module>

    <application>
        <activity
            android:name="<<package name>>.ValidateBarcodeActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
          
            <intent-filter
                android:autoVerify="true"
                android:order="1">
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />

                <data android:host="<<domain>>" />
                <data android:pathPrefix="/validate-barcode" />
                <data android:scheme="https" />
                <data android:scheme="http" />

            </intent-filter>
            <meta-data
                android:name="default-url"
                android:value="https://<<domain>>/validate-barcode" />
        </activity>

        <!-- other activities that are used within the instant module -->
    </application>
</manifest>

Tests

After you have added the above code, you could test the app. You do this in Android Studio by selecting the Instant app and click on Run. If it’s not added yet, you could add it manually. Click on “Edit configuration” and click on the + button and select the Instant module.

tip: just make sure the normal app is not on your phone.

After installing the app on your device the Instant app could be run via the command line.

adb shell am start -a android.intent.action.VIEW -d “<>”

Does it work right away? Then you did the job very well!

It probably won’t work the first time and you will have to solve a few problems. Please let us know, so we can add this and help others get it working quickly and smooth!

7. Create a build

After your app works, it’s time to create the App Bundle. You do this with the gradle command:

./gradlew app:bundle<>Release

In our case that is:

./gradlew app:bundleProductionRelease

Deploy in Play store

After you have tested the functionality, you can publish it to the Play Store.

Do you want to know how that works? Read that in this article.

Do you like the article? Please give it a clap and follow me! Have you tried everything but it still doesn’t work? Let me know so I can help you. You could also send me a message on LinkedIn.

To get access to unlimited stories, you can also consider signing up to become a Medium member for just $5 a month or $50 a year. If you sign up using my link, I’ll receive a small commission (with no extra cost for you, so thank you!)

AndroidDev
Android App Development
Android Tutorials
Instant Apps
Recycling Business
Recommended from ReadMedium