Dynamic module feature and ML Kit Crash on App open

Viewed 650

App has ML Kit functionality (translation). I'm trying to reduce the app size by introducing a dynamic module feature, on demand loading.

Following this guide Added 'com.google.mlkit:playstore-dynamic-feature-support:16.0.0-beta1' to base apk's build.gradle

com.google.mlkit:translate:16.1.2 in feature module build.gradle,

everything compiles and tries to run on emulator, but unfortunately crashes on app start with log

java.lang.RuntimeException: Unable to get provider com.google.mlkit.common.internal.MlKitInitProvider: com.google.firebase.components.MissingDependencyException: Unsatisfied dependency for component Component<[class com.google.android.gms.internal.mlkit_translate.zzxa]>{0, type=0, deps=[Dependency{anInterface=class com.google.mlkit.common.sdkinternal.SharedPrefManager, type=required, injection=direct}, Dependency{anInterface=class com.google.android.gms.internal.mlkit_translate.zzwx, type=required, injection=direct}]}: class com.google.mlkit.common.sdkinternal.SharedPrefManager

 Caused by: com.google.firebase.components.MissingDependencyException: Unsatisfied dependency for component Component<[class com.google.android.gms.internal.mlkit_translate.zzxa]>{0, type=0, deps=[Dependency{anInterface=class com.google.mlkit.common.sdkinternal.SharedPrefManager, type=required, injection=direct}, Dependency{anInterface=class com.google.android.gms.internal.mlkit_translate.zzwx, type=required, injection=direct}]}: class com.google.mlkit.common.sdkinternal.SharedPrefManager
    

Which kind of does not make sense. Because I've added playstore-dynamic-feature-support.

3 Answers

Figured it out,

Step 1. disable MlKitInitProvider in app module (stops app crash)

<provider
android:name="com.google.mlkit.common.internal.MlKitInitProvider"
            android:authorities="${applicationId}.mlkitinitprovider"
            tools:node="remove"
            />

Step 2. build apk and open the app manifest, find all MLKit Registrars used in your app. Step 3. add all found to a ComponentRegistrar array ArrayList; Step 4. In the dynamic feature library, call MlKitContext.initialize(context, arr); (in getProvider the service provider) prior to using mlkit functionality;

Also, only using these mlkit dependencies in app module (for split install) api group: 'com.google.mlkit', name: 'common', version: '17.5.0' api group: 'com.google.mlkit', name: 'playstore-dynamic-feature-support', version: '16.0.0-beta1'

If someone is still not able to figure out using @Shane Gallagher's answer I am detailing out the steps: First as mentioned add Provider in app module to disable MlKit initialization:

<provider
        android:name="com.google.mlkit.common.internal.MlKitInitProvider"
        android:authorities="${applicationId}.mlkitinitprovider"
        tools:node="remove"/>

Next build apk and open your merged manifest. Find all the component registrars used in your app. You can open merged manifest by clicking on merged manifest text in bottom left corner of Android Studio after opening AndroidManifest.xml

image for reference

Next in your dynamic feature module add the following code as per the registrars used in your app

val registrars = listOf(CommonComponentRegistrar(), VisionCommonRegistrar(), BarcodeRegistrar())
MlKitContext.initialize(this, registrars)

To set up your dynamic module, you will need to move the mlkit translate dependency from the base app's gradle file to the dynamic module's gradle build file. You will also need to move all related usage to the dynamic module. Therefore, when app start up, it won't look for any mlkit translate dependency. Please refer to the play store on demand delivery guide for step to step set up guidance.

Related