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.
This commit is contained in:
MohitMaliFtechiz 2025-02-12 18:31:04 +05:30
parent 0485691ab0
commit f918ce016b
5 changed files with 55 additions and 42 deletions

View File

@ -26,9 +26,11 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.rx3.rxSingle 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.dao.entities.BookOnDiskEntity_ import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity_
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book 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.reader.ZimReaderSource
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
import javax.inject.Inject import javax.inject.Inject
@ -42,7 +44,6 @@ class NewBookDao @Inject constructor(private val box: Box<BookOnDiskEntity>) {
.flatMapSingle { bookOnDiskEntity -> .flatMapSingle { bookOnDiskEntity ->
val file = bookOnDiskEntity.file val file = bookOnDiskEntity.file
val zimReaderSource = ZimReaderSource(file) val zimReaderSource = ZimReaderSource(file)
rxSingle { zimReaderSource.canOpenInLibkiwix() } rxSingle { zimReaderSource.canOpenInLibkiwix() }
.map { canOpen -> .map { canOpen ->
if (canOpen) { if (canOpen) {
@ -72,7 +73,8 @@ class NewBookDao @Inject constructor(private val box: Box<BookOnDiskEntity>) {
} }
} }
.filter { (bookOnDiskEntity, exists) -> .filter { (bookOnDiskEntity, exists) ->
exists && !isInTrashFolder(bookOnDiskEntity.zimReaderSource.toDatabase()) (instance.getMainActivity().isCustomApp() || exists) &&
!isInTrashFolder(bookOnDiskEntity.zimReaderSource.toDatabase())
} }
.map(Pair<BookOnDiskEntity, Boolean>::first) .map(Pair<BookOnDiskEntity, Boolean>::first)
.toList() .toList()
@ -152,6 +154,7 @@ class NewBookDao @Inject constructor(private val box: Box<BookOnDiskEntity>) {
} }
private suspend fun removeBooksThatDoNotExist(books: MutableList<BookOnDiskEntity>) { private suspend fun removeBooksThatDoNotExist(books: MutableList<BookOnDiskEntity>) {
if (instance.getMainActivity().isCustomApp()) return
delete(books.filterNot { it.zimReaderSource.exists() }) delete(books.filterNot { it.zimReaderSource.exists() })
} }

View File

@ -593,10 +593,6 @@ object FileUtils {
} }
} }
@JvmStatic
fun getDemoFilePathForCustomApp(context: Context) =
"${context.getExternalFilesDirs(null)[0]}/demo.zim"
@SuppressLint("Recycle") @SuppressLint("Recycle")
@JvmStatic @JvmStatic
fun getAssetFileDescriptorFromUri( fun getAssetFileDescriptorFromUri(
@ -633,6 +629,10 @@ object FileUtils {
// via the given file path before passing it to libkiwix. // via the given file path before passing it to libkiwix.
// This precaution helps prevent runtime crashes. // This precaution helps prevent runtime crashes.
// For more details, refer to https://github.com/kiwix/kiwix-android/pull/3636. // 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") FileInputStream("dev/fd/$fdNumber")
true true
} catch (ignore: Exception) { } catch (ignore: Exception) {

View File

@ -19,11 +19,15 @@
package org.kiwix.kiwixmobile.core.webserver package org.kiwix.kiwixmobile.core.webserver
import android.content.Context import android.content.Context
import android.os.Looper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext 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.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.Book
import org.kiwix.libkiwix.Library import org.kiwix.libkiwix.Library
import org.kiwix.libkiwix.Server import org.kiwix.libkiwix.Server
@ -44,29 +48,28 @@ class KiwixServer @Inject constructor(
private val context: Context, private val context: Context,
private val zimReaderContainer: ZimReaderContainer private val zimReaderContainer: ZimReaderContainer
) { ) {
@Suppress("NestedBlockDepth") @Suppress("NestedBlockDepth", "MagicNumber")
suspend fun createKiwixServer(selectedBooksPath: ArrayList<String>): KiwixServer = suspend fun createKiwixServer(selectedBooksPath: ArrayList<String>): KiwixServer =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val kiwixLibrary = Library() val kiwixLibrary = Library()
selectedBooksPath.forEach { path -> selectedBooksPath.forEach { path ->
try { try {
val book = Book().apply { 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 // Determine whether to create an Archive from an asset or a file path
val archive = if (path == getDemoFilePathForCustomApp(context)) { val archive =
// For custom apps using a demo file, create an Archive with FileDescriptor if (path == "null" && (context as CoreApp).getMainActivity().isCustomApp()) {
val assetFileDescriptor = // For custom apps using create an Archive with FileDescriptor
zimReaderContainer.zimReaderSource?.assetFileDescriptorList?.get(0) zimReaderContainer.zimReaderSource?.createArchive()
val startOffset = assetFileDescriptor?.startOffset ?: 0L } else {
val size = assetFileDescriptor?.length ?: 0L // For regular files, create an Archive from the file path
Archive( Archive(path)
assetFileDescriptor?.parcelFileDescriptor?.fileDescriptor, }
startOffset,
size
)
} else {
// For regular files, create an Archive from the file path
Archive(path)
}
update(archive) update(archive)
} }
kiwixLibrary.addBook(book) 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)) return@withContext KiwixServer(kiwixLibrary, Server(kiwixLibrary))
} }
} }

View File

@ -230,8 +230,10 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View {
} }
private fun handleStoragePermissionAndServer() { private fun handleStoragePermissionAndServer() {
// we does not require any permission for playStore variant. // we does not require any permission for playStore variant, and custom apps.
if (sharedPreferenceUtil.isPlayStoreBuildWithAndroid11OrAbove()) { if (sharedPreferenceUtil.isPlayStoreBuildWithAndroid11OrAbove() ||
requireActivity().isCustomApp()
) {
startStopServer() startStopServer()
return return
} }

View File

@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.custom.main
import android.app.Dialog import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.View 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.base.BaseActivity
import org.kiwix.kiwixmobile.core.extensions.browserIntent import org.kiwix.kiwixmobile.core.extensions.browserIntent
import org.kiwix.kiwixmobile.core.extensions.getResizedDrawable 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.CoreReaderFragment
import org.kiwix.kiwixmobile.core.main.MainMenu import org.kiwix.kiwixmobile.core.main.MainMenu
import org.kiwix.kiwixmobile.core.main.RestoreOrigin 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.reader.ZimReaderSource
import org.kiwix.kiwixmobile.core.utils.LanguageUtils import org.kiwix.kiwixmobile.core.utils.LanguageUtils
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower 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.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
import org.kiwix.kiwixmobile.custom.BuildConfig import org.kiwix.kiwixmobile.custom.BuildConfig
import org.kiwix.kiwixmobile.custom.R import org.kiwix.kiwixmobile.custom.R
import org.kiwix.kiwixmobile.custom.customActivityComponent import org.kiwix.kiwixmobile.custom.customActivityComponent
import java.io.File
import java.util.Locale import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
@ -220,19 +218,11 @@ class CustomReaderFragment : CoreReaderFragment() {
true, true,
shouldManageExternalLaunch 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) { if (shouldManageExternalLaunch) {
// Open the previous loaded pages after ZIM file loads. // Open the previous loaded pages after ZIM file loads.
manageExternalLaunchAndRestoringViewState() manageExternalLaunchAndRestoringViewState()
} }
saveBookInDatabase()
} }
is ValidationState.HasBothFiles -> { is ValidationState.HasBothFiles -> {
@ -242,6 +232,7 @@ class CustomReaderFragment : CoreReaderFragment() {
// Open the previous loaded pages after ZIM file loads. // Open the previous loaded pages after ZIM file loads.
manageExternalLaunchAndRestoringViewState() manageExternalLaunchAndRestoringViewState()
} }
saveBookInDatabase()
} }
else -> {} else -> {}
@ -256,16 +247,19 @@ class CustomReaderFragment : CoreReaderFragment() {
) )
} }
private suspend fun createDemoFile() = private fun saveBookInDatabase() {
File(getDemoFilePathForCustomApp(requireActivity())).also { // Save book in the database to display it in `ZimHostFragment`.
if (!it.isFileExist()) it.createNewFile() zimReaderContainer?.zimFileReader?.let { zimFileReader ->
Log.e("SELECTED_BOOKS", "saveBookInDatabase: Saving book to database")
repositoryActions?.saveBook(BookOnDisk(zimFileReader))
} }
}
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater) 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_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 { private fun enforcedLanguage(): Boolean {