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 -> adapter.getItem(exportPosition)?.let { book ->
Snackbar.make(binding.titleBar, R.string.exporting, Snackbar.LENGTH_INDEFINITE) Snackbar.make(binding.titleBar, R.string.exporting, Snackbar.LENGTH_INDEFINITE)
.show() .show()
viewModel.export(path, book) { viewModel.exportEPUB(path, book) {
binding.titleBar.snackbar(it) binding.titleBar.snackbar(it)
} }
} }

@ -1,8 +1,13 @@
package io.legado.app.ui.book.cache package io.legado.app.ui.book.cache
import android.app.Application import android.app.Application
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import androidx.documentfile.provider.DocumentFile 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.R
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppPattern 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.ContentProcessor
import io.legado.app.help.storage.BookWebDav import io.legado.app.help.storage.BookWebDav
import io.legado.app.utils.* 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.File
import java.io.FileOutputStream
import java.nio.charset.Charset import java.nio.charset.Charset
@ -127,4 +137,130 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
} }
return srcList 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; package me.ag2s.epublib.domain;
import me.ag2s.epublib.epub.PackageDocumentBase;
import java.io.Serializable; import java.io.Serializable;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Locale; import java.util.Locale;
import me.ag2s.epublib.epub.PackageDocumentBase;
/** /**
* A Date used by the book's metadata. * A Date used by the book's metadata.
* <p> * <p>
@ -48,6 +48,10 @@ public class Date implements Serializable {
private Event event; private Event event;
private String dateString; private String dateString;
public Date() {
this(new java.util.Date(), Event.CREATION);
}
public Date(java.util.Date date) { public Date(java.util.Date date) {
this(date, (Event) null); this(date, (Event) null);
} }

@ -27,7 +27,12 @@ import me.ag2s.epublib.epub.EpubProcessorSupport;
* @author paul * @author paul
*/ */
public class ResourceUtil { public class ResourceUtil {
/**
* 快速创建HTML类型的Resource
* @param title 章节的标题
* @param string 章节的正文
* @return 返回Resource
*/
public static Resource createHTMLResource(String title, String string) { public static Resource createHTMLResource(String title, String string) {
String html = createHtml(title, string); String html = createHtml(title, string);
MediaType mediaTypeProperty = MediaTypes.XHTML; MediaType mediaTypeProperty = MediaTypes.XHTML;
@ -35,6 +40,14 @@ public class ResourceUtil {
return new Resource(data, mediaTypeProperty); return new Resource(data, mediaTypeProperty);
} }
/**
* 快速创建HTML类型的Resource
* @param title 章节的标题
* @param string 章节的正文
* @param href Resource的href
* @return 返回Resource
*/
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static Resource createHTMLResource(String title, String string, String href) { public static Resource createHTMLResource(String title, String string, String href) {
String html = createHtml(title, string); String html = createHtml(title, string);
@ -65,6 +78,13 @@ public class ResourceUtil {
return html; return html;
} }
/**
* 快速从File创建Resource
* @param file File
* @return
* @throws IOException
*/
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static Resource createResource(File file) throws IOException { public static Resource createResource(File file) throws IOException {
if (file == null) { 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 title v
* @param href v * @param href v

Loading…
Cancel
Save