From 1606bc78439e09a1beba779ae2db967ae84d68ef Mon Sep 17 00:00:00 2001 From: Amit Siddhpura Date: Thu, 11 Apr 2024 17:18:44 +0530 Subject: [PATCH 01/20] PR Template Added. --- pr_template | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 pr_template diff --git a/pr_template b/pr_template new file mode 100644 index 0000000..1a7e9b7 --- /dev/null +++ b/pr_template @@ -0,0 +1,16 @@ +## What type of PR is this? (check all applicable) +- [ ] Feature +- [ ] Bug Fix +- [ ] Optimization + +## Description + + + +## Instructions, Screenshots, Recordings + + + +## Checks +- [ ] SonarLint +- [ ] Locally Tested From 0ea75fd97dc49f9aeb4b3b65104117e86517719f Mon Sep 17 00:00:00 2001 From: harshilpadsala88 Date: Thu, 11 Apr 2024 17:34:25 +0530 Subject: [PATCH 02/20] Added Store function for Android OS Version 10-14. --- .gitignore | 1 + .../c3c1434c45ed15ce4f358f51e25422c2f32f6c32 | 2 - .idea/sonarlint/issuestore/index.pb | 57 ------------------ .idea/sonarlint/securityhotspotstore/index.pb | 57 ------------------ app/build.gradle.kts | 5 +- app/src/main/AndroidManifest.xml | 4 ++ .../java/com/ss/smartstorage/MainActivity.kt | 11 +--- .../com/ss/smartstorage/SmartStorageSample.kt | 59 +++++++++++++++++-- .../ss/smartstorage/SmartStorageViewModel.kt | 7 +++ gradle/libs.versions.toml | 4 ++ .../java/com/ss/smart_storage/SmartStorage.kt | 49 +++++++++++++-- .../ss/smart_storage/util/SmartDirectory.kt | 19 +++--- .../ss/smart_storage/util/SmartFileType.kt | 9 +++ 13 files changed, 136 insertions(+), 148 deletions(-) delete mode 100644 .idea/sonarlint/issuestore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 delete mode 100644 .idea/sonarlint/issuestore/index.pb delete mode 100644 .idea/sonarlint/securityhotspotstore/index.pb create mode 100644 app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt create mode 100644 smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt diff --git a/.gitignore b/.gitignore index 24e6e50..e10ceb9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ git *.iml /.idea/modules.xml /.idea/workspace.xml /.idea/navEditor.xml +/.idea/sonarlint /.idea/assetWizardSettings.xml .DS_Store /build diff --git a/.idea/sonarlint/issuestore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 b/.idea/sonarlint/issuestore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 deleted file mode 100644 index c2057cc..0000000 --- a/.idea/sonarlint/issuestore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 +++ /dev/null @@ -1,2 +0,0 @@ - -| kotlin:S1135 "2Complete the task associated to this TODO comment.(¸â†ëþÿÿÿÿ8ß–ƒ“ì1J$2f697e6a-51c4-45d4-a1b7-b7dbcf8c2a02 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/index.pb b/.idea/sonarlint/issuestore/index.pb deleted file mode 100644 index 71554d8..0000000 --- a/.idea/sonarlint/issuestore/index.pb +++ /dev/null @@ -1,57 +0,0 @@ - -@ -build.gradle.kts,d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d -e -5app/src/main/java/com/ss/smartstorage/MainActivity.kt,f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 -N -smart-storage/build.gradle.kts,d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 -D -app/build.gradle.kts,d/2/d2a4383452aad84a18429a5844d31330a012a9e6 -R -"app/src/main/res/values/themes.xml,e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 -g -7app/src/main/java/com/ss/smartstorage/ui/theme/Color.kt,9/c/9c2a853ebd9f87844b147b05656fea1b7325609e -g -7app/src/main/java/com/ss/smartstorage/ui/theme/Theme.kt,7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 -f -6app/src/main/java/com/ss/smartstorage/ui/theme/Type.kt,c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 -h -8app/src/main/res/drawable-v24/ic_launcher_foreground.xml,0/7/078508c831007ccb3938b355f0d30a8368f99a8d -h -8app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml,6/e/6ec7d34b130497a10dc92abcde9b313d370a89df -S -#app/src/main/res/values/strings.xml,d/2/d2281fbb3027de2722081a53408dd77628bf080e -R -"app/src/main/res/values/colors.xml,9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b -U -%app/src/main/res/xml/backup_rules.xml,e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 -^ -.app/src/main/res/xml/data_extraction_rules.xml,3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d -P - app/src/main/AndroidManifest.xml,8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e -> -app/.gitignore,5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f -w -Gapp/src/androidTest/java/com/ss/smartstorage/ExampleInstrumentedTest.kt,a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b -F -app/proguard-rules.pro,9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 -h -8app/src/test/java/com/ss/smartstorage/ExampleUnitTest.kt,2/4/24ce74baca63d400e46baee54dfd1daccb063d26 -b -2app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml,8/e/8e27ba16c655f421171956147d0fde89b7d25d17 -d -4app/src/main/res/drawable/ic_launcher_background.xml,4/9/49845c622cb06d895975c7b1e3f943e320bce688 -k -;app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt,2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c -p -@smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt,c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 -Z -*smart-storage/src/main/AndroidManifest.xml,0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 -w -Gsmart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt,2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 -: - -.gitignore,a/5/a5cc2925ca8258af241be7e5b0381edf30266302 -: - -READ_ME.md,5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d \ No newline at end of file diff --git a/.idea/sonarlint/securityhotspotstore/index.pb b/.idea/sonarlint/securityhotspotstore/index.pb deleted file mode 100644 index 71554d8..0000000 --- a/.idea/sonarlint/securityhotspotstore/index.pb +++ /dev/null @@ -1,57 +0,0 @@ - -@ -build.gradle.kts,d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d -e -5app/src/main/java/com/ss/smartstorage/MainActivity.kt,f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 -N -smart-storage/build.gradle.kts,d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 -D -app/build.gradle.kts,d/2/d2a4383452aad84a18429a5844d31330a012a9e6 -R -"app/src/main/res/values/themes.xml,e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 -g -7app/src/main/java/com/ss/smartstorage/ui/theme/Color.kt,9/c/9c2a853ebd9f87844b147b05656fea1b7325609e -g -7app/src/main/java/com/ss/smartstorage/ui/theme/Theme.kt,7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 -f -6app/src/main/java/com/ss/smartstorage/ui/theme/Type.kt,c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 -h -8app/src/main/res/drawable-v24/ic_launcher_foreground.xml,0/7/078508c831007ccb3938b355f0d30a8368f99a8d -h -8app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml,6/e/6ec7d34b130497a10dc92abcde9b313d370a89df -S -#app/src/main/res/values/strings.xml,d/2/d2281fbb3027de2722081a53408dd77628bf080e -R -"app/src/main/res/values/colors.xml,9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b -U -%app/src/main/res/xml/backup_rules.xml,e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 -^ -.app/src/main/res/xml/data_extraction_rules.xml,3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d -P - app/src/main/AndroidManifest.xml,8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e -> -app/.gitignore,5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f -w -Gapp/src/androidTest/java/com/ss/smartstorage/ExampleInstrumentedTest.kt,a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b -F -app/proguard-rules.pro,9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 -h -8app/src/test/java/com/ss/smartstorage/ExampleUnitTest.kt,2/4/24ce74baca63d400e46baee54dfd1daccb063d26 -b -2app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml,8/e/8e27ba16c655f421171956147d0fde89b7d25d17 -d -4app/src/main/res/drawable/ic_launcher_background.xml,4/9/49845c622cb06d895975c7b1e3f943e320bce688 -k -;app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt,2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c -p -@smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt,c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 -Z -*smart-storage/src/main/AndroidManifest.xml,0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 -w -Gsmart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt,2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 -: - -.gitignore,a/5/a5cc2925ca8258af241be7e5b0381edf30266302 -: - -READ_ME.md,5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4ade17c..b347313 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -50,7 +50,6 @@ android { } dependencies { - implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) @@ -59,6 +58,8 @@ dependencies { implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) + implementation(libs.coil.compose) + implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(project(":smart-storage")) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) @@ -68,6 +69,8 @@ dependencies { debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) + + project(":smart-storage") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 923acd5..88da93a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,10 @@ + + + + + stream.write(fileData) + } + } catch (e: Exception) { + e.printStackTrace() + } } + + + private fun handleFileCreation(location: String, context: Context): File? { + return when (location) { + SmartDirectory.INTERNAL -> context.filesDir + SmartDirectory.EXTERNAL_APP -> context.getExternalFilesDir(null) + else -> Environment.getExternalStoragePublicDirectory(location) + } + } + + //todo : have to check how to handle on request permissions result + } + + diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt index 87eae42..5cbfc58 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt @@ -1,15 +1,15 @@ package com.ss.smart_storage.util -import android.os.Build import android.os.Environment -import androidx.annotation.RequiresApi -sealed class SmartDirectory{ - companion object{ - val INTERNAL : String = "Internal" + + class SmartDirectory{ + companion object { + const val INTERNAL: String = "Internal" + const val EXTERNAL_APP : String = "External_App" } - data object EXTERNAL : SmartDirectory() { + data object External { val music: String = Environment.DIRECTORY_MUSIC val podcasts: String = Environment.DIRECTORY_PODCASTS val ringtones: String = Environment.DIRECTORY_RINGTONES @@ -20,12 +20,7 @@ sealed class SmartDirectory{ val downloads: String = Environment.DIRECTORY_DOWNLOADS val dcim: String = Environment.DIRECTORY_DCIM val documents: String = Environment.DIRECTORY_DOCUMENTS - - @RequiresApi(Build.VERSION_CODES.Q) - val audiobooks: String = Environment.DIRECTORY_AUDIOBOOKS - - @RequiresApi(Build.VERSION_CODES.S) - val recordings: String = Environment.DIRECTORY_RECORDINGS } } + diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt new file mode 100644 index 0000000..657fbbd --- /dev/null +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt @@ -0,0 +1,9 @@ +package com.ss.smart_storage.util + +enum class SmartFileType { + txt, + jpeg, + png, + pdf, + webp, +} \ No newline at end of file From 249717fb0b5dee3cadaf609417fc47241d7372f2 Mon Sep 17 00:00:00 2001 From: harshilpadsala88 Date: Thu, 11 Apr 2024 17:53:40 +0530 Subject: [PATCH 03/20] Minor Change --- app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt b/app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt index 7d23f39..1e6aae6 100644 --- a/app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt +++ b/app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt @@ -1,7 +1,9 @@ package com.ss.smartstorage +import androidx.compose.runtime.mutableIntStateOf import androidx.lifecycle.ViewModel class SmartStorageViewModel : ViewModel() { + private val state = mutableIntStateOf(0) } \ No newline at end of file From 81ddb94940ed86499d9ff71284b4aa1bdbd32ac9 Mon Sep 17 00:00:00 2001 From: harshilpadsala88 Date: Mon, 15 Apr 2024 17:42:49 +0530 Subject: [PATCH 04/20] Added Permissions, and Storage Access Framework Support --- app/build.gradle.kts | 2 + app/src/main/AndroidManifest.xml | 10 +- .../java/com/ss/smartstorage/MainActivity.kt | 23 ++- .../com/ss/smartstorage/SmartStorageSample.kt | 48 +----- .../ss/smartstorage/SmartStorageViewModel.kt | 1 - gradle/libs.versions.toml | 2 + .../java/com/ss/smart_storage/SmartStorage.kt | 144 ++++++++++++++++-- .../ss/smart_storage/util/SmartDirectory.kt | 20 +-- 8 files changed, 174 insertions(+), 76 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b347313..be8fdca 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -61,6 +61,8 @@ dependencies { implementation(libs.coil.compose) implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(project(":smart-storage")) + implementation(libs.androidx.appcompat) + implementation(libs.androidx.documentfile) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 88da93a..2f46566 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,9 +2,14 @@ - - + + + + + - diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt index 45357b4..f766303 100644 --- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt +++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt @@ -7,23 +7,42 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier +import com.ss.smart_storage.SmartStorage +import com.ss.smart_storage.util.SmartDirectory +import com.ss.smart_storage.util.SmartFileType import com.ss.smartstorage.ui.theme.SmartStorageTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + val smartStorage = SmartStorage(this) + + setContent { SmartStorageTheme { - // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { - SmartStorageSample(applicationContext , this) + SmartStorageSample( + onStoreTap = { + smartStorage.store( + location = SmartDirectory.CUSTOM, + fileName = "interstellar", + fileType = SmartFileType.txt, + fileData = "Directed by Christopher Nolan".toByteArray() + ) + }, + ) } } } } + + + + } diff --git a/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt b/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt index 438ad74..ac0401a 100644 --- a/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt +++ b/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt @@ -1,63 +1,23 @@ package com.ss.smartstorage - -import android.content.Context -import android.content.pm.PackageManager import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.material3.ElevatedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import androidx.lifecycle.viewmodel.compose.viewModel -import com.ss.smart_storage.SmartStorage -import com.ss.smart_storage.util.SmartDirectory -import com.ss.smart_storage.util.SmartFileType + @Composable fun SmartStorageSample( - context : Context , - activity: MainActivity, - viewModel: SmartStorageViewModel = viewModel() + onStoreTap : () -> Unit, ){ - - val smartStorage = SmartStorage(activity) - - fun dummyStore(){ - smartStorage.store( - location = SmartDirectory.EXTERNAL_APP, - fileName = "figh", - fileType = SmartFileType.png, - fileData = "Fighters Live Forever".toByteArray() - ) - } - - fun askPermission(){ - if (ContextCompat.checkSelfPermission( - context, - android.Manifest.permission.WRITE_EXTERNAL_STORAGE - ) != PackageManager.PERMISSION_GRANTED - ) { - ActivityCompat.requestPermissions( - activity, - arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE), - 101 - ) - } - } - Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { - ElevatedButton(onClick = {dummyStore() }) { - Text(text = "SAVE DUMMY") - } + ElevatedButton(onClick = {onStoreTap()}) { + Text(text = "SAVE DUMMY") } - ElevatedButton(onClick = {askPermission()}) { - Text(text = "GET PERMSSION") - } } } diff --git a/app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt b/app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt index 1e6aae6..a8bfe1a 100644 --- a/app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt +++ b/app/src/main/java/com/ss/smartstorage/SmartStorageViewModel.kt @@ -5,5 +5,4 @@ import androidx.lifecycle.ViewModel class SmartStorageViewModel : ViewModel() { private val state = mutableIntStateOf(0) - } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d6004be..086afa8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,7 @@ composeBom = "2023.08.00" appcompat = "1.6.1" lifecycleViewmodelCompose = "2.6.1" material = "1.11.0" +documentfile = "1.0.1" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -32,6 +33,7 @@ androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit androidx-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } +androidx-documentfile = { group = "androidx.documentfile", name = "documentfile", version.ref = "documentfile" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } diff --git a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt index 179788f..0245dc4 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt @@ -1,41 +1,167 @@ package com.ss.smart_storage +import android.Manifest +import android.annotation.SuppressLint import android.app.Activity import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build import android.os.Environment +import android.widget.Toast +import androidx.activity.ComponentActivity +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.ContextCompat +import androidx.documentfile.provider.DocumentFile import com.ss.smart_storage.util.SmartDirectory import com.ss.smart_storage.util.SmartFileType import java.io.File import java.io.FileOutputStream +import java.io.IOException -class SmartStorage(private val activity: Activity) { + +data class FileDetails( + val name: String, + val location: String, + val fileType: SmartFileType, + val fileData: ByteArray, +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as FileDetails + return fileData.contentEquals(other.fileData) + } + + override fun hashCode(): Int { + return fileData.contentHashCode() + } +} + +class SmartStorage(private val activity: ComponentActivity) { + + + private var baseDocumentTreeUri: Uri? = null + private var fileDetails : FileDetails? = null + + + private val safLauncher = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val uri: Uri? = result.data?.data + if (uri != null) { + baseDocumentTreeUri = uri + if(fileDetails!=null){ + writeFileToDocumentTree( + baseDocumentTreeUri, + fileDetails!!.name, + fileDetails!!.fileData, + ) + } + } + } + } + + private val requestPermissionLauncher = activity.registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted: Boolean -> + if (isGranted) { + callFileDetails() + } else { + Toast.makeText(activity, "Permission denied", Toast.LENGTH_SHORT).show() + } + } + + private fun launchBaseDirectoryPicker() { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + safLauncher.launch(intent) + } + + +//todo : Remove Supress Lint + @SuppressLint("ObsoleteSdkInt") + fun isWritePermissionGranted(){ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (ContextCompat.checkSelfPermission( + activity, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) == PackageManager.PERMISSION_GRANTED + ) { + callFileDetails() + } else { + requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) + } + } else { + callFileDetails() + } + } + + private fun callFileDetails(){ + if(fileDetails != null){ + if(fileDetails!!.location == SmartDirectory.CUSTOM){ + launchBaseDirectoryPicker() + } + + else{ + storeToDirectory( + fileDetails = fileDetails!! + ) + } + } + } - //todo :Can be done location enforce use of SmartFileType sealed class fun store( location: String, fileName: String? = null, fileType: SmartFileType, fileData: ByteArray ) { - - //todo: Add Some Randomizer function in Default Naming of File val name = if (!fileName.isNullOrEmpty()) "$fileName.$fileType" else "smartStorage.${fileType.name}" - val directory = handleFileCreation(location, activity.applicationContext) + fileDetails = FileDetails( + name = name, + location = location, + fileType = fileType, + fileData = fileData + ) + isWritePermissionGranted() + } + + private fun storeToDirectory(fileDetails: FileDetails){ + val directory = handleFileCreation(fileDetails.location, activity.applicationContext) + + if(directory!=null && !directory.exists()){ + directory.mkdirs() + } val file = File( - directory, name + directory, fileDetails.name ) try { FileOutputStream(file).use { stream -> - stream.write(fileData) + stream.write(fileDetails.fileData) } } catch (e: Exception) { e.printStackTrace() } } - + private fun writeFileToDocumentTree(baseDocumentTreeUri: Uri?, fileName: String, content: ByteArray) { + baseDocumentTreeUri?.let { treeUri -> + try { + val directory = DocumentFile.fromTreeUri(activity.applicationContext, treeUri) + val file = directory?.createFile("text/*", fileName) + val pfd = file?.let { activity.applicationContext.contentResolver.openFileDescriptor(it.uri, "w") } + pfd?.use { descriptor -> + val fos = FileOutputStream(descriptor.fileDescriptor) + fos.write(content) + fos.close() + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } private fun handleFileCreation(location: String, context: Context): File? { return when (location) { @@ -45,8 +171,6 @@ class SmartStorage(private val activity: Activity) { } } - //todo : have to check how to handle on request permissions result - } diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt index 5cbfc58..3c587cf 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt @@ -1,25 +1,13 @@ package com.ss.smart_storage.util -import android.os.Environment - - class SmartDirectory{ +class SmartDirectory{ companion object { const val INTERNAL: String = "Internal" const val EXTERNAL_APP : String = "External_App" - } - - data object External { - val music: String = Environment.DIRECTORY_MUSIC - val podcasts: String = Environment.DIRECTORY_PODCASTS - val ringtones: String = Environment.DIRECTORY_RINGTONES - val alarms: String = Environment.DIRECTORY_ALARMS - val notifications: String = Environment.DIRECTORY_NOTIFICATIONS - val pictures: String = Environment.DIRECTORY_PICTURES - val movies: String = Environment.DIRECTORY_MOVIES - val downloads: String = Environment.DIRECTORY_DOWNLOADS - val dcim: String = Environment.DIRECTORY_DCIM - val documents: String = Environment.DIRECTORY_DOCUMENTS + const val CUSTOM : String = "Custom" + const val DOWNLOADS: String = "Download" + const val DOCUMENTS: String = "Documents" } } From 0d93fcf90263eb2dccde0e44f9c37315ea8ee982 Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Tue, 23 Apr 2024 16:18:12 +0530 Subject: [PATCH 05/20] PermissionManager class added --- .../java/com/ss/smartstorage/MainActivity.kt | 7 +- .../com/ss/smart_storage/PermissionManager.kt | 116 +++++++++++++++ .../java/com/ss/smart_storage/SmartStorage.kt | 138 +++++++++--------- .../ss/smart_storage/util/PermissionStatus.kt | 5 + .../ss/smart_storage/util/SmartDirectory.kt | 3 +- 5 files changed, 197 insertions(+), 72 deletions(-) create mode 100644 smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt create mode 100644 smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt index f766303..4a80008 100644 --- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt +++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt @@ -1,8 +1,10 @@ package com.ss.smartstorage +import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface @@ -14,6 +16,7 @@ import com.ss.smartstorage.ui.theme.SmartStorageTheme class MainActivity : ComponentActivity() { + @RequiresApi(Build.VERSION_CODES.R) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -29,8 +32,8 @@ class MainActivity : ComponentActivity() { SmartStorageSample( onStoreTap = { smartStorage.store( - location = SmartDirectory.CUSTOM, - fileName = "interstellar", + location = SmartDirectory.EXTERNAL_PUBLIC, + fileName = "abc", fileType = SmartFileType.txt, fileData = "Directed by Christopher Nolan".toByteArray() ) diff --git a/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt new file mode 100644 index 0000000..126d6ac --- /dev/null +++ b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt @@ -0,0 +1,116 @@ +package com.ss.smart_storage + +import android.Manifest +import android.content.pm.PackageManager +import android.os.Build +import androidx.activity.ComponentActivity +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.ContextCompat +import com.ss.smart_storage.util.PermissionStatus +import com.ss.smart_storage.util.SmartDirectory + + +class PermissionManager( + private val activity: ComponentActivity, + val onPermissionGranted: (PermissionStatus) -> Unit +) { + + + private val requestPermissionLauncher = activity.registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted: Boolean -> + if (isGranted) { + onPermissionGranted(PermissionStatus.ACCEPTED) + } else { + onPermissionGranted(PermissionStatus.DENIED) + } + } + + + + + fun checkLocation(location: String) { + when (location) { + SmartDirectory.CUSTOM -> { + onPermissionGranted(PermissionStatus.NOT_APPLICABLE) + } + + SmartDirectory.INTERNAL -> { + onPermissionGranted(PermissionStatus.NOT_NEEDED) + } + + SmartDirectory.DOCUMENTS -> { + checkOsForPermissions(location) + } + + SmartDirectory.DOWNLOADS -> { + checkOsForPermissions(location) + } + + SmartDirectory.SCOPED_STORAGE -> { + onPermissionGranted(PermissionStatus.NOT_NEEDED) + } + + SmartDirectory.EXTERNAL_PUBLIC -> { + checkOsForPermissions(location) + } + } + + } + + private fun checkOsForPermissions(location: String) { + + if (isVersionInBetween(Build.VERSION_CODES.M, Build.VERSION_CODES.Q)) { + + checkIfPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE, + onPermissionGranted = { + onPermissionGranted(PermissionStatus.ACCEPTED) + }) + } else if (isVersionInBetween( + Build.VERSION_CODES.R, Build.VERSION_CODES.S + ) && location == SmartDirectory.EXTERNAL_PUBLIC + ) { + checkIfManagePermissionGranted(Manifest.permission.MANAGE_EXTERNAL_STORAGE , + onPermissionGranted = { + granted -> + if(granted) onPermissionGranted(PermissionStatus.ACCEPTED) + else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS) + }) + + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && location == SmartDirectory.EXTERNAL_PUBLIC) { + onPermissionGranted(PermissionStatus.NOT_AVAILABLE) + } else { + onPermissionGranted(PermissionStatus.ACCEPTED) + } + } + + private fun checkIfPermissionGranted(permission: String, onPermissionGranted: () -> Unit) { + if (ContextCompat.checkSelfPermission( + activity, permission + ) == PackageManager.PERMISSION_GRANTED + ) { + onPermissionGranted() + } else { + requestPermissionLauncher.launch(permission) + } + } + + private fun checkIfManagePermissionGranted(permission: String, onPermissionGranted: (Boolean) -> Unit) { + if (ContextCompat.checkSelfPermission( + activity, permission + ) == PackageManager.PERMISSION_GRANTED + ) { + onPermissionGranted(true) + } else { + onPermissionGranted(false) + } + } + + + private fun isVersionInBetween(min: Int, max: Int): Boolean { + return Build.VERSION.SDK_INT in min..max + } + + +} \ No newline at end of file diff --git a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt index 0245dc4..fdafe3f 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt @@ -1,19 +1,15 @@ package com.ss.smart_storage -import android.Manifest -import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent -import android.content.pm.PackageManager import android.net.Uri -import android.os.Build import android.os.Environment import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.result.contract.ActivityResultContracts -import androidx.core.content.ContextCompat import androidx.documentfile.provider.DocumentFile +import com.ss.smart_storage.util.PermissionStatus import com.ss.smart_storage.util.SmartDirectory import com.ss.smart_storage.util.SmartFileType import java.io.File @@ -43,71 +39,60 @@ class SmartStorage(private val activity: ComponentActivity) { private var baseDocumentTreeUri: Uri? = null - private var fileDetails : FileDetails? = null - - - private val safLauncher = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == Activity.RESULT_OK) { - val uri: Uri? = result.data?.data - if (uri != null) { - baseDocumentTreeUri = uri - if(fileDetails!=null){ - writeFileToDocumentTree( - baseDocumentTreeUri, - fileDetails!!.name, - fileDetails!!.fileData, - ) - } - } - } - } + private var fileDetails: FileDetails? = null - private val requestPermissionLauncher = activity.registerForActivityResult( - ActivityResultContracts.RequestPermission() - ) { isGranted: Boolean -> - if (isGranted) { - callFileDetails() - } else { - Toast.makeText(activity, "Permission denied", Toast.LENGTH_SHORT).show() - } - } - - private fun launchBaseDirectoryPicker() { - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - safLauncher.launch(intent) - } + private val permissionManager = PermissionManager( + activity = activity, + onPermissionGranted = { status -> + when (status) { + PermissionStatus.NOT_NEEDED -> { + callFileDetails() + } -//todo : Remove Supress Lint - @SuppressLint("ObsoleteSdkInt") - fun isWritePermissionGranted(){ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (ContextCompat.checkSelfPermission( - activity, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) == PackageManager.PERMISSION_GRANTED - ) { + PermissionStatus.ACCEPTED -> { callFileDetails() - } else { - requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) } - } else { - callFileDetails() - } - } - private fun callFileDetails(){ - if(fileDetails != null){ - if(fileDetails!!.location == SmartDirectory.CUSTOM){ + PermissionStatus.DENIED -> { + Toast.makeText(activity, "Permission Denied", Toast.LENGTH_SHORT).show() + } + + PermissionStatus.NOT_APPLICABLE -> { launchBaseDirectoryPicker() } - else{ - storeToDirectory( - fileDetails = fileDetails!! - ) + PermissionStatus.NOT_AVAILABLE -> { + Toast.makeText(activity, "Feature not Available", Toast.LENGTH_SHORT).show() + } + + PermissionStatus.REDIRECT_TO_SETTINGS -> { + //Redirection + } + } + }) + + + private val safLauncher = + activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val uri: Uri? = result.data?.data + if (uri != null) { + baseDocumentTreeUri = uri + if (fileDetails != null) { + writeFileToDocumentTree( + baseDocumentTreeUri, + fileDetails!!.name, + fileDetails!!.fileData, + ) + } + } } } + + private fun launchBaseDirectoryPicker() { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + safLauncher.launch(intent) } @@ -118,18 +103,26 @@ class SmartStorage(private val activity: ComponentActivity) { if (!fileName.isNullOrEmpty()) "$fileName.$fileType" else "smartStorage.${fileType.name}" fileDetails = FileDetails( - name = name, - location = location, - fileType = fileType, - fileData = fileData + name = name, location = location, fileType = fileType, fileData = fileData ) - isWritePermissionGranted() + + permissionManager.checkLocation(location) + } + + + private fun callFileDetails() { + if (fileDetails != null) { + storeToDirectory( + fileDetails = fileDetails!! + ) + } } - private fun storeToDirectory(fileDetails: FileDetails){ + + private fun storeToDirectory(fileDetails: FileDetails) { val directory = handleFileCreation(fileDetails.location, activity.applicationContext) - if(directory!=null && !directory.exists()){ + if (directory != null && !directory.exists()) { directory.mkdirs() } @@ -146,12 +139,18 @@ class SmartStorage(private val activity: ComponentActivity) { } } - private fun writeFileToDocumentTree(baseDocumentTreeUri: Uri?, fileName: String, content: ByteArray) { + private fun writeFileToDocumentTree( + baseDocumentTreeUri: Uri?, fileName: String, content: ByteArray + ) { baseDocumentTreeUri?.let { treeUri -> try { val directory = DocumentFile.fromTreeUri(activity.applicationContext, treeUri) val file = directory?.createFile("text/*", fileName) - val pfd = file?.let { activity.applicationContext.contentResolver.openFileDescriptor(it.uri, "w") } + val pfd = file?.let { + activity.applicationContext.contentResolver.openFileDescriptor( + it.uri, "w" + ) + } pfd?.use { descriptor -> val fos = FileOutputStream(descriptor.fileDescriptor) fos.write(content) @@ -166,7 +165,8 @@ class SmartStorage(private val activity: ComponentActivity) { private fun handleFileCreation(location: String, context: Context): File? { return when (location) { SmartDirectory.INTERNAL -> context.filesDir - SmartDirectory.EXTERNAL_APP -> context.getExternalFilesDir(null) + SmartDirectory.EXTERNAL_PUBLIC -> Environment.getExternalStoragePublicDirectory("SmartStorage") + SmartDirectory.SCOPED_STORAGE -> context.getExternalFilesDir(null) else -> Environment.getExternalStoragePublicDirectory(location) } } diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt new file mode 100644 index 0000000..a45461c --- /dev/null +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt @@ -0,0 +1,5 @@ +package com.ss.smart_storage.util + +enum class PermissionStatus { + ACCEPTED, DENIED, NOT_APPLICABLE, NOT_NEEDED, NOT_AVAILABLE, REDIRECT_TO_SETTINGS +} \ No newline at end of file diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt index 3c587cf..0e121fb 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt @@ -4,10 +4,11 @@ package com.ss.smart_storage.util class SmartDirectory{ companion object { const val INTERNAL: String = "Internal" - const val EXTERNAL_APP : String = "External_App" + const val SCOPED_STORAGE : String = "Scoped_Storage" const val CUSTOM : String = "Custom" const val DOWNLOADS: String = "Download" const val DOCUMENTS: String = "Documents" + const val EXTERNAL_PUBLIC = "External_Public" } } From 89d6ea5ee0d5edf85a4ea9b80281f70cf404fbb9 Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Tue, 23 Apr 2024 18:00:19 +0530 Subject: [PATCH 06/20] redundant code removed in PermissionManager class --- app/src/main/AndroidManifest.xml | 1 - app/src/main/java/com/ss/smartstorage/MainActivity.kt | 4 ++-- app/src/main/res/values/colors.xml | 7 ------- gradle/libs.versions.toml | 10 +++++----- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2f46566..fffb69c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,7 +24,6 @@ diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt index 4a80008..266e1b4 100644 --- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt +++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt @@ -32,8 +32,8 @@ class MainActivity : ComponentActivity() { SmartStorageSample( onStoreTap = { smartStorage.store( - location = SmartDirectory.EXTERNAL_PUBLIC, - fileName = "abc", + location = SmartDirectory.DOWNLOADS, + fileName = "dd", fileType = SmartFileType.txt, fileData = "Directed by Christopher Nolan".toByteArray() ) diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f8c6127..55344e5 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,10 +1,3 @@ - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 086afa8..e343d2b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,16 +1,16 @@ [versions] -agp = "8.3.1" +agp = "8.3.2" coilCompose = "2.6.0" kotlin = "1.9.0" -coreKtx = "1.12.0" +coreKtx = "1.13.0" junit = "4.13.2" junitVersion = "1.1.5" espressoCore = "3.5.1" lifecycleRuntimeKtx = "2.7.0" -activityCompose = "1.8.2" -composeBom = "2023.08.00" +activityCompose = "1.9.0" +composeBom = "2024.04.01" appcompat = "1.6.1" -lifecycleViewmodelCompose = "2.6.1" +lifecycleViewmodelCompose = "2.7.0" material = "1.11.0" documentfile = "1.0.1" From a8458b875ac39b0e259c923f0279f36494c4326e Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Tue, 23 Apr 2024 16:18:12 +0530 Subject: [PATCH 07/20] PermissionManager class added --- .../java/com/ss/smartstorage/MainActivity.kt | 7 +- .../com/ss/smart_storage/PermissionManager.kt | 116 +++++++++++++++ .../java/com/ss/smart_storage/SmartStorage.kt | 138 +++++++++--------- .../ss/smart_storage/util/PermissionStatus.kt | 5 + .../ss/smart_storage/util/SmartDirectory.kt | 3 +- 5 files changed, 197 insertions(+), 72 deletions(-) create mode 100644 smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt create mode 100644 smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt index f766303..4a80008 100644 --- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt +++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt @@ -1,8 +1,10 @@ package com.ss.smartstorage +import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface @@ -14,6 +16,7 @@ import com.ss.smartstorage.ui.theme.SmartStorageTheme class MainActivity : ComponentActivity() { + @RequiresApi(Build.VERSION_CODES.R) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -29,8 +32,8 @@ class MainActivity : ComponentActivity() { SmartStorageSample( onStoreTap = { smartStorage.store( - location = SmartDirectory.CUSTOM, - fileName = "interstellar", + location = SmartDirectory.EXTERNAL_PUBLIC, + fileName = "abc", fileType = SmartFileType.txt, fileData = "Directed by Christopher Nolan".toByteArray() ) diff --git a/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt new file mode 100644 index 0000000..126d6ac --- /dev/null +++ b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt @@ -0,0 +1,116 @@ +package com.ss.smart_storage + +import android.Manifest +import android.content.pm.PackageManager +import android.os.Build +import androidx.activity.ComponentActivity +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.ContextCompat +import com.ss.smart_storage.util.PermissionStatus +import com.ss.smart_storage.util.SmartDirectory + + +class PermissionManager( + private val activity: ComponentActivity, + val onPermissionGranted: (PermissionStatus) -> Unit +) { + + + private val requestPermissionLauncher = activity.registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted: Boolean -> + if (isGranted) { + onPermissionGranted(PermissionStatus.ACCEPTED) + } else { + onPermissionGranted(PermissionStatus.DENIED) + } + } + + + + + fun checkLocation(location: String) { + when (location) { + SmartDirectory.CUSTOM -> { + onPermissionGranted(PermissionStatus.NOT_APPLICABLE) + } + + SmartDirectory.INTERNAL -> { + onPermissionGranted(PermissionStatus.NOT_NEEDED) + } + + SmartDirectory.DOCUMENTS -> { + checkOsForPermissions(location) + } + + SmartDirectory.DOWNLOADS -> { + checkOsForPermissions(location) + } + + SmartDirectory.SCOPED_STORAGE -> { + onPermissionGranted(PermissionStatus.NOT_NEEDED) + } + + SmartDirectory.EXTERNAL_PUBLIC -> { + checkOsForPermissions(location) + } + } + + } + + private fun checkOsForPermissions(location: String) { + + if (isVersionInBetween(Build.VERSION_CODES.M, Build.VERSION_CODES.Q)) { + + checkIfPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE, + onPermissionGranted = { + onPermissionGranted(PermissionStatus.ACCEPTED) + }) + } else if (isVersionInBetween( + Build.VERSION_CODES.R, Build.VERSION_CODES.S + ) && location == SmartDirectory.EXTERNAL_PUBLIC + ) { + checkIfManagePermissionGranted(Manifest.permission.MANAGE_EXTERNAL_STORAGE , + onPermissionGranted = { + granted -> + if(granted) onPermissionGranted(PermissionStatus.ACCEPTED) + else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS) + }) + + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && location == SmartDirectory.EXTERNAL_PUBLIC) { + onPermissionGranted(PermissionStatus.NOT_AVAILABLE) + } else { + onPermissionGranted(PermissionStatus.ACCEPTED) + } + } + + private fun checkIfPermissionGranted(permission: String, onPermissionGranted: () -> Unit) { + if (ContextCompat.checkSelfPermission( + activity, permission + ) == PackageManager.PERMISSION_GRANTED + ) { + onPermissionGranted() + } else { + requestPermissionLauncher.launch(permission) + } + } + + private fun checkIfManagePermissionGranted(permission: String, onPermissionGranted: (Boolean) -> Unit) { + if (ContextCompat.checkSelfPermission( + activity, permission + ) == PackageManager.PERMISSION_GRANTED + ) { + onPermissionGranted(true) + } else { + onPermissionGranted(false) + } + } + + + private fun isVersionInBetween(min: Int, max: Int): Boolean { + return Build.VERSION.SDK_INT in min..max + } + + +} \ No newline at end of file diff --git a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt index 0245dc4..fdafe3f 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt @@ -1,19 +1,15 @@ package com.ss.smart_storage -import android.Manifest -import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent -import android.content.pm.PackageManager import android.net.Uri -import android.os.Build import android.os.Environment import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.result.contract.ActivityResultContracts -import androidx.core.content.ContextCompat import androidx.documentfile.provider.DocumentFile +import com.ss.smart_storage.util.PermissionStatus import com.ss.smart_storage.util.SmartDirectory import com.ss.smart_storage.util.SmartFileType import java.io.File @@ -43,71 +39,60 @@ class SmartStorage(private val activity: ComponentActivity) { private var baseDocumentTreeUri: Uri? = null - private var fileDetails : FileDetails? = null - - - private val safLauncher = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == Activity.RESULT_OK) { - val uri: Uri? = result.data?.data - if (uri != null) { - baseDocumentTreeUri = uri - if(fileDetails!=null){ - writeFileToDocumentTree( - baseDocumentTreeUri, - fileDetails!!.name, - fileDetails!!.fileData, - ) - } - } - } - } + private var fileDetails: FileDetails? = null - private val requestPermissionLauncher = activity.registerForActivityResult( - ActivityResultContracts.RequestPermission() - ) { isGranted: Boolean -> - if (isGranted) { - callFileDetails() - } else { - Toast.makeText(activity, "Permission denied", Toast.LENGTH_SHORT).show() - } - } - - private fun launchBaseDirectoryPicker() { - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - safLauncher.launch(intent) - } + private val permissionManager = PermissionManager( + activity = activity, + onPermissionGranted = { status -> + when (status) { + PermissionStatus.NOT_NEEDED -> { + callFileDetails() + } -//todo : Remove Supress Lint - @SuppressLint("ObsoleteSdkInt") - fun isWritePermissionGranted(){ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (ContextCompat.checkSelfPermission( - activity, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) == PackageManager.PERMISSION_GRANTED - ) { + PermissionStatus.ACCEPTED -> { callFileDetails() - } else { - requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) } - } else { - callFileDetails() - } - } - private fun callFileDetails(){ - if(fileDetails != null){ - if(fileDetails!!.location == SmartDirectory.CUSTOM){ + PermissionStatus.DENIED -> { + Toast.makeText(activity, "Permission Denied", Toast.LENGTH_SHORT).show() + } + + PermissionStatus.NOT_APPLICABLE -> { launchBaseDirectoryPicker() } - else{ - storeToDirectory( - fileDetails = fileDetails!! - ) + PermissionStatus.NOT_AVAILABLE -> { + Toast.makeText(activity, "Feature not Available", Toast.LENGTH_SHORT).show() + } + + PermissionStatus.REDIRECT_TO_SETTINGS -> { + //Redirection + } + } + }) + + + private val safLauncher = + activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val uri: Uri? = result.data?.data + if (uri != null) { + baseDocumentTreeUri = uri + if (fileDetails != null) { + writeFileToDocumentTree( + baseDocumentTreeUri, + fileDetails!!.name, + fileDetails!!.fileData, + ) + } + } } } + + private fun launchBaseDirectoryPicker() { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + safLauncher.launch(intent) } @@ -118,18 +103,26 @@ class SmartStorage(private val activity: ComponentActivity) { if (!fileName.isNullOrEmpty()) "$fileName.$fileType" else "smartStorage.${fileType.name}" fileDetails = FileDetails( - name = name, - location = location, - fileType = fileType, - fileData = fileData + name = name, location = location, fileType = fileType, fileData = fileData ) - isWritePermissionGranted() + + permissionManager.checkLocation(location) + } + + + private fun callFileDetails() { + if (fileDetails != null) { + storeToDirectory( + fileDetails = fileDetails!! + ) + } } - private fun storeToDirectory(fileDetails: FileDetails){ + + private fun storeToDirectory(fileDetails: FileDetails) { val directory = handleFileCreation(fileDetails.location, activity.applicationContext) - if(directory!=null && !directory.exists()){ + if (directory != null && !directory.exists()) { directory.mkdirs() } @@ -146,12 +139,18 @@ class SmartStorage(private val activity: ComponentActivity) { } } - private fun writeFileToDocumentTree(baseDocumentTreeUri: Uri?, fileName: String, content: ByteArray) { + private fun writeFileToDocumentTree( + baseDocumentTreeUri: Uri?, fileName: String, content: ByteArray + ) { baseDocumentTreeUri?.let { treeUri -> try { val directory = DocumentFile.fromTreeUri(activity.applicationContext, treeUri) val file = directory?.createFile("text/*", fileName) - val pfd = file?.let { activity.applicationContext.contentResolver.openFileDescriptor(it.uri, "w") } + val pfd = file?.let { + activity.applicationContext.contentResolver.openFileDescriptor( + it.uri, "w" + ) + } pfd?.use { descriptor -> val fos = FileOutputStream(descriptor.fileDescriptor) fos.write(content) @@ -166,7 +165,8 @@ class SmartStorage(private val activity: ComponentActivity) { private fun handleFileCreation(location: String, context: Context): File? { return when (location) { SmartDirectory.INTERNAL -> context.filesDir - SmartDirectory.EXTERNAL_APP -> context.getExternalFilesDir(null) + SmartDirectory.EXTERNAL_PUBLIC -> Environment.getExternalStoragePublicDirectory("SmartStorage") + SmartDirectory.SCOPED_STORAGE -> context.getExternalFilesDir(null) else -> Environment.getExternalStoragePublicDirectory(location) } } diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt new file mode 100644 index 0000000..a45461c --- /dev/null +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt @@ -0,0 +1,5 @@ +package com.ss.smart_storage.util + +enum class PermissionStatus { + ACCEPTED, DENIED, NOT_APPLICABLE, NOT_NEEDED, NOT_AVAILABLE, REDIRECT_TO_SETTINGS +} \ No newline at end of file diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt index 3c587cf..0e121fb 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt @@ -4,10 +4,11 @@ package com.ss.smart_storage.util class SmartDirectory{ companion object { const val INTERNAL: String = "Internal" - const val EXTERNAL_APP : String = "External_App" + const val SCOPED_STORAGE : String = "Scoped_Storage" const val CUSTOM : String = "Custom" const val DOWNLOADS: String = "Download" const val DOCUMENTS: String = "Documents" + const val EXTERNAL_PUBLIC = "External_Public" } } From fd0231adfd93b5df9b5afdf17ae86dfd643b365d Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Tue, 23 Apr 2024 18:00:19 +0530 Subject: [PATCH 08/20] redundant code removed in PermissionManager class --- app/src/main/AndroidManifest.xml | 1 - app/src/main/java/com/ss/smartstorage/MainActivity.kt | 4 ++-- app/src/main/res/values/colors.xml | 7 ------- gradle/libs.versions.toml | 10 +++++----- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2f46566..fffb69c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,7 +24,6 @@ diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt index 4a80008..266e1b4 100644 --- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt +++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt @@ -32,8 +32,8 @@ class MainActivity : ComponentActivity() { SmartStorageSample( onStoreTap = { smartStorage.store( - location = SmartDirectory.EXTERNAL_PUBLIC, - fileName = "abc", + location = SmartDirectory.DOWNLOADS, + fileName = "dd", fileType = SmartFileType.txt, fileData = "Directed by Christopher Nolan".toByteArray() ) diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f8c6127..55344e5 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,10 +1,3 @@ - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 086afa8..e343d2b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,16 +1,16 @@ [versions] -agp = "8.3.1" +agp = "8.3.2" coilCompose = "2.6.0" kotlin = "1.9.0" -coreKtx = "1.12.0" +coreKtx = "1.13.0" junit = "4.13.2" junitVersion = "1.1.5" espressoCore = "3.5.1" lifecycleRuntimeKtx = "2.7.0" -activityCompose = "1.8.2" -composeBom = "2023.08.00" +activityCompose = "1.9.0" +composeBom = "2024.04.01" appcompat = "1.6.1" -lifecycleViewmodelCompose = "2.6.1" +lifecycleViewmodelCompose = "2.7.0" material = "1.11.0" documentfile = "1.0.1" From d4fc92624366d1ec1754711deddee1de9dc3e768 Mon Sep 17 00:00:00 2001 From: harshilpadsala88 Date: Mon, 29 Apr 2024 12:36:45 +0530 Subject: [PATCH 09/20] Suggested-Changes-In-The-PR-done --- .idea/androidTestResultsUserPreferences.xml | 22 +++ .idea/deploymentTargetDropDown.xml | 15 +- .../f4ccae7b16112b00a2d85965108cf28a4b17a2b4 | 4 + app/src/main/AndroidManifest.xml | 2 + .../java/com/ss/smartstorage/MainActivity.kt | 10 +- .../com/ss/smart_storage/PermissionManager.kt | 32 +++-- .../java/com/ss/smart_storage/SmartStorage.kt | 130 ++++++++++-------- .../com/ss/smart_storage/model/FileDetails.kt | 21 +++ .../ss/smart_storage/util/SmartFileType.kt | 17 ++- smart-storage/src/main/res/values/strings.xml | 6 + 10 files changed, 172 insertions(+), 87 deletions(-) create mode 100644 .idea/androidTestResultsUserPreferences.xml create mode 100644 smart-storage/src/main/java/com/ss/smart_storage/model/FileDetails.kt create mode 100644 smart-storage/src/main/res/values/strings.xml diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml new file mode 100644 index 0000000..44968c6 --- /dev/null +++ b/.idea/androidTestResultsUserPreferences.xml @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 0c0c338..199ec2f 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -3,7 +3,20 @@ - + + + + + + + + + + + + + + diff --git a/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 b/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 index e69de29..14e2494 100644 --- a/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 +++ b/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 @@ -0,0 +1,4 @@ + +_ kotlin:S1128"Remove this unused import.(ܺ¸¡8­–žÄò1J$340b6a82-7242-48ff-883d-0bef7f6ba469 +d kotlin:S1128"Remove this unused import.(ÊÒÅ­ùÿÿÿÿ8à» Äò1J$6a454b06-2ed2-46ae-a0f6-aea197adecdb +d kotlin:S1128 "Remove this unused import.(£“×”ýÿÿÿÿ8­–žÄò1J$59941629-e906-4ad0-aa23-d43fb6262f12 \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fffb69c..2354b92 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,8 @@ + Unit ) { - - private val requestPermissionLauncher = activity.registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted: Boolean -> @@ -26,11 +29,9 @@ class PermissionManager( } } - - - fun checkLocation(location: String) { when (location) { + SmartDirectory.CUSTOM -> { onPermissionGranted(PermissionStatus.NOT_APPLICABLE) } @@ -55,13 +56,10 @@ class PermissionManager( checkOsForPermissions(location) } } - } private fun checkOsForPermissions(location: String) { - if (isVersionInBetween(Build.VERSION_CODES.M, Build.VERSION_CODES.Q)) { - checkIfPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE, onPermissionGranted = { onPermissionGranted(PermissionStatus.ACCEPTED) @@ -70,13 +68,14 @@ class PermissionManager( Build.VERSION_CODES.R, Build.VERSION_CODES.S ) && location == SmartDirectory.EXTERNAL_PUBLIC ) { - checkIfManagePermissionGranted(Manifest.permission.MANAGE_EXTERNAL_STORAGE , - onPermissionGranted = { - granted -> - if(granted) onPermissionGranted(PermissionStatus.ACCEPTED) - else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS) - }) - + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + checkIfManagePermissionGranted(Manifest.permission.MANAGE_EXTERNAL_STORAGE , + onPermissionGranted = { + granted -> + if(granted) onPermissionGranted(PermissionStatus.ACCEPTED) + else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS) + }) + } } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && location == SmartDirectory.EXTERNAL_PUBLIC) { onPermissionGranted(PermissionStatus.NOT_AVAILABLE) @@ -85,6 +84,7 @@ class PermissionManager( } } + private fun checkIfPermissionGranted(permission: String, onPermissionGranted: () -> Unit) { if (ContextCompat.checkSelfPermission( activity, permission @@ -108,6 +108,8 @@ class PermissionManager( } + + private fun isVersionInBetween(min: Int, max: Int): Boolean { return Build.VERSION.SDK_INT in min..max } diff --git a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt index fdafe3f..0659d4f 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt @@ -1,14 +1,19 @@ package com.ss.smart_storage +import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri +import android.os.Build import android.os.Environment +import android.provider.Settings import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.RequiresApi import androidx.documentfile.provider.DocumentFile +import com.ss.smart_storage.model.FileDetails import com.ss.smart_storage.util.PermissionStatus import com.ss.smart_storage.util.SmartDirectory import com.ss.smart_storage.util.SmartFileType @@ -17,60 +22,50 @@ import java.io.FileOutputStream import java.io.IOException -data class FileDetails( - val name: String, - val location: String, - val fileType: SmartFileType, - val fileData: ByteArray, -) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - other as FileDetails - return fileData.contentEquals(other.fileData) - } - - override fun hashCode(): Int { - return fileData.contentHashCode() - } -} - class SmartStorage(private val activity: ComponentActivity) { - private var baseDocumentTreeUri: Uri? = null - private var fileDetails: FileDetails? = null + private lateinit var fileDetails: FileDetails - private val permissionManager = PermissionManager( - activity = activity, - onPermissionGranted = { status -> - when (status) { - PermissionStatus.NOT_NEEDED -> { - callFileDetails() - } + @SuppressLint("NewApi") + private val permissionManager = + PermissionManager(activity = activity, onPermissionGranted = { status -> - PermissionStatus.ACCEPTED -> { - callFileDetails() - } + when (status) { + PermissionStatus.NOT_NEEDED -> { + callFileDetails() + } - PermissionStatus.DENIED -> { - Toast.makeText(activity, "Permission Denied", Toast.LENGTH_SHORT).show() - } + PermissionStatus.ACCEPTED -> { + callFileDetails() + } - PermissionStatus.NOT_APPLICABLE -> { - launchBaseDirectoryPicker() - } + PermissionStatus.DENIED -> { + Toast.makeText( + activity, + activity.getString(R.string.perm_denied), + Toast.LENGTH_SHORT + ).show() + } - PermissionStatus.NOT_AVAILABLE -> { - Toast.makeText(activity, "Feature not Available", Toast.LENGTH_SHORT).show() - } + PermissionStatus.NOT_APPLICABLE -> { + launchBaseDirectoryPicker() + } + + PermissionStatus.NOT_AVAILABLE -> { + Toast.makeText( + activity, + activity.getString(R.string.feature_not_available), + Toast.LENGTH_SHORT + ).show() + } - PermissionStatus.REDIRECT_TO_SETTINGS -> { - //Redirection + PermissionStatus.REDIRECT_TO_SETTINGS -> { + requestFullStorageAccess() + } } - } - }) + }) private val safLauncher = @@ -79,13 +74,9 @@ class SmartStorage(private val activity: ComponentActivity) { val uri: Uri? = result.data?.data if (uri != null) { baseDocumentTreeUri = uri - if (fileDetails != null) { - writeFileToDocumentTree( - baseDocumentTreeUri, - fileDetails!!.name, - fileDetails!!.fileData, - ) - } + writeFileToDocumentTree( + baseDocumentTreeUri, + ) } } } @@ -95,12 +86,18 @@ class SmartStorage(private val activity: ComponentActivity) { safLauncher.launch(intent) } + @RequiresApi(Build.VERSION_CODES.R) + private fun requestFullStorageAccess(){ + activity.startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)) + } + fun store( location: String, fileName: String? = null, fileType: SmartFileType, fileData: ByteArray ) { + val name = - if (!fileName.isNullOrEmpty()) "$fileName.$fileType" else "smartStorage.${fileType.name}" + if(fileName.isNullOrEmpty()) randomFileName(fileType.extension) else fileName.plus(fileType.extension) fileDetails = FileDetails( name = name, location = location, fileType = fileType, fileData = fileData @@ -111,11 +108,17 @@ class SmartStorage(private val activity: ComponentActivity) { private fun callFileDetails() { - if (fileDetails != null) { - storeToDirectory( - fileDetails = fileDetails!! - ) - } + storeToDirectory( + fileDetails = fileDetails + ) + } + + private fun randomFileName(extension : String): String { + val alphanumericChars = ('a'..'z') + ('A'..'Z') + ('0'..'9') + val randomString = (1..8) + .map { alphanumericChars.random() } + .joinToString("") + return randomString.plus(extension) } @@ -140,12 +143,13 @@ class SmartStorage(private val activity: ComponentActivity) { } private fun writeFileToDocumentTree( - baseDocumentTreeUri: Uri?, fileName: String, content: ByteArray + baseDocumentTreeUri: Uri? ) { baseDocumentTreeUri?.let { treeUri -> try { val directory = DocumentFile.fromTreeUri(activity.applicationContext, treeUri) - val file = directory?.createFile("text/*", fileName) + val file = + directory?.createFile(fileDetails.fileType.mimeType, fileDetails.fileType.name) val pfd = file?.let { activity.applicationContext.contentResolver.openFileDescriptor( it.uri, "w" @@ -153,7 +157,7 @@ class SmartStorage(private val activity: ComponentActivity) { } pfd?.use { descriptor -> val fos = FileOutputStream(descriptor.fileDescriptor) - fos.write(content) + fos.write(fileDetails.fileData) fos.close() } } catch (e: IOException) { @@ -165,12 +169,18 @@ class SmartStorage(private val activity: ComponentActivity) { private fun handleFileCreation(location: String, context: Context): File? { return when (location) { SmartDirectory.INTERNAL -> context.filesDir - SmartDirectory.EXTERNAL_PUBLIC -> Environment.getExternalStoragePublicDirectory("SmartStorage") + SmartDirectory.EXTERNAL_PUBLIC -> Environment.getExternalStoragePublicDirectory( + getPackage() + ) + SmartDirectory.SCOPED_STORAGE -> context.getExternalFilesDir(null) else -> Environment.getExternalStoragePublicDirectory(location) } } + private fun getPackage(): String = activity.packageName.substringAfterLast('.') + + } diff --git a/smart-storage/src/main/java/com/ss/smart_storage/model/FileDetails.kt b/smart-storage/src/main/java/com/ss/smart_storage/model/FileDetails.kt new file mode 100644 index 0000000..4c81544 --- /dev/null +++ b/smart-storage/src/main/java/com/ss/smart_storage/model/FileDetails.kt @@ -0,0 +1,21 @@ +package com.ss.smart_storage.model + +import com.ss.smart_storage.util.SmartFileType + +data class FileDetails( + val name: String, + val location: String, + val fileType: SmartFileType, + val fileData: ByteArray, +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as FileDetails + return fileData.contentEquals(other.fileData) + } + + override fun hashCode(): Int { + return fileData.contentHashCode() + } +} diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt index 657fbbd..78a86b6 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt @@ -1,9 +1,12 @@ package com.ss.smart_storage.util -enum class SmartFileType { - txt, - jpeg, - png, - pdf, - webp, -} \ No newline at end of file + +enum class SmartFileType(val extension: String, val mimeType: String) { + TXT(extension = ".txt", mimeType = "text/plain"), JPEG( + extension = ".jpeg", mimeType = "image/jpeg" + ), + PNG(extension = ".png", mimeType = "image/png"), PDF( + extension = ".pdf", mimeType = "application/pdf" + ), + WEBP(extension = ".webp", mimeType = "image/webp"), +} diff --git a/smart-storage/src/main/res/values/strings.xml b/smart-storage/src/main/res/values/strings.xml new file mode 100644 index 0000000..0e1b6de --- /dev/null +++ b/smart-storage/src/main/res/values/strings.xml @@ -0,0 +1,6 @@ + + + Permission Denied + Feature not Available + + \ No newline at end of file From bff0ffa2d28a2f4be207ab2d3770e3843b392064 Mon Sep 17 00:00:00 2001 From: harshilpadsala88 Date: Mon, 29 Apr 2024 12:41:35 +0530 Subject: [PATCH 10/20] Solar-Lint-Checks-Passed --- .../f4ccae7b16112b00a2d85965108cf28a4b17a2b4 | 4 -- .../java/com/ss/smartstorage/MainActivity.kt | 3 -- .../com/ss/smart_storage/PermissionManager.kt | 54 +++++++++---------- 3 files changed, 26 insertions(+), 35 deletions(-) diff --git a/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 b/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 index 14e2494..e69de29 100644 --- a/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 +++ b/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 @@ -1,4 +0,0 @@ - -_ kotlin:S1128"Remove this unused import.(ܺ¸¡8­–žÄò1J$340b6a82-7242-48ff-883d-0bef7f6ba469 -d kotlin:S1128"Remove this unused import.(ÊÒÅ­ùÿÿÿÿ8à» Äò1J$6a454b06-2ed2-46ae-a0f6-aea197adecdb -d kotlin:S1128 "Remove this unused import.(£“×”ýÿÿÿÿ8­–žÄò1J$59941629-e906-4ad0-aa23-d43fb6262f12 \ No newline at end of file diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt index 6e43cd8..7a023b2 100644 --- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt +++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt @@ -1,12 +1,9 @@ package com.ss.smartstorage import android.annotation.SuppressLint -import android.os.Build import android.os.Bundle -import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface diff --git a/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt index 88dd12a..787ce5f 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt @@ -1,15 +1,10 @@ package com.ss.smart_storage import android.Manifest -import android.content.Intent import android.content.pm.PackageManager import android.os.Build -import android.provider.Settings -import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.result.contract.ActivityResultContracts -import androidx.annotation.RequiresApi -import androidx.annotation.RequiresPermission import androidx.core.content.ContextCompat import com.ss.smart_storage.util.PermissionStatus import com.ss.smart_storage.util.SmartDirectory @@ -59,46 +54,49 @@ class PermissionManager( } private fun checkOsForPermissions(location: String) { - if (isVersionInBetween(Build.VERSION_CODES.M, Build.VERSION_CODES.Q)) { - checkIfPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE, - onPermissionGranted = { - onPermissionGranted(PermissionStatus.ACCEPTED) - }) - } else if (isVersionInBetween( - Build.VERSION_CODES.R, Build.VERSION_CODES.S - ) && location == SmartDirectory.EXTERNAL_PUBLIC - ) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - checkIfManagePermissionGranted(Manifest.permission.MANAGE_EXTERNAL_STORAGE , + when { + isVersionInBetween(Build.VERSION_CODES.M, Build.VERSION_CODES.Q) -> { + checkIfPermissionGranted( onPermissionGranted = { - granted -> - if(granted) onPermissionGranted(PermissionStatus.ACCEPTED) - else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS) + onPermissionGranted(PermissionStatus.ACCEPTED) }) } + isVersionInBetween( + Build.VERSION_CODES.R, Build.VERSION_CODES.S + ) && location == SmartDirectory.EXTERNAL_PUBLIC -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + checkIfManagePermissionGranted( + onPermissionGranted = { granted -> + if(granted) onPermissionGranted(PermissionStatus.ACCEPTED) + else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS) + }) + } - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && location == SmartDirectory.EXTERNAL_PUBLIC) { - onPermissionGranted(PermissionStatus.NOT_AVAILABLE) - } else { - onPermissionGranted(PermissionStatus.ACCEPTED) + } + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && location == SmartDirectory.EXTERNAL_PUBLIC -> { + onPermissionGranted(PermissionStatus.NOT_AVAILABLE) + } + else -> { + onPermissionGranted(PermissionStatus.ACCEPTED) + } } } - private fun checkIfPermissionGranted(permission: String, onPermissionGranted: () -> Unit) { + private fun checkIfPermissionGranted(onPermissionGranted: () -> Unit) { if (ContextCompat.checkSelfPermission( - activity, permission + activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, ) == PackageManager.PERMISSION_GRANTED ) { onPermissionGranted() } else { - requestPermissionLauncher.launch(permission) + requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE,) } } - private fun checkIfManagePermissionGranted(permission: String, onPermissionGranted: (Boolean) -> Unit) { + private fun checkIfManagePermissionGranted( onPermissionGranted: (Boolean) -> Unit) { if (ContextCompat.checkSelfPermission( - activity, permission + activity, Manifest.permission.MANAGE_EXTERNAL_STORAGE , ) == PackageManager.PERMISSION_GRANTED ) { onPermissionGranted(true) From c01d3338b366df7280a59ceeddae243b7b247c67 Mon Sep 17 00:00:00 2001 From: harshilpadsala88 Date: Mon, 29 Apr 2024 14:37:05 +0530 Subject: [PATCH 11/20] Gitignore updated and removed sonarlint folder from idea folder. --- .../issuestore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 | 0 .../issuestore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d | 0 .../issuestore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 | 0 .../issuestore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c | 0 .../issuestore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 | 0 .../issuestore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d | 2 -- .../issuestore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 | 0 .../issuestore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f | 0 .../issuestore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d | 0 .../issuestore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df | 0 .../issuestore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 | 0 .../issuestore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e | 0 .../issuestore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 | 0 .../issuestore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b | 0 .../issuestore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e | 0 .../issuestore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 | 0 .../issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 | 0 .../issuestore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b | 0 .../issuestore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 | 0 .../issuestore/d/2/d2281fbb3027de2722081a53408dd77628bf080e | 0 .../issuestore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 | 0 .../issuestore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 | 0 .../issuestore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d | 0 .../issuestore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 | 0 .../issuestore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 | 0 .../issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 | 0 .../0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 | 0 .../0/7/078508c831007ccb3938b355f0d30a8368f99a8d | 0 .../2/4/24ce74baca63d400e46baee54dfd1daccb063d26 | 0 .../2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c | 0 .../2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 | 0 .../3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d | 0 .../4/9/49845c622cb06d895975c7b1e3f943e320bce688 | 0 .../5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f | 0 .../5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d | 0 .../6/e/6ec7d34b130497a10dc92abcde9b313d370a89df | 0 .../7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 | 0 .../8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e | 0 .../8/e/8e27ba16c655f421171956147d0fde89b7d25d17 | 0 .../9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b | 0 .../9/c/9c2a853ebd9f87844b147b05656fea1b7325609e | 0 .../9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 | 0 .../a/5/a5cc2925ca8258af241be7e5b0381edf30266302 | 0 .../a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b | 0 .../c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 | 0 .../c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 | 0 .../d/2/d2281fbb3027de2722081a53408dd77628bf080e | 0 .../d/2/d2a4383452aad84a18429a5844d31330a012a9e6 | 0 .../d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 | 0 .../d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d | 0 .../e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 | 0 .../e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 | 0 .../f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 | 0 53 files changed, 2 deletions(-) delete mode 100644 .idea/sonarlint/issuestore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 delete mode 100644 .idea/sonarlint/issuestore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d delete mode 100644 .idea/sonarlint/issuestore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 delete mode 100644 .idea/sonarlint/issuestore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c delete mode 100644 .idea/sonarlint/issuestore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 delete mode 100644 .idea/sonarlint/issuestore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d delete mode 100644 .idea/sonarlint/issuestore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 delete mode 100644 .idea/sonarlint/issuestore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f delete mode 100644 .idea/sonarlint/issuestore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d delete mode 100644 .idea/sonarlint/issuestore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df delete mode 100644 .idea/sonarlint/issuestore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 delete mode 100644 .idea/sonarlint/issuestore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e delete mode 100644 .idea/sonarlint/issuestore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 delete mode 100644 .idea/sonarlint/issuestore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b delete mode 100644 .idea/sonarlint/issuestore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e delete mode 100644 .idea/sonarlint/issuestore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 delete mode 100644 .idea/sonarlint/issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 delete mode 100644 .idea/sonarlint/issuestore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b delete mode 100644 .idea/sonarlint/issuestore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 delete mode 100644 .idea/sonarlint/issuestore/d/2/d2281fbb3027de2722081a53408dd77628bf080e delete mode 100644 .idea/sonarlint/issuestore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 delete mode 100644 .idea/sonarlint/issuestore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 delete mode 100644 .idea/sonarlint/issuestore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d delete mode 100644 .idea/sonarlint/issuestore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 delete mode 100644 .idea/sonarlint/issuestore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 delete mode 100644 .idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 delete mode 100644 .idea/sonarlint/securityhotspotstore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 delete mode 100644 .idea/sonarlint/securityhotspotstore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d delete mode 100644 .idea/sonarlint/securityhotspotstore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 delete mode 100644 .idea/sonarlint/securityhotspotstore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c delete mode 100644 .idea/sonarlint/securityhotspotstore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 delete mode 100644 .idea/sonarlint/securityhotspotstore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d delete mode 100644 .idea/sonarlint/securityhotspotstore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 delete mode 100644 .idea/sonarlint/securityhotspotstore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f delete mode 100644 .idea/sonarlint/securityhotspotstore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d delete mode 100644 .idea/sonarlint/securityhotspotstore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df delete mode 100644 .idea/sonarlint/securityhotspotstore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 delete mode 100644 .idea/sonarlint/securityhotspotstore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e delete mode 100644 .idea/sonarlint/securityhotspotstore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 delete mode 100644 .idea/sonarlint/securityhotspotstore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b delete mode 100644 .idea/sonarlint/securityhotspotstore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e delete mode 100644 .idea/sonarlint/securityhotspotstore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 delete mode 100644 .idea/sonarlint/securityhotspotstore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 delete mode 100644 .idea/sonarlint/securityhotspotstore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b delete mode 100644 .idea/sonarlint/securityhotspotstore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 delete mode 100644 .idea/sonarlint/securityhotspotstore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 delete mode 100644 .idea/sonarlint/securityhotspotstore/d/2/d2281fbb3027de2722081a53408dd77628bf080e delete mode 100644 .idea/sonarlint/securityhotspotstore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 delete mode 100644 .idea/sonarlint/securityhotspotstore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 delete mode 100644 .idea/sonarlint/securityhotspotstore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d delete mode 100644 .idea/sonarlint/securityhotspotstore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 delete mode 100644 .idea/sonarlint/securityhotspotstore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 delete mode 100644 .idea/sonarlint/securityhotspotstore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 diff --git a/.idea/sonarlint/issuestore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 b/.idea/sonarlint/issuestore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d b/.idea/sonarlint/issuestore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 b/.idea/sonarlint/issuestore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c b/.idea/sonarlint/issuestore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 b/.idea/sonarlint/issuestore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d b/.idea/sonarlint/issuestore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d deleted file mode 100644 index 70bf876..0000000 --- a/.idea/sonarlint/issuestore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d +++ /dev/null @@ -1,2 +0,0 @@ - -I xml:S1135"4Complete the task associated to this "TODO" comment.(ÿ°Á‡ \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 b/.idea/sonarlint/issuestore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f b/.idea/sonarlint/issuestore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d b/.idea/sonarlint/issuestore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df b/.idea/sonarlint/issuestore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 b/.idea/sonarlint/issuestore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e b/.idea/sonarlint/issuestore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 b/.idea/sonarlint/issuestore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b b/.idea/sonarlint/issuestore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e b/.idea/sonarlint/issuestore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 b/.idea/sonarlint/issuestore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 b/.idea/sonarlint/issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b b/.idea/sonarlint/issuestore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 b/.idea/sonarlint/issuestore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/d/2/d2281fbb3027de2722081a53408dd77628bf080e b/.idea/sonarlint/issuestore/d/2/d2281fbb3027de2722081a53408dd77628bf080e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 b/.idea/sonarlint/issuestore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 b/.idea/sonarlint/issuestore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d b/.idea/sonarlint/issuestore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 b/.idea/sonarlint/issuestore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 b/.idea/sonarlint/issuestore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 b/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 b/.idea/sonarlint/securityhotspotstore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d b/.idea/sonarlint/securityhotspotstore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 b/.idea/sonarlint/securityhotspotstore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c b/.idea/sonarlint/securityhotspotstore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 b/.idea/sonarlint/securityhotspotstore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d b/.idea/sonarlint/securityhotspotstore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 b/.idea/sonarlint/securityhotspotstore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f b/.idea/sonarlint/securityhotspotstore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d b/.idea/sonarlint/securityhotspotstore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df b/.idea/sonarlint/securityhotspotstore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 b/.idea/sonarlint/securityhotspotstore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e b/.idea/sonarlint/securityhotspotstore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 b/.idea/sonarlint/securityhotspotstore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b b/.idea/sonarlint/securityhotspotstore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e b/.idea/sonarlint/securityhotspotstore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 b/.idea/sonarlint/securityhotspotstore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 b/.idea/sonarlint/securityhotspotstore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b b/.idea/sonarlint/securityhotspotstore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 b/.idea/sonarlint/securityhotspotstore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 b/.idea/sonarlint/securityhotspotstore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/d/2/d2281fbb3027de2722081a53408dd77628bf080e b/.idea/sonarlint/securityhotspotstore/d/2/d2281fbb3027de2722081a53408dd77628bf080e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 b/.idea/sonarlint/securityhotspotstore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 b/.idea/sonarlint/securityhotspotstore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d b/.idea/sonarlint/securityhotspotstore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 b/.idea/sonarlint/securityhotspotstore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 b/.idea/sonarlint/securityhotspotstore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/securityhotspotstore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 b/.idea/sonarlint/securityhotspotstore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 deleted file mode 100644 index e69de29..0000000 From 067d0a1b5415e89f62bba8c8662ac1937d2ccf5d Mon Sep 17 00:00:00 2001 From: harshilpadsala88 Date: Mon, 29 Apr 2024 14:43:29 +0530 Subject: [PATCH 12/20] Gitignore updated and removed .idea --- .gitignore | 1 + .idea/.gitignore | 3 -- .idea/androidTestResultsUserPreferences.xml | 22 ----------- .idea/compiler.xml | 6 --- .idea/deploymentTargetDropDown.xml | 23 ----------- .idea/gradle.xml | 20 ---------- .idea/inspectionProfiles/Project_Default.xml | 41 -------------------- .idea/kotlinc.xml | 6 --- .idea/migrations.xml | 10 ----- .idea/misc.xml | 10 ----- .idea/vcs.xml | 6 --- 11 files changed, 1 insertion(+), 147 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/androidTestResultsUserPreferences.xml delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/deploymentTargetDropDown.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/kotlinc.xml delete mode 100644 .idea/migrations.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index e10ceb9..4972f4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ git *.iml .gradle +.idea /local.properties /.idea/caches /.idea/libraries diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml deleted file mode 100644 index 44968c6..0000000 --- a/.idea/androidTestResultsUserPreferences.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index b589d56..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml deleted file mode 100644 index 199ec2f..0000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index ee7b132..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 44ca2d9..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml deleted file mode 100644 index fdf8d99..0000000 --- a/.idea/kotlinc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml deleted file mode 100644 index f8051a6..0000000 --- a/.idea/migrations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 0ad17cb..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 5638116a07aadc90f7ae1d1e7032cc18e4dee24f Mon Sep 17 00:00:00 2001 From: harshilpadsala88 Date: Mon, 29 Apr 2024 14:44:24 +0530 Subject: [PATCH 13/20] Removed unused things from gitignore --- .gitignore | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.gitignore b/.gitignore index 4972f4a..1fad173 100644 --- a/.gitignore +++ b/.gitignore @@ -2,13 +2,6 @@ git *.iml .gradle .idea /local.properties -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/sonarlint -/.idea/assetWizardSettings.xml .DS_Store /build /captures From bc06e3bcd8308b3d70e10be9b169dc38830a6501 Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Thu, 9 May 2024 12:26:11 +0530 Subject: [PATCH 14/20] Changed git ignote --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1fad173..cc698b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -git *.iml .gradle .idea /local.properties From ba37fe222641c5228f5a101c11b6a47fa8459612 Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Fri, 10 May 2024 15:05:09 +0530 Subject: [PATCH 15/20] Added sample app to check the app features. --- .../java/com/ss/smartstorage/MainActivity.kt | 16 +- .../com/ss/smartstorage/SmartStorageSample.kt | 264 +++++++++++++++++- .../java/com/ss/smart_storage/SmartStorage.kt | 3 +- 3 files changed, 265 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt index 7a023b2..910c426 100644 --- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt +++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt @@ -29,14 +29,14 @@ class MainActivity : ComponentActivity() { color = MaterialTheme.colorScheme.background ) { SmartStorageSample( - onStoreTap = { - smartStorage.store( - location = SmartDirectory.DOWNLOADS, - fileType = SmartFileType.TXT, - fileName = "SampleFile.txt", - fileData = "This is a sample txt file.".toByteArray() - ) - }, + onStoreTap = { fileName, fileType, location -> + smartStorage.store( + location = location, + fileType = fileType, + fileName = fileName, + fileData = "This is a sample txt file.".toByteArray() + ) + } ) } } diff --git a/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt b/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt index ac0401a..3e2a643 100644 --- a/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt +++ b/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt @@ -1,23 +1,269 @@ package com.ss.smartstorage + import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.material3.ElevatedButton +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TextField +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.ss.smart_storage.util.SmartDirectory +import com.ss.smart_storage.util.SmartFileType +import kotlinx.coroutines.launch +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SmartStorageToolBar() { + TopAppBar( + title = { + Text( + text = "Smart Storage Demo", + textAlign = TextAlign.Center, + fontSize = 30.sp, + fontWeight = FontWeight.Bold + ) + }, + + ) +} + +@OptIn(ExperimentalMaterial3Api::class) @Composable fun SmartStorageSample( - onStoreTap : () -> Unit, -){ - Column( - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - ElevatedButton(onClick = {onStoreTap()}) { - Text(text = "SAVE DUMMY") } + onStoreTap: (String, SmartFileType, String) -> Unit +) { + var showBottomSheetD by remember { mutableStateOf(false) } + + val sheetState = rememberModalBottomSheetState() + val scope = rememberCoroutineScope() + + var selectedDestination by remember { + mutableStateOf("") + } + + var isSaveButtonVisible by remember { + mutableStateOf(false) + } + var showBottomSheetF by remember { + mutableStateOf(false) + } + var fileName by remember { + mutableStateOf("") + } + + var selectedFiletype by remember { + mutableStateOf(SmartFileType.TXT) + } + val snackbarHostState = remember { SnackbarHostState() } + + Scaffold(topBar = { SmartStorageToolBar() }, snackbarHost = { + SnackbarHost(hostState = snackbarHostState) + }, content = { contentPadding -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues = contentPadding) + ) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(start = 20.dp, end = 30.dp, top = 10.dp) + ) { + Column( + modifier = Modifier.fillMaxWidth() + ) { + Text(text = "File Name : ") + Spacer(modifier = Modifier.height(16.dp)) + + Row { + + TextField( + value = fileName, + onValueChange = { + fileName = it + }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), + modifier = Modifier.fillMaxWidth() + ) + + + } + } + Spacer(modifier = Modifier.height(20.dp)) + + + Column( + modifier = Modifier.fillMaxWidth() + ) { + Text(text = "File Storage Type : ") + Spacer(modifier = Modifier.height(16.dp)) + OutlinedButton(onClick = { showBottomSheetF = true }) { + Text(text = selectedFiletype.toString().ifEmpty { "Select" }) + + } + + } + + + + + Spacer(modifier = Modifier.height(20.dp)) + + Column( + modifier = Modifier.fillMaxWidth() + ) { + Text(text = "File Storage Destination : ") + Spacer(modifier = Modifier.height(16.dp)) + OutlinedButton(onClick = { showBottomSheetD = true }) { + Text(text = selectedDestination.ifEmpty { "Select" }) + + } + + } + + Spacer(modifier = Modifier.height(40.dp)) + + + + Column( + modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center + ) { + Button( + enabled = isSaveButtonVisible, onClick = { + onStoreTap(fileName, selectedFiletype, selectedDestination) + }, modifier = Modifier.align(Alignment.CenterHorizontally) + ) { + Text(text = "Save") + } + } + } + + } + }) + if (showBottomSheetF) { + ModalBottomSheet( + onDismissRequest = { showBottomSheetF = false }, + sheetState = sheetState, + modifier = Modifier.fillMaxSize() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Text( + text = "Select File Type to store File", + style = MaterialTheme.typography.titleMedium + ) + + Spacer(modifier = Modifier.height(16.dp)) + + val fileTypes = listOf( + SmartFileType.TXT, + SmartFileType.JPEG, + SmartFileType.PDF, + SmartFileType.PNG, + SmartFileType.WEBP + ) + + fileTypes.forEach { fileType -> + TextButton(onClick = { + selectedFiletype = fileType + scope.launch { sheetState.hide() }.invokeOnCompletion { + if (!sheetState.isVisible) { + showBottomSheetF = false + } + } + }) { + Text(text = fileType.toString()) + } + } + + } + + + } + } + + if (showBottomSheetD) { + ModalBottomSheet( + onDismissRequest = { showBottomSheetD = false }, + sheetState = sheetState, + modifier = Modifier.fillMaxSize() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Text( + text = "Select Destination to store File", + style = MaterialTheme.typography.titleMedium + ) + + Spacer(modifier = Modifier.height(16.dp)) + + val destinations = listOf( + SmartDirectory.INTERNAL, + SmartDirectory.SCOPED_STORAGE, + SmartDirectory.CUSTOM, + SmartDirectory.DOWNLOADS, + SmartDirectory.DOCUMENTS, + SmartDirectory.EXTERNAL_PUBLIC + ) + + destinations.forEach { destination -> + TextButton(onClick = { + selectedDestination = destination + scope.launch { sheetState.hide() }.invokeOnCompletion { + if (!sheetState.isVisible) { + isSaveButtonVisible = true + showBottomSheetD = false + } + } + }) { + Text(text = destination) + } + } + + } + + + } } } + + + + diff --git a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt index 0659d4f..ff74e71 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt @@ -8,6 +8,7 @@ import android.net.Uri import android.os.Build import android.os.Environment import android.provider.Settings +import android.util.Log import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.result.contract.ActivityResultContracts @@ -132,7 +133,7 @@ class SmartStorage(private val activity: ComponentActivity) { val file = File( directory, fileDetails.name ) - + Log.d("Path to directory:", directory!!.path) try { FileOutputStream(file).use { stream -> stream.write(fileDetails.fileData) From 69ce1b553ba3934df0ae223bc096f9bdc11aa993 Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Fri, 10 May 2024 15:06:20 +0530 Subject: [PATCH 16/20] Sonarlint issue resolved --- app/src/main/java/com/ss/smartstorage/MainActivity.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt index 910c426..0cb29d3 100644 --- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt +++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt @@ -9,8 +9,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier import com.ss.smart_storage.SmartStorage -import com.ss.smart_storage.util.SmartDirectory -import com.ss.smart_storage.util.SmartFileType import com.ss.smartstorage.ui.theme.SmartStorageTheme class MainActivity : ComponentActivity() { From 36a79bb53952ad06d88edb74713dfb6c3eeea8e9 Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Fri, 10 May 2024 15:07:44 +0530 Subject: [PATCH 17/20] Sonarlint issue resolved --- app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt b/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt index 3e2a643..3ad8a7c 100644 --- a/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt +++ b/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt @@ -134,9 +134,6 @@ fun SmartStorageSample( } - - - Spacer(modifier = Modifier.height(20.dp)) Column( From 75c3968e7a97993cbf2193fb370a4816847ac1da Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Fri, 10 May 2024 15:54:05 +0530 Subject: [PATCH 18/20] Companion object replaced with object properties with value --- .../ss/smart_storage/util/SmartDirectory.kt | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt index 0e121fb..fd7465b 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt @@ -1,15 +1,10 @@ package com.ss.smart_storage.util - -class SmartDirectory{ - companion object { - const val INTERNAL: String = "Internal" - const val SCOPED_STORAGE : String = "Scoped_Storage" - const val CUSTOM : String = "Custom" - const val DOWNLOADS: String = "Download" - const val DOCUMENTS: String = "Documents" - const val EXTERNAL_PUBLIC = "External_Public" - } -} - - +object SmartDirectory{ + const val INTERNAL: String = "Internal" + const val SCOPED_STORAGE : String = "Scoped_Storage" + const val CUSTOM : String = "Custom" + const val DOWNLOADS: String = "Download" + const val DOCUMENTS: String = "Documents" + const val EXTERNAL_PUBLIC = "External_Public" +} \ No newline at end of file From 4aa082a9eff8cc9fc974cb71b368ae78efce0c70 Mon Sep 17 00:00:00 2001 From: Amit Siddhpura Date: Fri, 10 May 2024 16:22:25 +0530 Subject: [PATCH 19/20] Removed unnecessary dependencies from library gradle file. --- smart-storage/build.gradle.kts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/smart-storage/build.gradle.kts b/smart-storage/build.gradle.kts index c23da6b..43b5f95 100644 --- a/smart-storage/build.gradle.kts +++ b/smart-storage/build.gradle.kts @@ -9,7 +9,6 @@ android { defaultConfig { minSdk = 23 - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } @@ -33,11 +32,7 @@ android { } dependencies { - implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.material) - testImplementation(libs.junit) - androidTestImplementation(libs.androidx.junit) - androidTestImplementation(libs.androidx.espresso.core) } \ No newline at end of file From c35628e844e3a920593191bebb2019adcd9ee269 Mon Sep 17 00:00:00 2001 From: Dhruvi-sS Date: Mon, 13 May 2024 12:54:47 +0530 Subject: [PATCH 20/20] SmartStorage applicable in Android 11 and above for External Public Directory and Refactored Code --- .../com/ss/smart_storage/PermissionManager.kt | 55 ++++++++----------- .../java/com/ss/smart_storage/SmartStorage.kt | 8 --- .../ss/smart_storage/util/PermissionStatus.kt | 2 +- 3 files changed, 23 insertions(+), 42 deletions(-) diff --git a/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt index 787ce5f..f13c97e 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt @@ -3,16 +3,19 @@ package com.ss.smart_storage import android.Manifest import android.content.pm.PackageManager import android.os.Build +import android.os.Build.VERSION_CODES.M +import android.os.Build.VERSION_CODES.Q +import android.os.Environment import androidx.activity.ComponentActivity import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat import com.ss.smart_storage.util.PermissionStatus import com.ss.smart_storage.util.SmartDirectory class PermissionManager( - private val activity: ComponentActivity, - val onPermissionGranted: (PermissionStatus) -> Unit + private val activity: ComponentActivity, val onPermissionGranted: (PermissionStatus) -> Unit ) { private val requestPermissionLauncher = activity.registerForActivityResult( ActivityResultContracts.RequestPermission() @@ -55,27 +58,22 @@ class PermissionManager( private fun checkOsForPermissions(location: String) { when { - isVersionInBetween(Build.VERSION_CODES.M, Build.VERSION_CODES.Q) -> { - checkIfPermissionGranted( - onPermissionGranted = { - onPermissionGranted(PermissionStatus.ACCEPTED) - }) + Build.VERSION.SDK_INT in M..Q -> { + checkIfPermissionGranted(onPermissionGranted = { + onPermissionGranted(PermissionStatus.ACCEPTED) + }) } - isVersionInBetween( - Build.VERSION_CODES.R, Build.VERSION_CODES.S - ) && location == SmartDirectory.EXTERNAL_PUBLIC -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - checkIfManagePermissionGranted( - onPermissionGranted = { granted -> - if(granted) onPermissionGranted(PermissionStatus.ACCEPTED) - else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS) - }) - } + + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && location == SmartDirectory.EXTERNAL_PUBLIC -> { + + checkIfManagePermissionGranted(onPermissionGranted = { granted -> + if (granted) onPermissionGranted(PermissionStatus.ACCEPTED) + else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS) + }) + } - Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && location == SmartDirectory.EXTERNAL_PUBLIC -> { - onPermissionGranted(PermissionStatus.NOT_AVAILABLE) - } + else -> { onPermissionGranted(PermissionStatus.ACCEPTED) } @@ -90,15 +88,13 @@ class PermissionManager( ) { onPermissionGranted() } else { - requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE,) + requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) } } - private fun checkIfManagePermissionGranted( onPermissionGranted: (Boolean) -> Unit) { - if (ContextCompat.checkSelfPermission( - activity, Manifest.permission.MANAGE_EXTERNAL_STORAGE , - ) == PackageManager.PERMISSION_GRANTED - ) { + @RequiresApi(Build.VERSION_CODES.R) + private fun checkIfManagePermissionGranted(onPermissionGranted: (Boolean) -> Unit) { + if (Environment.isExternalStorageManager()) { onPermissionGranted(true) } else { onPermissionGranted(false) @@ -106,11 +102,4 @@ class PermissionManager( } - - - private fun isVersionInBetween(min: Int, max: Int): Boolean { - return Build.VERSION.SDK_INT in min..max - } - - } \ No newline at end of file diff --git a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt index ff74e71..36ff32d 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt @@ -54,14 +54,6 @@ class SmartStorage(private val activity: ComponentActivity) { launchBaseDirectoryPicker() } - PermissionStatus.NOT_AVAILABLE -> { - Toast.makeText( - activity, - activity.getString(R.string.feature_not_available), - Toast.LENGTH_SHORT - ).show() - } - PermissionStatus.REDIRECT_TO_SETTINGS -> { requestFullStorageAccess() } diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt index a45461c..60b8a87 100644 --- a/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt +++ b/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt @@ -1,5 +1,5 @@ package com.ss.smart_storage.util enum class PermissionStatus { - ACCEPTED, DENIED, NOT_APPLICABLE, NOT_NEEDED, NOT_AVAILABLE, REDIRECT_TO_SETTINGS + ACCEPTED, DENIED, NOT_APPLICABLE, NOT_NEEDED, REDIRECT_TO_SETTINGS } \ No newline at end of file