This commit is contained in:
2024-12-24 18:12:54 +09:00
parent 2be0549b73
commit d00c97e7d7
8 changed files with 334 additions and 295 deletions
@@ -0,0 +1,250 @@
package bums.lunatic.launcher.home
import android.content.Context
import android.content.Intent
import android.os.Environment
import android.webkit.CookieManager
import androidx.core.content.FileProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kr.lunaticbum.awesomewebview.helpers.DownPicUtil
import kr.lunaticbum.awesomewebview.helpers.DownPicUtil.DownFinishListener
import kr.lunaticbum.utils.log.LogUtil
import org.jsoup.Jsoup
import org.jsoup.UnsupportedMimeTypeException
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
import java.net.URL
import java.text.SimpleDateFormat
import java.util.Date
val defaultTime = 200L
class OfflineContents(val context: Context, val host : String, val cookie: String, val agent: String, val current: String, val newPath: String, val value: String, val autoCheck : Boolean, val mediaUrls : ArrayList<String>) {
val targetFile : File
val filePath = "index.html"
val path = File(
Environment.getExternalStorageDirectory(),
"bums"
)
val newFolder = File(path, newPath).apply { mkdirs() }
val newFile : File
var htmlString : StringBuffer
val urlPathMap : HashMap<String,String> = hashMapOf()
var reqCount = 0
var endOfLooPCheck = false
val lDownFinishListener = object : DownFinishListener {
override fun onDownFinish(url: String, path: String) {
LogUtil.e("Url >> ${url} path >> ${path}")
urlPathMap.put(url, path)
reqCount -= 1
if (reqCount == 0 && endOfLooPCheck) {
enofLoop()
}
}
override fun onError() {
reqCount -= 1
if (reqCount == 0 && endOfLooPCheck) {
enofLoop()
}
}
}
init {
targetFile = File(newFolder, filePath)
newFile = File(
path,
newPath.plus(SimpleDateFormat("yyyMMdd").format(Date())).plus(".html")
)
htmlString= trimHtnl(value, host)
}
var onItEndof = false
fun enofLoop() {
if (onItEndof) return
onItEndof = true
LogUtil.e("on it enofLoop")
urlPathMap.forEach { t, u ->
val file = File(u)
var contentsUriString = FileProvider.getUriForFile(
context,
"${context.packageName}.fileprovider",
file
).toString()
var targetString = t
var targetIdx = htmlString.indexOf(targetString)
if (targetIdx > 0) {
htmlString?.replace(
targetIdx,
targetIdx.plus(targetString.length),
contentsUriString
)
}
targetString = t.replace("&", "&amp;")
targetIdx = htmlString.indexOf(targetString)
if (targetIdx > 0) {
htmlString?.replace(
targetIdx,
targetIdx.plus(targetString.length),
contentsUriString
)
}
}
if (autoCheck) {
LogUtil.e("on it enofLoop autoCheck ${autoCheck}")
moveFile()
context.startActivity(Intent(context,RssViewerActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = FileProvider.getUriForFile(
context,
"${context.packageName}.fileprovider",
newFile
)
})
} else {
moveFile()
}
}
fun moveFile() {
indexSave(htmlString, targetFile, host)
targetFile.copyTo(newFile)
if (targetFile.parentFile.isDirectory) {
targetFile.parentFile.listFiles().forEach {
it.delete()
}
targetFile.parentFile.delete()
}
targetFile.delete()
}
fun excute() {
CoroutineScope(Dispatchers.IO).launch {
LogUtil.e("onHtml value >> ${value}")
mediaUrls.forEach { url ->
var downPic = false
try {
LogUtil.e("try Jsoup.parse ${url}")
Jsoup.parse(URL(url), defaultTime.times(4).toInt()).let {
try {
LogUtil.e("onit Jsoup.parse ${it.title()}")
if (it.select("svg").size > 0) {
try {
downPic(url, agent, current!!, cookie!!, lDownFinishListener)
reqCount += 1
} catch (e : Exception) {
e.printStackTrace()
}
} else {
it.getElementsByTag("video")?.forEach {
it.attribute("src").value?.let {
var url = if (it.startsWith("http")) {
it
} else {
"https:".plus(it)
}
try {
downMp4(url, agent, current!!, cookie!!, lDownFinishListener)
reqCount += 1
} catch (e : Exception) {
e.printStackTrace()
}
}
}
}
} catch (e: UnsupportedMimeTypeException) {
LogUtil.e("e.message3 ${e.message}")
} catch (e: Exception) {
LogUtil.e("e.message4 ${e.message}")
}
}
} catch (e: UnsupportedMimeTypeException) {
LogUtil.e("e.message ${e.message}")
LogUtil.e("e.message ${e.localizedMessage}")
if (e.message?.contains("Must be text") == true) {
downPic = true
}
} catch (e: Exception) {
if (url.contains("dcimg") == true) {
downPic = true
}
LogUtil.e("e.message2 ${e.message}")
} finally {
if (downPic) {
try {
downPic(url, agent, current!!, cookie!!, lDownFinishListener)
reqCount += 1
} catch (e : Exception) {
e.printStackTrace()
}
}
}
delay(defaultTime)
}
LogUtil.e("END OF LOOP ${reqCount}")
endOfLooPCheck = true
delay(defaultTime.times(4))
if (reqCount <= 0) {
enofLoop()
}
}
}
fun indexSave(htmlString:StringBuffer, targetFile :File, host: String) {
BufferedWriter(FileWriter(targetFile)).use { writer ->
trimHtnl(htmlString.toString(), host)?.let { result ->
writer.write(result.toString())
}
}
}
fun trimHtnl(target : String, host : String) : StringBuffer {
var result = target.replace("\\\"","\"").replace("\\n\\t\\t\\t","").replace("\\n\\t\\t","").replace("\\n\\t","").replace("\\t", "").replace("\\n", "").replace("\"\"\"","").replace("href=\"//","href=\"https://").replace("src=\"//","src=\"https://").replace("url(\"//","url(\"https://").replace("url(&quot;//","url(&quot;https://")
if (host?.contains("clien") == true) {
result = result.replace("href=\"/service","href=\"https://m.clien.net/service").replace("href=\"\\&quot;/service","href=\"\\&quot;https://m.clien.net/service")
}
return StringBuffer(result)
}
fun downMp4(url : String, agent : String, current : String,cookie : String, listner :DownFinishListener) {
LogUtil.e("try imageFile down ${url}")
val path = File(
Environment.getExternalStorageDirectory(),
"bums"
)
DownPicUtil.downMp4(
File(
path,"private_mp4"
).path,
url,
agent,
current,
cookie,
listner
)
}
fun downPic( url : String, agent : String, current : String,cookie : String, listner :DownFinishListener) {
LogUtil.e("try imageFile down ${url}")
val cookieManager =
CookieManager.getInstance()
val cookie =
cookieManager.getCookie(current)
val path = File(
Environment.getExternalStorageDirectory(),
"bums"
)
DownPicUtil.downPic(
File(path, "private_img").path,
url,
agent,
current,
cookie,
listner)
}
}
@@ -33,6 +33,7 @@ import bums.lunatic.launcher.workers.WorkersDb
import io.realm.kotlin.ext.query
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kr.lunaticbum.awesomewebview.AwesomeWebView
import kr.lunaticbum.awesomewebview.AwesomeWebViewActivity
@@ -55,6 +56,8 @@ import java.net.URL
import java.security.MessageDigest
import java.text.SimpleDateFormat
import java.util.Date
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.text.Charsets.UTF_8
@@ -264,37 +267,25 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
}
fun rightClick() {
if (currentIdx < rssList.size - 1) {
currentIdx += 1
rssId = rssList.removeAt(currentIdx)
Blog.LOGE("Arrow Right Click ${currentIdx} ${rssId}")
load(rssId)
registCancelSearch()
} else {
Toast.makeText(this, "없어 끄자", Toast.LENGTH_LONG).show()
fast()
}
doNextPage()
}
fun leftClick() {
if (currentIdx > 0) {
currentIdx -= 1
rssId = rssList.removeAt(currentIdx)
Blog.LOGE("Arrow Left Click ${currentIdx} ${rssId}")
load(rssId)
registCancelSearch()
} else {
Toast.makeText(this, "없어 끄자", Toast.LENGTH_LONG).show()
fast()
}
Blog.LOGE("Arrow Left Click")
hideRss()
}
fun getUnit() = ((webView?.height ?: 0) * 0.4).toInt()
fun scrollDown() {
Blog.LOGE("Arrow Down Click")
registCancelSearch()
webView?.scrollTo(webView?.scrollX ?: 0, (webView?.scrollY ?: 0) + getUnit())
try {
Blog.LOGE("Arrow Down Click")
registCancelSearch()
runOnUiThread {
webView?.scrollTo(webView?.scrollX?: 0,(webView?.scrollY?: 0) + getUnit())
}
} catch (e : Exception) {
e.printStackTrace()
}
}
override var pdfListner : PDFPrint.OnPDFPrintListener? = object : PDFPrint.OnPDFPrintListener {
@@ -316,7 +307,7 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
}
}
// val tika: Tika = Tika()
// val tika: Tika = Tika()
override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
if (ev?.device?.name?.contains("BLE-M3") == true) {
Blog.LOGE("keyEvent >>>>> dispatchGenericMotionEvent ${ev}")
@@ -451,6 +442,9 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
return Base64.encodeToString(bytes, Base64.DEFAULT)
}
fun run(value : String, autoCheck : Boolean) {
webView!!.setOnScrollChangeListener(null)
var mediaUrls = arrayListOf<String>()
@@ -465,225 +459,34 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
val agent = webView!!.settings.userAgentString
val current = webView!!.url
val newPath = hashString(current!!, "MD5").toHex()
CoroutineScope(Dispatchers.IO).launch {
LogUtil.e("onHtml value >> ${value}")
val path = File(
Environment.getExternalStorageDirectory(),
"bums"
)
val filePath = "index.html"
val newFolder = File(path, newPath).apply { mkdirs() }
var htmlString = trimHtnl(value!!)
val targetFile = File(newFolder, filePath)
var reqCount = 0
var endOfLooPCheck = false
var urlPathMap = hashMapOf<String, String>()
var newFile = File(
path,
newPath.plus(SimpleDateFormat("yyyMMdd").format(Date())).plus(".html")
)
fun moveFile() {
indexSave(htmlString, targetFile)
targetFile.copyTo(newFile)
if (targetFile.parentFile.isDirectory) {
targetFile.parentFile.listFiles().forEach {
it.delete()
}
targetFile.parentFile.delete()
}
targetFile.delete()
}
fun enofLoop() {
CoroutineScope(Dispatchers.IO).launch {
LogUtil.e("on it enofLoop")
urlPathMap.forEach { t, u ->
val file = File(u)
var contentsUriString = FileProvider.getUriForFile(
this@RssViewerActivity,
"${this@RssViewerActivity.packageName}.fileprovider",
file
).toString()
// try {
// val detectedType: String = tika.detect(file)
// e("Detected type: $detectedType")
// } catch (e: IOException) {
// e("Error detecting type: " + e.message)
// }
var targetString = t
var targetIdx = htmlString.indexOf(targetString)
if (targetIdx > 0) {
htmlString?.replace(
targetIdx,
targetIdx.plus(targetString.length),
contentsUriString
)
}
targetString = t.replace("&", "&amp;")
targetIdx = htmlString.indexOf(targetString)
if (targetIdx > 0) {
htmlString?.replace(
targetIdx,
targetIdx.plus(targetString.length),
contentsUriString
)
}
}
if (autoCheck) {
LogUtil.e("on it enofLoop autoCheck ${autoCheck}")
webView?.postDelayed({
hideBlock()
webView?.setOnScrollChangeListener(null)
moveFile()
startActivity(Intent(this@RssViewerActivity,RssViewerActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = FileProvider.getUriForFile(
this@RssViewerActivity,
"${this@RssViewerActivity.packageName}.fileprovider",
newFile
)
})
}, defaultTime.times(4))
} else {
runOnUiThread {
moveFile()
Toast.makeText(
applicationContext,
resources.getString(
stringResPhotoSavedTo
) + targetFile.absolutePath,
Toast.LENGTH_LONG
).show()
hideBlock()
doNextPage()
LogUtil.e("on it enofLoop autoCheck ${autoCheck}")
}
}
}
}
val lDownFinishListener = object : DownFinishListener {
override fun onDownFinish(url: String, path: String) {
LogUtil.e("Url >> ${url} path >> ${path}")
urlPathMap.put(url, path)
reqCount -= 1
if (reqCount == 0 && endOfLooPCheck) {
enofLoop()
}
}
override fun onError() {
if (showToastPhotoSavedOrFailed) {
Toast.makeText(
applicationContext,
resources.getString(
stringResPhotoSaveFailed
),
Toast.LENGTH_LONG
).show()
}
reqCount -= 1
if (reqCount == 0 && endOfLooPCheck) {
enofLoop()
}
}
}
mediaUrls.forEach { url ->
var downPic = false
try {
LogUtil.e("try Jsoup.parse ${url}")
Jsoup.parse(URL(url), defaultTime.times(4).toInt()).let {
try {
LogUtil.e("onit Jsoup.parse ${it.title()}")
if (it.select("svg").size > 0) {
try {
downPic(url, agent, current!!, cookie!!, lDownFinishListener)
reqCount += 1
} catch (e : Exception) {
e.printStackTrace()
}
} else {
it.getElementsByTag("video")?.forEach {
it.attribute("src").value?.let {
var url = if (it.startsWith("http")) {
it
} else {
"https:".plus(it)
}
try {
downMp4(url, agent, current!!, cookie!!, lDownFinishListener)
reqCount += 1
} catch (e : Exception) {
e.printStackTrace()
}
}
}
}
} catch (e: UnsupportedMimeTypeException) {
LogUtil.e("e.message3 ${e.message}")
} catch (e: Exception) {
LogUtil.e("e.message4 ${e.message}")
}
}
} catch (e: UnsupportedMimeTypeException) {
LogUtil.e("e.message ${e.message}")
LogUtil.e("e.message ${e.localizedMessage}")
if (e.message?.contains("Must be text") == true) {
downPic = true
}
} catch (e: Exception) {
if (url.contains("dcimg") == true) {
downPic = true
}
LogUtil.e("e.message2 ${e.message}")
} finally {
if (downPic) {
try {
downPic(url, agent, current!!, cookie!!, lDownFinishListener)
reqCount += 1
} catch (e : Exception) {
e.printStackTrace()
}
}
}
sleep(defaultTime)
}
LogUtil.e("END OF LOOP ${reqCount}")
endOfLooPCheck = true
if (reqCount <= 0) {
webView?.postDelayed({
enofLoop()
},defaultTime.times(4))
Executors.newSingleThreadScheduledExecutor().schedule({
OfflineContents(this@RssViewerActivity, host!!,cookie,agent,current,newPath,value,autoCheck,mediaUrls).excute()
}, defaultTime, TimeUnit.MILLISECONDS)
runOnUiThread {
hideBlock()
if (!autoCheck) {
doNextPage()
}
}
}
val defaultTime = 200L
override fun onHtml(value: String?, autoCheck : Boolean) {
chechHandler.removeCallbacks(cancelSearch)
if (loadWithIntent){
return
}
showBlock()
var count = (webView!!.contentHeight / (webView!!.height * 0.3).toInt())
LogUtil.e("count >>>> ${count} webView!!.contentHeight >>>> ${webView!!.contentHeight} , webView!!.height >>>> ${webView!!.height} :: ${(webView!!.height * 0.3).toInt()}")
webView!!.postDelayed({
webView!!.pageDown(false)
},defaultTime)
chechHandler.postDelayed(pageDown, defaultTime)
webView!!.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
val measuredHeight: Int = v.measuredHeight
LogUtil.e("OnScrollChange >>> ${scrollY} , ${oldScrollY}")
if(measuredHeight + scrollY == webView!!.computeVerticalScrollRange()){
webView!!.postDelayed({
chechHandler.removeCallbacks(scrollDown)
chechHandler.removeCallbacks(pageDown)
chechHandler.postDelayed({
webView!!.evaluateJavascript("document.documentElement.outerHTML",object : ValueCallback<String> {
override fun onReceiveValue(value: String?) {
val html = value?.replace("\\u003C", "<")
@@ -692,66 +495,39 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
})
},defaultTime.times(2))
} else {
webView!!.postDelayed({
webView!!.pageDown(false)
},defaultTime)
chechHandler.removeCallbacks(cancelSearch)
Blog.LOGE("onScrollChanged called PageDown")
// chechHandler.removeCallbacks(scrollDown)
if (switch) {
chechHandler.removeCallbacks(pageDown)
chechHandler.postDelayed(scrollDown, defaultTime)
switch = false
} else {
switch = true
chechHandler.removeCallbacks(scrollDown)
chechHandler.postDelayed(pageDown, defaultTime)
}
}
// else if (scrollY % 10 == 0 || oldScrollY % 10 == 0){
//// chechHandler.removeCallbacks(pageDown)
//// chechHandler.postDelayed(scrollDown, defaultTime)
// }
}
}
var switch = false
var scrollDown : Runnable = Runnable{
webView?.let {
var times = if (it.scrollY > 50) it.scrollY / 50 else 5
it.scrollTo(it.scrollX,times.plus(1).times(50))
}
}
fun trimHtnl(target : String) : StringBuffer {
var result = target.replace("\\\"","\"").replace("\\n\\t\\t\\t","").replace("\\n\\t\\t","").replace("\\n\\t","").replace("\\t", "").replace("\\n", "").replace("\"\"\"","").replace("href=\"//","href=\"https://").replace("src=\"//","src=\"https://").replace("url(\"//","url(\"https://").replace("url(&quot;//","url(&quot;https://")
if (host?.contains("clien") == true) {
result = result.replace("href=\"/service","href=\"https://m.clien.net/service").replace("href=\"\\&quot;/service","href=\"\\&quot;https://m.clien.net/service")
}
return StringBuffer(result)
var pageDown : Runnable = Runnable{
webView!!.pageDown(false)
}
fun indexSave(htmlString:StringBuffer, targetFile :File) {
BufferedWriter(FileWriter(targetFile)).use { writer ->
trimHtnl(htmlString.toString())?.let { result ->
writer.write(result.toString())
}
}
}
fun downMp4(url : String, agent : String, current : String,cookie : String, listner :DownFinishListener) {
LogUtil.e("try imageFile down ${url}")
val path = File(
Environment.getExternalStorageDirectory(),
"bums"
)
DownPicUtil.downMp4(
File(
path,"private_mp4"
).path,
url,
agent,
current,
cookie,
listner
)
}
fun downPic( url : String, agent : String, current : String,cookie : String, listner :DownFinishListener) {
LogUtil.e("try imageFile down ${url}")
val cookieManager =
CookieManager.getInstance()
val cookie =
cookieManager.getCookie(current)
val path = File(
Environment.getExternalStorageDirectory(),
"bums"
)
DownPicUtil.downPic(
File(path, "private_img").path,
url,
agent,
current,
cookie,
listner)
}
override fun webviewOnPageFinished() {
double = false
if(hasYoutubePlayer) {