a) Directory changed from app specific to public now its sharable. b) Library androidx document addition c) this resolve issue file deleting after uninstall the app d) this also resolve bug related to zim file not able to load from app specific folder in android 10 and above.

This commit is contained in:
MohitMali 2022-04-13 17:16:05 +05:30 committed by Emmanuel Engelhart
parent d25929a78a
commit 16f3dd2e64
No known key found for this signature in database
GPG Key ID: 120B30D020B553D3
9 changed files with 186 additions and 48 deletions

View File

@ -18,6 +18,8 @@
package org.kiwix.kiwixmobile.nav.destination.library
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.net.ConnectivityManager
import android.os.Bundle
@ -31,6 +33,7 @@ import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
@ -53,7 +56,10 @@ import org.kiwix.kiwixmobile.core.extensions.closeKeyboard
import org.kiwix.kiwixmobile.core.extensions.snack
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
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.REQUEST_SELECT_FOLDER_PERMISSION
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener
import org.kiwix.kiwixmobile.core.utils.SimpleTextListener
@ -66,6 +72,7 @@ import org.kiwix.kiwixmobile.zim_manager.library_view.AvailableSpaceCalculator
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryAdapter
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryDelegate
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem
import java.io.File
import javax.inject.Inject
class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
@ -243,7 +250,52 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
}
private fun storeDeviceInPreferences(storageDevice: StorageDevice) {
sharedPreferenceUtil.putPrefStorage(storageDevice.name)
if (storageDevice.isInternal) {
sharedPreferenceUtil.putPrefStorage(
sharedPreferenceUtil.getActualPath(storageDevice.name)
)
sharedPreferenceUtil.putStoragePosition(INTERNAL_SELECT_POSITION)
} else {
setFolder()
}
}
private fun setFolder() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.putExtra("android.content.extra.SHOW_ADVANCED", true)
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) {
val uri = data!!.data
val takeFlags = data.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
requireActivity().grantUriPermission(
requireActivity().packageName, uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
requireActivity().contentResolver.takePersistableUriPermission(uri!!, takeFlags)
val dfile = DocumentFile.fromTreeUri(requireActivity(), uri)
val meraPath = dfile!!.uri.path!!.substring(
dfile.uri.path!!.lastIndexOf(":") + 1
)
var path = "${requireActivity().getExternalFilesDirs("")[1]}"
val separator = "/Android"
val sepPos = path.indexOf(separator)
if (sepPos == -1) {
} else {
path = path.substring(0, sepPos)
}
path = path + File.separator + meraPath
sharedPreferenceUtil.putPrefStorage(path)
sharedPreferenceUtil.putStoragePosition(EXTERNAL_SELECT_POSITION)
}
}
private fun onBookItemClick(item: LibraryListItem.BookItem) {

View File

@ -41,7 +41,7 @@ class KiwixPrefsFragment : CorePrefsFragment() {
override fun setStorage() {
findPreference<Preference>(PREF_STORAGE)?.title = getString(
if (sharedPreferenceUtil.prefStorage == internalStorage()) R.string.internal_storage
if (sharedPreferenceUtil.prefStorage == internalStorage()?.let(sharedPreferenceUtil::getActualPath)) R.string.internal_storage
else R.string.external_storage
)
findPreference<Preference>(PREF_STORAGE)?.summary = storageCalculator.calculateAvailableSpace()

View File

@ -7,54 +7,62 @@ import kotlin.String
* `$ ./gradlew buildSrcVersions`
*/
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
*/
const val kotlinx_coroutines_android: String =
"org.jetbrains.kotlinx:kotlinx-coroutines-android:" +
"org.jetbrains.kotlinx:kotlinx-coroutines-android:" +
Versions.org_jetbrains_kotlinx_kotlinx_coroutines
/**
* https://github.com/Kotlin/kotlinx.coroutines
*/
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
*/
const val espresso_contrib: String = "androidx.test.espresso:espresso-contrib:" +
Versions.androidx_test_espresso
Versions.androidx_test_espresso
/**
* https://developer.android.com/testing
*/
const val espresso_core: String = "androidx.test.espresso:espresso-core:" +
Versions.androidx_test_espresso
Versions.androidx_test_espresso
/**
* https://developer.android.com/testing
*/
const val espresso_intents: String = "androidx.test.espresso:espresso-intents:" +
Versions.androidx_test_espresso
Versions.androidx_test_espresso
/**
* https://developer.android.com/testing
*/
const val espresso_web: String = "androidx.test.espresso:espresso-web:" +
Versions.androidx_test_espresso
Versions.androidx_test_espresso
/**
* https://github.com/square/retrofit
*/
const val adapter_rxjava2: String = "com.squareup.retrofit2:adapter-rxjava2:" +
Versions.com_squareup_retrofit2
Versions.com_squareup_retrofit2
/**
* https://github.com/square/retrofit
*/
const val converter_simplexml: String = "com.squareup.retrofit2:converter-simplexml:" +
Versions.com_squareup_retrofit2
Versions.com_squareup_retrofit2
/**
* https://github.com/square/retrofit
@ -65,13 +73,13 @@ object Libs {
* https://square.github.io/okhttp/
*/
const val logging_interceptor: String = "com.squareup.okhttp3:logging-interceptor:" +
Versions.com_squareup_okhttp3
Versions.com_squareup_okhttp3
/**
* https://square.github.io/okhttp/
*/
const val mockwebserver: String = "com.squareup.okhttp3:mockwebserver:" +
Versions.com_squareup_okhttp3
Versions.com_squareup_okhttp3
/**
* https://square.github.io/okhttp/
@ -82,55 +90,55 @@ object Libs {
* https://kotlinlang.org/
*/
const val kotlin_android_extensions: String = "org.jetbrains.kotlin:kotlin-android-extensions:" +
Versions.org_jetbrains_kotlin
Versions.org_jetbrains_kotlin
/**
* https://kotlinlang.org/
*/
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/
*/
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/
*/
const val kotlin_gradle_plugin: String = "org.jetbrains.kotlin:kotlin-gradle-plugin:" +
Versions.org_jetbrains_kotlin
Versions.org_jetbrains_kotlin
/**
* https://kotlinlang.org/
*/
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
*/
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
*/
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
*/
const val navigation_testing: String = "androidx.navigation:navigation-testing:" +
Versions.androidx_navigation
Versions.androidx_navigation
/**
* https://developer.android.com/topic/libraries/architecture/index.html
*/
const val navigation_ui_ktx: String = "androidx.navigation:navigation-ui-ktx:" +
Versions.androidx_navigation
Versions.androidx_navigation
/**
* https://github.com/google/dagger
@ -141,19 +149,19 @@ object Libs {
* https://github.com/google/dagger
*/
const val dagger_android: String = "com.google.dagger:dagger-android:" +
Versions.com_google_dagger
Versions.com_google_dagger
/**
* https://github.com/google/dagger
*/
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
*/
const val dagger_compiler: String = "com.google.dagger:dagger-compiler:" +
Versions.com_google_dagger
Versions.com_google_dagger
/**
* https://github.com/yahoo/squidb
@ -164,13 +172,13 @@ object Libs {
* https://github.com/yahoo/squidb
*/
const val squidb_annotations: String = "com.yahoo.squidb:squidb-annotations:" +
Versions.com_yahoo_squidb
Versions.com_yahoo_squidb
/**
* https://github.com/yahoo/squidb
*/
const val squidb_processor: String = "com.yahoo.squidb:squidb-processor:" +
Versions.com_yahoo_squidb
Versions.com_yahoo_squidb
/**
* https://github.com/JakeWharton/butterknife/
@ -181,13 +189,13 @@ object Libs {
* https://github.com/JakeWharton/butterknife/
*/
const val butterknife_compiler: String = "com.jakewharton:butterknife-compiler:" +
Versions.com_jakewharton
Versions.com_jakewharton
/**
* https://github.com/JakeWharton/butterknife/
*/
const val butterknife_gradle_plugin: String = "com.jakewharton:butterknife-gradle-plugin:" +
Versions.com_jakewharton
Versions.com_jakewharton
/**
* https://developer.android.com/testing
@ -218,7 +226,7 @@ object Libs {
* https://objectbox.io
*/
const val objectbox_gradle_plugin: String = "io.objectbox:objectbox-gradle-plugin:" +
Versions.io_objectbox
Versions.io_objectbox
/**
* https://objectbox.io
@ -234,7 +242,7 @@ object Libs {
* https://objectbox.io
*/
const val objectbox_processor: String = "io.objectbox:objectbox-processor:" +
Versions.io_objectbox
Versions.io_objectbox
/**
* https://objectbox.io
@ -270,42 +278,42 @@ object Libs {
* https://developer.android.com/topic/libraries/architecture/index.html
*/
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
*/
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 =
"de.fayard.buildSrcVersions:de.fayard.buildSrcVersions.gradle.plugin:" +
"de.fayard.buildSrcVersions:de.fayard.buildSrcVersions.gradle.plugin:" +
Versions.de_fayard_buildsrcversions_gradle_plugin
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
/**
* http://jcp.org/en/jsr/detail?id=250
*/
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:" +
Versions.ink_page_indicator
Versions.ink_page_indicator
/**
* http://github.com/square/leakcanary/
*/
const val leakcanary_android: String = "com.squareup.leakcanary:leakcanary-android:" +
Versions.leakcanary_android
Versions.leakcanary_android
/**
* http://tools.android.com
*/
const val constraintlayout: String = "androidx.constraintlayout:constraintlayout:" +
Versions.constraintlayout
Versions.constraintlayout
/**
* 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 xfetch2okhttp: String = "androidx.tonyodev.fetch2okhttp:xfetch2okhttp:" +
Versions.xfetch2okhttp
Versions.xfetch2okhttp
/**
* https://assertj.github.io/doc/

View File

@ -11,6 +11,9 @@ import org.gradle.plugin.use.PluginDependencySpec
* YOU are responsible for updating manually the dependency version.
*/
object Versions {
const val document_file_version: String = "1.0.1"
const val org_jetbrains_kotlinx_kotlinx_coroutines: String = "1.4.1"
const val androidx_test_espresso: String = "3.3.0"
@ -121,4 +124,4 @@ object Versions {
*/
val PluginDependenciesSpec.buildSrcVersions: PluginDependencySpec
inline get() =
id("de.fayard.buildSrcVersions").version(Versions.de_fayard_buildsrcversions_gradle_plugin)
id("de.fayard.buildSrcVersions").version(Versions.de_fayard_buildsrcversions_gradle_plugin)

View File

@ -47,6 +47,9 @@ dependencies {
implementation(Libs.squidb_annotations)
add("kapt", Libs.squidb_processor)
// Document File
implementation(Libs.select_folder_document_file)
// Square
implementation(Libs.converter_simplexml) {
exclude(group = "xpp3", module = "xpp3")

View File

@ -43,7 +43,9 @@ internal class StorageViewHolder(
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) + " / " +
storageCalculator.calculateTotalSpace(item.file) + " "
clickOverlay.setOnClickListener {

View File

@ -20,12 +20,17 @@ package org.kiwix.kiwixmobile.core.settings;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.webkit.WebView;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.documentfile.provider.DocumentFile;
import androidx.navigation.NavController;
import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
@ -51,6 +56,10 @@ import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil;
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower;
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog;
import static android.app.Activity.RESULT_OK;
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_STORAGE;
@ -175,9 +184,6 @@ public abstract class CorePrefsFragment extends PreferenceFragmentCompat impleme
versionPref.setSummary(getVersionName() + " Build: " + getVersionCode());
}
private int getVersionCode() {
try {
return getActivity().getPackageManager()
@ -278,13 +284,52 @@ public abstract class CorePrefsFragment extends PreferenceFragmentCompat impleme
findPreference(PREF_STORAGE).setSummary(
storageCalculator.calculateAvailableSpace(storageDevice.getFile())
);
sharedPreferenceUtil.putPrefStorage(storageDevice.getName());
if (storageDevice.isInternal()) {
sharedPreferenceUtil.putPrefStorage(
sharedPreferenceUtil.getActualPath(storageDevice.getName()));
findPreference(PREF_STORAGE).setTitle(getString(R.string.internal_storage));
sharedPreferenceUtil.putStoragePosition(INTERNAL_SELECT_POSITION);
} else {
findPreference(PREF_STORAGE).setTitle(getString(R.string.external_storage));
setFolder();
}
return Unit.INSTANCE;
}
private void setFolder() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
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) {
Uri uri = data.getData();
int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getActivity().grantUriPermission(getActivity().getPackageName(), uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getActivity().getContentResolver().takePersistableUriPermission(uri, takeFlags);
DocumentFile dfile = DocumentFile.fromTreeUri(getActivity(), uri);
String meraPath =
dfile.getUri().getPath().substring(dfile.getUri().getPath().lastIndexOf(":") + 1);
String path = getActivity().getExternalFilesDirs("")[1].toString();
String separator = "/Android";
int sepPos = path.indexOf(separator);
if (sepPos == -1) {
} else {
path = path.substring(0, sepPos);
}
path = path + File.separator + meraPath;
sharedPreferenceUtil.putPrefStorage(path);
findPreference(PREF_STORAGE).setTitle(getString(R.string.external_storage));
sharedPreferenceUtil.putStoragePosition(EXTERNAL_SELECT_POSITION);
}
}
}

View File

@ -23,6 +23,7 @@ const val CONTACT_EMAIL_ADDRESS = "android@kiwix.org"
// Request stuff
const val REQUEST_STORAGE_PERMISSION = 1
const val REQUEST_WRITE_STORAGE_PERMISSION_ADD_NOTE = 3
const val REQUEST_SELECT_FOLDER_PERMISSION = 4
// Tags
const val TAG_FILE_SEARCHED = "searchedarticle"
@ -37,3 +38,8 @@ const val TAG_FROM_TAB_SWITCHER = "fromtabswitcher"
const val EXTRA_IS_WIDGET_VOICE = "isWidgetVoice"
const val HOTSPOT_SERVICE_CHANNEL_ID = "hotspotService"
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

View File

@ -76,12 +76,15 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
get() {
val storage = sharedPreferences.getString(PREF_STORAGE, null)
return when {
storage == null -> defaultStorage().also(::putPrefStorage)
!File(storage).exists() -> defaultStorage()
storage == null -> getActualPath(defaultStorage()).also(::putPrefStorage)
!File(storage).exists() -> getActualPath(defaultStorage())
else -> storage
}
}
val storagePosition: Int
get() = sharedPreferences.getInt(STORAGE_POSITION, 0)
private fun defaultStorage(): String =
getExternalFilesDirs(context, null)[0]?.path
?: context.filesDir.path // a workaround for emulators
@ -108,6 +111,10 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
_prefStorages.onNext(storage)
}
fun putStoragePosition(pos: Int) {
sharedPreferences.edit { putInt(STORAGE_POSITION, pos) }
}
fun putPrefFullScreen(fullScreen: Boolean) =
sharedPreferences.edit { putBoolean(PREF_FULLSCREEN, fullScreen) }
@ -160,10 +167,22 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
_textZooms.offer(textZoom)
}
fun getActualPath(path: String): String {
var s = path
val separator = "/Android"
val sepPos = path.indexOf(separator)
if (sepPos == -1) {
} else {
s = path.substring(0, sepPos)
}
return s
}
companion object {
// Prefs
const val PREF_LANG = "pref_language_chooser"
const val PREF_STORAGE = "pref_select_folder"
const val STORAGE_POSITION = "storage_position"
const val PREF_WIFI_ONLY = "pref_wifi_only"
const val PREF_KIWIX_MOBILE = "kiwix-mobile"
const val PREF_SHOW_INTRO = "showIntro"