Merge pull request #2800 from kiwix/Issue#2787
Change the method to get data directory path in Android 10+
@ -18,8 +18,11 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.nav.destination.library
|
package org.kiwix.kiwixmobile.nav.destination.library
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -28,6 +31,7 @@ import android.view.MenuInflater
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
@ -51,15 +55,21 @@ import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.navigate
|
|||||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.viewModel
|
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.viewModel
|
||||||
import org.kiwix.kiwixmobile.core.extensions.closeKeyboard
|
import org.kiwix.kiwixmobile.core.extensions.closeKeyboard
|
||||||
import org.kiwix.kiwixmobile.core.extensions.snack
|
import org.kiwix.kiwixmobile.core.extensions.snack
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.toast
|
||||||
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||||
import org.kiwix.kiwixmobile.core.utils.BookUtils
|
import org.kiwix.kiwixmobile.core.utils.BookUtils
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.EXTERNAL_SELECT_POSITION
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.INTERNAL_SELECT_POSITION
|
||||||
import org.kiwix.kiwixmobile.core.utils.NetworkUtils
|
import org.kiwix.kiwixmobile.core.utils.NetworkUtils
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.REQUEST_SELECT_FOLDER_PERMISSION
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener
|
import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener
|
||||||
import org.kiwix.kiwixmobile.core.utils.SimpleTextListener
|
import org.kiwix.kiwixmobile.core.utils.SimpleTextListener
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.SelectFolder
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.YesNoDialog.WifiOnly
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.YesNoDialog.WifiOnly
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getPathFromUri
|
||||||
import org.kiwix.kiwixmobile.zim_manager.NetworkState
|
import org.kiwix.kiwixmobile.zim_manager.NetworkState
|
||||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel
|
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel
|
||||||
import org.kiwix.kiwixmobile.zim_manager.library_view.AvailableSpaceCalculator
|
import org.kiwix.kiwixmobile.zim_manager.library_view.AvailableSpaceCalculator
|
||||||
@ -242,8 +252,53 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
|||||||
downloader.download(book)
|
downloader.download(book)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("InflateParams")
|
||||||
private fun storeDeviceInPreferences(storageDevice: StorageDevice) {
|
private fun storeDeviceInPreferences(storageDevice: StorageDevice) {
|
||||||
sharedPreferenceUtil.putPrefStorage(storageDevice.name)
|
if (storageDevice.isInternal) {
|
||||||
|
sharedPreferenceUtil.putPrefStorage(
|
||||||
|
sharedPreferenceUtil.getPublicDirectoryPath(storageDevice.name)
|
||||||
|
)
|
||||||
|
sharedPreferenceUtil.putStoragePosition(INTERNAL_SELECT_POSITION)
|
||||||
|
} else {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
val view = LayoutInflater.from(activity).inflate(R.layout.select_folder_dialog, null)
|
||||||
|
dialogShower.show(SelectFolder { view }, ::selectFolder)
|
||||||
|
} else {
|
||||||
|
sharedPreferenceUtil.putPrefStorage(storageDevice.name)
|
||||||
|
sharedPreferenceUtil.putStoragePosition(EXTERNAL_SELECT_POSITION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun selectFolder() {
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
intent.addFlags(
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||||
|
or Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
|
||||||
|
)
|
||||||
|
startActivityForResult(intent, REQUEST_SELECT_FOLDER_PERMISSION)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("WrongConstant") override fun onActivityResult(
|
||||||
|
requestCode: Int,
|
||||||
|
resultCode: Int,
|
||||||
|
data: Intent?
|
||||||
|
) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
if (requestCode == REQUEST_SELECT_FOLDER_PERMISSION && resultCode == Activity.RESULT_OK) {
|
||||||
|
data?.let {
|
||||||
|
getPathFromUri(requireActivity(), data)?.let(sharedPreferenceUtil::putPrefStorage)
|
||||||
|
sharedPreferenceUtil.putStoragePosition(EXTERNAL_SELECT_POSITION)
|
||||||
|
} ?: run {
|
||||||
|
activity.toast(
|
||||||
|
resources
|
||||||
|
.getString(R.string.system_unable_to_grant_permission_message),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onBookItemClick(item: LibraryListItem.BookItem) {
|
private fun onBookItemClick(item: LibraryListItem.BookItem) {
|
||||||
|
@ -41,7 +41,9 @@ class KiwixPrefsFragment : CorePrefsFragment() {
|
|||||||
|
|
||||||
override fun setStorage() {
|
override fun setStorage() {
|
||||||
findPreference<Preference>(PREF_STORAGE)?.title = getString(
|
findPreference<Preference>(PREF_STORAGE)?.title = getString(
|
||||||
if (sharedPreferenceUtil.prefStorage == internalStorage()) R.string.internal_storage
|
if (sharedPreferenceUtil.prefStorage == internalStorage()?.let
|
||||||
|
(sharedPreferenceUtil::getPublicDirectoryPath)
|
||||||
|
) R.string.internal_storage
|
||||||
else R.string.external_storage
|
else R.string.external_storage
|
||||||
)
|
)
|
||||||
findPreference<Preference>(PREF_STORAGE)?.summary = storageCalculator.calculateAvailableSpace()
|
findPreference<Preference>(PREF_STORAGE)?.summary = storageCalculator.calculateAvailableSpace()
|
||||||
|
@ -7,54 +7,62 @@ import kotlin.String
|
|||||||
* `$ ./gradlew buildSrcVersions`
|
* `$ ./gradlew buildSrcVersions`
|
||||||
*/
|
*/
|
||||||
object Libs {
|
object Libs {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Getting Path of Selected Folder
|
||||||
|
**/
|
||||||
|
|
||||||
|
const val select_folder_document_file =
|
||||||
|
"androidx.documentfile:documentfile:" + Versions.document_file_version
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/Kotlin/kotlinx.coroutines
|
* https://github.com/Kotlin/kotlinx.coroutines
|
||||||
*/
|
*/
|
||||||
const val kotlinx_coroutines_android: String =
|
const val kotlinx_coroutines_android: String =
|
||||||
"org.jetbrains.kotlinx:kotlinx-coroutines-android:" +
|
"org.jetbrains.kotlinx:kotlinx-coroutines-android:" +
|
||||||
Versions.org_jetbrains_kotlinx_kotlinx_coroutines
|
Versions.org_jetbrains_kotlinx_kotlinx_coroutines
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/Kotlin/kotlinx.coroutines
|
* https://github.com/Kotlin/kotlinx.coroutines
|
||||||
*/
|
*/
|
||||||
const val kotlinx_coroutines_test: String = "org.jetbrains.kotlinx:kotlinx-coroutines-test:" +
|
const val kotlinx_coroutines_test: String = "org.jetbrains.kotlinx:kotlinx-coroutines-test:" +
|
||||||
Versions.org_jetbrains_kotlinx_kotlinx_coroutines
|
Versions.org_jetbrains_kotlinx_kotlinx_coroutines
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/testing
|
* https://developer.android.com/testing
|
||||||
*/
|
*/
|
||||||
const val espresso_contrib: String = "androidx.test.espresso:espresso-contrib:" +
|
const val espresso_contrib: String = "androidx.test.espresso:espresso-contrib:" +
|
||||||
Versions.androidx_test_espresso
|
Versions.androidx_test_espresso
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/testing
|
* https://developer.android.com/testing
|
||||||
*/
|
*/
|
||||||
const val espresso_core: String = "androidx.test.espresso:espresso-core:" +
|
const val espresso_core: String = "androidx.test.espresso:espresso-core:" +
|
||||||
Versions.androidx_test_espresso
|
Versions.androidx_test_espresso
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/testing
|
* https://developer.android.com/testing
|
||||||
*/
|
*/
|
||||||
const val espresso_intents: String = "androidx.test.espresso:espresso-intents:" +
|
const val espresso_intents: String = "androidx.test.espresso:espresso-intents:" +
|
||||||
Versions.androidx_test_espresso
|
Versions.androidx_test_espresso
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/testing
|
* https://developer.android.com/testing
|
||||||
*/
|
*/
|
||||||
const val espresso_web: String = "androidx.test.espresso:espresso-web:" +
|
const val espresso_web: String = "androidx.test.espresso:espresso-web:" +
|
||||||
Versions.androidx_test_espresso
|
Versions.androidx_test_espresso
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/square/retrofit
|
* https://github.com/square/retrofit
|
||||||
*/
|
*/
|
||||||
const val adapter_rxjava2: String = "com.squareup.retrofit2:adapter-rxjava2:" +
|
const val adapter_rxjava2: String = "com.squareup.retrofit2:adapter-rxjava2:" +
|
||||||
Versions.com_squareup_retrofit2
|
Versions.com_squareup_retrofit2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/square/retrofit
|
* https://github.com/square/retrofit
|
||||||
*/
|
*/
|
||||||
const val converter_simplexml: String = "com.squareup.retrofit2:converter-simplexml:" +
|
const val converter_simplexml: String = "com.squareup.retrofit2:converter-simplexml:" +
|
||||||
Versions.com_squareup_retrofit2
|
Versions.com_squareup_retrofit2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/square/retrofit
|
* https://github.com/square/retrofit
|
||||||
@ -65,13 +73,13 @@ object Libs {
|
|||||||
* https://square.github.io/okhttp/
|
* https://square.github.io/okhttp/
|
||||||
*/
|
*/
|
||||||
const val logging_interceptor: String = "com.squareup.okhttp3:logging-interceptor:" +
|
const val logging_interceptor: String = "com.squareup.okhttp3:logging-interceptor:" +
|
||||||
Versions.com_squareup_okhttp3
|
Versions.com_squareup_okhttp3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://square.github.io/okhttp/
|
* https://square.github.io/okhttp/
|
||||||
*/
|
*/
|
||||||
const val mockwebserver: String = "com.squareup.okhttp3:mockwebserver:" +
|
const val mockwebserver: String = "com.squareup.okhttp3:mockwebserver:" +
|
||||||
Versions.com_squareup_okhttp3
|
Versions.com_squareup_okhttp3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://square.github.io/okhttp/
|
* https://square.github.io/okhttp/
|
||||||
@ -82,55 +90,55 @@ object Libs {
|
|||||||
* https://kotlinlang.org/
|
* https://kotlinlang.org/
|
||||||
*/
|
*/
|
||||||
const val kotlin_android_extensions: String = "org.jetbrains.kotlin:kotlin-android-extensions:" +
|
const val kotlin_android_extensions: String = "org.jetbrains.kotlin:kotlin-android-extensions:" +
|
||||||
Versions.org_jetbrains_kotlin
|
Versions.org_jetbrains_kotlin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://kotlinlang.org/
|
* https://kotlinlang.org/
|
||||||
*/
|
*/
|
||||||
const val kotlin_android_extensions_runtime: String =
|
const val kotlin_android_extensions_runtime: String =
|
||||||
"org.jetbrains.kotlin:kotlin-android-extensions-runtime:" + Versions.org_jetbrains_kotlin
|
"org.jetbrains.kotlin:kotlin-android-extensions-runtime:" + Versions.org_jetbrains_kotlin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://kotlinlang.org/
|
* https://kotlinlang.org/
|
||||||
*/
|
*/
|
||||||
const val kotlin_annotation_processing_gradle: String =
|
const val kotlin_annotation_processing_gradle: String =
|
||||||
"org.jetbrains.kotlin:kotlin-annotation-processing-gradle:" + Versions.org_jetbrains_kotlin
|
"org.jetbrains.kotlin:kotlin-annotation-processing-gradle:" + Versions.org_jetbrains_kotlin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://kotlinlang.org/
|
* https://kotlinlang.org/
|
||||||
*/
|
*/
|
||||||
const val kotlin_gradle_plugin: String = "org.jetbrains.kotlin:kotlin-gradle-plugin:" +
|
const val kotlin_gradle_plugin: String = "org.jetbrains.kotlin:kotlin-gradle-plugin:" +
|
||||||
Versions.org_jetbrains_kotlin
|
Versions.org_jetbrains_kotlin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://kotlinlang.org/
|
* https://kotlinlang.org/
|
||||||
*/
|
*/
|
||||||
const val kotlin_stdlib_jdk7: String = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:" +
|
const val kotlin_stdlib_jdk7: String = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:" +
|
||||||
Versions.org_jetbrains_kotlin
|
Versions.org_jetbrains_kotlin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/topic/libraries/architecture/index.html
|
* https://developer.android.com/topic/libraries/architecture/index.html
|
||||||
*/
|
*/
|
||||||
const val navigation_fragment_ktx: String = "androidx.navigation:navigation-fragment-ktx:" +
|
const val navigation_fragment_ktx: String = "androidx.navigation:navigation-fragment-ktx:" +
|
||||||
Versions.androidx_navigation
|
Versions.androidx_navigation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/topic/libraries/architecture/index.html
|
* https://developer.android.com/topic/libraries/architecture/index.html
|
||||||
*/
|
*/
|
||||||
const val navigation_safe_args_gradle_plugin: String =
|
const val navigation_safe_args_gradle_plugin: String =
|
||||||
"androidx.navigation:navigation-safe-args-gradle-plugin:" + Versions.androidx_navigation
|
"androidx.navigation:navigation-safe-args-gradle-plugin:" + Versions.androidx_navigation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/topic/libraries/architecture/index.html
|
* https://developer.android.com/topic/libraries/architecture/index.html
|
||||||
*/
|
*/
|
||||||
const val navigation_testing: String = "androidx.navigation:navigation-testing:" +
|
const val navigation_testing: String = "androidx.navigation:navigation-testing:" +
|
||||||
Versions.androidx_navigation
|
Versions.androidx_navigation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/topic/libraries/architecture/index.html
|
* https://developer.android.com/topic/libraries/architecture/index.html
|
||||||
*/
|
*/
|
||||||
const val navigation_ui_ktx: String = "androidx.navigation:navigation-ui-ktx:" +
|
const val navigation_ui_ktx: String = "androidx.navigation:navigation-ui-ktx:" +
|
||||||
Versions.androidx_navigation
|
Versions.androidx_navigation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/google/dagger
|
* https://github.com/google/dagger
|
||||||
@ -141,19 +149,19 @@ object Libs {
|
|||||||
* https://github.com/google/dagger
|
* https://github.com/google/dagger
|
||||||
*/
|
*/
|
||||||
const val dagger_android: String = "com.google.dagger:dagger-android:" +
|
const val dagger_android: String = "com.google.dagger:dagger-android:" +
|
||||||
Versions.com_google_dagger
|
Versions.com_google_dagger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/google/dagger
|
* https://github.com/google/dagger
|
||||||
*/
|
*/
|
||||||
const val dagger_android_processor: String = "com.google.dagger:dagger-android-processor:" +
|
const val dagger_android_processor: String = "com.google.dagger:dagger-android-processor:" +
|
||||||
Versions.com_google_dagger
|
Versions.com_google_dagger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/google/dagger
|
* https://github.com/google/dagger
|
||||||
*/
|
*/
|
||||||
const val dagger_compiler: String = "com.google.dagger:dagger-compiler:" +
|
const val dagger_compiler: String = "com.google.dagger:dagger-compiler:" +
|
||||||
Versions.com_google_dagger
|
Versions.com_google_dagger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/yahoo/squidb
|
* https://github.com/yahoo/squidb
|
||||||
@ -164,13 +172,13 @@ object Libs {
|
|||||||
* https://github.com/yahoo/squidb
|
* https://github.com/yahoo/squidb
|
||||||
*/
|
*/
|
||||||
const val squidb_annotations: String = "com.yahoo.squidb:squidb-annotations:" +
|
const val squidb_annotations: String = "com.yahoo.squidb:squidb-annotations:" +
|
||||||
Versions.com_yahoo_squidb
|
Versions.com_yahoo_squidb
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/yahoo/squidb
|
* https://github.com/yahoo/squidb
|
||||||
*/
|
*/
|
||||||
const val squidb_processor: String = "com.yahoo.squidb:squidb-processor:" +
|
const val squidb_processor: String = "com.yahoo.squidb:squidb-processor:" +
|
||||||
Versions.com_yahoo_squidb
|
Versions.com_yahoo_squidb
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/JakeWharton/butterknife/
|
* https://github.com/JakeWharton/butterknife/
|
||||||
@ -181,13 +189,13 @@ object Libs {
|
|||||||
* https://github.com/JakeWharton/butterknife/
|
* https://github.com/JakeWharton/butterknife/
|
||||||
*/
|
*/
|
||||||
const val butterknife_compiler: String = "com.jakewharton:butterknife-compiler:" +
|
const val butterknife_compiler: String = "com.jakewharton:butterknife-compiler:" +
|
||||||
Versions.com_jakewharton
|
Versions.com_jakewharton
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/JakeWharton/butterknife/
|
* https://github.com/JakeWharton/butterknife/
|
||||||
*/
|
*/
|
||||||
const val butterknife_gradle_plugin: String = "com.jakewharton:butterknife-gradle-plugin:" +
|
const val butterknife_gradle_plugin: String = "com.jakewharton:butterknife-gradle-plugin:" +
|
||||||
Versions.com_jakewharton
|
Versions.com_jakewharton
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/testing
|
* https://developer.android.com/testing
|
||||||
@ -218,7 +226,7 @@ object Libs {
|
|||||||
* https://objectbox.io
|
* https://objectbox.io
|
||||||
*/
|
*/
|
||||||
const val objectbox_gradle_plugin: String = "io.objectbox:objectbox-gradle-plugin:" +
|
const val objectbox_gradle_plugin: String = "io.objectbox:objectbox-gradle-plugin:" +
|
||||||
Versions.io_objectbox
|
Versions.io_objectbox
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://objectbox.io
|
* https://objectbox.io
|
||||||
@ -234,7 +242,7 @@ object Libs {
|
|||||||
* https://objectbox.io
|
* https://objectbox.io
|
||||||
*/
|
*/
|
||||||
const val objectbox_processor: String = "io.objectbox:objectbox-processor:" +
|
const val objectbox_processor: String = "io.objectbox:objectbox-processor:" +
|
||||||
Versions.io_objectbox
|
Versions.io_objectbox
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://objectbox.io
|
* https://objectbox.io
|
||||||
@ -270,42 +278,42 @@ object Libs {
|
|||||||
* https://developer.android.com/topic/libraries/architecture/index.html
|
* https://developer.android.com/topic/libraries/architecture/index.html
|
||||||
*/
|
*/
|
||||||
const val android_arch_lifecycle_extensions: String = "android.arch.lifecycle:extensions:" +
|
const val android_arch_lifecycle_extensions: String = "android.arch.lifecycle:extensions:" +
|
||||||
Versions.android_arch_lifecycle_extensions
|
Versions.android_arch_lifecycle_extensions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://developer.android.com/studio
|
* https://developer.android.com/studio
|
||||||
*/
|
*/
|
||||||
const val com_android_tools_build_gradle: String = "com.android.tools.build:gradle:" +
|
const val com_android_tools_build_gradle: String = "com.android.tools.build:gradle:" +
|
||||||
Versions.com_android_tools_build_gradle
|
Versions.com_android_tools_build_gradle
|
||||||
|
|
||||||
const val de_fayard_buildsrcversions_gradle_plugin: String =
|
const val de_fayard_buildsrcversions_gradle_plugin: String =
|
||||||
"de.fayard.buildSrcVersions:de.fayard.buildSrcVersions.gradle.plugin:" +
|
"de.fayard.buildSrcVersions:de.fayard.buildSrcVersions.gradle.plugin:" +
|
||||||
Versions.de_fayard_buildsrcversions_gradle_plugin
|
Versions.de_fayard_buildsrcversions_gradle_plugin
|
||||||
|
|
||||||
const val com_github_triplet_play_gradle_plugin: String =
|
const val com_github_triplet_play_gradle_plugin: String =
|
||||||
"com.github.triplet.play:com.github.triplet.play.gradle.plugin:" +
|
"com.github.triplet.play:com.github.triplet.play.gradle.plugin:" +
|
||||||
Versions.com_github_triplet_play_gradle_plugin
|
Versions.com_github_triplet_play_gradle_plugin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http://jcp.org/en/jsr/detail?id=250
|
* http://jcp.org/en/jsr/detail?id=250
|
||||||
*/
|
*/
|
||||||
const val javax_annotation_api: String = "javax.annotation:javax.annotation-api:" +
|
const val javax_annotation_api: String = "javax.annotation:javax.annotation-api:" +
|
||||||
Versions.javax_annotation_api
|
Versions.javax_annotation_api
|
||||||
|
|
||||||
const val ink_page_indicator: String = "com.pacioianu.david:ink-page-indicator:" +
|
const val ink_page_indicator: String = "com.pacioianu.david:ink-page-indicator:" +
|
||||||
Versions.ink_page_indicator
|
Versions.ink_page_indicator
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http://github.com/square/leakcanary/
|
* http://github.com/square/leakcanary/
|
||||||
*/
|
*/
|
||||||
const val leakcanary_android: String = "com.squareup.leakcanary:leakcanary-android:" +
|
const val leakcanary_android: String = "com.squareup.leakcanary:leakcanary-android:" +
|
||||||
Versions.leakcanary_android
|
Versions.leakcanary_android
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http://tools.android.com
|
* http://tools.android.com
|
||||||
*/
|
*/
|
||||||
const val constraintlayout: String = "androidx.constraintlayout:constraintlayout:" +
|
const val constraintlayout: String = "androidx.constraintlayout:constraintlayout:" +
|
||||||
Versions.constraintlayout
|
Versions.constraintlayout
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http://developer.android.com/tools/extras/support-library.html
|
* http://developer.android.com/tools/extras/support-library.html
|
||||||
@ -323,7 +331,7 @@ object Libs {
|
|||||||
const val junit_jupiter: String = "org.junit.jupiter:junit-jupiter:" + Versions.junit_jupiter
|
const val junit_jupiter: String = "org.junit.jupiter:junit-jupiter:" + Versions.junit_jupiter
|
||||||
|
|
||||||
const val xfetch2okhttp: String = "androidx.tonyodev.fetch2okhttp:xfetch2okhttp:" +
|
const val xfetch2okhttp: String = "androidx.tonyodev.fetch2okhttp:xfetch2okhttp:" +
|
||||||
Versions.xfetch2okhttp
|
Versions.xfetch2okhttp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://assertj.github.io/doc/
|
* https://assertj.github.io/doc/
|
||||||
|
@ -11,6 +11,9 @@ import org.gradle.plugin.use.PluginDependencySpec
|
|||||||
* YOU are responsible for updating manually the dependency version.
|
* YOU are responsible for updating manually the dependency version.
|
||||||
*/
|
*/
|
||||||
object Versions {
|
object Versions {
|
||||||
|
|
||||||
|
const val document_file_version: String = "1.0.1"
|
||||||
|
|
||||||
const val org_jetbrains_kotlinx_kotlinx_coroutines: String = "1.4.1"
|
const val org_jetbrains_kotlinx_kotlinx_coroutines: String = "1.4.1"
|
||||||
|
|
||||||
const val androidx_test_espresso: String = "3.3.0"
|
const val androidx_test_espresso: String = "3.3.0"
|
||||||
@ -121,4 +124,4 @@ object Versions {
|
|||||||
*/
|
*/
|
||||||
val PluginDependenciesSpec.buildSrcVersions: PluginDependencySpec
|
val PluginDependenciesSpec.buildSrcVersions: PluginDependencySpec
|
||||||
inline get() =
|
inline get() =
|
||||||
id("de.fayard.buildSrcVersions").version(Versions.de_fayard_buildsrcversions_gradle_plugin)
|
id("de.fayard.buildSrcVersions").version(Versions.de_fayard_buildsrcversions_gradle_plugin)
|
||||||
|
@ -47,6 +47,9 @@ dependencies {
|
|||||||
implementation(Libs.squidb_annotations)
|
implementation(Libs.squidb_annotations)
|
||||||
add("kapt", Libs.squidb_processor)
|
add("kapt", Libs.squidb_processor)
|
||||||
|
|
||||||
|
// Document File
|
||||||
|
implementation(Libs.select_folder_document_file)
|
||||||
|
|
||||||
// Square
|
// Square
|
||||||
implementation(Libs.converter_simplexml) {
|
implementation(Libs.converter_simplexml) {
|
||||||
exclude(group = "xpp3", module = "xpp3")
|
exclude(group = "xpp3", module = "xpp3")
|
||||||
|
@ -33,7 +33,7 @@ object StorageDeviceUtils {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getReadableStorage(context: Context): List<StorageDevice> {
|
fun getReadableStorage(context: Context): List<StorageDevice> {
|
||||||
val storageDevices = ArrayList<StorageDevice>().apply {
|
val storageDevices = ArrayList<StorageDevice>().apply {
|
||||||
add(environmentDevices())
|
add(environmentDevices(context))
|
||||||
addAll(externalMountPointDevices())
|
addAll(externalMountPointDevices())
|
||||||
addAll(externalFilesDirsDevices(context, false))
|
addAll(externalFilesDirsDevices(context, false))
|
||||||
}
|
}
|
||||||
@ -63,9 +63,9 @@ object StorageDeviceUtils {
|
|||||||
?.map { dir -> StorageDevice(dir, false) }
|
?.map { dir -> StorageDevice(dir, false) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
private fun environmentDevices() =
|
private fun environmentDevices(context: Context) =
|
||||||
StorageDevice(
|
StorageDevice(
|
||||||
generalisePath(Environment.getExternalStorageDirectory().path, false),
|
generalisePath(context.getExternalFilesDir("").toString(), true),
|
||||||
Environment.isExternalStorageEmulated()
|
Environment.isExternalStorageEmulated()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,7 +43,9 @@ internal class StorageViewHolder(
|
|||||||
else R.string.external_storage
|
else R.string.external_storage
|
||||||
)
|
)
|
||||||
|
|
||||||
file_name.isChecked = sharedPreferenceUtil.prefStorage == item.name
|
if (adapterPosition == sharedPreferenceUtil.storagePosition) {
|
||||||
|
file_name.isChecked = true
|
||||||
|
}
|
||||||
file_size.text = storageCalculator.calculateAvailableSpace(item.file) + " / " +
|
file_size.text = storageCalculator.calculateAvailableSpace(item.file) + " / " +
|
||||||
storageCalculator.calculateTotalSpace(item.file) + " "
|
storageCalculator.calculateTotalSpace(item.file) + " "
|
||||||
clickOverlay.setOnClickListener {
|
clickOverlay.setOnClickListener {
|
||||||
|
@ -20,11 +20,15 @@ package org.kiwix.kiwixmobile.core.settings;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.preference.EditTextPreference;
|
import androidx.preference.EditTextPreference;
|
||||||
@ -50,7 +54,13 @@ import org.kiwix.kiwixmobile.core.utils.LanguageUtils;
|
|||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil;
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil;
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower;
|
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower;
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog;
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog;
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.files.FileUtils;
|
||||||
|
|
||||||
|
import static android.app.Activity.RESULT_OK;
|
||||||
|
import static android.content.Intent.ACTION_OPEN_DOCUMENT_TREE;
|
||||||
|
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTERNAL_SELECT_POSITION;
|
||||||
|
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.INTERNAL_SELECT_POSITION;
|
||||||
|
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.REQUEST_SELECT_FOLDER_PERMISSION;
|
||||||
import static org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_NIGHT_MODE;
|
import static org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_NIGHT_MODE;
|
||||||
import static org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_STORAGE;
|
import static org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_STORAGE;
|
||||||
|
|
||||||
@ -175,9 +185,6 @@ public abstract class CorePrefsFragment extends PreferenceFragmentCompat impleme
|
|||||||
versionPref.setSummary(getVersionName() + " Build: " + getVersionCode());
|
versionPref.setSummary(getVersionName() + " Build: " + getVersionCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private int getVersionCode() {
|
private int getVersionCode() {
|
||||||
try {
|
try {
|
||||||
return getActivity().getPackageManager()
|
return getActivity().getPackageManager()
|
||||||
@ -278,13 +285,47 @@ public abstract class CorePrefsFragment extends PreferenceFragmentCompat impleme
|
|||||||
findPreference(PREF_STORAGE).setSummary(
|
findPreference(PREF_STORAGE).setSummary(
|
||||||
storageCalculator.calculateAvailableSpace(storageDevice.getFile())
|
storageCalculator.calculateAvailableSpace(storageDevice.getFile())
|
||||||
);
|
);
|
||||||
sharedPreferenceUtil.putPrefStorage(storageDevice.getName());
|
|
||||||
if (storageDevice.isInternal()) {
|
if (storageDevice.isInternal()) {
|
||||||
|
sharedPreferenceUtil.putPrefStorage(
|
||||||
|
sharedPreferenceUtil.getPublicDirectoryPath(storageDevice.getName()));
|
||||||
findPreference(PREF_STORAGE).setTitle(getString(R.string.internal_storage));
|
findPreference(PREF_STORAGE).setTitle(getString(R.string.internal_storage));
|
||||||
|
sharedPreferenceUtil.putStoragePosition(INTERNAL_SELECT_POSITION);
|
||||||
} else {
|
} else {
|
||||||
findPreference(PREF_STORAGE).setTitle(getString(R.string.external_storage));
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
@SuppressLint("InflateParams") View view = LayoutInflater.from(getActivity()).inflate(R.layout.select_folder_dialog, null);
|
||||||
|
alertDialogShower.show(new KiwixDialog.SelectFolder(() -> view), () -> {
|
||||||
|
selectFolder();
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sharedPreferenceUtil.putPrefStorage(storageDevice.getName());
|
||||||
|
findPreference(PREF_STORAGE).setTitle(getString(R.string.external_storage));
|
||||||
|
sharedPreferenceUtil.putStoragePosition(EXTERNAL_SELECT_POSITION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Unit.INSTANCE;
|
return Unit.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void selectFolder() {
|
||||||
|
Intent intent = new Intent(ACTION_OPEN_DOCUMENT_TREE);
|
||||||
|
intent.addFlags(
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||||
|
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
|
||||||
|
startActivityForResult(intent, REQUEST_SELECT_FOLDER_PERMISSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("WrongConstant") @Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode,
|
||||||
|
@Nullable Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == REQUEST_SELECT_FOLDER_PERMISSION && resultCode == RESULT_OK) {
|
||||||
|
sharedPreferenceUtil.putPrefStorage(
|
||||||
|
FileUtils.getPathFromUri(requireActivity(), data));
|
||||||
|
findPreference(PREF_STORAGE).setTitle(getString(R.string.external_storage));
|
||||||
|
sharedPreferenceUtil.putStoragePosition(EXTERNAL_SELECT_POSITION);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ const val CONTACT_EMAIL_ADDRESS = "android@kiwix.org"
|
|||||||
// Request stuff
|
// Request stuff
|
||||||
const val REQUEST_STORAGE_PERMISSION = 1
|
const val REQUEST_STORAGE_PERMISSION = 1
|
||||||
const val REQUEST_WRITE_STORAGE_PERMISSION_ADD_NOTE = 3
|
const val REQUEST_WRITE_STORAGE_PERMISSION_ADD_NOTE = 3
|
||||||
|
const val REQUEST_SELECT_FOLDER_PERMISSION = 4
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
const val TAG_FILE_SEARCHED = "searchedarticle"
|
const val TAG_FILE_SEARCHED = "searchedarticle"
|
||||||
@ -37,3 +38,7 @@ const val TAG_FROM_TAB_SWITCHER = "fromtabswitcher"
|
|||||||
const val EXTRA_IS_WIDGET_VOICE = "isWidgetVoice"
|
const val EXTRA_IS_WIDGET_VOICE = "isWidgetVoice"
|
||||||
const val HOTSPOT_SERVICE_CHANNEL_ID = "hotspotService"
|
const val HOTSPOT_SERVICE_CHANNEL_ID = "hotspotService"
|
||||||
const val OLD_PROVIDER_DOMAIN = "org.kiwix.zim.base"
|
const val OLD_PROVIDER_DOMAIN = "org.kiwix.zim.base"
|
||||||
|
|
||||||
|
// For Storage select dialog
|
||||||
|
const val INTERNAL_SELECT_POSITION = 0
|
||||||
|
const val EXTERNAL_SELECT_POSITION = 1
|
||||||
|
@ -27,6 +27,7 @@ import io.reactivex.Flowable
|
|||||||
import io.reactivex.processors.PublishProcessor
|
import io.reactivex.processors.PublishProcessor
|
||||||
import org.kiwix.kiwixmobile.core.NightModeConfig
|
import org.kiwix.kiwixmobile.core.NightModeConfig
|
||||||
import org.kiwix.kiwixmobile.core.NightModeConfig.Mode.Companion.from
|
import org.kiwix.kiwixmobile.core.NightModeConfig.Mode.Companion.from
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -76,12 +77,20 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
get() {
|
get() {
|
||||||
val storage = sharedPreferences.getString(PREF_STORAGE, null)
|
val storage = sharedPreferences.getString(PREF_STORAGE, null)
|
||||||
return when {
|
return when {
|
||||||
storage == null -> defaultStorage().also(::putPrefStorage)
|
storage == null -> getPublicDirectoryPath(defaultStorage()).also {
|
||||||
!File(storage).exists() -> defaultStorage()
|
putPrefStorage(it)
|
||||||
|
putStoragePosition(0)
|
||||||
|
}
|
||||||
|
!File(storage).exists() -> getPublicDirectoryPath(defaultStorage()).also {
|
||||||
|
putStoragePosition(0)
|
||||||
|
}
|
||||||
else -> storage
|
else -> storage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val storagePosition: Int
|
||||||
|
get() = sharedPreferences.getInt(STORAGE_POSITION, 0)
|
||||||
|
|
||||||
private fun defaultStorage(): String =
|
private fun defaultStorage(): String =
|
||||||
getExternalFilesDirs(context, null)[0]?.path
|
getExternalFilesDirs(context, null)[0]?.path
|
||||||
?: context.filesDir.path // a workaround for emulators
|
?: context.filesDir.path // a workaround for emulators
|
||||||
@ -108,6 +117,10 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
_prefStorages.onNext(storage)
|
_prefStorages.onNext(storage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun putStoragePosition(pos: Int) {
|
||||||
|
sharedPreferences.edit { putInt(STORAGE_POSITION, pos) }
|
||||||
|
}
|
||||||
|
|
||||||
fun putPrefFullScreen(fullScreen: Boolean) =
|
fun putPrefFullScreen(fullScreen: Boolean) =
|
||||||
sharedPreferences.edit { putBoolean(PREF_FULLSCREEN, fullScreen) }
|
sharedPreferences.edit { putBoolean(PREF_FULLSCREEN, fullScreen) }
|
||||||
|
|
||||||
@ -160,10 +173,14 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
_textZooms.offer(textZoom)
|
_textZooms.offer(textZoom)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPublicDirectoryPath(path: String): String =
|
||||||
|
path.substringBefore(context.getString(R.string.android_directory_seperator))
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Prefs
|
// Prefs
|
||||||
const val PREF_LANG = "pref_language_chooser"
|
const val PREF_LANG = "pref_language_chooser"
|
||||||
const val PREF_STORAGE = "pref_select_folder"
|
const val PREF_STORAGE = "pref_select_folder"
|
||||||
|
const val STORAGE_POSITION = "storage_position"
|
||||||
const val PREF_WIFI_ONLY = "pref_wifi_only"
|
const val PREF_WIFI_ONLY = "pref_wifi_only"
|
||||||
const val PREF_KIWIX_MOBILE = "kiwix-mobile"
|
const val PREF_KIWIX_MOBILE = "kiwix-mobile"
|
||||||
const val PREF_SHOW_INTRO = "showIntro"
|
const val PREF_SHOW_INTRO = "showIntro"
|
||||||
|
@ -185,6 +185,14 @@ sealed class KiwixDialog(
|
|||||||
getView = customGetView
|
getView = customGetView
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class SelectFolder(val customGetView: (() -> View)?) : KiwixDialog(
|
||||||
|
R.string.select_folder,
|
||||||
|
null,
|
||||||
|
android.R.string.ok,
|
||||||
|
null,
|
||||||
|
getView = customGetView
|
||||||
|
)
|
||||||
|
|
||||||
object NotesDiscardConfirmation : KiwixDialog(
|
object NotesDiscardConfirmation : KiwixDialog(
|
||||||
null,
|
null,
|
||||||
R.string.confirmation_alert_dialog_message,
|
R.string.confirmation_alert_dialog_message,
|
||||||
|
@ -17,19 +17,25 @@
|
|||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.core.utils.files
|
package org.kiwix.kiwixmobile.core.utils.files
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import org.kiwix.kiwixmobile.core.downloader.ChunkUtils
|
import org.kiwix.kiwixmobile.core.downloader.ChunkUtils
|
||||||
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book
|
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book
|
||||||
import org.kiwix.kiwixmobile.core.extensions.get
|
import org.kiwix.kiwixmobile.core.extensions.get
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.toast
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
object FileUtils {
|
object FileUtils {
|
||||||
|
|
||||||
@ -228,4 +234,44 @@ object FileUtils {
|
|||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
"".also { e.printStackTrace() }
|
"".also { e.printStackTrace() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("WrongConstant")
|
||||||
|
@JvmStatic fun getPathFromUri(activity: Activity, data: Intent): String? {
|
||||||
|
val uri: Uri? = data.data
|
||||||
|
val takeFlags: Int = data.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
uri?.let {
|
||||||
|
activity.grantUriPermission(
|
||||||
|
activity.packageName, it,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
|
activity.contentResolver.takePersistableUriPermission(it, takeFlags)
|
||||||
|
|
||||||
|
val dFile = DocumentFile.fromTreeUri(activity, it)
|
||||||
|
if (dFile != null) {
|
||||||
|
dFile.uri.path?.let { file ->
|
||||||
|
val originalPath = file.substring(
|
||||||
|
file.lastIndexOf(":") + 1
|
||||||
|
)
|
||||||
|
val path = "${activity.getExternalFilesDirs("")[1]}"
|
||||||
|
return@getPathFromUri path.substringBefore(
|
||||||
|
activity.getString(R.string.android_directory_seperator)
|
||||||
|
)
|
||||||
|
.plus(File.separator).plus(originalPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activity.toast(
|
||||||
|
activity.resources
|
||||||
|
.getString(R.string.system_unable_to_grant_permission_message),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
} ?: run {
|
||||||
|
activity.toast(
|
||||||
|
activity.resources
|
||||||
|
.getString(R.string.system_unable_to_grant_permission_message),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
BIN
core/src/main/res/drawable-hdpi/select_folder_preview_image1.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
core/src/main/res/drawable-hdpi/select_folder_preview_image2.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
core/src/main/res/drawable-ldpi/select_folder_preview_image1.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
core/src/main/res/drawable-ldpi/select_folder_preview_image2.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
core/src/main/res/drawable-mdpi/select_folder_preview_image1.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
core/src/main/res/drawable-mdpi/select_folder_preview_image2.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 10 KiB |
45
core/src/main/res/layout/select_folder_dialog.xml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Kiwix Android
|
||||||
|
~ Copyright (c) 2022 Kiwix <android.kiwix.org>
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
~
|
||||||
|
-->
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/img"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="120dp"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:contentDescription="@string/app_name"
|
||||||
|
android:src="@drawable/select_folder_preview_image1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="120dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:contentDescription="@string/app_name"
|
||||||
|
android:src="@drawable/select_folder_preview_image2"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/img" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -295,6 +295,9 @@
|
|||||||
<string name="all_files_permission_needed_message">In order to access all the zim files across device we need to have All Files Permission</string>
|
<string name="all_files_permission_needed_message">In order to access all the zim files across device we need to have All Files Permission</string>
|
||||||
<string name="allowed">Allowed</string>
|
<string name="allowed">Allowed</string>
|
||||||
<string name="not_allowed">Not allowed</string>
|
<string name="not_allowed">Not allowed</string>
|
||||||
|
<string name="android_directory_seperator" translatable="false">/Android</string>
|
||||||
|
<string name="select_folder" translatable="false">Please select a folder for external storage.</string>
|
||||||
|
<string name="system_unable_to_grant_permission_message" translatable="false">System unable to grant permission!</string>
|
||||||
<string-array name="pref_night_modes_entries">
|
<string-array name="pref_night_modes_entries">
|
||||||
<item>@string/on</item>
|
<item>@string/on</item>
|
||||||
<item>@string/off</item>
|
<item>@string/off</item>
|
||||||
|