From f918ce016bf69bdfa618e7800587b2511e522f3d Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Wed, 12 Feb 2025 18:31:04 +0530 Subject: [PATCH] Refactored the code to not ask permission for custom apps while starting the hotspot since we do not required any permission for starting the server in custom apps. * Fixed: ZIM file was not showing in the Hotspot screen. * Removed the unnecessary code and creation of demo file for custom app. --- .../kiwix/kiwixmobile/core/dao/NewBookDao.kt | 7 ++- .../kiwixmobile/core/utils/files/FileUtils.kt | 8 +-- .../kiwixmobile/core/webserver/KiwixServer.kt | 50 ++++++++++++------- .../core/webserver/ZimHostFragment.kt | 6 ++- .../custom/main/CustomReaderFragment.kt | 26 ++++------ 5 files changed, 55 insertions(+), 42 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt index b05d691ae..b0e56eead 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt @@ -26,9 +26,11 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.rx3.rxSingle +import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity_ import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book +import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk import javax.inject.Inject @@ -42,7 +44,6 @@ class NewBookDao @Inject constructor(private val box: Box) { .flatMapSingle { bookOnDiskEntity -> val file = bookOnDiskEntity.file val zimReaderSource = ZimReaderSource(file) - rxSingle { zimReaderSource.canOpenInLibkiwix() } .map { canOpen -> if (canOpen) { @@ -72,7 +73,8 @@ class NewBookDao @Inject constructor(private val box: Box) { } } .filter { (bookOnDiskEntity, exists) -> - exists && !isInTrashFolder(bookOnDiskEntity.zimReaderSource.toDatabase()) + (instance.getMainActivity().isCustomApp() || exists) && + !isInTrashFolder(bookOnDiskEntity.zimReaderSource.toDatabase()) } .map(Pair::first) .toList() @@ -152,6 +154,7 @@ class NewBookDao @Inject constructor(private val box: Box) { } private suspend fun removeBooksThatDoNotExist(books: MutableList) { + if (instance.getMainActivity().isCustomApp()) return delete(books.filterNot { it.zimReaderSource.exists() }) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt index d4f437357..2b728d71b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt @@ -593,10 +593,6 @@ object FileUtils { } } - @JvmStatic - fun getDemoFilePathForCustomApp(context: Context) = - "${context.getExternalFilesDirs(null)[0]}/demo.zim" - @SuppressLint("Recycle") @JvmStatic fun getAssetFileDescriptorFromUri( @@ -633,6 +629,10 @@ object FileUtils { // via the given file path before passing it to libkiwix. // This precaution helps prevent runtime crashes. // For more details, refer to https://github.com/kiwix/kiwix-android/pull/3636. + Log.e( + "CAN_OPEN_IN_LIBKIWIX", + "isFileDescriptorCanOpenWithLibkiwix: ${FileInputStream("dev/fd/$fdNumber")}" + ) FileInputStream("dev/fd/$fdNumber") true } catch (ignore: Exception) { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/KiwixServer.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/KiwixServer.kt index fd49f3cf9..9c6692593 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/KiwixServer.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/KiwixServer.kt @@ -19,11 +19,15 @@ package org.kiwix.kiwixmobile.core.webserver import android.content.Context +import android.os.Looper +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.kiwix.kiwixmobile.core.utils.files.Log +import org.kiwix.kiwixmobile.core.CoreApp +import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer -import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getDemoFilePathForCustomApp +import org.kiwix.kiwixmobile.core.utils.files.Log import org.kiwix.libkiwix.Book import org.kiwix.libkiwix.Library import org.kiwix.libkiwix.Server @@ -44,29 +48,28 @@ class KiwixServer @Inject constructor( private val context: Context, private val zimReaderContainer: ZimReaderContainer ) { - @Suppress("NestedBlockDepth") + @Suppress("NestedBlockDepth", "MagicNumber") suspend fun createKiwixServer(selectedBooksPath: ArrayList): KiwixServer = withContext(Dispatchers.IO) { val kiwixLibrary = Library() selectedBooksPath.forEach { path -> try { val book = Book().apply { + Log.e( + TAG, + " FD is valid = ${zimReaderContainer.zimReaderSource?.exists()} \n" + + "FD can read via the dev/fd/fdNumber = " + + "${zimReaderContainer.zimReaderSource?.canOpenInLibkiwix()}" + ) // Determine whether to create an Archive from an asset or a file path - val archive = if (path == getDemoFilePathForCustomApp(context)) { - // For custom apps using a demo file, create an Archive with FileDescriptor - val assetFileDescriptor = - zimReaderContainer.zimReaderSource?.assetFileDescriptorList?.get(0) - val startOffset = assetFileDescriptor?.startOffset ?: 0L - val size = assetFileDescriptor?.length ?: 0L - Archive( - assetFileDescriptor?.parcelFileDescriptor?.fileDescriptor, - startOffset, - size - ) - } else { - // For regular files, create an Archive from the file path - Archive(path) - } + val archive = + if (path == "null" && (context as CoreApp).getMainActivity().isCustomApp()) { + // For custom apps using create an Archive with FileDescriptor + zimReaderContainer.zimReaderSource?.createArchive() + } else { + // For regular files, create an Archive from the file path + Archive(path) + } update(archive) } kiwixLibrary.addBook(book) @@ -79,6 +82,17 @@ class KiwixServer @Inject constructor( ) } } + android.os.Handler(Looper.getMainLooper()).postDelayed({ + CoroutineScope(Dispatchers.IO).launch { + Log.e( + TAG, + "After 5 second FD is valid = " + + "${zimReaderContainer.zimReaderSource?.exists()} \n" + + "FD can read via the dev/fd/fdNumber =" + + " ${zimReaderContainer.zimReaderSource?.canOpenInLibkiwix()}" + ) + } + }, 5000) return@withContext KiwixServer(kiwixLibrary, Server(kiwixLibrary)) } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt index 164e9a61e..673114619 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt @@ -230,8 +230,10 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { } private fun handleStoragePermissionAndServer() { - // we does not require any permission for playStore variant. - if (sharedPreferenceUtil.isPlayStoreBuildWithAndroid11OrAbove()) { + // we does not require any permission for playStore variant, and custom apps. + if (sharedPreferenceUtil.isPlayStoreBuildWithAndroid11OrAbove() || + requireActivity().isCustomApp() + ) { startStopServer() return } diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt index 9e3602498..4b73b2855 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt @@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.custom.main import android.app.Dialog import android.os.Bundle +import android.util.Log import android.view.Menu import android.view.MenuInflater import android.view.View @@ -36,7 +37,6 @@ import org.kiwix.kiwixmobile.core.R.dimen import org.kiwix.kiwixmobile.core.base.BaseActivity import org.kiwix.kiwixmobile.core.extensions.browserIntent import org.kiwix.kiwixmobile.core.extensions.getResizedDrawable -import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.main.CoreReaderFragment import org.kiwix.kiwixmobile.core.main.MainMenu import org.kiwix.kiwixmobile.core.main.RestoreOrigin @@ -44,12 +44,10 @@ import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.LanguageUtils import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower -import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getDemoFilePathForCustomApp import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk import org.kiwix.kiwixmobile.custom.BuildConfig import org.kiwix.kiwixmobile.custom.R import org.kiwix.kiwixmobile.custom.customActivityComponent -import java.io.File import java.util.Locale import javax.inject.Inject @@ -220,19 +218,11 @@ class CustomReaderFragment : CoreReaderFragment() { true, shouldManageExternalLaunch ) - // Save book in the database to display it in `ZimHostFragment`. - zimReaderContainer?.zimFileReader?.let { zimFileReader -> - // Check if the file is not null. If the file is null, - // it means we have created zimFileReader with a fileDescriptor, - // so we create a demo file to save it in the database for display on the `ZimHostFragment`. - val file = it.file ?: createDemoFile() - val bookOnDisk = BookOnDisk(zimFileReader) - repositoryActions?.saveBook(bookOnDisk) - } if (shouldManageExternalLaunch) { // Open the previous loaded pages after ZIM file loads. manageExternalLaunchAndRestoringViewState() } + saveBookInDatabase() } is ValidationState.HasBothFiles -> { @@ -242,6 +232,7 @@ class CustomReaderFragment : CoreReaderFragment() { // Open the previous loaded pages after ZIM file loads. manageExternalLaunchAndRestoringViewState() } + saveBookInDatabase() } else -> {} @@ -256,16 +247,19 @@ class CustomReaderFragment : CoreReaderFragment() { ) } - private suspend fun createDemoFile() = - File(getDemoFilePathForCustomApp(requireActivity())).also { - if (!it.isFileExist()) it.createNewFile() + private fun saveBookInDatabase() { + // Save book in the database to display it in `ZimHostFragment`. + zimReaderContainer?.zimFileReader?.let { zimFileReader -> + Log.e("SELECTED_BOOKS", "saveBookInDatabase: Saving book to database") + repositoryActions?.saveBook(BookOnDisk(zimFileReader)) } + } @Suppress("DEPRECATION") override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { super.onCreateOptionsMenu(menu, inflater) menu.findItem(org.kiwix.kiwixmobile.core.R.id.menu_help)?.isVisible = false - menu.findItem(org.kiwix.kiwixmobile.core.R.id.menu_host_books)?.isVisible = false + menu.findItem(org.kiwix.kiwixmobile.core.R.id.menu_host_books)?.isVisible = true } private fun enforcedLanguage(): Boolean {