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

Fixpng #345

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.0.3
- 1.Upgrade flutter version to 3.10.5
- 2.Android build tools are upgraded to 7.3.0
- 3.Optimize the Android plugin library code

## 2.0.2
- 1.Optimization android plugin

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ We use the `image_picker` plugin to select images from the Android and iOS image
To use this plugin, add `image_gallery_saver` as a dependency in your pubspec.yaml file. For example:
```yaml
dependencies:
image_gallery_saver: '^2.0.2'
image_gallery_saver: '^2.0.3'
```

## iOS
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:7.2.0'
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.imagegallerysaver

import androidx.annotation.NonNull
import android.annotation.TargetApi
import android.content.ContentValues
import android.content.Context
Expand All @@ -26,10 +27,16 @@ import android.webkit.MimeTypeMap
import java.io.OutputStream

class ImageGallerySaverPlugin : FlutterPlugin, MethodCallHandler {
private lateinit var methodChannel: MethodChannel
private var applicationContext: Context? = null
private var methodChannel: MethodChannel? = null

override fun onMethodCall(call: MethodCall, result: Result): Unit {
override fun onAttachedToEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
this.applicationContext = binding.applicationContext
methodChannel = MethodChannel(binding.binaryMessenger, "image_gallery_saver")
methodChannel.setMethodCallHandler(this)
}

override fun onMethodCall(@NonNull call: MethodCall,@NonNull result: Result): Unit {
when (call.method) {
"saveImageToGallery" -> {
val image = call.argument<ByteArray?>("imageBytes")
Expand Down Expand Up @@ -57,13 +64,18 @@ class ImageGallerySaverPlugin : FlutterPlugin, MethodCallHandler {
}
}

override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
applicationContext = null
methodChannel.setMethodCallHandler(null);
}

private fun generateUri(extension: String = "", name: String? = null): Uri? {
var fileName = name ?: System.currentTimeMillis().toString()
val mimeType = getMIMEType(extension)
val isVideo = mimeType?.startsWith("video")==true

return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// >= android 10
val mimeType = getMIMEType(extension)
val isVideo = mimeType?.startsWith("video")==true
val uri = when {
isVideo -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
else -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
Expand All @@ -78,7 +90,9 @@ class ImageGallerySaverPlugin : FlutterPlugin, MethodCallHandler {
}
)
if (!TextUtils.isEmpty(mimeType)) {
put(MediaStore.Images.Media.MIME_TYPE, mimeType)
put(when {isVideo -> MediaStore.Video.Media.MIME_TYPE
else -> MediaStore.Images.Media.MIME_TYPE
}, mimeType)
}
}

Expand All @@ -87,7 +101,10 @@ class ImageGallerySaverPlugin : FlutterPlugin, MethodCallHandler {
} else {
// < android 10
val storePath =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).absolutePath
Environment.getExternalStoragePublicDirectory(when {
isVideo -> Environment.DIRECTORY_MOVIES
else -> Environment.DIRECTORY_PICTURES
}).absolutePath
val appDir = File(storePath).apply {
if (!exists()) {
mkdir()
Expand Down Expand Up @@ -121,10 +138,10 @@ class ImageGallerySaverPlugin : FlutterPlugin, MethodCallHandler {
* @param fileUri file path
*/
private fun sendBroadcast(context: Context, fileUri: Uri?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaScannerConnection.scanFile(context, arrayOf(fileUri?.toString()), null) { _, _ -> }
} else {
context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, fileUri))
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
mediaScanIntent.data = fileUri
context.sendBroadcast(mediaScanIntent)
}
}

Expand All @@ -134,32 +151,49 @@ class ImageGallerySaverPlugin : FlutterPlugin, MethodCallHandler {
name: String?
): HashMap<String, Any?> {
// check parameters
if (bmp == null || quality == null) {
if (bmp == null || quality == null || name.isNullOrEmpty()) {
return SaveResultModel(false, null, "parameters error").toHashMap()
}

// check applicationContext
val context = applicationContext
?: return SaveResultModel(false, null, "applicationContext null").toHashMap()

var fileUri: Uri? = null
var fos: OutputStream? = null
var success = false

try {
fileUri = generateUri("jpg", name = name)
// Get file extension from name
val fileExtension = getFileExtensionFromName(name)

// Determine the compression format based on the extension
val compressFormat = when (fileExtension) {
"png" -> Bitmap.CompressFormat.PNG
"jpeg", "jpg" -> Bitmap.CompressFormat.JPEG
else -> Bitmap.CompressFormat.PNG // Default to PNG if extension is not recognized
}

// Generate the file URI (use the extension passed as argument)
fileUri = generateUri(fileExtension, name)

if (fileUri != null) {
fos = context.contentResolver.openOutputStream(fileUri)
if (fos != null) {
println("ImageGallerySaverPlugin $quality")
bmp.compress(Bitmap.CompressFormat.JPEG, quality, fos)
// Compress bitmap with the correct format and quality
bmp.compress(compressFormat, quality, fos)
fos.flush()
success = true
}
}
} catch (e: IOException) {
SaveResultModel(false, null, e.toString()).toHashMap()
return SaveResultModel(false, null, e.toString()).toHashMap()
} finally {
fos?.close()
bmp.recycle()
}

return if (success) {
sendBroadcast(context, fileUri)
SaveResultModel(fileUri.toString().isNotEmpty(), fileUri.toString(), null).toHashMap()
Expand All @@ -168,6 +202,14 @@ class ImageGallerySaverPlugin : FlutterPlugin, MethodCallHandler {
}
}

private fun getFileExtensionFromName(name: String): String {
// Extract the file extension from the name and convert to lowercase
val extension = name.substringAfterLast('.', "").lowercase()
return extension
}



private fun saveFileToGallery(filePath: String?, name: String?): HashMap<String, Any?> {
// check parameters
if (filePath == null) {
Expand Down Expand Up @@ -209,29 +251,12 @@ class ImageGallerySaverPlugin : FlutterPlugin, MethodCallHandler {
fileInputStream?.close()
}
return if (success) {
// sendBroadcast(context, fileUri)
sendBroadcast(context, fileUri)
SaveResultModel(fileUri.toString().isNotEmpty(), fileUri.toString(), null).toHashMap()
} else {
SaveResultModel(false, null, "saveFileToGallery fail").toHashMap()
}
}

override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
onAttachedToEngine(binding.applicationContext, binding.binaryMessenger)
}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
applicationContext = null
methodChannel!!.setMethodCallHandler(null);
methodChannel = null;
}

private fun onAttachedToEngine(applicationContext: Context, messenger: BinaryMessenger) {
this.applicationContext = applicationContext
methodChannel = MethodChannel(messenger, "image_gallery_saver")
methodChannel!!.setMethodCallHandler(this)
}

}

class SaveResultModel(var isSuccess: Boolean,
Expand Down
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:7.2.0'
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand Down
2 changes: 1 addition & 1 deletion example/ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
# platform :ios, '12.0'

# source '源地址'
source 'https://github.com/CocoaPods/Specs.git'
Expand Down
8 changes: 4 additions & 4 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
Expand Down Expand Up @@ -342,7 +342,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down Expand Up @@ -420,7 +420,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -469,7 +469,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
2 changes: 1 addition & 1 deletion example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Demonstrates how to use the image_gallery_saver plugin.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# Read more about versioning at semver.org.
version: 2.0.2+2
version: 2.0.3+3

environment:
sdk: '>=2.19.6 <4.0.0'
Expand Down
Loading