Coder Social home page Coder Social logo

epub-viewer's Introduction

epub-viewer

Build Status Codacy Badge

epub file viewer android application

BEYOND GOOD AND EVIL 책에선 정상 동작이 확인되어 해당 서적으로 테스트해보시면 원활한 결과를 보실 수 있습니다.

Preview

screenshot-1 screenshot-2 screenshot-3
screenshot-4 screenshot-5 screenshot-6

Spec

  • DRM 없는 EPUB 파일 열람
  • EPUB 콘텐츠의 처음부터 끝까지 볼 수 있어야함
  • 뷰어 내에서 EPUB 파일에 포함되어 있는 책 제목, 저자명, 목차 목록 등이 표시되어야함
  • 목차 목록에서 목차 선택 시 해당 위치로 이동이 가능해야함
  • Slider 혹은 Seek bar 형태의 UI를 통한 네비게이션이 가능해야함
  • 스크롤 보기, 페이지 넘겨 보기 방식이 모두 가능해야함
    • 중간에 보기 방식을 전환할 때 보던 위치가 반드시 유지될 필요는 없음
  • (추가스펙) 본문 내 검색 기능
  • (추가스펙) 보기 방식 전환 시 보던 위치 유지

Structure

├── dto
│   ├── Epub.kt
│   ├── LoadData.kt
│   ├── PageInfo.kt
│   ├── SearchResult.kt
│   └── ViewerType.kt
├── paginator
│   ├── PagePaginator.kt
│   ├── Paginator.kt
│   └── ScrollPaginator.kt
├── ui
│   ├── base
│   │   ├── BaseActivity.kt
│   │   ├── BaseFragment.kt
│   │   ├── BaseView.kt
│   │   ├── BaseViewModel.kt
│   │   └── EpubWebClient.kt
│   ├── common
│   │   └── LoadingDialog.kt
│   ├── etc
│   │   ├── EtcActivity.kt
│   │   └── EtcViewModel.kt
│   ├── library
│   │   ├── LibraryActivity.kt
│   │   ├── LibraryAdapter.kt
│   │   ├── LibraryViewHolder.kt
│   │   └── LibraryViewModel.kt
│   ├── reader
│   │   ├── ReaderActivity.kt
│   │   ├── ReaderViewModel.kt
│   │   ├── strategy
│   │   │   ├── PageTypeStrategy.kt
│   │   │   ├── ScrollTypeStrategy.kt
│   │   │   └── ViewerTypeStrategy.kt
│   │   ├── toolbox
│   │   │   └── ToolboxView.kt
│   │   └── viewer
│   │       ├── EpubLoadingView.kt
│   │       ├── EpubPagerAdapter.kt
│   │       ├── EpubView.kt
│   │       ├── ScrollStatus.kt
│   │       ├── BiDirectionViewPager.kt
│   │       └── WebContainerFragment.kt
│   └── search
│       ├── SearchActivity.kt
│       ├── SearchAdapter.kt
│       ├── SearchViewHolder.kt
│       ├── SearchViewModel.kt
│       └── finder
│           ├── PageFinder.kt
│           ├── PagePageFinder.kt
│           └── ScrollPageFinder.kt
└── util
    ├── BindingAdapter.kt
    ├── LazyUtil.kt
    ├── LifecycleTransformer.kt
    └── ViewUtil.kt
  • ui/library : 서재 페이지
  • ui/reader : 뷰어 페이지
  • ui/etc : 기타 페이지

Reader Layout 구조

└── ReaderActivity
    └── FrameLayout
        ├── EpubView
        │   └── ViewPager
        │       └── WebFragment
        │           └── WebView
        └── ToolboxView

Paginator

가상의 WebView를 통해 렌더링 될 내용의 길이를 구하고 그를 통해 페이지수를 계산합니다.

ScrollPaginator

WebView를 통해 컨텐츠를 렌더링하고 scroll height를 구합니다.

Performance

BEYOND GOOD AND EVIL.epub 파일로(약 300쪽) worker 갯수별 퍼포먼스 체크를 하였습니다.

  • 테스트 기기 : Galaxy S8
  • 테스트 파일 : BEYOND GOOD AND EVIL.epub

paginator-performance (worker 갯수 별 수행 시간, 단위 : ms)

PagePaginator

html body를 잘라 하나씩 추가해보며 '디바이스 높이' 단위로 페이지를 분할합니다.

Performance

BEYOND GOOD AND EVIL.epub 파일로(약 300쪽) 탐색 방법별 퍼포먼스 체크를 하였습니다.

  • 처음부터 1단어씩 추가하는 방식 : 42s
  • 이진탐색으로 변경후 : 9s
  • 탐색방식 최적화후 : 7s
  • javascript interface 최소화후 : 5s

epub-viewer's People

Contributors

jspiner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

epub-viewer's Issues

파일 로딩중 크래시

개요

간헐적으로 파일 로딩중 ReaderActivity에서 크래시가 발생
특정 빌드에 국한된 내용이 아닌 1/30 확률정도로 발생함
해당 크래시 발생시 adb와 연결이 끊어져 stacktrace 확인 불가능...

가능한 해결방안

  • fabric 등을 연동해서 에러 확인
  • branch 단위로 복구해서 에러지점 유추해보기

xhtml 포맷 지원

개요

epub 내부 파일 중 xhtml 파일의 경우 innerHtml을 가져올 수 없어
현재 구현된 코드로 넘겨보기(페이지)가 지원되지 않음.

또한 xhtml 특성상 tag를 닫지 않는경우 제대로 표시되지 않을 가능성이 농후함.

간헐적으로 뷰어 터치시 발생하는 크래시

개요

간헐적으로 뷰어화면에서 화면 터치시 아래와 같은 오류가 발생

java.lang.NoSuchMethodError: No virtual method getCurrentToolboxVisible()Z in class Lnet/jspiner/epub_viewer/ui/reader/ReaderViewModel; 

ReaderViewModel에서 getCurrentToolboxVisible() 라는 virtual method를 찾을수 없다는데,
getCurrentToolboxVisible()는 open method도 abstract method도 아닌 method임.
또한 Build>Clean Project 수행시 해당 오류가 없어짐.(하다보면 또 생김 😭)
kotlin으로 인해 생긴 오류로 추정...

해당함수 선언부

class ReaderViewModel : BaseViewModel() {
    //중략
    fun getCurrentToolboxVisible() = toolboxShowSubject.value!!
    //중략
}

에러 전문

10-26 15:15:25.414 6022-6022/net.jspiner.epub_viewer E/AndroidRuntime: FATAL EXCEPTION: main
    Process: net.jspiner.epub_viewer, PID: 6022
    java.lang.NoSuchMethodError: No virtual method getCurrentToolboxVisible()Z in class Lnet/jspiner/epub_viewer/ui/reader/ReaderViewModel; or its super classes (declaration of 'net.jspiner.epub_viewer.ui.reader.ReaderViewModel' appears in /data/app/net.jspiner.epub_viewer-98FYWfFK3vVrmX5nWybGEg==/base.apk)
        at net.jspiner.epub_viewer.ui.reader.toolbox.ToolboxView.performClick(ToolboxView.kt:113)
        at net.jspiner.epub_viewer.ui.reader.toolbox.ToolboxView$onTouchViewTouchEvent$1.invoke(ToolboxView.kt:139)
        at net.jspiner.epub_viewer.ui.reader.toolbox.ToolboxView$onTouchViewTouchEvent$1.invoke(ToolboxView.kt:21)
        at net.jspiner.epub_viewer.ui.reader.toolbox.ToolboxView$onAttachedToWindow$3.onTouch(ToolboxView.kt:59)
        at android.view.View.dispatchTouchEvent(View.java:12530)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:600)
        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1871)
        at android.app.Activity.dispatchTouchEvent(Activity.java:3384)
        at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
        at com.android.tools.profiler.support.event.WindowProfilerCallback.dispatchTouchEvent(WindowProfilerCallback.java:69)
        at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:562)
        at android.view.View.dispatchPointerEvent(View.java:12782)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5662)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5457)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4950)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5003)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4969)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5106)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4977)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5163)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4950)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5003)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4969)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4977)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4950)
        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7719)
        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7659)
        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7620)
        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7830)
        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
10-26 15:15:25.415 6022-6022/net.jspiner.epub_viewer E/AndroidRuntime:     at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:325)
        at android.os.Looper.loop(Looper.java:142)
        at android.app.ActivityThread.main(ActivityThread.java:6938)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Bug File Not Found Mimetype Directory

Please, I need your help in this awesome epub library.
The project runs successfully on my Android Studio 3.1.2.
But, I get this single error:

Caused by: java.io.FileNotFoundException: /data/user/0/net.jspiner.epub_viewer/cache/beyond_good_and_evil.epub/mimetype (Not a directory) at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(FileOutputStream.java:308) at java.io.FileOutputStream.<init>(FileOutputStream.java:238) at java.io.FileOutputStream.<init>(FileOutputStream.java:180) at net.jspiner.epubstream.EpubStream.extractFile(EpubStream.kt:64) at net.jspiner.epubstream.EpubStream.access$extractFile(EpubStream.kt:22) at net.jspiner.epubstream.EpubStream$unzip$1.subscribe(EpubStream.kt:49) ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.