optimize code
This commit is contained in:
parent
eafedcb225
commit
4a2b9dcf1c
@ -10,7 +10,6 @@ import android.graphics.ImageDecoder
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
import androidx.annotation.NonNull
|
|
||||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||||
import io.flutter.plugin.common.MethodCall
|
import io.flutter.plugin.common.MethodCall
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
@ -81,18 +80,18 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
|
|
||||||
private val executor: ExecutorService = Executors.newSingleThreadExecutor()
|
private val executor: ExecutorService = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "photo_gallery")
|
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "photo_gallery")
|
||||||
val plugin = PhotoGalleryPlugin()
|
val plugin = PhotoGalleryPlugin()
|
||||||
plugin.context = flutterPluginBinding.applicationContext
|
plugin.context = flutterPluginBinding.applicationContext
|
||||||
channel.setMethodCallHandler(plugin)
|
channel.setMethodCallHandler(plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
channel.setMethodCallHandler(null)
|
channel.setMethodCallHandler(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
override fun onMethodCall(call: MethodCall, result: Result) {
|
||||||
when (call.method) {
|
when (call.method) {
|
||||||
"listAlbums" -> {
|
"listAlbums" -> {
|
||||||
val mediumType = call.argument<String>("mediumType")
|
val mediumType = call.argument<String>("mediumType")
|
||||||
@ -102,6 +101,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"listMedia" -> {
|
"listMedia" -> {
|
||||||
val albumId = call.argument<String>("albumId")
|
val albumId = call.argument<String>("albumId")
|
||||||
val mediumType = call.argument<String>("mediumType")
|
val mediumType = call.argument<String>("mediumType")
|
||||||
@ -114,6 +114,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"getMedium" -> {
|
"getMedium" -> {
|
||||||
val mediumId = call.argument<String>("mediumId")
|
val mediumId = call.argument<String>("mediumId")
|
||||||
val mediumType = call.argument<String>("mediumType")
|
val mediumType = call.argument<String>("mediumType")
|
||||||
@ -123,6 +124,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"getThumbnail" -> {
|
"getThumbnail" -> {
|
||||||
val mediumId = call.argument<String>("mediumId")
|
val mediumId = call.argument<String>("mediumId")
|
||||||
val mediumType = call.argument<String>("mediumType")
|
val mediumType = call.argument<String>("mediumType")
|
||||||
@ -135,6 +137,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"getAlbumThumbnail" -> {
|
"getAlbumThumbnail" -> {
|
||||||
val albumId = call.argument<String>("albumId")
|
val albumId = call.argument<String>("albumId")
|
||||||
val mediumType = call.argument<String>("mediumType")
|
val mediumType = call.argument<String>("mediumType")
|
||||||
@ -148,6 +151,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"getFile" -> {
|
"getFile" -> {
|
||||||
val mediumId = call.argument<String>("mediumId")
|
val mediumId = call.argument<String>("mediumId")
|
||||||
val mediumType = call.argument<String>("mediumType")
|
val mediumType = call.argument<String>("mediumType")
|
||||||
@ -158,6 +162,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"cleanCache" -> {
|
"cleanCache" -> {
|
||||||
executor.submit {
|
executor.submit {
|
||||||
result.success(
|
result.success(
|
||||||
@ -165,6 +170,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> result.notImplemented()
|
else -> result.notImplemented()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,9 +180,11 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
imageType -> {
|
imageType -> {
|
||||||
listImageAlbums().values.toList()
|
listImageAlbums().values.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
videoType -> {
|
videoType -> {
|
||||||
listVideoAlbums().values.toList()
|
listVideoAlbums().values.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
listAllAlbums().values.toList()
|
listAllAlbums().values.toList()
|
||||||
}
|
}
|
||||||
@ -224,13 +232,10 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val albumLinkedMap = linkedMapOf<String, Map<String, Any>>()
|
val albumLinkedMap = linkedMapOf<String, Map<String, Any>>()
|
||||||
albumLinkedMap.put(
|
albumLinkedMap[allAlbumId] = hashMapOf(
|
||||||
allAlbumId,
|
"id" to allAlbumId,
|
||||||
hashMapOf(
|
"name" to allAlbumName,
|
||||||
"id" to allAlbumId,
|
"count" to total
|
||||||
"name" to allAlbumName,
|
|
||||||
"count" to total
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
albumLinkedMap.putAll(albumHashMap)
|
albumLinkedMap.putAll(albumHashMap)
|
||||||
return albumLinkedMap
|
return albumLinkedMap
|
||||||
@ -278,13 +283,10 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val albumLinkedMap = linkedMapOf<String, Map<String, Any>>()
|
val albumLinkedMap = linkedMapOf<String, Map<String, Any>>()
|
||||||
albumLinkedMap.put(
|
albumLinkedMap[allAlbumId] = hashMapOf(
|
||||||
allAlbumId,
|
"id" to allAlbumId,
|
||||||
hashMapOf(
|
"name" to allAlbumName,
|
||||||
"id" to allAlbumId,
|
"count" to total
|
||||||
"name" to allAlbumName,
|
|
||||||
"count" to total
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
albumLinkedMap.putAll(albumHashMap)
|
albumLinkedMap.putAll(albumHashMap)
|
||||||
return albumLinkedMap
|
return albumLinkedMap
|
||||||
@ -304,18 +306,28 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
return albumMap
|
return albumMap
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun listMedia(mediumType: String?, albumId: String, newest: Boolean, skip: Int?, take: Int?): Map<String, Any?> {
|
private fun listMedia(
|
||||||
|
mediumType: String?,
|
||||||
|
albumId: String,
|
||||||
|
newest: Boolean,
|
||||||
|
skip: Int?,
|
||||||
|
take: Int?
|
||||||
|
): Map<String, Any?> {
|
||||||
return when (mediumType) {
|
return when (mediumType) {
|
||||||
imageType -> {
|
imageType -> {
|
||||||
listImages(albumId, newest, skip, take)
|
listImages(albumId, newest, skip, take)
|
||||||
}
|
}
|
||||||
|
|
||||||
videoType -> {
|
videoType -> {
|
||||||
listVideos(albumId, newest, skip, take)
|
listVideos(albumId, newest, skip, take)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val images = listImages(albumId, newest, null, null)["items"] as List<Map<String, Any?>>
|
val images = listImages(albumId, newest, null, null)["items"] as List<Map<String, Any?>>
|
||||||
val videos = listVideos(albumId, newest, null, null)["items"] as List<Map<String, Any?>>
|
val videos = listVideos(albumId, newest, null, null)["items"] as List<Map<String, Any?>>
|
||||||
var items = (images + videos).sortedWith(compareBy<Map<String, Any?>> { it["creationDate"] as Long }.thenBy { it["modifiedDate"] as Long })
|
val comparator = compareBy<Map<String, Any?>> { it["creationDate"] as Long }
|
||||||
|
.thenBy { it["modifiedDate"] as Long }
|
||||||
|
var items = (images + videos).sortedWith(comparator)
|
||||||
if (newest) {
|
if (newest) {
|
||||||
items = items.reversed()
|
items = items.reversed()
|
||||||
}
|
}
|
||||||
@ -452,9 +464,11 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
imageType -> {
|
imageType -> {
|
||||||
getImageMedia(mediumId)
|
getImageMedia(mediumId)
|
||||||
}
|
}
|
||||||
|
|
||||||
videoType -> {
|
videoType -> {
|
||||||
getVideoMedia(mediumId)
|
getVideoMedia(mediumId)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
getImageMedia(mediumId) ?: getVideoMedia(mediumId)
|
getImageMedia(mediumId) ?: getVideoMedia(mediumId)
|
||||||
}
|
}
|
||||||
@ -505,14 +519,22 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
return videoMetadata
|
return videoMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getThumbnail(mediumId: String, mediumType: String?, width: Int?, height: Int?, highQuality: Boolean?): ByteArray? {
|
private fun getThumbnail(
|
||||||
|
mediumId: String,
|
||||||
|
mediumType: String?,
|
||||||
|
width: Int?,
|
||||||
|
height: Int?,
|
||||||
|
highQuality: Boolean?
|
||||||
|
): ByteArray? {
|
||||||
return when (mediumType) {
|
return when (mediumType) {
|
||||||
imageType -> {
|
imageType -> {
|
||||||
getImageThumbnail(mediumId, width, height, highQuality)
|
getImageThumbnail(mediumId, width, height, highQuality)
|
||||||
}
|
}
|
||||||
|
|
||||||
videoType -> {
|
videoType -> {
|
||||||
getVideoThumbnail(mediumId, width, height, highQuality)
|
getVideoThumbnail(mediumId, width, height, highQuality)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
getImageThumbnail(mediumId, width, height, highQuality)
|
getImageThumbnail(mediumId, width, height, highQuality)
|
||||||
?: getVideoThumbnail(mediumId, width, height, highQuality)
|
?: getVideoThumbnail(mediumId, width, height, highQuality)
|
||||||
@ -537,7 +559,9 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val kind = if (highQuality == true) MediaStore.Images.Thumbnails.MINI_KIND else MediaStore.Images.Thumbnails.MICRO_KIND
|
val kind =
|
||||||
|
if (highQuality == true) MediaStore.Images.Thumbnails.MINI_KIND
|
||||||
|
else MediaStore.Images.Thumbnails.MICRO_KIND
|
||||||
MediaStore.Images.Thumbnails.getThumbnail(
|
MediaStore.Images.Thumbnails.getThumbnail(
|
||||||
this.contentResolver, mediumId.toLong(),
|
this.contentResolver, mediumId.toLong(),
|
||||||
kind, null
|
kind, null
|
||||||
@ -572,7 +596,8 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val kind =
|
val kind =
|
||||||
if (highQuality == true) MediaStore.Video.Thumbnails.MINI_KIND else MediaStore.Video.Thumbnails.MICRO_KIND
|
if (highQuality == true) MediaStore.Video.Thumbnails.MINI_KIND
|
||||||
|
else MediaStore.Video.Thumbnails.MICRO_KIND
|
||||||
MediaStore.Video.Thumbnails.getThumbnail(
|
MediaStore.Video.Thumbnails.getThumbnail(
|
||||||
this.contentResolver, mediumId.toLong(),
|
this.contentResolver, mediumId.toLong(),
|
||||||
kind, null
|
kind, null
|
||||||
@ -589,21 +614,36 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
return byteArray
|
return byteArray
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAlbumThumbnail(albumId: String, mediumType: String?, newest: Boolean, width: Int?, height: Int?, highQuality: Boolean?): ByteArray? {
|
private fun getAlbumThumbnail(
|
||||||
|
albumId: String,
|
||||||
|
mediumType: String?,
|
||||||
|
newest: Boolean,
|
||||||
|
width: Int?,
|
||||||
|
height: Int?,
|
||||||
|
highQuality: Boolean?
|
||||||
|
): ByteArray? {
|
||||||
return when (mediumType) {
|
return when (mediumType) {
|
||||||
imageType -> {
|
imageType -> {
|
||||||
getImageAlbumThumbnail(albumId, newest, width, height, highQuality)
|
getImageAlbumThumbnail(albumId, newest, width, height, highQuality)
|
||||||
}
|
}
|
||||||
|
|
||||||
videoType -> {
|
videoType -> {
|
||||||
getVideoAlbumThumbnail(albumId, newest, width, height, highQuality)
|
getVideoAlbumThumbnail(albumId, newest, width, height, highQuality)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
getAllAlbumThumbnail(albumId, newest, width, height, highQuality)
|
getAllAlbumThumbnail(albumId, newest, width, height, highQuality)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getImageAlbumThumbnail(albumId: String, newest: Boolean, width: Int?, height: Int?, highQuality: Boolean?): ByteArray? {
|
private fun getImageAlbumThumbnail(
|
||||||
|
albumId: String,
|
||||||
|
newest: Boolean,
|
||||||
|
width: Int?,
|
||||||
|
height: Int?,
|
||||||
|
highQuality: Boolean?
|
||||||
|
): ByteArray? {
|
||||||
return this.context.run {
|
return this.context.run {
|
||||||
val projection = arrayOf(MediaStore.Images.Media._ID)
|
val projection = arrayOf(MediaStore.Images.Media._ID)
|
||||||
|
|
||||||
@ -621,7 +661,13 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getVideoAlbumThumbnail(albumId: String, newest: Boolean, width: Int?, height: Int?, highQuality: Boolean?): ByteArray? {
|
private fun getVideoAlbumThumbnail(
|
||||||
|
albumId: String,
|
||||||
|
newest: Boolean,
|
||||||
|
width: Int?,
|
||||||
|
height: Int?,
|
||||||
|
highQuality: Boolean?
|
||||||
|
): ByteArray? {
|
||||||
return this.context.run {
|
return this.context.run {
|
||||||
val projection = arrayOf(MediaStore.Video.Media._ID)
|
val projection = arrayOf(MediaStore.Video.Media._ID)
|
||||||
|
|
||||||
@ -639,7 +685,13 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAllAlbumThumbnail(albumId: String, newest: Boolean, width: Int?, height: Int?, highQuality: Boolean?): ByteArray? {
|
private fun getAllAlbumThumbnail(
|
||||||
|
albumId: String,
|
||||||
|
newest: Boolean,
|
||||||
|
width: Int?,
|
||||||
|
height: Int?,
|
||||||
|
highQuality: Boolean?
|
||||||
|
): ByteArray? {
|
||||||
return this.context.run {
|
return this.context.run {
|
||||||
val imageProjection = arrayOf(
|
val imageProjection = arrayOf(
|
||||||
MediaStore.Images.Media._ID,
|
MediaStore.Images.Media._ID,
|
||||||
@ -688,20 +740,16 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (imageId != null && videoId != null) {
|
if (imageId != null && videoId != null) {
|
||||||
if (imageDateAdded != null && videoDateAdded != null) {
|
if (newest && imageDateAdded!! > videoDateAdded!! || !newest && imageDateAdded!! < videoDateAdded!!) {
|
||||||
if (newest && imageDateAdded!! < videoDateAdded!! || !newest && imageDateAdded!! > videoDateAdded!!) {
|
return@run getImageThumbnail(imageId.toString(), width, height, highQuality)
|
||||||
return@run getVideoThumbnail(videoId.toString(), width, height, highQuality)
|
|
||||||
} else {
|
|
||||||
return@run getImageThumbnail(imageId.toString(), width, height, highQuality)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (imageDateModified != null && videoDateModified != null) {
|
if (newest && imageDateAdded!! < videoDateAdded!! || !newest && imageDateAdded!! > videoDateAdded!!) {
|
||||||
if (newest && imageDateModified!! < videoDateModified!! || !newest && imageDateModified!! > videoDateModified!!) {
|
return@run getVideoThumbnail(videoId.toString(), width, height, highQuality)
|
||||||
return@run getVideoThumbnail(videoId.toString(), width, height, highQuality)
|
|
||||||
} else {
|
|
||||||
return@run getImageThumbnail(imageId.toString(), width, height, highQuality)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (newest && imageDateModified!! >= videoDateModified!! || !newest && imageDateModified!! <= videoDateModified!!) {
|
||||||
|
return@run getImageThumbnail(imageId.toString(), width, height, highQuality)
|
||||||
|
}
|
||||||
|
return@run getVideoThumbnail(videoId.toString(), width, height, highQuality)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageId != null) {
|
if (imageId != null) {
|
||||||
@ -805,9 +853,11 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
imageType -> {
|
imageType -> {
|
||||||
getImageFile(mediumId, mimeType = mimeType)
|
getImageFile(mediumId, mimeType = mimeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
videoType -> {
|
videoType -> {
|
||||||
getVideoFile(mediumId)
|
getVideoFile(mediumId)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
getImageFile(mediumId, mimeType = mimeType) ?: getVideoFile(mediumId)
|
getImageFile(mediumId, mimeType = mimeType) ?: getVideoFile(mediumId)
|
||||||
}
|
}
|
||||||
@ -874,10 +924,12 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
val bitmap: Bitmap? = this.context.run {
|
val bitmap: Bitmap? = this.context.run {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
try {
|
try {
|
||||||
ImageDecoder.decodeBitmap(ImageDecoder.createSource(
|
ImageDecoder.decodeBitmap(
|
||||||
this.contentResolver,
|
ImageDecoder.createSource(
|
||||||
ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediumId.toLong())
|
this.contentResolver,
|
||||||
))
|
ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediumId.toLong())
|
||||||
|
)
|
||||||
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@ -891,24 +943,39 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
|
|
||||||
bitmap?.let {
|
bitmap?.let {
|
||||||
val compressFormat: Bitmap.CompressFormat
|
val compressFormat: Bitmap.CompressFormat
|
||||||
if (mimeType == "image/jpeg") {
|
when (mimeType) {
|
||||||
val path = File(getCachePath(), "$mediumId.jpeg")
|
"image/jpeg" -> {
|
||||||
val out = FileOutputStream(path)
|
val path = File(getCachePath(), "$mediumId.jpeg")
|
||||||
compressFormat = Bitmap.CompressFormat.JPEG
|
val out = FileOutputStream(path)
|
||||||
it.compress(compressFormat, 100, out)
|
compressFormat = Bitmap.CompressFormat.JPEG
|
||||||
return path.absolutePath
|
it.compress(compressFormat, 100, out)
|
||||||
} else if (mimeType == "image/png") {
|
return path.absolutePath
|
||||||
val path = File(getCachePath(), "$mediumId.png")
|
}
|
||||||
val out = FileOutputStream(path)
|
|
||||||
compressFormat = Bitmap.CompressFormat.PNG
|
"image/png" -> {
|
||||||
it.compress(compressFormat, 100, out)
|
val path = File(getCachePath(), "$mediumId.png")
|
||||||
return path.absolutePath
|
val out = FileOutputStream(path)
|
||||||
} else if (mimeType == "image/webp") {
|
compressFormat = Bitmap.CompressFormat.PNG
|
||||||
val path = File(getCachePath(), "$mediumId.webp")
|
it.compress(compressFormat, 100, out)
|
||||||
val out = FileOutputStream(path)
|
return path.absolutePath
|
||||||
compressFormat = Bitmap.CompressFormat.WEBP_LOSSLESS
|
}
|
||||||
it.compress(compressFormat, 100, out)
|
|
||||||
return path.absolutePath
|
"image/webp" -> {
|
||||||
|
val path = File(getCachePath(), "$mediumId.webp")
|
||||||
|
val out = FileOutputStream(path)
|
||||||
|
compressFormat = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
Bitmap.CompressFormat.WEBP_LOSSLESS
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Bitmap.CompressFormat.WEBP
|
||||||
|
}
|
||||||
|
it.compress(compressFormat, 100, out)
|
||||||
|
return path.absolutePath
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1013,7 +1080,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCachePath(): File? {
|
private fun getCachePath(): File {
|
||||||
return this.context.run {
|
return this.context.run {
|
||||||
val cachePath = File(this.cacheDir, "photo_gallery")
|
val cachePath = File(this.cacheDir, "photo_gallery")
|
||||||
if (!cachePath.exists()) {
|
if (!cachePath.exists()) {
|
||||||
@ -1025,6 +1092,6 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
|
|
||||||
private fun cleanCache() {
|
private fun cleanCache() {
|
||||||
val cachePath = getCachePath()
|
val cachePath = getCachePath()
|
||||||
cachePath?.deleteRecursively()
|
cachePath.deleteRecursively()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,8 +83,8 @@ class _MyAppState extends State<MyApp> {
|
|||||||
...?_albums?.map(
|
...?_albums?.map(
|
||||||
(album) => GestureDetector(
|
(album) => GestureDetector(
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () => Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(builder: (context) => AlbumPage(album)),
|
||||||
builder: (context) => AlbumPage(album))),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
@ -95,8 +95,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
width: gridWidth,
|
width: gridWidth,
|
||||||
child: FadeInImage(
|
child: FadeInImage(
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
placeholder:
|
placeholder: MemoryImage(kTransparentImage),
|
||||||
MemoryImage(kTransparentImage),
|
|
||||||
image: AlbumThumbnailProvider(
|
image: AlbumThumbnailProvider(
|
||||||
album: album,
|
album: album,
|
||||||
highQuality: true,
|
highQuality: true,
|
||||||
@ -186,8 +185,9 @@ class AlbumPageState extends State<AlbumPage> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
...?_media?.map(
|
...?_media?.map(
|
||||||
(medium) => GestureDetector(
|
(medium) => GestureDetector(
|
||||||
onTap: () => Navigator.of(context).push(MaterialPageRoute(
|
onTap: () => Navigator.of(context).push(
|
||||||
builder: (context) => ViewerPage(medium))),
|
MaterialPageRoute(builder: (context) => ViewerPage(medium)),
|
||||||
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.grey[300],
|
color: Colors.grey[300],
|
||||||
child: FadeInImage(
|
child: FadeInImage(
|
||||||
@ -293,9 +293,7 @@ class _VideoProviderState extends State<VideoProvider> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_controller!.value.isPlaying
|
_controller!.value.isPlaying ? _controller!.pause() : _controller!.play();
|
||||||
? _controller!.pause()
|
|
||||||
: _controller!.play();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
|
@ -34,7 +34,8 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
mediumId: mediumId,
|
mediumId: mediumId,
|
||||||
completion: { (data: [String: Any?]?, error: Error?) -> Void in
|
completion: { (data: [String: Any?]?, error: Error?) -> Void in
|
||||||
result(data)
|
result(data)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else if(call.method == "getThumbnail") {
|
else if(call.method == "getThumbnail") {
|
||||||
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
||||||
@ -49,7 +50,8 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
highQuality: highQuality,
|
highQuality: highQuality,
|
||||||
completion: { (data: Data?, error: Error?) -> Void in
|
completion: { (data: Data?, error: Error?) -> Void in
|
||||||
result(data)
|
result(data)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else if(call.method == "getAlbumThumbnail") {
|
else if(call.method == "getAlbumThumbnail") {
|
||||||
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
||||||
@ -68,7 +70,8 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
highQuality: highQuality,
|
highQuality: highQuality,
|
||||||
completion: { (data: Data?, error: Error?) -> Void in
|
completion: { (data: Data?, error: Error?) -> Void in
|
||||||
result(data)
|
result(data)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else if(call.method == "getFile") {
|
else if(call.method == "getFile") {
|
||||||
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
||||||
@ -79,7 +82,8 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
mimeType: mimeType,
|
mimeType: mimeType,
|
||||||
completion: { (filepath: String?, error: Error?) -> Void in
|
completion: { (filepath: String?, error: Error?) -> Void in
|
||||||
result(filepath?.replacingOccurrences(of: "file://", with: ""))
|
result(filepath?.replacingOccurrences(of: "file://", with: ""))
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else if(call.method == "cleanCache") {
|
else if(call.method == "cleanCache") {
|
||||||
cleanCache()
|
cleanCache()
|
||||||
@ -254,7 +258,8 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
}
|
}
|
||||||
let bytes = image.jpegData(compressionQuality: CGFloat(70))
|
let bytes = image.jpegData(compressionQuality: CGFloat(70))
|
||||||
completion(bytes, nil)
|
completion(bytes, nil)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +317,8 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
}
|
}
|
||||||
let bytes = image.jpegData(compressionQuality: CGFloat(80))
|
let bytes = image.jpegData(compressionQuality: CGFloat(80))
|
||||||
completion(bytes, nil)
|
completion(bytes, nil)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,25 +372,28 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else if(asset.mediaType == PHAssetMediaType.video
|
} else if(asset.mediaType == PHAssetMediaType.video
|
||||||
|| asset.mediaType == PHAssetMediaType.audio) {
|
|| asset.mediaType == PHAssetMediaType.audio) {
|
||||||
let options = PHVideoRequestOptions()
|
let options = PHVideoRequestOptions()
|
||||||
options.version = .current
|
options.version = .current
|
||||||
options.deliveryMode = .highQualityFormat
|
options.deliveryMode = .highQualityFormat
|
||||||
options.isNetworkAccessAllowed = true
|
options.isNetworkAccessAllowed = true
|
||||||
|
|
||||||
manager.requestAVAsset(forVideo: asset, options: options, resultHandler: { (avAsset, avAudioMix, info) in
|
manager.requestAVAsset(
|
||||||
DispatchQueue.main.async(execute: {
|
forVideo: asset,
|
||||||
do {
|
options: options,
|
||||||
let avAsset = avAsset as? AVURLAsset
|
resultHandler: { (avAsset, avAudioMix, info) in
|
||||||
let data = try Data(contentsOf: avAsset!.url)
|
DispatchQueue.main.async(execute: {
|
||||||
let fileExt = self.extractFileExtensionFromAsset(asset: asset)
|
do {
|
||||||
let filepath = self.exportPathForAsset(asset: asset, ext: fileExt)
|
let avAsset = avAsset as? AVURLAsset
|
||||||
try! data.write(to: filepath, options: .atomic)
|
let data = try Data(contentsOf: avAsset!.url)
|
||||||
completion(filepath.absoluteString, nil)
|
let fileExt = self.extractFileExtensionFromAsset(asset: asset)
|
||||||
} catch {
|
let filepath = self.exportPathForAsset(asset: asset, ext: fileExt)
|
||||||
completion(nil, NSError(domain: "photo_gallery", code: 500, userInfo: nil))
|
try! data.write(to: filepath, options: .atomic)
|
||||||
}
|
completion(filepath.absoluteString, nil)
|
||||||
})
|
} catch {
|
||||||
|
completion(nil, NSError(domain: "photo_gallery", code: 500, userInfo: nil))
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -406,11 +415,11 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getMediumFromAsset(asset: PHAsset) -> [String: Any?] {
|
private func getMediumFromAsset(asset: PHAsset) -> [String: Any?] {
|
||||||
let mimeType = self.extractMimeTypeFromAsset(asset: asset)
|
let mimeType = self.extractMimeTypeFromAsset(asset: asset)
|
||||||
let filename = self.extractFilenameFromAsset(asset: asset)
|
let filename = self.extractFilenameFromAsset(asset: asset)
|
||||||
let size = self.extractSizeFromAsset(asset: asset)
|
let size = self.extractSizeFromAsset(asset: asset)
|
||||||
return [
|
return [
|
||||||
"id": asset.localIdentifier,
|
"id": asset.localIdentifier,
|
||||||
"filename": filename,
|
"filename": filename,
|
||||||
@ -419,7 +428,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
"mimeType": mimeType,
|
"mimeType": mimeType,
|
||||||
"height": asset.pixelHeight,
|
"height": asset.pixelHeight,
|
||||||
"width": asset.pixelWidth,
|
"width": asset.pixelWidth,
|
||||||
"size": size,
|
"size": size,
|
||||||
"duration": NSInteger(asset.duration * 1000),
|
"duration": NSInteger(asset.duration * 1000),
|
||||||
"creationDate": (asset.creationDate != nil) ? NSInteger(asset.creationDate!.timeIntervalSince1970 * 1000) : nil,
|
"creationDate": (asset.creationDate != nil) ? NSInteger(asset.creationDate!.timeIntervalSince1970 * 1000) : nil,
|
||||||
"modifiedDate": (asset.modificationDate != nil) ? NSInteger(asset.modificationDate!.timeIntervalSince1970 * 1000) : nil
|
"modifiedDate": (asset.modificationDate != nil) ? NSInteger(asset.modificationDate!.timeIntervalSince1970 * 1000) : nil
|
||||||
@ -429,7 +438,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
private func getMediumFromAssetAsync(asset: PHAsset, completion: @escaping ([String : Any?]?, Error?) -> Void) -> Void {
|
private func getMediumFromAssetAsync(asset: PHAsset, completion: @escaping ([String : Any?]?, Error?) -> Void) -> Void {
|
||||||
let mimeType = self.extractMimeTypeFromAsset(asset: asset)
|
let mimeType = self.extractMimeTypeFromAsset(asset: asset)
|
||||||
let filename = self.extractFilenameFromAsset(asset: asset)
|
let filename = self.extractFilenameFromAsset(asset: asset)
|
||||||
let size = self.extractSizeFromAsset(asset: asset)
|
let size = self.extractSizeFromAsset(asset: asset)
|
||||||
let manager = PHImageManager.default()
|
let manager = PHImageManager.default()
|
||||||
manager.requestImageData(
|
manager.requestImageData(
|
||||||
for: asset,
|
for: asset,
|
||||||
@ -443,7 +452,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
"mimeType": mimeType,
|
"mimeType": mimeType,
|
||||||
"height": asset.pixelHeight,
|
"height": asset.pixelHeight,
|
||||||
"width": asset.pixelWidth,
|
"width": asset.pixelWidth,
|
||||||
"size": size,
|
"size": size,
|
||||||
"orientation": self.toOrientationValue(orientation: orientation),
|
"orientation": self.toOrientationValue(orientation: orientation),
|
||||||
"duration": NSInteger(asset.duration * 1000),
|
"duration": NSInteger(asset.duration * 1000),
|
||||||
"creationDate": (asset.creationDate != nil) ? NSInteger(asset.creationDate!.timeIntervalSince1970 * 1000) : nil,
|
"creationDate": (asset.creationDate != nil) ? NSInteger(asset.creationDate!.timeIntervalSince1970 * 1000) : nil,
|
||||||
@ -452,7 +461,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func exportPathForAsset(asset: PHAsset, ext: String) -> URL {
|
private func exportPathForAsset(asset: PHAsset, ext: String) -> URL {
|
||||||
let mediumId = asset.localIdentifier
|
let mediumId = asset.localIdentifier
|
||||||
.replacingOccurrences(of: "/", with: "__")
|
.replacingOccurrences(of: "/", with: "__")
|
||||||
@ -511,7 +520,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
}
|
}
|
||||||
return NSPredicate(format: "mediaType = %d", swiftType.rawValue)
|
return NSPredicate(format: "mediaType = %d", swiftType.rawValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func extractFileExtensionFromUTI(uti: String?) -> String {
|
private func extractFileExtensionFromUTI(uti: String?) -> String {
|
||||||
guard let assetUTI = uti else {
|
guard let assetUTI = uti else {
|
||||||
return ""
|
return ""
|
||||||
@ -561,14 +570,14 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
}
|
}
|
||||||
return asset.value(forKey: "filename") as? String
|
return asset.value(forKey: "filename") as? String
|
||||||
}
|
}
|
||||||
|
|
||||||
private func extractSizeFromAsset(asset: PHAsset) -> Int64? {
|
private func extractSizeFromAsset(asset: PHAsset) -> Int64? {
|
||||||
let resources = PHAssetResource.assetResources(for: asset)
|
let resources = PHAssetResource.assetResources(for: asset)
|
||||||
guard let resource = resources.first,
|
guard let resource = resources.first,
|
||||||
let unsignedInt64 = resource.value(forKey: "fileSize") as? CLong else {
|
let unsignedInt64 = resource.value(forKey: "fileSize") as? CLong else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return Int64(bitPattern: UInt64(unsignedInt64))
|
return Int64(bitPattern: UInt64(unsignedInt64))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func extractTitleFromFilename(filename: String?) -> String? {
|
private func extractTitleFromFilename(filename: String?) -> String? {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user