Merge pull request #921 from ag2s20150909/master

在CacheViewModel中添加导出为epub的方法
pull/931/head
kunfei 4 years ago committed by GitHub
commit 12d83321a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt
  2. 136
      app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt
  3. 8
      epublib/src/main/java/me/ag2s/epublib/domain/Date.java
  4. 24
      epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java

@ -239,7 +239,7 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
adapter.getItem(exportPosition)?.let { book ->
Snackbar.make(binding.titleBar, R.string.exporting, Snackbar.LENGTH_INDEFINITE)
.show()
viewModel.export(path, book) {
viewModel.exportEPUB(path, book) {
binding.titleBar.snackbar(it)
}
}

@ -1,8 +1,13 @@
package io.legado.app.ui.book.cache
import android.app.Application
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import io.legado.app.R
import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppPattern
@ -13,7 +18,12 @@ import io.legado.app.help.BookHelp
import io.legado.app.help.ContentProcessor
import io.legado.app.help.storage.BookWebDav
import io.legado.app.utils.*
import me.ag2s.epublib.domain.*
import me.ag2s.epublib.epub.EpubWriter
import me.ag2s.epublib.util.ResourceUtil
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.nio.charset.Charset
@ -127,4 +137,130 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
}
return srcList
}
//////////////////Start EPUB
/**
* 导出Epub
*/
fun exportEPUB(path: String, book: Book, finally: (msg: String) -> Unit) {
execute {
if (path.isContentScheme()) {
val uri = Uri.parse(path)
DocumentFile.fromTreeUri(context, uri)?.let {
exportEpub(it, book)
}
} else {
exportEpub(FileUtils.createFolderIfNotExist(path), book)
}
}.onError {
finally(it.localizedMessage ?: "ERROR")
}.onSuccess {
finally(context.getString(R.string.success))
}
}
@Suppress("BlockingMethodInNonBlockingContext")
private suspend fun exportEpub(doc: DocumentFile, book: Book) {
val filename = "${book.name} by ${book.author}.epub"
DocumentUtils.delete(doc, filename)
val epubBook = EpubBook()
epubBook.version = "2.0"
//set metadata
setEpubMetadata(book,epubBook)
//set cover
setCover(book, epubBook)
//set css
epubBook.resources.add(
Resource(
"h1 {color: blue;}p {text-indent:2em;}".encodeToByteArray(),
"css/style.css"
)
)
//设置正文
setEpubContent(book, epubBook)
DocumentUtils.createFileIfNotExist(doc, filename)?.let { bookDoc ->
context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs ->
EpubWriter().write(epubBook, bookOs)
}
}
}
private suspend fun exportEpub(file: File, book: Book) {
val filename = "${book.name} by ${book.author}.epub"
val epubBook = EpubBook()
epubBook.version = "2.0"
//set metadata
setEpubMetadata(book,epubBook)
//set cover
setCover(book, epubBook)
//set css
epubBook.resources.add(
Resource(
"h1 {color: blue;}p {text-indent:2em;}".encodeToByteArray(),
"css/style.css"
)
)
val bookPath = FileUtils.getPath(file, filename)
val bookFile = FileUtils.createFileWithReplace(bookPath)
//设置正文
setEpubContent(book, epubBook)
EpubWriter().write(epubBook, FileOutputStream(bookFile))
}
private fun setCover(book: Book, epubBook: EpubBook) {
Glide.with(context)
.asBitmap()
.load(book.coverUrl)
.into(object : CustomTarget<Bitmap>(){
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val stream = ByteArrayOutputStream()
resource.compress(Bitmap.CompressFormat.JPEG, 100, stream)
val byteArray: ByteArray = stream.toByteArray()
resource.recycle()
epubBook.coverImage= Resource(byteArray,"cover.jpg")
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
}
private fun setEpubContent(book: Book, epubBook: EpubBook) {
val useReplace = AppConfig.exportUseReplace
val contentProcessor = ContentProcessor(book.name, book.origin)
appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter ->
BookHelp.getContent(book, chapter).let { content ->
val content1 = contentProcessor
.getContent(book, chapter.title, content ?: "null", false, useReplace)
.joinToString("\n")
.replace(chapter.title,"")
epubBook.addSection(
chapter.title,
ResourceUtil.createHTMLResource(chapter.title, content1)
)
}
}
}
private fun setEpubMetadata(book: Book,epubBook: EpubBook) {
val metadata = Metadata()
metadata.titles.add(book.name)//书籍的名称
metadata.authors.add(Author(book.author))//书籍的作者
metadata.language = "zh"//数据的语言
metadata.dates.add(Date())//数据的创建日期
metadata.publishers.add("Legado APP")//数据的创建者
metadata.descriptions.add(book.getDisplayIntro())//书籍的简介
//metadata.subjects.add("")//书籍的主题,在静读天下里面有使用这个分类书籍
epubBook.metadata=metadata
}
//////end of EPUB
}

@ -1,11 +1,11 @@
package me.ag2s.epublib.domain;
import me.ag2s.epublib.epub.PackageDocumentBase;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Locale;
import me.ag2s.epublib.epub.PackageDocumentBase;
/**
* A Date used by the book's metadata.
* <p>
@ -48,6 +48,10 @@ public class Date implements Serializable {
private Event event;
private String dateString;
public Date() {
this(new java.util.Date(), Event.CREATION);
}
public Date(java.util.Date date) {
this(date, (Event) null);
}

@ -27,7 +27,12 @@ import me.ag2s.epublib.epub.EpubProcessorSupport;
* @author paul
*/
public class ResourceUtil {
/**
* 快速创建HTML类型的Resource
* @param title 章节的标题
* @param string 章节的正文
* @return 返回Resource
*/
public static Resource createHTMLResource(String title, String string) {
String html = createHtml(title, string);
MediaType mediaTypeProperty = MediaTypes.XHTML;
@ -35,6 +40,14 @@ public class ResourceUtil {
return new Resource(data, mediaTypeProperty);
}
/**
* 快速创建HTML类型的Resource
* @param title 章节的标题
* @param string 章节的正文
* @param href Resource的href
* @return 返回Resource
*/
@SuppressWarnings("unused")
public static Resource createHTMLResource(String title, String string, String href) {
String html = createHtml(title, string);
@ -65,6 +78,13 @@ public class ResourceUtil {
return html;
}
/**
* 快速从File创建Resource
* @param file File
* @return
* @throws IOException
*/
@SuppressWarnings("unused")
public static Resource createResource(File file) throws IOException {
if (file == null) {
@ -77,7 +97,7 @@ public class ResourceUtil {
/**
* Creates a resource with as contents a html page with the given title.
* 创建一个只带标题的HTMl类型的Resource,常用于封面页大卷页
*
* @param title v
* @param href v

Loading…
Cancel
Save