0

I am looking to create a custom image picker in my Flutter application using Method Channels. I have been looking for a while and there really is no great documentation on the subject.

The Flutter docs reference getting the battery level, but it is not much help to be honest. I would like to avoid using third-party packages because there are none out there with high reviews and that support multi-image selection.

Requirements:

  • Display your image gallery in-app (photo below)
  • Select multiple images
  • Display the chosen images full-size on another screen
  • Be in a format I can save to my cloud datastore

Current implementation

I am able to get an image preview of my camera gallery in my flutter application using Method Channels by using the swift code below:

 let controller : FlutterViewController = window?.rootViewController as! FlutterViewController

    let channel = FlutterMethodChannel(name: "/gallery", binaryMessenger: controller.binaryMessenger)

    channel.setMethodCallHandler({
      (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
      switch (call.method) {
      case "getItemCount": result(self.getGalleryImageCount())
      case "getItem":
        let index = call.arguments as? Int ?? 0
        self.dataForGalleryItem(index: index, completion: { (data, id, created, location) in
            result([
                "data": data ?? Data(),
                "id": id,
                "created": created,
                "location": location
            ])
        })
      default: result(FlutterError(code: "0", message: nil, details: nil))
      }
    })

dataForGalleryItem:

func dataForGalleryItem(index: Int, completion: @escaping (Data?, String, Int, URL?) -> Void) {
     let fetchOptions = PHFetchOptions()
     fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
      fetchOptions.includeHiddenAssets = false
      fetchOptions.predicate = NSPredicate(format: "mediaType = %d", 
      PHAssetMediaType.image.rawValue)

let collection: PHFetchResult = PHAsset.fetchAssets(with: fetchOptions)  
  if (index >= collection.count) {
    return
  }

    var url : URL?
let asset = collection.object(at: index)
    asset.requestContentEditingInput(with: PHContentEditingInputRequestOptions()) {(editingInput, info) in
    if let input = editingInput, let photoUrl = input.fullSizeImageURL {
        url = photoUrl;
    }}

let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat
options.isSynchronous = false

let imageSize = CGSize(width: 600,
                        height: 600)

let imageManager = PHCachingImageManager()
imageManager.requestImage(for: asset, targetSize: imageSize, contentMode: .aspectFit, options: options) { (image, info) in

  
  if let image = image {
   
    let data = image.jpegData(compressionQuality: 1.0)
 
    completion(data,
                asset.localIdentifier,
                Int(asset.creationDate?.timeIntervalSince1970 ?? 0),
                url)
  } else {
    completion(nil, "", 0, nil)
  }
  }
}

Using the imageManager.requestImage() I am able to get the image data and send it back to the Flutter client.

On the Flutter side I am taking that data and using Image.memory() on the byte list to display the preview image pictured in the screenshot above.

Issues

  • Is this an acceptable Swift implementation for getting camera roll images?

  • How on earth do I get the local file path from the Swift code to be able to use Image.file() on the Flutter client?

    let asset = collection.object(at: index)
        asset.requestContentEditingInput(with: PHContentEditingInputRequestOptions()) {(editingInput, info) in
        if let input = editingInput, let photoUrl = input.fullSizeImageURL {
            url = photoUrl;
        }}
    
    

The URL keeps coming back as NULL.

I need to get the file path to be able to save the image to my Google Cloud Bucket.

4

0 回答 0