diff --git a/android/src/main/kotlin/com/morbit/photogallery/PhotoGalleryPlugin.kt b/android/src/main/kotlin/com/morbit/photogallery/PhotoGalleryPlugin.kt index a8cf998..f437cb8 100644 --- a/android/src/main/kotlin/com/morbit/photogallery/PhotoGalleryPlugin.kt +++ b/android/src/main/kotlin/com/morbit/photogallery/PhotoGalleryPlugin.kt @@ -56,6 +56,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { val imageMetadataProjection = arrayOf( MediaStore.Images.Media._ID, + MediaStore.Images.Media.DISPLAY_NAME, + MediaStore.Images.Media.TITLE, MediaStore.Images.Media.WIDTH, MediaStore.Images.Media.HEIGHT, MediaStore.Images.Media.ORIENTATION, @@ -66,6 +68,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { val videoMetadataProjection = arrayOf( MediaStore.Video.Media._ID, + MediaStore.Video.Media.DISPLAY_NAME, + MediaStore.Video.Media.TITLE, MediaStore.Video.Media.WIDTH, MediaStore.Video.Media.HEIGHT, MediaStore.Video.Media.ORIENTATION, @@ -797,6 +801,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { private fun getImageMetadata(cursor: Cursor): Map { val idColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID) + val filenameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) + val titleColumn = cursor.getColumnIndex(MediaStore.Images.Media.TITLE) val widthColumn = cursor.getColumnIndex(MediaStore.Images.Media.WIDTH) val heightColumn = cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT) val orientationColumn = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION) @@ -805,6 +811,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { val dateModifiedColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED) val id = cursor.getLong(idColumn) + val filename = cursor.getString(filenameColumn) + val title = cursor.getString(titleColumn) val width = cursor.getLong(widthColumn) val height = cursor.getLong(heightColumn) val orientation = cursor.getLong(orientationColumn) @@ -820,6 +828,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { return mapOf( "id" to id.toString(), + "filename" to filename, + "title" to title, "mediumType" to imageType, "width" to width, "height" to height, @@ -832,6 +842,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { private fun getVideoMetadata(cursor: Cursor): Map { val idColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID) + val filenameColumn = cursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME) + val titleColumn = cursor.getColumnIndex(MediaStore.Video.Media.TITLE) val widthColumn = cursor.getColumnIndex(MediaStore.Video.Media.WIDTH) val heightColumn = cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT) val orientationColumn = cursor.getColumnIndex(MediaStore.Video.Media.ORIENTATION) @@ -841,6 +853,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { val dateModifiedColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATE_MODIFIED) val id = cursor.getLong(idColumn) + val filename = cursor.getString(filenameColumn) + val title = cursor.getString(titleColumn) val width = cursor.getLong(widthColumn) val height = cursor.getLong(heightColumn) val orientation = cursor.getLong(orientationColumn) @@ -857,6 +871,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { return mapOf( "id" to id.toString(), + "filename" to filename, + "title" to title, "mediumType" to videoType, "width" to width, "orientation" to orientationDegree2Value(orientation), diff --git a/ios/Classes/SwiftPhotoGalleryPlugin.swift b/ios/Classes/SwiftPhotoGalleryPlugin.swift index b2d7c77..1df7e58 100644 --- a/ios/Classes/SwiftPhotoGalleryPlugin.swift +++ b/ios/Classes/SwiftPhotoGalleryPlugin.swift @@ -416,8 +416,11 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin { private func getMediumFromAsset(asset: PHAsset) -> [String: Any?] { let mimeType = self.extractMimeTypeFromAsset(asset: asset) + let filename = self.extractFilenameFromAsset(asset: asset) return [ "id": asset.localIdentifier, + "filename": filename, + "title": self.extractTitleFromFilename(filename: filename), "mediumType": toDartMediumType(value: asset.mediaType), "mimeType": mimeType, "height": asset.pixelHeight, @@ -430,6 +433,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin { private func getMediumFromAssetAsync(asset: PHAsset, completion: @escaping ([String : Any?]?, Error?) -> Void) -> Void { let mimeType = self.extractMimeTypeFromAsset(asset: asset) + let filename = self.extractFilenameFromAsset(asset: asset) let manager = PHImageManager.default() manager.requestImageData( for: asset, @@ -437,6 +441,8 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin { resultHandler: { (data: Data?, uti: String?, orientation: UIImage.Orientation, info: ([AnyHashable: Any]?)) -> Void in completion([ "id": asset.localIdentifier, + "filename": filename, + "title": self.extractTitleFromFilename(filename: filename), "mediumType": self.toDartMediumType(value: asset.mediaType), "mimeType": mimeType, "height": asset.pixelHeight, @@ -551,6 +557,23 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin { return self.extractMimeTypeFromUTI(uti: uti) } + private func extractFilenameFromAsset(asset: PHAsset) -> String? { + if #available(iOS 9.0, *) { + let resources = PHAssetResource.assetResources(for: asset) + if let resource = resources.first { + return resource.originalFilename + } + } + return asset.value(forKey: "filename") as? String + } + + private func extractTitleFromFilename(filename: String?) -> String? { + if let name = filename { + return (name as NSString).deletingPathExtension + } + return nil + } + private func cachePath() -> URL { let paths = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask) let cacheFolder = paths[0].appendingPathComponent("photo_gallery") diff --git a/lib/src/models/medium.dart b/lib/src/models/medium.dart index 1e99d7f..d1951cc 100644 --- a/lib/src/models/medium.dart +++ b/lib/src/models/medium.dart @@ -8,6 +8,12 @@ class Medium { /// A unique identifier for the medium. final String id; + /// The medium filename. + final String? filename; + + /// The medium title + final String? title; + /// The medium type. final MediumType? mediumType; @@ -34,6 +40,8 @@ class Medium { Medium({ required this.id, + this.filename, + this.title, this.mediumType, this.width, this.height, @@ -47,6 +55,8 @@ class Medium { /// Creates a medium from platform channel protocol. Medium.fromJson(dynamic json) : id = json["id"], + filename = json["filename"], + title = json["title"], mediumType = jsonToMediumType(json["mediumType"]), width = json["width"], height = json["height"], @@ -63,6 +73,8 @@ class Medium { static Medium fromMap(Map map) { return Medium( id: map['id'], + filename: map['filename'], + title: map['title'], mediumType: jsonToMediumType(map['mediumType']), width: map['width'], height: map['height'], @@ -76,6 +88,8 @@ class Medium { Map toMap() { return { "id": this.id, + "filename": this.filename, + "title": this.title, "mediumType": mediumTypeToJson(this.mediumType), "height": this.height, "orientation": this.orientation, @@ -115,6 +129,8 @@ class Medium { other is Medium && runtimeType == other.runtimeType && id == other.id && + filename == other.filename && + title == other.title && mediumType == other.mediumType && width == other.width && height == other.height && @@ -126,6 +142,8 @@ class Medium { @override int get hashCode => id.hashCode ^ + filename.hashCode ^ + title.hashCode ^ mediumType.hashCode ^ width.hashCode ^ height.hashCode ^ @@ -137,6 +155,8 @@ class Medium { @override String toString() { return 'Medium{id: $id, ' + 'filename: $filename, ' + 'title: $title, ' 'mediumType: $mediumType, ' 'width: $width, ' 'height: $height, '