readium / kotlin-toolkit

A toolkit for ebooks, audiobooks and comics written in Kotlin
https://readium.org/kotlin-toolkit
BSD 3-Clause "New" or "Revised" License
163 stars 72 forks source link

[Bug] How to pass in the epub path and display it simply #491

Closed songxing10000 closed 3 months ago

songxing10000 commented 3 months ago

Describe the bug

How to simply display an epub file (that is, pass an epub file path) and then call the interface display in the library. The scenario is that the flutter project is made into a plug-in. The flutter project passes an epub file path to the plug-in, and then opens a new page directly from the flutter page to directly display the content of the epub. What should I do if I haven’t found it after a long time? I am an iOS developer and I hope to get help. My code is as follows

package com.example.flutter

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.readium.r2.navigator.epub.EpubNavigatorFactory
import org.readium.r2.navigator.epub.EpubNavigatorFragment
import org.readium.r2.shared.ExperimentalReadiumApi
import org.readium.r2.shared.publication.Publication
import org.readium.r2.shared.publication.asset.FileAsset
import org.readium.r2.streamer.Streamer
import java.io.File
import androidx.fragment.app.FragmentTransaction;

class FlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {

    private lateinit var channel: MethodChannel
    private lateinit var applicationContext: Context
    private lateinit var activity: Activity

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        applicationContext = flutterPluginBinding.applicationContext

        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter")
        channel.setMethodCallHandler(this)
    }

    @OptIn(DelicateCoroutinesApi::class)
    override fun onMethodCall(call: MethodCall, result: Result) = when (call.method) {

        "showEpub" -> {
            val epubPath = call.argument<String>("path")
            GlobalScope.launch {
                openEpub(epubPath)
            }
            result.success(null)
        }
        else -> result.notImplemented()
    }

    @OptIn(ExperimentalReadiumApi::class)
    private suspend fun openEpub(epubPath: String?) {
        epubPath?.let {

            val intent = Intent(applicationContext, Main2Activity::class.java)
//            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            intent.putExtra("epubPath", it)
            activity.startActivity(intent)
        }
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }
    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.activity
    }
    override fun onDetachedFromActivityForConfigChanges() {}
    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        activity = binding.activity
    }
    override fun onDetachedFromActivity() { }
}

class Main2Activity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val epubPath = intent.getStringExtra("epubPath")
        epubPath?.let {
            val fragment = ReadEpubFragment.newInstance(it)
            supportFragmentManager.beginTransaction().apply {
                replace(android.R.id.content, fragment)
                commit()
            }
        }
    }
}

class ReadEpubFragment : Fragment() {
    private lateinit var streamer: Streamer
    private var epubPath: String? = null

    companion object {
        private const val ARG_EPUB_PATH = "epubPath"
        fun newInstance(epubPath: String): ReadEpubFragment {
            val fragment = ReadEpubFragment()
            val args = Bundle()
            args.putString(ARG_EPUB_PATH, epubPath)
            fragment.arguments = args
            return fragment
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            epubPath = it.getString(ARG_EPUB_PATH)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val rootView = View(requireContext())
        rootView.setBackgroundColor(resources.getColor(android.R.color.holo_red_light))
        return rootView
    }

    @OptIn(DelicateCoroutinesApi::class, ExperimentalReadiumApi::class)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        streamer = Streamer(context = requireContext())
        epubPath?.let {
            val file = File(it)
            val asset = FileAsset(file)
            GlobalScope.launch {
                val pub = streamer
                    .open(asset, allowUserInteraction = true, sender = this@ReadEpubFragment)
                    .getOrThrow()

                val navigatorFactory = EpubNavigatorFactory(pub)

                requireActivity().runOnUiThread {

                    val fragmentFactory = navigatorFactory.createFragmentFactory(initialLocator = null)

                    childFragmentManager.fragmentFactory = fragmentFactory

                    childFragmentManager.commitNow  {
                        add(
                            android.R.id.content,
                            EpubNavigatorFragment::class.java,
                            bundleOf(),
                            "read"
                        )
                    }
                }
            }
        }

        super.onViewCreated(view, savedInstanceState)
    }
}

How to reproduce?

Not sure

Readium version

Not sure

Android API version

Not sure

Additional context

No response

mickael-menu commented 3 months ago

Please open a discussion instead of an issue if you are not reporting a bug.

And please clarify your problem in the discussion, I don't understand it.

songxing10000 commented 3 months ago

ok