add "mimeType" parameter in "getFile" API to allow specifying image format when get full image on both platforms
This commit is contained in:
parent
f40f83204f
commit
270432154d
@ -15,9 +15,11 @@ import android.provider.MediaStore
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.database.Cursor.FIELD_TYPE_INTEGER
|
||||
import android.graphics.ImageDecoder
|
||||
import android.os.AsyncTask
|
||||
import android.os.Build
|
||||
import android.util.Size
|
||||
import java.io.FileOutputStream
|
||||
|
||||
/** PhotoGalleryPlugin */
|
||||
class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
||||
@ -138,8 +140,9 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
||||
"getFile" -> {
|
||||
val mediumId = call.argument<String>("mediumId")
|
||||
val mediumType = call.argument<String>("mediumType")
|
||||
val mimeType = call.argument<String>("mimeType")
|
||||
BackgroundAsyncTask({
|
||||
getFile(mediumId!!, mediumType)
|
||||
getFile(mediumId!!, mediumType, mimeType)
|
||||
}, { v ->
|
||||
result.success(v)
|
||||
})
|
||||
@ -666,24 +669,31 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFile(mediumId: String, mediumType: String?): String? {
|
||||
private fun getFile(mediumId: String, mediumType: String?, mimeType: String?): String? {
|
||||
return when (mediumType) {
|
||||
imageType -> {
|
||||
getImageFile(mediumId)
|
||||
getImageFile(mediumId, mimeType = mimeType)
|
||||
}
|
||||
videoType -> {
|
||||
getVideoFile(mediumId)
|
||||
}
|
||||
else -> {
|
||||
getImageFile(mediumId) ?: getVideoFile(mediumId)
|
||||
getImageFile(mediumId, mimeType = mimeType) ?: getVideoFile(mediumId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getImageFile(mediumId: String): String? {
|
||||
var path: String? = null
|
||||
|
||||
private fun getImageFile(mediumId: String, mimeType: String? = null): String? {
|
||||
this.context?.run {
|
||||
mimeType?.let {
|
||||
val type = this.contentResolver.getType(
|
||||
ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediumId.toLong())
|
||||
)
|
||||
if (it != type) {
|
||||
return cacheImage(mediumId, it)
|
||||
}
|
||||
}
|
||||
|
||||
val imageCursor = this.contentResolver.query(
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
arrayOf(MediaStore.Images.Media.DATA),
|
||||
@ -695,12 +705,12 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
||||
imageCursor?.use { cursor ->
|
||||
if (cursor.moveToNext()) {
|
||||
val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
|
||||
path = cursor.getString(dataColumn)
|
||||
return cursor.getString(dataColumn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getVideoFile(mediumId: String): String? {
|
||||
@ -725,6 +735,51 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
||||
return path
|
||||
}
|
||||
|
||||
private fun cacheImage(mediumId: String, mimeType: String): String? {
|
||||
val bitmap: Bitmap? = this.context?.run {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
try {
|
||||
ImageDecoder.decodeBitmap(ImageDecoder.createSource(
|
||||
this.contentResolver,
|
||||
ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediumId.toLong())
|
||||
))
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
MediaStore.Images.Media.getBitmap(
|
||||
this.contentResolver,
|
||||
ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediumId.toLong())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
bitmap?.let {
|
||||
val compressFormat: Bitmap.CompressFormat
|
||||
if (mimeType == "image/jpeg") {
|
||||
val path = File(getCachePath(), "$mediumId.jpeg")
|
||||
val out = FileOutputStream(path)
|
||||
compressFormat = Bitmap.CompressFormat.JPEG
|
||||
it.compress(compressFormat, 100, out)
|
||||
return path.absolutePath
|
||||
} else if (mimeType == "image/png") {
|
||||
val path = File(getCachePath(), "$mediumId.png")
|
||||
val out = FileOutputStream(path)
|
||||
compressFormat = Bitmap.CompressFormat.PNG
|
||||
it.compress(compressFormat, 100, out)
|
||||
return path.absolutePath
|
||||
} else if (mimeType == "image/webp") {
|
||||
val path = File(getCachePath(), "$mediumId.webp")
|
||||
val out = FileOutputStream(path)
|
||||
compressFormat = Bitmap.CompressFormat.WEBP
|
||||
it.compress(compressFormat, 100, out)
|
||||
return path.absolutePath
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getImageMetadata(cursor: Cursor): Map<String, Any?> {
|
||||
val idColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID)
|
||||
val widthColumn = cursor.getColumnIndex(MediaStore.Images.Media.WIDTH)
|
||||
|
@ -70,8 +70,10 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
||||
else if(call.method == "getFile") {
|
||||
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
||||
let mediumId = arguments["mediumId"] as! String
|
||||
let mimeType = arguments["mimeType"] as? String
|
||||
getFile(
|
||||
mediumId: mediumId,
|
||||
mimeType: mimeType,
|
||||
completion: { (filepath: String?, error: Error?) -> Void in
|
||||
result(filepath?.replacingOccurrences(of: "file://", with: ""))
|
||||
})
|
||||
@ -319,7 +321,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
||||
completion(nil , NSError(domain: "photo_gallery", code: 404, userInfo: nil))
|
||||
}
|
||||
|
||||
private func getFile(mediumId: String, completion: @escaping (String?, Error?) -> Void) {
|
||||
private func getFile(mediumId: String, mimeType: String?, completion: @escaping (String?, Error?) -> Void) {
|
||||
let manager = PHImageManager.default()
|
||||
|
||||
let fetchOptions = PHFetchOptions()
|
||||
@ -350,6 +352,14 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
||||
completion(nil, NSError(domain: "photo_gallery", code: 404, userInfo: nil))
|
||||
return
|
||||
}
|
||||
if mimeType != nil {
|
||||
let type = self.extractMimeTypeFromUTI(uti: assetUTI)
|
||||
if type != mimeType {
|
||||
let path = self.cacheImage(asset: asset, data: imageData, mimeType: mimeType!)
|
||||
completion(path, NSError(domain: "photo_gallery", code: 404, userInfo: nil))
|
||||
return
|
||||
}
|
||||
}
|
||||
let fileExt = self.extractFileExtensionFromUTI(uti: assetUTI)
|
||||
let filepath = self.exportPathForAsset(asset: asset, ext: fileExt)
|
||||
try! imageData.write(to: filepath, options: .atomic)
|
||||
@ -383,6 +393,22 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
private func cacheImage(asset: PHAsset, data: Data, mimeType: String) -> String? {
|
||||
if mimeType == "image/jpeg" {
|
||||
let filepath = self.exportPathForAsset(asset: asset, ext: ".jpeg")
|
||||
let uiImage = UIImage(data: data)
|
||||
try! uiImage?.jpegData(compressionQuality: 100)?.write(to: filepath, options: .atomic)
|
||||
return filepath.absoluteString
|
||||
} else if mimeType == "image/png" {
|
||||
let filepath = self.exportPathForAsset(asset: asset, ext: ".png")
|
||||
let uiImage = UIImage(data: data)
|
||||
try! uiImage?.pngData()?.write(to: filepath, options: .atomic)
|
||||
return filepath.absoluteString
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func getMediumFromAsset(asset: PHAsset) -> [String: Any?] {
|
||||
let mimeType = self.extractMimeTypeFromAsset(asset: asset)
|
||||
return [
|
||||
|
@ -103,11 +103,14 @@ class PhotoGallery {
|
||||
static Future<File> getFile({
|
||||
required String mediumId,
|
||||
MediumType? mediumType,
|
||||
String? mimeType,
|
||||
}) async {
|
||||
final path = await _channel.invokeMethod('getFile', {
|
||||
'mediumId': mediumId,
|
||||
'mediumType': mediumTypeToJson(mediumType),
|
||||
}) as String;
|
||||
'mimeType': mimeType,
|
||||
}) as String?;
|
||||
if (path == null) throw "Cannot get file $mediumId with type $mimeType";
|
||||
return File(path);
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,11 @@ part of photogallery;
|
||||
class PhotoProvider extends ImageProvider<PhotoProvider> {
|
||||
PhotoProvider({
|
||||
required this.mediumId,
|
||||
this.mimeType,
|
||||
});
|
||||
|
||||
final String mediumId;
|
||||
final String? mimeType;
|
||||
|
||||
@override
|
||||
ImageStreamCompleter load(key, decode) {
|
||||
@ -22,7 +24,7 @@ class PhotoProvider extends ImageProvider<PhotoProvider> {
|
||||
Future<ui.Codec> _loadAsync(PhotoProvider key, DecoderCallback decode) async {
|
||||
assert(key == this);
|
||||
final file = await PhotoGallery.getFile(
|
||||
mediumId: mediumId, mediumType: MediumType.image);
|
||||
mediumId: mediumId, mediumType: MediumType.image, mimeType: mimeType);
|
||||
|
||||
final bytes = await file.readAsBytes();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user