From e3e2d50b9b4d6fb20e103cd8557949c619cf1a04 Mon Sep 17 00:00:00 2001 From: Dhruvan Bhalara Date: Sun, 30 Apr 2023 19:45:19 +0530 Subject: [PATCH 1/5] fix: Fixed file name issue while saving when intent type is `CATEGORY_OPENABLE` - when file is already present with provided file name and user doesn't change the new file name then saved file is not properly executable due to incorrect file name --- .../cr_file_saver/CrFileSaverPlugin.kt | 20 ++++++++++++++----- .../cleveroad/cr_file_saver/FileSaverImpl.kt | 2 +- .../base/FileSaverPluginCallback.kt | 2 ++ .../com/cleveroad/cr_file_saver/utils/File.kt | 8 ++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/android/src/main/kotlin/com/cleveroad/cr_file_saver/CrFileSaverPlugin.kt b/android/src/main/kotlin/com/cleveroad/cr_file_saver/CrFileSaverPlugin.kt index e54a786..b3c329e 100644 --- a/android/src/main/kotlin/com/cleveroad/cr_file_saver/CrFileSaverPlugin.kt +++ b/android/src/main/kotlin/com/cleveroad/cr_file_saver/CrFileSaverPlugin.kt @@ -1,15 +1,20 @@ package com.cleveroad.cr_file_saver import android.app.Activity +import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.os.Build +import android.provider.MediaStore + import android.util.Log import androidx.annotation.NonNull import androidx.core.app.ActivityCompat import com.cleveroad.cr_file_saver.base.AbstractActivityAware import com.cleveroad.cr_file_saver.base.FileSaverPluginCallback import com.cleveroad.cr_file_saver.utils.getFileName +import com.cleveroad.cr_file_saver.utils.getFileNameWithoutExtension +import com.cleveroad.cr_file_saver.utils.getMimeType import com.cleveroad.cr_file_saver.utils.saveFileInBackground import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding @@ -19,6 +24,7 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.PluginRegistry import java.io.File +import kotlin.math.log /** CrFileSaverPlugin */ class CrFileSaverPlugin : FlutterPlugin, MethodCallHandler, AbstractActivityAware(), @@ -82,14 +88,18 @@ class CrFileSaverPlugin : FlutterPlugin, MethodCallHandler, AbstractActivityAwar } override fun onSaveFileDialog( - sourceFile: File, - result: Pigeon.Result?, - destinationFileName: String? + context: Context, + sourceFile: File, + result: Pigeon.Result?, + destinationFileName: String? ) { + val mimeType = getMimeType(context, sourceFile.path); + val fileNameWithoutExtension = destinationFileName?.let { getFileNameWithoutExtension(it) } ?: getFileNameWithoutExtension(getFileName(sourceFile.path)); Intent(Intent.ACTION_CREATE_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) - putExtra(Intent.EXTRA_TITLE, destinationFileName ?: getFileName(sourceFile.path)) - type = "*/*" + putExtra(Intent.EXTRA_TITLE, fileNameWithoutExtension) + putExtra(MediaStore.MediaColumns.MIME_TYPE, mimeType) + type = mimeType }.let { this.sourceFile = sourceFile this.saveFilePendingResult = result diff --git a/android/src/main/kotlin/com/cleveroad/cr_file_saver/FileSaverImpl.kt b/android/src/main/kotlin/com/cleveroad/cr_file_saver/FileSaverImpl.kt index 92e7289..c1c81b7 100644 --- a/android/src/main/kotlin/com/cleveroad/cr_file_saver/FileSaverImpl.kt +++ b/android/src/main/kotlin/com/cleveroad/cr_file_saver/FileSaverImpl.kt @@ -66,7 +66,7 @@ class FileSaverImpl(private val context: Context, private val callback: FileSave result: Pigeon.Result? ) { val sourceFile = File(params.sourceFilePath) - callback.onSaveFileDialog(sourceFile, result, params.destinationFileName) + callback.onSaveFileDialog(context, sourceFile, result, params.destinationFileName) } @Suppress("DEPRECATION") diff --git a/android/src/main/kotlin/com/cleveroad/cr_file_saver/base/FileSaverPluginCallback.kt b/android/src/main/kotlin/com/cleveroad/cr_file_saver/base/FileSaverPluginCallback.kt index df1b519..ea14e68 100644 --- a/android/src/main/kotlin/com/cleveroad/cr_file_saver/base/FileSaverPluginCallback.kt +++ b/android/src/main/kotlin/com/cleveroad/cr_file_saver/base/FileSaverPluginCallback.kt @@ -1,11 +1,13 @@ package com.cleveroad.cr_file_saver.base +import android.content.Context import com.cleveroad.cr_file_saver.Pigeon import java.io.File interface FileSaverPluginCallback { fun onRequestPermission(result: Pigeon.Result?) fun onSaveFileDialog( + context: Context, sourceFile: File, result: Pigeon.Result?, destinationFileName: String? diff --git a/android/src/main/kotlin/com/cleveroad/cr_file_saver/utils/File.kt b/android/src/main/kotlin/com/cleveroad/cr_file_saver/utils/File.kt index d83d458..24531d2 100644 --- a/android/src/main/kotlin/com/cleveroad/cr_file_saver/utils/File.kt +++ b/android/src/main/kotlin/com/cleveroad/cr_file_saver/utils/File.kt @@ -20,6 +20,14 @@ fun getFileName(url: String): String { val last = segments.last(); return last } +// get file name without extension +fun getFileNameWithoutExtension(fileName: String): String { + val lastIndex = fileName.lastIndexOf('.') + if (lastIndex != -1) { + return fileName.substring(0, lastIndex) + } + return fileName +} // Only used in old APIs @Suppress("DEPRECATION") From a08326ecb48f581b4b09e2e2665d31ed1704c7af Mon Sep 17 00:00:00 2001 From: Dhruvan Bhalara Date: Sun, 30 Apr 2023 20:04:12 +0530 Subject: [PATCH 2/5] chore: Bump `compileSdkVersion` to 33 --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index d46258b..ddb4166 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -25,7 +25,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion 31 + compileSdkVersion 33 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 From 410703245af7ca37421ccd7e8e37281a4e57026f Mon Sep 17 00:00:00 2001 From: Dhruvan Bhalara Date: Thu, 11 May 2023 22:34:59 +0530 Subject: [PATCH 3/5] fix: Fixed `MIME_TYPE` not reterived correctly --- .../cr_file_saver/CrFileSaverPlugin.kt | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/android/src/main/kotlin/com/cleveroad/cr_file_saver/CrFileSaverPlugin.kt b/android/src/main/kotlin/com/cleveroad/cr_file_saver/CrFileSaverPlugin.kt index b3c329e..796c0c0 100644 --- a/android/src/main/kotlin/com/cleveroad/cr_file_saver/CrFileSaverPlugin.kt +++ b/android/src/main/kotlin/com/cleveroad/cr_file_saver/CrFileSaverPlugin.kt @@ -93,23 +93,46 @@ class CrFileSaverPlugin : FlutterPlugin, MethodCallHandler, AbstractActivityAwar result: Pigeon.Result?, destinationFileName: String? ) { - val mimeType = getMimeType(context, sourceFile.path); - val fileNameWithoutExtension = destinationFileName?.let { getFileNameWithoutExtension(it) } ?: getFileNameWithoutExtension(getFileName(sourceFile.path)); - Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - putExtra(Intent.EXTRA_TITLE, fileNameWithoutExtension) - putExtra(MediaStore.MediaColumns.MIME_TYPE, mimeType) - type = mimeType - }.let { - this.sourceFile = sourceFile - this.saveFilePendingResult = result - - activity?.let { activity -> - // Checking for available activity to handle - if (it.resolveActivity(activity.packageManager) != null) { - activity.startActivityForResult(it, SAVEFILE_REQCODE) - } else { - result?.error(NoResolvedActivityException()) + val mimeType = getMimeType(context, sourceFile.path) + if (mimeType == null) { + Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + putExtra(Intent.EXTRA_TITLE, destinationFileName ?: getFileName(sourceFile.path)) + type = "*/*" + }.let { + this.sourceFile = sourceFile + this.saveFilePendingResult = result + + activity?.let { activity -> + // Checking for available activity to handle + if (it.resolveActivity(activity.packageManager) != null) { + activity.startActivityForResult(it, SAVEFILE_REQCODE) + } else { + result?.error(NoResolvedActivityException()) + } + } + } + } else { + val fileNameWithoutExtension = + destinationFileName?.let { getFileNameWithoutExtension(it) } + ?: getFileNameWithoutExtension(getFileName(sourceFile.path)) + + Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + putExtra(Intent.EXTRA_TITLE, fileNameWithoutExtension) + putExtra(MediaStore.MediaColumns.MIME_TYPE, mimeType) + type = mimeType + }.let { + this.sourceFile = sourceFile + this.saveFilePendingResult = result + + activity?.let { activity -> + // Checking for available activity to handle + if (it.resolveActivity(activity.packageManager) != null) { + activity.startActivityForResult(it, SAVEFILE_REQCODE) + } else { + result?.error(NoResolvedActivityException()) + } } } } From 0f1011cff486652e792956de1b392193df0b1e19 Mon Sep 17 00:00:00 2001 From: Dhruvan Bhalara Date: Thu, 30 Nov 2023 16:11:28 +0530 Subject: [PATCH 4/5] Update .gitignore --- .gitignore | 81 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 96486fd..6e947b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,30 +1,63 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp +# https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +.pub/ +build/ +pubspec.lock + +# Directory created by dartdoc +/doc/api/ + +# IDE +*.iml // IntelliJ +*.ipr // IntelliJ +*.iws // IntelliJ +.idea/ // IntelliJ +.DS_Store // Mac + +# copied from https://github.com/flutter/plugins/blob/master/.gitignore .DS_Store .atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws .idea/ +.vscode/ -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ .packages +.pub/ +.dart_tool/ +pubspec.lock +flutter_export_environment.sh + +examples/all_plugins/pubspec.yaml + +Podfile +Podfile.lock +Pods/ +.symlinks/ +**/Flutter/App.framework/ +**/Flutter/Flutter.framework/ +**/Flutter/Generated.xcconfig +**/Flutter/flutter_assets/ +ServiceDefinitions.json +xcuserdata/ +**/DerivedData/ + +local.properties +keystore.properties +.gradle/ +gradlew +gradlew.bat +gradle-wrapper.jar +.flutter-plugins-dependencies +*.iml + +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m +GeneratedPluginRegistrant.java build/ +.flutter-plugins + +.project +.classpath +.settings \ No newline at end of file From d07417d2a0078a2715ac70a65edddbfe286d0282 Mon Sep 17 00:00:00 2001 From: Dhruvan Bhalara Date: Thu, 30 Nov 2023 16:12:53 +0530 Subject: [PATCH 5/5] feat: Added support of AGP 8 --- android/build.gradle | 8 ++++++-- android/gradle/wrapper/gradle-wrapper.properties | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 android/gradle/wrapper/gradle-wrapper.properties diff --git a/android/build.gradle b/android/build.gradle index ddb4166..06eeb72 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,14 +2,14 @@ group 'com.cleveroad.cr_file_saver' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.6.10' + ext.kotlin_version = '1.7.10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' + classpath 'com.android.tools.build:gradle:7.3.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -25,6 +25,10 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { + // Conditional for compatibility with AGP <4.2. + if (project.android.hasProperty("namespace")) { + namespace 'com.cleveroad.cr_file_saver' + } compileSdkVersion 33 compileOptions { diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..ae04661 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists