juliansteenbakker / mobile_scanner

A universal scanner for Flutter based on MLKit. Uses CameraX on Android and AVFoundation on iOS.
BSD 3-Clause "New" or "Revised" License
744 stars 444 forks source link

MlKitContext has not been initialized #1017

Open Tareq-Ghassan opened 1 month ago

Tareq-Ghassan commented 1 month ago

I am using it on both Android and IOS, on IOS it works fines! But on Android after run the app it gives an exception in Logcat and when I open the scanner it don't open the camera preview.

this is how my preview looks like:

What is a Gaze Point image

this is the exception am facing:

Error registering plugin mobile_scanner, dev.steenbakker.mobile_scanner.MobileScannerPlugin java.lang.IllegalStateException: MlKitContext has not been initialized at com.google.android.gms.common.internal.Preconditions.checkState(com.google.android.gms:play-services-basement@@18.2.0:2) at com.google.mlkit.common.sdkinternal.MlKitContext.getInstance(com.google.mlkit:common@@18.9.0:1) at com.google.mlkit.vision.barcode.BarcodeScanning.getClient(com.google.android.gms:play-services-mlkit-barcode-scanning@@18.3.0:1) at dev.steenbakker.mobile_scanner.MobileScanner.(MobileScanner.kt:52) at dev.steenbakker.mobile_scanner.MobileScannerHandler.(MobileScannerHandler.kt:85) at dev.steenbakker.mobile_scanner.MobileScannerPlugin.onAttachedToActivity(MobileScannerPlugin.kt:24) at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.add(FlutterEngineConnectionRegistry.java:157) at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:79) at java.lang.reflect.Method.invoke(Native Method) at io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister.registerGeneratedPlugins(GeneratedPluginRegister.java:80) at io.flutter.embedding.android.FlutterFragmentActivity.configureFlutterEngine(FlutterFragmentActivity.java:743) at com.bankofjordan.mobileapp.MainActivity.configureFlutterEngine(MainActivity.kt:80) at io.flutter.embedding.android.FlutterFragment.configureFlutterEngine(FlutterFragment.java:1531) at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onAttach(FlutterActivityAndFragmentDelegate.java:213) at io.flutter.embedding.android.FlutterFragment.onAttach(FlutterFragment.java:1062) at androidx.fragment.app.Fragment.performAttach(Fragment.java:3068) at androidx.fragment.app.FragmentStateManager.attach(FragmentStateManager.java:490) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:265) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1943) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1839) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1782) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3042) at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2952) at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:263) at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:350) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1582) at android.app.Activity.performStart(Activity.java:8977) at android.app.ActivityThread.handleStartActivity(ActivityThread.java:4198) at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:225) at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:205) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:177) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:98) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:230) at android.os.Looper.loop(Looper.java:319) at android.app.ActivityThread.main(ActivityThread.java:8893) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)

Odaykhz commented 1 month ago

I'm experiencing the same issue as described. The app functions correctly on iOS, but on Android, it encounter an exception upon launch as indicated by the Logcat error. Additionally, the scanner feature fails to initiate the camera preview. Is there any update or potential fix for this problem?

navaronbracke commented 1 month ago

Do you have the following information? 1) The Flutter version that you use 2) The version of mobile_scanner 3) A minimal code sample to reproduce the error

Tareq-Ghassan commented 1 month ago

Sure!

class CliQQRScanner extends StatefulWidget {
  const CliQQRScanner({super.key});

  @override
  State<CliQQRScanner> createState() => CliQQRScannerState();
}

class CliQQRScannerState extends State<CliQQRScanner> {
  @override
  void dispose() {
    cameraScanner.dispose();
    super.dispose();
  }

  void decodQR(BarcodeCapture barcodeCapture) {
    final List<Barcode> code = barcodeCapture.barcodes;
    debugPrint('Barcode found! ${code[0].rawValue}');
    Provider.of<CliQProvider>(context, listen: false)
        .parseQR(context, emvstring: code[0].rawValue!);
  }

  MobileScannerController cameraScanner = MobileScannerController(
      detectionSpeed: DetectionSpeed.noDuplicates,
      formats: [
        BarcodeFormat.qrCode,
      ]);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: MobileScanner(
        controller: cameraScanner,
        onDetect: decodQR,
      ),
    );
  }
}

knowing that the exception happens before I even reach the screen

Baseljamal commented 1 month ago

Facing the same issue here!

navaronbracke commented 3 weeks ago

I did a bit of digging and in this thread https://github.com/googlesamples/mlkit/issues/264 there is a discussion about an MLKit <provider> tag in the merged Android Manifest.

The mobile_scanner example app does receive this provider:

Screenshot 2024-04-22 at 09 47 16

Do you have such a provider in your application's merged Manifest? Do you manually initialize MLKit in your native Android code? (for example in your Activity?)

Tareq-Ghassan commented 3 weeks ago

I've already tried this solution before and added it to my Android Manifest under the tag, but it didn't work.

In my native Android, I've only included method channels that I created, none of which use MLKit. Therefore, I haven't manually initialized MLKit

Screenshot 2024-04-22 at 16 48 01
navaronbracke commented 3 weeks ago

Which version of MLKit are you using? The provider I listed above has the exported=false annotation (which is required for more recent versions of Android), while yours does not. I also think that the tools:node="remove" on your provider means that the MLKit provider that automatically initializes the MLKit context might get removed in the actual application binary?

Which would explain your issue, since then neither the provider or your own code initializes MLKit?

navaronbracke commented 3 weeks ago

@Tareq-Ghassan The tools:node="remove" indeed disables the automatic initialization it seems.

See this documentation https://developers.google.com/android/reference/com/google/mlkit/common/MlKit#public-methods The line How to disable ML Kit initialization content provider: provides a code sample like

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

You'll have to call that initialize(Context context) method manually in your Application's onCreate() then.

We should probably document this in mobile_scanner's README.

Tareq-Ghassan commented 3 weeks ago

@navaronbracke I modified my provider to this

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

and now I had a different error

Error registering plugin mobile_scanner, dev.steenbakker.mobile_scanner.MobileScannerPlugin
                 java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.mlkit.vision.barcode.internal.BarcodeScannerImpl com.google.mlkit.vision.barcode.internal.zzg.zza()' on a null object reference
                    at com.google.mlkit.vision.barcode.BarcodeScanning.getClient(com.google.android.gms:play-services-mlkit-barcode-scanning@@18.3.0:1)
                    at dev.steenbakker.mobile_scanner.MobileScanner.<init>(MobileScanner.kt:52)
                    at dev.steenbakker.mobile_scanner.MobileScannerHandler.<init>(MobileScannerHandler.kt:85)
                    at dev.steenbakker.mobile_scanner.MobileScannerPlugin.onAttachedToActivity(MobileScannerPlugin.kt:24)
                    at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.add(FlutterEngineConnectionRegistry.java:157)
                    at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:79)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister.registerGeneratedPlugins(GeneratedPluginRegister.java:80)
                    at io.flutter.embedding.android.FlutterFragmentActivity.configureFlutterEngine(FlutterFragmentActivity.java:743)
                    at com.bankofjordan.mobileapp.MainActivity.configureFlutterEngine(MainActivity.kt:82)
                    at io.flutter.embedding.android.FlutterFragment.configureFlutterEngine(FlutterFragment.java:1531)
                    at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onAttach(FlutterActivityAndFragmentDelegate.java:213)
                    at io.flutter.embedding.android.FlutterFragment.onAttach(FlutterFragment.java:1062)
                    at androidx.fragment.app.Fragment.performAttach(Fragment.java:3068)
                    at androidx.fragment.app.FragmentStateManager.attach(FragmentStateManager.java:490)
                    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:265)
                    at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1943)
                    at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1839)
                    at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1782)
                    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3042)
                    at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2952)
                    at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:263)
                    at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:350)
                    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1582)
                    at android.app.Activity.performStart(Activity.java:8628)
                    at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3807)
                    at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:225)
                    at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:205)
                    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:177)
                    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:98)
                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
                    at android.os.Handler.dispatchMessage(Handler.java:106)
                    at android.os.Looper.loopOnce(Looper.java:205)
                    at android.os.Looper.loop(Looper.java:294)
                    at android.app.ActivityThread.main(ActivityThread.java:8177)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Samuel-Fipps commented 2 weeks 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.

navaronbracke commented 2 weeks ago

I guess what we could do is invoke the MLKitContext.initiliazeIfNeeded() when we start the scanner. However, we would need access to the Context for that.

It seems a lot of people are having this issue

I am unsure if that is because they disabled the automatic init provider or not, since the basic example does work without issues.