Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug report] Can't use in flutter module to embed in iOS app #1207

Closed
rosenpin opened this issue Oct 20, 2024 · 6 comments
Closed

[Bug report] Can't use in flutter module to embed in iOS app #1207

rosenpin opened this issue Oct 20, 2024 · 6 comments

Comments

@rosenpin
Copy link

rosenpin commented Oct 20, 2024

Brief

When trying to create a flutter module to embed in an existing iOS app with this library, I consistently get a MissingPluginException. It only happens to me when using this library and doesn't happen when using other libraries.

Version

3.5.1

Platforms

iOS

Device Model

iPhone 13 Pro Max

flutter info

flutter doctor -v                                                                                                                   (base) 
[✓] Flutter (Channel stable, 3.24.3, on macOS 14.7 23H124 darwin-arm64, locale en-IL)
    • Flutter version 3.24.3 on channel stable at /Users/tomer.rosenfeld/Programs/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 2663184aa7 (6 weeks ago), 2024-09-11 16:27:48 -0500
    • Engine revision 36335019a8
    • Dart version 3.5.3
    • DevTools version 2.37.3

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/to/macos-android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✓] Xcode - develop for iOS and macOS (Xcode 16.0)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16A242d
    • CocoaPods version 1.15.2

[✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/to/macos-android-setup for detailed instructions).

[✓] Connected device (3 available)
    • Testing iPhone 13 pro max (mobile) • 00008110-001848222EDA801E • ios          • iOS 18.0 22A3354
    • macOS (desktop)                    • macos                     • darwin-arm64 • macOS 14.7 23H124 darwin-arm64
    • Mac Designed for iPad (desktop)    • mac-designed-for-ipad     • darwin       • macOS 14.7 23H124 darwin-arm64
    ! Error: Browsing on the local area network for Gazal’s iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local
      area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 3 categories.

How to reproduce?

  1. Create a new flutter module
    image
  2. Add the library using flutter pub add photo_manager
  3. Use the library for example with the example code below (Flutter part)
  4. Build and run using Flutter to make sure it works correctly (it works as expected)
  5. Build the module using: flutter build ios-framework --debug --no-release --no-profile
  6. Create a new iOS project in Xcode
  7. Embed the built frameworks into the iOS project (example tutorial: https://www.youtube.com/watch?v=lUtlMV0NJw4)
  8. Try to access the flutter module through the app
  9. Get an error:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method requestPermissionExtend on channel com.fluttercandies/photo_manager)
#0      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332:7)
<asynchronous suspension>
#1      PhotoManagerPlugin.requestPermissionExtend (package:photo_manager/src/internal/plugin.dart:167:24)
<asynchronous suspension>
#2      _MyHomePageState._fetchPhotos (package:demo_photo_manager/main.dart:41:32)
<asynchronous suspension>

Logs

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method requestPermissionExtend on channel com.fluttercandies/photo_manager)
#0      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332:7)
<asynchronous suspension>
#1      PhotoManagerPlugin.requestPermissionExtend (package:photo_manager/src/internal/plugin.dart:167:24)
<asynchronous suspension>
#2      _MyHomePageState._fetchPhotos (package:demo_photo_manager/main.dart:41:32)
<asynchronous suspension>

Example code (optional)

Flutter part:  
 dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:photo_manager/photo_manager.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Photo Gallery',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Photo Gallery'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<AssetEntity> _mediaList = [];

  @override
  void initState() {
    super.initState();
    _fetchPhotos();
  }

  Future<void> _fetchPhotos() async {
    final PermissionState ps = await PhotoManager.requestPermissionExtend();
    if (ps.isAuth) {
      final List<AssetPathEntity> albums = await PhotoManager.getAssetPathList(onlyAll: true);
      if (albums.isNotEmpty) {
        final recentAlbum = albums.first;
        final List<AssetEntity> media = await recentAlbum.getAssetListPaged(page: 0, size: 60);
        setState(() {
          _mediaList = media;
        });
      }
    } else {
      // Handle permission denied
      print('Permission denied');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: GridView.builder(
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          mainAxisSpacing: 2,
          crossAxisSpacing: 2,
        ),
        itemCount: _mediaList.length,
        itemBuilder: (context, index) {
          return AssetThumbnail(asset: _mediaList[index]);
        },
      ),
    );
  }
}

class AssetThumbnail extends StatelessWidget {
  const AssetThumbnail({Key? key, required this.asset}) : super(key: key);

  final AssetEntity asset;

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Uint8List?>(
      future: asset.thumbnailData,
      builder: (_, snapshot) {
        final bytes = snapshot.data;
        if (bytes == null) return const CircularProgressIndicator();
        return Image.memory(bytes, fit: BoxFit.cover);
      },
    );
  }
}

Swift part:

import SwiftUI
import Flutter

@Observable
class FlutterDependencies {
 let flutterEngine = FlutterEngine(name: "my flutter engine")
 init() {
   // Runs the default Dart entrypoint with a default Flutter route.
   flutterEngine.run()
 }
}

@main
struct add_to_thisApp: App {
    @State var flutterDependencies = FlutterDependencies()

    var body: some Scene {
        WindowGroup {
              ContentView()
                .environment(flutterDependencies)
            }
    }
}

import SwiftUI
import Flutter


struct FlutterViewControllerRepresentable: UIViewControllerRepresentable {
  func makeUIViewController(context: Context) -> some UIViewController {
    return FlutterViewController(
      project: nil,
      nibName: nil,
      bundle: nil)
  }
  
  func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}

struct ContentView: View {
  var body: some View {
    NavigationStack {
      NavigationLink("My Flutter Feature") {
        FlutterViewControllerRepresentable()
      }
    }
  }
}
#Preview {
    ContentView()
}


### Contact

github/rosenpin
@AlexV525
Copy link
Member

Can you provide a minimal example that integrates photo_manager and some other native plugins?

@rosenpin
Copy link
Author

That's what I did under the example code section. The code I attached is enough to replicate this issue.
Would you prefer a full project in both xcode and flutter?

@AlexV525
Copy link
Member

That's what I did under the example code section. The code I attached is enough to replicate this issue.

Yes but what I suggest is combining another native plugin.

Would you prefer a full project in both xcode and flutter?

Sure this is the best option. Provide a clean zip without Pods and Symlinks if you can.

@rosenpin
Copy link
Author

rosenpin commented Oct 22, 2024

Yes but what I suggest is combining another native plugin.

What exactly do you mean by native plugin? Any flutter plugin that contains native code?

Sure this is the best option. Provide a clean zip without Pods and Symlinks if you can.

Got you, hopefully I'll get around to it tomorrow, thanks for the quick reply

@AlexV525
Copy link
Member

What exactly do you mean by native plugin? Any flutter plugin that contains native code?

Yes. Such as url_launcher.

@rosenpin
Copy link
Author

My bad, thank you for suggesting trying another native library.
The problem seems to have been that I missed the @StateObject private var flutterDependencies = FlutterDependencies()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants