googlesamples / mlkit

A collection of sample apps to demonstrate how to use Google's ML Kit APIs on Android and iOS
Apache License 2.0
3.58k stars 2.93k forks source link

IllegalStateException: MlKitContext has not been initialized #264

Closed ber4444 closed 3 years ago

ber4444 commented 3 years ago

I'm also getting a IllegalStateException: MlKitContext has not been initialized crash in EntityExtraction.getClient which is called in Application.onCreate.

How do I declare the content provider in the manifest? The need for it is called out at https://developers.google.com/android/reference/com/google/mlkit/common/MlKit#initialize(android.content.Context) but the syntax is not explained.

There is no provider in the sample https://github.com/googlesamples/mlkit/blob/master/android/entityextraction/app/src/main/AndroidManifest.xml

sheepmaster commented 3 years ago

You don't need to explicitly declare the content provider, as it wouldn't run anyway before you access the entity extraction API. You need to manually initialize ML Kit in Application.onCreate() using the MlKit.initialize() method you linked to, passing in the application itself.

ber4444 commented 3 years ago

Bleh, if I do that, I get IllegalStateException: MlKitContext is already initialized

sheepmaster commented 3 years ago

Hm, maybe the order in which content providers and the application are created is not deterministic… If you do explicitly initialize ML Kit, you could try disabling the content provider in the manifest by adding the following to your AndroidManifest.xml under the <application> tag:

<provider
    android:name="com.google.mlkit.common.internal.MlKitInitProvider"
    tools:node="remove" />

(But please manually verify that the provider is not in the manifest for the final APK; I've only written this down from memory, not tested it.)

And all of that being said, the simplest solution would be to not call ML Kit APIs right away when your application is created, but only later e.g. when the Activity is launched, if that is possible :)

ber4444 commented 3 years ago

We cannot wait until our Activity is launched with EntityExtraction.getClient(options).downloadModelIfNeeded() because download takes potentially a long time so we'd be blocking the user

For now we'll be doing

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

and let us know if a better solution is documented.

sheepmaster commented 3 years ago

I would do tools:node="remove" instead of android:enabled="false", but otherwise that is likely to be the best solution.

khosbayar-b commented 1 year ago

@sheepmaster it is weird that we are getting MlKitContext has not been initialized even though we haven't disabled content provider and not manually initializing MlKitContext. Do you have any idea?

sheepmaster commented 1 year ago

That is weird indeed! A couple of things to check: 1) Is the content provider declaration showing up in the final APKs manifest? It could be that something about manifest merging is not working. 2) As above, are you maybe trying to use ML Kit APIs before or during Application creation? In that case the content provider might not have been initialized yet.

In any case, manually initializing ML Kit before you call ML Kit APIs should always work.

khosbayar-b commented 1 year ago

Hey @sheepmaster , thanks for quick reply, really appreciate your support.

I will check number one, but just to clarify: Did you mean the AndroidManifest.xml of com.google.mlkit:barcode-scanning? If so, I'm not really able to locate it. Or did you mean by this com.google.android.gms? (I have created separate issue about this on #644 for more context)

Another weird thing is that it was just working fine and then suddenly happened without any update or change (I'm suspecting this device tho - which says Armor 11 5G - might be specific to this device only).

sheepmaster commented 1 year ago

Hi Khosbayar, I meant the AndroidManifest.xml in the final built APK of your app.

khosbayar-b commented 1 year ago

Oh actually, yes, i can see it is declared in the final built APK's AndroidManifest.xml

DoTheMonkeyBusiness commented 1 year ago

Hi! @sheepmaster Today I faced the same behaviour in my app that uses MLKit TextRecognition. We don't disable content provider and do not manually initialize MlKitContex as @khosbayar-b has already mentioned and the provider is decclared in our manifest(in the final built APK). It just happened ones today and after reinstalling the app the issue dissapeared. 🤔

GonzalezVictorJavier commented 9 months ago

Hi! @sheepmaster, please could you helpme with some doubts... sometimes i have this issue when i check MLKit barcode module availability at startUp.

sheepmaster commented 9 months ago

Hey, I'm no longer on this project, but all the comment that you linked means is that the passed Context is not required to be the application context, but it is allowed to be.

GonzalezVictorJavier commented 9 months ago

Oh great, thanks for the fast response. I have another one please... i got this error at to places: 1- Startup, becase i check MLkit barcode module availability 2- At the scanner setup so.. i'll implement MLKit.initialize(context) at startup check.... but suppose that this init fail... I should implement it at setupScanner too? Thanks in advance

sheepmaster commented 9 months ago

Hm, do you have concrete evidence that explicit initialization is failing? (As opposed to an ML Kit API failing because ML Kit hasn't been initialized yet.)

I can't think of many ways in which explicit initialization might fail initially but succeed later – if it does fail, there would be something majorly wrong with the app. Conversely, it should be okay to just do explicit initialization once and not try to gracefully handle failure.

GonzalezVictorJavier commented 9 months ago

@sheepmaster sorry about the delayed response and thanks for the support... Well... actually i'm not worry about an explicit initialization fail... the thing is i'm working on a library.. and the initialization is at the app that implement my library. I'm sure that the this app initialize MLKit... but i can't be sure about apps that will do it in the future. So, just in case, i wanted to add a second initialization (Where i use MLKit).

Indeed, i saw that the is ->

MLKitContext.initializeIfNeeded(Context)
and
MLKitContext.initializeIfNeeded(Context, Registers)

I'm gonna try this.. but i'm a little scary about these registers

sheepmaster commented 9 months ago

Part of me wants to say that failing to properly initialize ML Kit is the app's problem 😝 Usually, the content provider that will do that automatically at startup should be merged into the app's manifest and everything should work (and the app developer would need to take explicit steps to disable that behavior, at which point they're shooting themselves in the foot).

But ok, if you really want to ensure that ML Kit is initialized, MLKitContext.initializeIfNeeded(Context) can be called even after initialization, and it will just do nothing in that case (hence the "ifNeeded" part). The other overload is internal and should not be used (and will likely break things if you don't pass the right set of components).

(In general, the rule is that only documented methods should be called -- being documented is how ML Kit and other related SDKs define their public API surface.)

GonzalezVictorJavier commented 8 months ago

Thanks @sheepmaster, great response So... coudn't be a better solution run MLKitContext.initializeIfNeeded(context) at startup against removing the automatic provider and initializing it manually.?.. I mean, i guess i could leave mlkit as provider at the manifest and do this check just in case.. What do you think about that?

The problem is that this issue isn't easy to reproduce.

Part of me wants to say that failing to properly initialize ML Kit is the app's problem 😝 Usually, the content provider that will do that automatically at startup should be merged into the app's manifest and everything should work (and the app developer would need to take explicit steps to disable that behavior, at which point they're shooting themselves in the foot).

But ok, if you really want to ensure that ML Kit is initialized, MLKitContext.initializeIfNeeded(Context) can be called even after initialization, and it will just do nothing in that case (hence the "ifNeeded" part). The other overload is internal and should not be used (and will likely break things if you don't pass the right set of components).

(In general, the rule is that only documented methods should be called -- being documented is how ML Kit and other related SDKs define their public API surface.)

sheepmaster commented 8 months ago

Right, if you want to do initialization manually, you are free to, that's what the method is for :) The content provider is there to make things easier for the simple case so we don't require developers to do it manually.

aruno14 commented 7 months ago

I have the same error: MlKitContext has not been initialized. There is noprovider tag in the manifest. I would like the MlKitContext to be initialized automatically, but it is not happened. If I initialize it manually, I have the below error: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.mlkit.vision.common.internal.MobileVisionBase com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator.create(com.google.mlkit.vision.common.internal.MultiFlavorDetectorCreator$DetectorOptions)' on a null object reference

Before I updated the library, it works without problem.

sheepmaster commented 7 months ago

@aruno14, at this point you might be looking at a different issue. Mind filing a new bug (with a full stack trace)?

aruno14 commented 7 months ago

@sheepmaster Thank you for your very fast reply.

Mind filing a new bug (with a full stack trace)?

It's an old app, with several update issues, so I cannot share a full stack trace.

I use the MlKit in a module, do you think it can be the cause of the probleme ?

Samuel-Fipps commented 6 months ago

Any updates on this? It seems a lot of people are having this issue and I can tell you it only happens on some android phones not all. I get it on my note9 and not my s21.

aruno14 commented 6 months ago

@Samuel-Fipps I created a new project, copy all the code and it works without error. I tested it on a Sony Xperia 1 IV.

khalidkhan020 commented 1 week ago

Resolved the issue by Just enable multidex. No need to initialize manually