Repository: flutter
Issue: [Camera] Flutter module - Android app - No implementation found for method availableCameras on channel plugins.flutter.io/camera
Labels: platform-android,a: existing-apps,p: camera,package,has reproducible steps,P2,found in release: 2.2,found in release: 2.6,team-android,triaged-android

Hello,
I created a Flutter Module with a simple Camera screen that I use at the root of the (main) module.
There are 2 variants: Full & Partial screen. Not important in relation to the bug.

Running the module alone has no problem. Permissions are requested (camera, microphone) and the camera starts up.
When the latter is used from a native Android application, the camera fails to initialize. There is no permission request and the call to the availableCameras() method throws an exception

**Error**
```
 E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: MissingPluginException(No implementation found for method availableCameras on channel plugins.flutter.io/camera)
    #0      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:7)
    <asynchronous suspension>
    #1      MethodChannel.invokeListMethod (package:flutter/src/services/platform_channel.dart:344:35)
    <asynchronous suspension>
    #2      MethodChannelCamera.availableCameras (package:camera_platform_interface/src/method_channel/method_channel_camera.dart:62:52)
    <asynchronous suspension>
    #3      _CameraScreenState._initializeCamera (package:camera_flutter_module/camera.dart:27:15)
    <asynchronous suspension>
```

### Flutter module
**pubspec.yaml**
```
name: camera_flutter_module
description: A new Flutter module.

version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2

  camera: ^0.9.2+2

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

  # This section identifies your Flutter project as a module meant for
  # embedding in a native host app.  These identifiers should _not_ ordinarily
  # be changed after generation - they are used to ensure that the tooling can
  # maintain consistency when adding or modifying assets and plugins.
  # They also do not have any bearing on your native host application's
  # identifiers, which may be completely independent or the same as these.
  module:
    androidX: true
    androidPackage: com.jeremyg.camera_flutter_module
    iosBundleIdentifier: com.jeremyg.cameraFlutterModule

```

**camera.dart**
```
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';

List<CameraDescription> cameras;

class CameraScreen extends StatefulWidget {
  @override
  _CameraScreenState createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {
  CameraController _camera;

  @override
  void initState() {
    super.initState();
    _initializeCamera();
  }

  @override
  void dispose() {
    _camera.dispose();
    super.dispose();
  }

  void _initializeCamera() async {
    cameras = await availableCameras();
    _camera = CameraController(cameras[0], ResolutionPreset.max);
    _camera.initialize().then((_) {
      if (!mounted) {
        return;
      }
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      constraints: const BoxConstraints.expand(),
      child: _camera == null
          ? const Center(
        child: Text(
          'Initializing Camera...',
          style: TextStyle(
            color: Colors.blue,
            fontSize: 30.0,
          ),
        ),
      )
          : Stack(
        fit: StackFit.expand,
        children: [
          CameraPreview(_camera),
        ],
      ),
    );
  }
}
```

**main.dart**
```
import 'package:camera_flutter_module/camera.dart';
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(FullScreen());
}

@pragma('vm:entry-point')
Future<void> partialScreenEntryPoint() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(PartialScreen());
}

class FullScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter full screen widget',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Module Widget'),
        ),
        body: CameraScreen(),
      ),
    );
  }
}

class PartialScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Container(
        color: Colors.grey.shade200,
        height: 100.0,
        child: Scaffold(
          body: Center(
            child: CameraScreen(),
          ),
        ),
      ),
    );
  }
}
```

### Android app
**Application**
```
const val FULL_SCREEN_ENGINE_ID = "fullScreenEngineId"

class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        // Instantiate a FlutterEngine
        val flutterEngineFullScreen = FlutterEngine(this)

        // Pre-warm flutter
        flutterEngineFullScreen
            .dartExecutor
            .executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
            )

        // Cache to faster when you re-navigate to flutter
        FlutterEngineCache
            .getInstance()
            .put(FULL_SCREEN_ENGINE_ID, flutterEngineFullScreen)
    }
}
```
**Activity**
```
class FullScreenFlutterActivity : FlutterActivity() {

    private val CHANNEL = "CHANNEL_NAME"

    override fun onResume() {
        super.onResume()
        MethodChannel(
            FlutterEngineCache.getInstance()
                .get(FULL_SCREEN_ENGINE_ID)?.dartExecutor?.binaryMessenger, CHANNEL_NAME
        ).invokeMethod("notifyNavToFlutter", intent.getStringExtra("screen"))
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_NAME)
            .setMethodCallHandler { call, result ->
                when (call.method) {
                    else -> result.notImplemented()
                }
            }
    }

    override fun provideFlutterEngine(context: Context): FlutterEngine? {
        return FlutterEngineCache.getInstance().get(FULL_SCREEN_ENGINE_ID)
    }
}
```

Flutter doctor
```
[√] Flutter (Channel stable, 2.0.4, on Microsoft Windows [version 10.0.19042.1165], locale fr-CH)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    X Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.7.4)
[√] Android Studio (version 4.1.0)
[√] Connected device (4 available)
```