pull/1395/head
gedoor 4 years ago
parent 18f14ec1df
commit b186c4cdc6
  1. 2
      app/build.gradle
  2. 31
      app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt
  3. 11
      app/src/main/java/io/legado/app/help/http/cronet/CronetRequestCallback.kt
  4. 10
      app/src/main/java/io/legado/app/ui/widget/recycler/DragSelectTouchHelper.kt
  5. 8
      app/src/main/java/io/legado/app/utils/ZipUtils.kt
  6. 16
      epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentReader.java
  7. 6
      epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentWriter.java

@ -150,6 +150,8 @@ dependencies {
implementation('com.google.code.gson:gson:2.8.8') implementation('com.google.code.gson:gson:2.8.8')
implementation('androidx.webkit:webkit:1.4.0') implementation('androidx.webkit:webkit:1.4.0')
implementation('com.jakewharton.timber:timber:5.0.1')
//media //media
implementation("androidx.media:media:1.4.1") implementation("androidx.media:media:1.4.1")
def exoplayer_version = '2.15.0' def exoplayer_version = '2.15.0'

@ -5,7 +5,6 @@ import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.os.Build import android.os.Build
import android.text.TextUtils import android.text.TextUtils
import android.util.Log
import com.google.android.gms.net.CronetProviderInstaller import com.google.android.gms.net.CronetProviderInstaller
import io.legado.app.BuildConfig import io.legado.app.BuildConfig
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
@ -14,6 +13,7 @@ import io.legado.app.utils.printOnDebug
import org.chromium.net.CronetEngine import org.chromium.net.CronetEngine
import org.json.JSONObject import org.json.JSONObject
import splitties.init.appCtx import splitties.init.appCtx
import timber.log.Timber
import java.io.* import java.io.*
import java.math.BigInteger import java.math.BigInteger
import java.net.HttpURLConnection import java.net.HttpURLConnection
@ -24,7 +24,6 @@ import java.util.*
object CronetLoader : CronetEngine.Builder.LibraryLoader() { object CronetLoader : CronetEngine.Builder.LibraryLoader() {
//https://storage.googleapis.com/chromium-cronet/android/92.0.4515.159/Release/cronet/libs/arm64-v8a/libcronet.92.0.4515.159.so //https://storage.googleapis.com/chromium-cronet/android/92.0.4515.159/Release/cronet/libs/arm64-v8a/libcronet.92.0.4515.159.so
private const val TAG = "CronetLoader"
private const val soVersion = BuildConfig.Cronet_Version private const val soVersion = BuildConfig.Cronet_Version
private const val soName = "libcronet.$soVersion.so" private const val soName = "libcronet.$soVersion.so"
@ -44,10 +43,10 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
val dir = appCtx.getDir("cronet", Context.MODE_PRIVATE) val dir = appCtx.getDir("cronet", Context.MODE_PRIVATE)
soFile = File(dir.toString() + "/" + getCpuAbi(appCtx), soName) soFile = File(dir.toString() + "/" + getCpuAbi(appCtx), soName)
downloadFile = File(appCtx.cacheDir.toString() + "/so_download", soName) downloadFile = File(appCtx.cacheDir.toString() + "/so_download", soName)
Log.e(TAG, "soName+:$soName") Timber.d("soName+:$soName")
Log.e(TAG, "destSuccessFile:$soFile") Timber.d("destSuccessFile:$soFile")
Log.e(TAG, "tempFile:$downloadFile") Timber.d("tempFile:$downloadFile")
Log.e(TAG, "soUrl:$soUrl") Timber.d("soUrl:$soUrl")
} }
@ -85,11 +84,11 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
Coroutine.async { Coroutine.async {
//md5 = getUrlMd5(md5Url) //md5 = getUrlMd5(md5Url)
if (soFile.exists() && md5 == getFileMD5(soFile)) { if (soFile.exists() && md5 == getFileMD5(soFile)) {
Log.e(TAG, "So 库已存在") Timber.d("So 库已存在")
} else { } else {
download(soUrl, md5, downloadFile, soFile) download(soUrl, md5, downloadFile, soFile)
} }
Log.e(TAG, soName) Timber.d(soName)
} }
} }
@ -116,7 +115,7 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
@SuppressLint("UnsafeDynamicallyLoadedCode") @SuppressLint("UnsafeDynamicallyLoadedCode")
override fun loadLibrary(libName: String) { override fun loadLibrary(libName: String) {
Log.e(TAG, "libName:$libName") Timber.d("libName:$libName")
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
@Suppress("SameParameterValue") @Suppress("SameParameterValue")
try { try {
@ -128,13 +127,13 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
//以下逻辑为cronet加载,优先加载本地,否则从远程加载 //以下逻辑为cronet加载,优先加载本地,否则从远程加载
//首先调用系统行为进行加载 //首先调用系统行为进行加载
System.loadLibrary(libName) System.loadLibrary(libName)
Log.i(TAG, "load from system") Timber.d("load from system")
} catch (e: Throwable) { } catch (e: Throwable) {
//如果找不到,则从远程下载 //如果找不到,则从远程下载
//删除历史文件 //删除历史文件
deleteHistoryFile(Objects.requireNonNull(soFile.parentFile), soFile) deleteHistoryFile(Objects.requireNonNull(soFile.parentFile), soFile)
//md5 = getUrlMd5(md5Url) //md5 = getUrlMd5(md5Url)
Log.i(TAG, "soMD5:$md5") Timber.d("soMD5:$md5")
if (md5.length != 32 || soUrl.isEmpty()) { if (md5.length != 32 || soUrl.isEmpty()) {
//如果md5或下载的url为空,则调用系统行为进行加载 //如果md5或下载的url为空,则调用系统行为进行加载
System.loadLibrary(libName) System.loadLibrary(libName)
@ -153,7 +152,7 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
if (fileMD5 != null && fileMD5.equals(md5, ignoreCase = true)) { if (fileMD5 != null && fileMD5.equals(md5, ignoreCase = true)) {
//md5值一样,则加载 //md5值一样,则加载
System.load(soFile.absolutePath) System.load(soFile.absolutePath)
Log.e(TAG, "load from:$soFile") Timber.d("load from:$soFile")
return return
} }
//md5不一样则删除 //md5不一样则删除
@ -164,7 +163,7 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
//使用系统加载方法 //使用系统加载方法
System.loadLibrary(libName) System.loadLibrary(libName)
} finally { } finally {
Log.e(TAG, "time:" + (System.currentTimeMillis() - start)) Timber.d("time:" + (System.currentTimeMillis() - start))
} }
} }
@ -199,7 +198,7 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
for (f in files) { for (f in files) {
if (f.exists() && (currentFile == null || f.absolutePath != currentFile.absolutePath)) { if (f.exists() && (currentFile == null || f.absolutePath != currentFile.absolutePath)) {
val delete = f.delete() val delete = f.delete()
Log.e(TAG, "delete file: $f result: $delete") Timber.d("delete file: $f result: $delete")
if (!delete) { if (!delete) {
f.deleteOnExit() f.deleteOnExit()
} }
@ -271,7 +270,7 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
download = true download = true
executor.execute { executor.execute {
val result = downloadFileIfNotExist(url, downloadTempFile) val result = downloadFileIfNotExist(url, downloadTempFile)
Log.e(TAG, "download result:$result") Timber.d("download result:$result")
//文件md5再次校验 //文件md5再次校验
val fileMD5 = getFileMD5(downloadTempFile) val fileMD5 = getFileMD5(downloadTempFile)
if (md5 != null && !md5.equals(fileMD5, ignoreCase = true)) { if (md5 != null && !md5.equals(fileMD5, ignoreCase = true)) {
@ -282,7 +281,7 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
download = false download = false
return@execute return@execute
} }
Log.e(TAG, "download success, copy to $destSuccessFile") Timber.d("download success, copy to $destSuccessFile")
//下载成功拷贝文件 //下载成功拷贝文件
copyFile(downloadTempFile, destSuccessFile) copyFile(downloadTempFile, destSuccessFile)
cacheInstall = false cacheInstall = false

@ -1,7 +1,6 @@
package io.legado.app.help.http.cronet package io.legado.app.help.http.cronet
import android.os.ConditionVariable import android.os.ConditionVariable
import android.util.Log
import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.okHttpClient
import okhttp3.* import okhttp3.*
import okhttp3.EventListener import okhttp3.EventListener
@ -11,6 +10,7 @@ import okio.Buffer
import org.chromium.net.CronetException import org.chromium.net.CronetException
import org.chromium.net.UrlRequest import org.chromium.net.UrlRequest
import org.chromium.net.UrlResponseInfo import org.chromium.net.UrlResponseInfo
import timber.log.Timber
import java.io.IOException import java.io.IOException
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.* import java.util.*
@ -86,7 +86,7 @@ class CronetRequestCallback @JvmOverloads internal constructor(
// } // }
// Log.e("Cronet", sb.toString()) // Log.e("Cronet", sb.toString())
//打印协议,用于调试 //打印协议,用于调试
Log.i("Cronet", info.negotiatedProtocol) Timber.i(info.negotiatedProtocol)
if (eventListener != null) { if (eventListener != null) {
eventListener.responseHeadersEnd(mCall, this.mResponse) eventListener.responseHeadersEnd(mCall, this.mResponse)
eventListener.responseBodyStart(mCall) eventListener.responseBodyStart(mCall)
@ -107,7 +107,7 @@ class CronetRequestCallback @JvmOverloads internal constructor(
try { try {
mBuffer.write(byteBuffer) mBuffer.write(byteBuffer)
} catch (e: IOException) { } catch (e: IOException) {
Log.i(TAG, "IOException during ByteBuffer read. Details: ", e) Timber.i(e, "IOException during ByteBuffer read. Details: ")
throw e throw e
} }
byteBuffer.clear() byteBuffer.clear()
@ -135,7 +135,7 @@ class CronetRequestCallback @JvmOverloads internal constructor(
//UrlResponseInfo可能为null //UrlResponseInfo可能为null
override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) { override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) {
Log.e(TAG, error.message.toString()) Timber.e(error.message.toString())
val msg = error.localizedMessage val msg = error.localizedMessage
val e = IOException(msg?.substring(msg.indexOf("net::")), error) val e = IOException(msg?.substring(msg.indexOf("net::")), error)
mException = e mException = e
@ -153,7 +153,6 @@ class CronetRequestCallback @JvmOverloads internal constructor(
} }
companion object { companion object {
private const val TAG = "Callback"
private const val MAX_FOLLOW_COUNT = 20 private const val MAX_FOLLOW_COUNT = 20
private fun protocolFromNegotiatedProtocol(responseInfo: UrlResponseInfo): Protocol { private fun protocolFromNegotiatedProtocol(responseInfo: UrlResponseInfo): Protocol {
@ -195,7 +194,7 @@ class CronetRequestCallback @JvmOverloads internal constructor(
} }
add(key, value) add(key, value)
} catch (e: Exception) { } catch (e: Exception) {
Log.w(TAG, "Invalid HTTP header/value: $key$value") Timber.w("Invalid HTTP header/value: $key$value")
// Ignore that header // Ignore that header
} }
} }

@ -18,7 +18,6 @@ package io.legado.app.ui.widget.recycler
import android.content.res.Resources import android.content.res.Resources
import android.text.TextUtils import android.text.TextUtils
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
@ -28,6 +27,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener
import io.legado.app.BuildConfig import io.legado.app.BuildConfig
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper.AdvanceCallback.Mode import io.legado.app.ui.widget.recycler.DragSelectTouchHelper.AdvanceCallback.Mode
import timber.log.Timber
import java.util.* import java.util.*
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -971,17 +971,15 @@ class DragSelectTouchHelper(
private object Logger { private object Logger {
private val DEBUG = BuildConfig.DEBUG private val DEBUG = BuildConfig.DEBUG
fun d(msg: String) { fun d(msg: String) {
if (DEBUG) { Timber.d(msg)
Log.d(TAG, msg)
}
} }
fun e(msg: String) { fun e(msg: String) {
Log.e(TAG, msg) Timber.e(msg)
} }
fun i(msg: String) { fun i(msg: String) {
Log.i(TAG, msg) Timber.i(msg)
} }
fun logSelectStateChange(before: Int, after: Int) { fun logSelectStateChange(before: Int, after: Int) {

@ -1,8 +1,8 @@
package io.legado.app.utils package io.legado.app.utils
import android.util.Log
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.* import java.io.*
import java.util.* import java.util.*
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
@ -242,7 +242,7 @@ object ZipUtils {
val entry = entries.nextElement() as ZipEntry val entry = entries.nextElement() as ZipEntry
val entryName = entry.name val entryName = entry.name
if (entryName.contains("../")) { if (entryName.contains("../")) {
Log.e("ZipUtils", "entryName: $entryName is dangerous!") Timber.e("entryName: $entryName is dangerous!")
continue continue
} }
if (!unzipChildFile(destDir, files, zip, entry, entryName)) return files if (!unzipChildFile(destDir, files, zip, entry, entryName)) return files
@ -252,7 +252,7 @@ object ZipUtils {
val entry = entries.nextElement() as ZipEntry val entry = entries.nextElement() as ZipEntry
val entryName = entry.name val entryName = entry.name
if (entryName.contains("../")) { if (entryName.contains("../")) {
Log.e("ZipUtils", "entryName: $entryName is dangerous!") Timber.e("entryName: $entryName is dangerous!")
continue continue
} }
if (entryName.contains(keyword!!)) { if (entryName.contains(keyword!!)) {
@ -315,7 +315,7 @@ object ZipUtils {
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
val entryName = (entries.nextElement() as ZipEntry).name val entryName = (entries.nextElement() as ZipEntry).name
if (entryName.contains("../")) { if (entryName.contains("../")) {
Log.e("ZipUtils", "entryName: $entryName is dangerous!") Timber.e("entryName: $entryName is dangerous!")
paths.add(entryName) paths.add(entryName)
} else { } else {
paths.add(entryName) paths.add(entryName)

@ -72,16 +72,6 @@ public class PackageDocumentReader extends PackageDocumentBase {
} }
} }
// private static Resource readCoverImage(Element metadataElement, Resources resources) {
// String coverResourceId = DOMUtil.getFindAttributeValue(metadataElement.getOwnerDocument(), NAMESPACE_OPF, OPFTags.meta, OPFAttributes.name, OPFValues.meta_cover, OPFAttributes.content);
// if (StringUtil.isBlank(coverResourceId)) {
// return null;
// }
// Resource coverResource = resources.getByIdOrHref(coverResourceId);
// return coverResource;
// }
/** /**
* Reads the manifest containing the resource ids, hrefs and mediatypes. * Reads the manifest containing the resource ids, hrefs and mediatypes.
* *
@ -316,8 +306,10 @@ public class PackageDocumentReader extends PackageDocumentBase {
* @param resources g * @param resources g
* @return the Resource containing the table of contents * @return the Resource containing the table of contents
*/ */
static Resource findTableOfContentsResource(String tocResourceId, static Resource findTableOfContentsResource(
Resources resources) { String tocResourceId,
Resources resources
) {
Resource tocResource; Resource tocResource;
//一些epub3的文件为了兼容epub2,保留的epub2的目录文件,这里优先选择epub3的xml目录 //一些epub3的文件为了兼容epub2,保留的epub2的目录文件,这里优先选择epub3的xml目录
tocResource = resources.getByProperties("nav"); tocResource = resources.getByProperties("nav");

@ -152,22 +152,16 @@ public class PackageDocumentWriter extends PackageDocumentBase {
return; return;
} }
if (StringUtil.isBlank(resource.getId())) { if (StringUtil.isBlank(resource.getId())) {
// log.error("resource id must not be empty (href: " + resource.getHref()
// + ", mediatype:" + resource.getMediaType() + ")");
Log.e(TAG, "resource id must not be empty (href: " + resource.getHref() Log.e(TAG, "resource id must not be empty (href: " + resource.getHref()
+ ", mediatype:" + resource.getMediaType() + ")"); + ", mediatype:" + resource.getMediaType() + ")");
return; return;
} }
if (StringUtil.isBlank(resource.getHref())) { if (StringUtil.isBlank(resource.getHref())) {
// log.error("resource href must not be empty (id: " + resource.getId()
// + ", mediatype:" + resource.getMediaType() + ")");
Log.e(TAG, "resource href must not be empty (id: " + resource.getId() Log.e(TAG, "resource href must not be empty (id: " + resource.getId()
+ ", mediatype:" + resource.getMediaType() + ")"); + ", mediatype:" + resource.getMediaType() + ")");
return; return;
} }
if (resource.getMediaType() == null) { if (resource.getMediaType() == null) {
// log.error("resource mediatype must not be empty (id: " + resource.getId()
// + ", href:" + resource.getHref() + ")");
Log.e(TAG, "resource mediatype must not be empty (id: " + resource.getId() Log.e(TAG, "resource mediatype must not be empty (id: " + resource.getId()
+ ", href:" + resource.getHref() + ")"); + ", href:" + resource.getHref() + ")");
return; return;

Loading…
Cancel
Save