...
This commit is contained in:
parent
4d8b9b728b
commit
1169b159e8
@ -17,6 +17,7 @@ android {
|
|||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 38
|
versionCode = 38
|
||||||
versionName = "2.8.2"
|
versionName = "2.8.2"
|
||||||
|
multiDexEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@ -70,6 +71,9 @@ android {
|
|||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
packagingOptions.resources.excludes.add("META-INF/*")
|
||||||
|
packagingOptions.resources.excludes.add("mozilla/*")
|
||||||
|
packagingOptions.resources.excludes.add("META-INF/*/*")
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
@ -105,6 +109,8 @@ dependencies {
|
|||||||
implementation("com.github.delight-im:Android-AdvancedWebView:v3.2.1")
|
implementation("com.github.delight-im:Android-AdvancedWebView:v3.2.1")
|
||||||
implementation(project(":library"))
|
implementation(project(":library"))
|
||||||
implementation(project(":utils"))
|
implementation(project(":utils"))
|
||||||
|
// implementation ("org.apache.tika:tika-parsers:1.12")
|
||||||
|
|
||||||
implementation ("androidx.media:media:1.7.0")
|
implementation ("androidx.media:media:1.7.0")
|
||||||
// implementation ("me.everything:providers-android:1.0.1")
|
// implementation ("me.everything:providers-android:1.0.1")
|
||||||
// implementation ("me.everything:providers-core:1.0.1")
|
// implementation ("me.everything:providers-core:1.0.1")
|
||||||
|
|||||||
@ -72,7 +72,7 @@
|
|||||||
android:enableOnBackInvokedCallback="true"
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="false"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:screenOrientation="nosensor"
|
android:screenOrientation="nosensor"
|
||||||
android:windowSoftInputMode="adjustResize"
|
android:windowSoftInputMode="adjustResize"
|
||||||
@ -191,11 +191,22 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".home.RssViewerActivity"
|
android:name=".home.RssViewerActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="false"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
|
android:exported="true"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:theme="@style/FinestWebViewTheme.Fullscreen" >
|
android:theme="@style/FinestWebViewTheme.Fullscreen" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:scheme="file"/>
|
||||||
|
<data android:scheme="content"/>
|
||||||
|
<data android:mimeType="text/html"/>
|
||||||
|
<data android:mimeType="text/plain"/>
|
||||||
|
<data android:mimeType="text/xml"/>
|
||||||
|
<data android:mimeType="application/xhtml+xml"/>
|
||||||
|
<data android:mimeType="application/vnd.wap.xhtml+xml"/>
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
package bums.lunatic.launcher.home
|
package bums.lunatic.launcher.home
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.print.PDFPrint
|
import android.print.PDFPrint
|
||||||
|
import android.util.Base64
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.KeyEvent.ACTION_UP
|
import android.view.KeyEvent.ACTION_UP
|
||||||
import android.view.KeyEvent.KEYCODE_BUTTON_A
|
import android.view.KeyEvent.KEYCODE_BUTTON_A
|
||||||
@ -22,34 +22,41 @@ import android.view.MotionEvent
|
|||||||
import android.view.MotionEvent.ACTION_MOVE
|
import android.view.MotionEvent.ACTION_MOVE
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.webkit.CookieManager
|
import android.webkit.CookieManager
|
||||||
|
import android.webkit.CookieSyncManager
|
||||||
|
import android.webkit.ValueCallback
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.view.contains
|
|
||||||
import androidx.core.view.drawToBitmap
|
|
||||||
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
|
|
||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import bums.lunatic.launcher.workers.WorkersDb
|
import bums.lunatic.launcher.workers.WorkersDb
|
||||||
import io.realm.kotlin.UpdatePolicy
|
|
||||||
import io.realm.kotlin.ext.query
|
import io.realm.kotlin.ext.query
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kr.lunaticbum.awesomewebview.AwesomeWebView
|
import kr.lunaticbum.awesomewebview.AwesomeWebView
|
||||||
import kr.lunaticbum.awesomewebview.AwesomeWebView.Builder
|
|
||||||
import kr.lunaticbum.awesomewebview.AwesomeWebViewActivity
|
import kr.lunaticbum.awesomewebview.AwesomeWebViewActivity
|
||||||
import kr.lunaticbum.awesomewebview.helpers.DownPicUtil
|
import kr.lunaticbum.awesomewebview.helpers.DownPicUtil
|
||||||
import kr.lunaticbum.awesomewebview.helpers.DownPicUtil.DownFinishListener
|
import kr.lunaticbum.awesomewebview.helpers.DownPicUtil.DownFinishListener
|
||||||
import kr.lunaticbum.awesomewebview.listeners.BroadCastManager
|
import kr.lunaticbum.awesomewebview.listeners.BroadCastManager
|
||||||
import kr.lunaticbum.awesomewebview.objects.CustomMenu
|
|
||||||
import kr.lunaticbum.utils.content.ContextUtil
|
import kr.lunaticbum.utils.content.ContextUtil
|
||||||
import kr.lunaticbum.utils.log.LogUtil
|
import kr.lunaticbum.utils.log.LogUtil
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.UnsupportedMimeTypeException
|
import org.jsoup.UnsupportedMimeTypeException
|
||||||
import org.jsoup.nodes.Element
|
import java.io.BufferedWriter
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.Exception
|
import java.io.FileInputStream
|
||||||
|
import java.io.FileWriter
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.lang.Thread.sleep
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import kotlin.text.Charsets.UTF_8
|
||||||
|
|
||||||
|
|
||||||
class RssViewBuilder(context: Context) : AwesomeWebView.Builder(context) {
|
class RssViewBuilder(context: Context) : AwesomeWebView.Builder(context) {
|
||||||
var rssId : String = ""
|
var rssId : String = ""
|
||||||
@ -87,11 +94,34 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
|
|||||||
var double = false
|
var double = false
|
||||||
var rssList: MutableList<String> = ArrayList()
|
var rssList: MutableList<String> = ArrayList()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
LogUtil.e("intent >>>> ${intent}")
|
||||||
|
if (intent.action.equals(Intent.ACTION_VIEW)) {
|
||||||
|
intent.data.toString()?.let {
|
||||||
|
loadWithIntent = true
|
||||||
|
load(it)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loadWithIntent = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
webView?.setOnGenericMotionListener(this)
|
webView?.setOnGenericMotionListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent?) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
if (intent?.action?.equals(Intent.ACTION_VIEW) == true) {
|
||||||
|
intent?.data?.toString()?.let {
|
||||||
|
loadWithIntent = true
|
||||||
|
load(it)
|
||||||
|
}
|
||||||
|
} else {}
|
||||||
|
}
|
||||||
|
|
||||||
var lasteventTime = 0L
|
var lasteventTime = 0L
|
||||||
override fun onGenericMotion(p0: View?, ev: MotionEvent?): Boolean {
|
override fun onGenericMotion(p0: View?, ev: MotionEvent?): Boolean {
|
||||||
if (ev?.device?.name?.contains("SM-031N Mouse") == true) {
|
if (ev?.device?.name?.contains("SM-031N Mouse") == true) {
|
||||||
@ -172,15 +202,30 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun vote(){
|
fun vote(){
|
||||||
Blog.LOGE("Arrow Center Click")
|
if (!loadWithIntent) {
|
||||||
WorkersDb.getRealm().apply {
|
|
||||||
writeBlocking {
|
Blog.LOGE("Arrow Center Click")
|
||||||
val result = query<RssData>().query("originPage == $0", rssId).find()
|
WorkersDb.getRealm().apply {
|
||||||
if(result.size > 0) {
|
writeBlocking {
|
||||||
result.forEach { it.vote = true }
|
val result = query<RssData>().query("originPage == $0", rssId).find()
|
||||||
|
if (result.size > 0) {
|
||||||
|
result.forEach { it.vote = true }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
webView?.evaluateJavascript("document.documentElement.outerHTML",
|
||||||
|
object : ValueCallback<String> {
|
||||||
|
override fun onReceiveValue(value: String?) {
|
||||||
|
val html = value?.replace("\\u003C", "<")
|
||||||
|
onHtml(html, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doNextPage() {
|
||||||
rssList.remove(rssId)
|
rssList.remove(rssId)
|
||||||
if (currentIdx < rssList.size - 1) {
|
if (currentIdx < rssList.size - 1) {
|
||||||
currentIdx += 1
|
currentIdx += 1
|
||||||
@ -198,31 +243,21 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
|
|||||||
}
|
}
|
||||||
registCancelSearch()
|
registCancelSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideRss() {
|
fun hideRss() {
|
||||||
Blog.LOGE("make no show")
|
if (!loadWithIntent) {
|
||||||
WorkersDb.getRealm().apply {
|
Blog.LOGE("make no show")
|
||||||
writeBlocking {
|
WorkersDb.getRealm().apply {
|
||||||
val result =
|
writeBlocking {
|
||||||
query<RssData>().query("originPage == $0", rssId)
|
val result =
|
||||||
.find()
|
query<RssData>().query("originPage == $0", rssId)
|
||||||
if (result.size > 0) {
|
.find()
|
||||||
result.forEach { it.read += 5 }
|
if (result.size > 0) {
|
||||||
|
result.forEach { it.read += 5 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
doNextPage()
|
||||||
rssList.remove(rssId)
|
|
||||||
if (currentIdx < rssList.size - 1) {
|
|
||||||
currentIdx += 1
|
|
||||||
rssId = rssList.get(currentIdx)
|
|
||||||
Blog.LOGE("Arrow Right Click ${currentIdx} ${rssId}")
|
|
||||||
load(rssId)
|
|
||||||
registCancelSearch()
|
|
||||||
} else if (currentIdx > 0) {
|
|
||||||
currentIdx -= 1
|
|
||||||
rssId = rssList.get(currentIdx)
|
|
||||||
Blog.LOGE("Arrow Left Click ${currentIdx} ${rssId}")
|
|
||||||
load(rssId)
|
|
||||||
registCancelSearch()
|
|
||||||
} else {
|
} else {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
@ -265,13 +300,23 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
|
|||||||
override var pdfListner : PDFPrint.OnPDFPrintListener? = object : PDFPrint.OnPDFPrintListener {
|
override var pdfListner : PDFPrint.OnPDFPrintListener? = object : PDFPrint.OnPDFPrintListener {
|
||||||
override fun onSuccess(file: File?) {
|
override fun onSuccess(file: File?) {
|
||||||
LogUtil.e("file.absolutePath >>> ${file?.absolutePath}")
|
LogUtil.e("file.absolutePath >>> ${file?.absolutePath}")
|
||||||
|
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
resources.getString(
|
||||||
|
stringResPhotoSavedTo
|
||||||
|
) + file?.absolutePath,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).apply {
|
||||||
|
|
||||||
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(exception: Exception?) {
|
override fun onError(exception: Exception?) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// val tika: Tika = Tika()
|
||||||
override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
|
override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
|
||||||
if (ev?.device?.name?.contains("BLE-M3") == true) {
|
if (ev?.device?.name?.contains("BLE-M3") == true) {
|
||||||
Blog.LOGE("keyEvent >>>>> dispatchGenericMotionEvent ${ev}")
|
Blog.LOGE("keyEvent >>>>> dispatchGenericMotionEvent ${ev}")
|
||||||
@ -344,6 +389,7 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
|
|||||||
registCancelSearch()
|
registCancelSearch()
|
||||||
}
|
}
|
||||||
protected fun load(newUrl: String) {
|
protected fun load(newUrl: String) {
|
||||||
|
LogUtil.e("newUrl >>> ${newUrl}")
|
||||||
newUrl.toUri().host?.let {
|
newUrl.toUri().host?.let {
|
||||||
val splits = it.replace("http://","").replace("https://","").split(".")
|
val splits = it.replace("http://","").replace("https://","").split(".")
|
||||||
when(splits.size) {
|
when(splits.size) {
|
||||||
@ -380,81 +426,332 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onHtml(value: String?) {
|
fun ByteArray.toHex() = joinToString(separator = "") { byte -> "%02x".format(byte) }
|
||||||
|
|
||||||
|
fun hashString(str: String, algorithm: String): ByteArray =
|
||||||
|
MessageDigest.getInstance(algorithm).digest(str.toByteArray(UTF_8))
|
||||||
|
|
||||||
|
fun getBase64ImageData(fileName : String) : String {
|
||||||
|
val inputStream: InputStream =
|
||||||
|
FileInputStream(fileName) // You can get an inputStream using any I/O API
|
||||||
|
val bytes: ByteArray
|
||||||
|
val buffer = ByteArray(8192)
|
||||||
|
var bytesRead: Int
|
||||||
|
val output = ByteArrayOutputStream()
|
||||||
|
|
||||||
|
try {
|
||||||
|
while ((inputStream.read(buffer).also { bytesRead = it }) != -1) {
|
||||||
|
output.write(buffer, 0, bytesRead)
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = output.toByteArray()
|
||||||
|
return Base64.encodeToString(bytes, Base64.DEFAULT)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun run(value : String, autoCheck : Boolean) {
|
||||||
|
webView!!.setOnScrollChangeListener(null)
|
||||||
|
var mediaUrls = arrayListOf<String>()
|
||||||
|
mediaUrls.addAll(this.mediaUrls)
|
||||||
|
CookieSyncManager.createInstance(applicationContext)
|
||||||
|
CookieSyncManager.getInstance().sync()
|
||||||
|
val cookieManager =
|
||||||
|
CookieManager.getInstance()
|
||||||
|
val cookie =
|
||||||
|
cookieManager.getCookie(webView!!.url)
|
||||||
|
|
||||||
val agent = webView!!.settings.userAgentString
|
val agent = webView!!.settings.userAgentString
|
||||||
val current = webView!!.url
|
val current = webView!!.url
|
||||||
|
val newPath = hashString(current!!, "MD5").toHex()
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
mediaUrls.forEach {
|
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("&", "&")
|
||||||
|
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 {
|
try {
|
||||||
LogUtil.e("try Jsoup.parse ${it}")
|
LogUtil.e("try Jsoup.parse ${url}")
|
||||||
Jsoup.parse(URL(it), 3000)?.let {
|
Jsoup.parse(URL(url), defaultTime.times(4).toInt()).let {
|
||||||
try {
|
try {
|
||||||
LogUtil.e("onit Jsoup.parse ${it.title()}")
|
LogUtil.e("onit Jsoup.parse ${it.title()}")
|
||||||
it.getElementsByTag("video")?.forEach {
|
if (it.select("svg").size > 0) {
|
||||||
it.attribute("src").value?.let {
|
try {
|
||||||
var url = if (it.startsWith("http")) {
|
downPic(url, agent, current!!, cookie!!, lDownFinishListener)
|
||||||
it
|
reqCount += 1
|
||||||
} else {
|
} catch (e : Exception) {
|
||||||
"https:".plus(it)
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val cookieManager =
|
|
||||||
CookieManager.getInstance()
|
|
||||||
val cookie =
|
|
||||||
cookieManager.getCookie(current)
|
|
||||||
DownPicUtil.downMp4(
|
|
||||||
File(
|
|
||||||
Environment.getExternalStorageDirectory(),
|
|
||||||
"bums"
|
|
||||||
).path,
|
|
||||||
url,
|
|
||||||
agent,
|
|
||||||
current,
|
|
||||||
cookie,
|
|
||||||
object : DownFinishListener {
|
|
||||||
override fun onDownFinish(path: String) {
|
|
||||||
if (showToastPhotoSavedOrFailed) {
|
|
||||||
Toast.makeText(
|
|
||||||
applicationContext,
|
|
||||||
resources.getString(
|
|
||||||
stringResPhotoSavedTo
|
|
||||||
) + path,
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
// 最后通知图库更新
|
|
||||||
applicationContext.sendBroadcast(
|
|
||||||
Intent(
|
|
||||||
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
|
|
||||||
Uri.parse("file://$path")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError() {
|
|
||||||
if (showToastPhotoSavedOrFailed) {
|
|
||||||
Toast.makeText(
|
|
||||||
applicationContext,
|
|
||||||
resources.getString(
|
|
||||||
stringResPhotoSaveFailed
|
|
||||||
),
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e : UnsupportedMimeTypeException) {
|
} catch (e: UnsupportedMimeTypeException) {
|
||||||
|
LogUtil.e("e.message3 ${e.message}")
|
||||||
} catch (e : Exception){}
|
} catch (e: Exception) {
|
||||||
|
LogUtil.e("e.message4 ${e.message}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e : UnsupportedMimeTypeException) {
|
} 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()
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e : Exception){}
|
}
|
||||||
|
}
|
||||||
|
sleep(defaultTime)
|
||||||
|
}
|
||||||
|
LogUtil.e("END OF LOOP ${reqCount}")
|
||||||
|
endOfLooPCheck = true
|
||||||
|
if (reqCount <= 0) {
|
||||||
|
webView?.postDelayed({
|
||||||
|
enofLoop()
|
||||||
|
},defaultTime.times(4))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
webView!!.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
|
||||||
|
val measuredHeight: Int = v.measuredHeight
|
||||||
|
if(measuredHeight + scrollY == webView!!.computeVerticalScrollRange()){
|
||||||
|
webView!!.postDelayed({
|
||||||
|
webView!!.evaluateJavascript("document.documentElement.outerHTML",object : ValueCallback<String> {
|
||||||
|
override fun onReceiveValue(value: String?) {
|
||||||
|
val html = value?.replace("\\u003C", "<")
|
||||||
|
this@RssViewerActivity.run(html!!, autoCheck)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},defaultTime.times(2))
|
||||||
|
} else {
|
||||||
|
webView!!.postDelayed({
|
||||||
|
webView!!.pageDown(false)
|
||||||
|
},defaultTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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("//","url("https://")
|
||||||
|
if (host?.contains("clien") == true) {
|
||||||
|
result = result.replace("href=\"/service","href=\"https://m.clien.net/service").replace("href=\"\\"/service","href=\"\\"https://m.clien.net/service")
|
||||||
|
}
|
||||||
|
return StringBuffer(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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() {
|
override fun webviewOnPageFinished() {
|
||||||
double = false
|
double = false
|
||||||
if(hasYoutubePlayer) {
|
if(hasYoutubePlayer) {
|
||||||
@ -473,14 +770,35 @@ class RssViewerActivity : AwesomeWebViewActivity(), View.OnGenericMotionListene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
registCancelSearch()
|
registCancelSearch()
|
||||||
|
//<meta name="viewport" content="initial-scale=1.0">
|
||||||
|
if (loadWithIntent) {
|
||||||
|
webView?.evaluateJavascript(
|
||||||
|
"try{document.querySelector('meta[name=viewport]').setAttribute('content','initial-scale=1.0')}catch(e){}",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
webView?.evaluateJavascript(
|
||||||
|
"try{document.querySelector('meta[name=viewport]').setAttribute('content','initial-scale=1.0')}catch(e){}",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
webView?.settings?.useWideViewPort = true
|
||||||
|
}
|
||||||
if (webView?.url?.contains("dcinside") == true){
|
if (webView?.url?.contains("dcinside") == true){
|
||||||
webView?.evaluateJavascript("try{document.querySelector('#div_adnmore_area').hidden = true;}catch(e){}",null)
|
webView?.evaluateJavascript("try{document.querySelector('#div_adnmore_area').hidden = true;}catch(e){}",null)
|
||||||
} else if(webView?.url?.contains("fmkorea") == true) {
|
} else if(webView?.url?.contains("fmkorea") == true) {
|
||||||
webView?.postDelayed({
|
if (loadWithIntent) {
|
||||||
webView?.evaluateJavascript("try{document.querySelector('.m_rd_nav_side').hidden = true;}catch(e){}",null)
|
|
||||||
webView?.evaluateJavascript("try{document.querySelector(\"[class*='bd bd_mobile ']\").remove();}catch(e){}",null)
|
} else {
|
||||||
},500L)
|
webView?.postDelayed({
|
||||||
|
webView?.evaluateJavascript(
|
||||||
|
"try{document.querySelector('.m_rd_nav_side').hidden = true;}catch(e){}",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
webView?.evaluateJavascript(
|
||||||
|
"try{document.querySelector('[class*='bd bd_mobile ']').remove();}catch(e){}",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}, 500L)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,6 +41,7 @@ dependencies {
|
|||||||
implementation ("androidx.annotation:annotation:1.9.1")
|
implementation ("androidx.annotation:annotation:1.9.1")
|
||||||
implementation ("androidx.appcompat:appcompat:1.7.0")
|
implementation ("androidx.appcompat:appcompat:1.7.0")
|
||||||
implementation ("com.google.android.material:material:1.12.0")
|
implementation ("com.google.android.material:material:1.12.0")
|
||||||
|
// implementation ("org.apache.tika:tika-parsers:1.24")
|
||||||
// implementation ("com.nineoldandroids:library:2.4.0")
|
// implementation ("com.nineoldandroids:library:2.4.0")
|
||||||
implementation ("androidx.core:core-ktx:1.15.0")
|
implementation ("androidx.core:core-ktx:1.15.0")
|
||||||
implementation(project(":utils"))
|
implementation(project(":utils"))
|
||||||
|
|||||||
@ -99,6 +99,7 @@ import kotlin.math.abs
|
|||||||
|
|
||||||
open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
||||||
Handler.Callback {
|
Handler.Callback {
|
||||||
|
var loadWithIntent : Boolean = false
|
||||||
var mediaUrls = arrayListOf<String>()
|
var mediaUrls = arrayListOf<String>()
|
||||||
protected var key: Int = 0
|
protected var key: Int = 0
|
||||||
|
|
||||||
@ -258,7 +259,7 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
// protected var back: AppCompatImageButton? = null
|
// protected var back: AppCompatImageButton? = null
|
||||||
// protected var forward: AppCompatImageButton? = null
|
// protected var forward: AppCompatImageButton? = null
|
||||||
// protected var more: AppCompatImageButton? = null
|
// protected var more: AppCompatImageButton? = null
|
||||||
protected var webView: WebView? = null
|
protected var webView: VideoEnabledWebView? = null
|
||||||
protected var webChromeClient: WebChromeClient? = null
|
protected var webChromeClient: WebChromeClient? = null
|
||||||
protected var webViewClient: WebViewClient? = null
|
protected var webViewClient: WebViewClient? = null
|
||||||
// protected var gradient: View? = null
|
// protected var gradient: View? = null
|
||||||
@ -577,7 +578,7 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
|
|
||||||
fun fast() {
|
fun fast() {
|
||||||
chechHandler.removeCallbacks(cancelSearch)
|
chechHandler.removeCallbacks(cancelSearch)
|
||||||
chechHandler.postDelayed(cancelSearch, 6000L)
|
chechHandler.postDelayed(cancelSearch, 90000L)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registCancelSearch() {
|
fun registCancelSearch() {
|
||||||
@ -799,12 +800,14 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
|
|
||||||
LogUtil.e("hitTestResult.type >>> ${hitTestResult.type}")
|
LogUtil.e("hitTestResult.type >>> ${hitTestResult.type}")
|
||||||
LogUtil.e("hitTestResult.extra >>> ${hitTestResult.extra}")
|
LogUtil.e("hitTestResult.extra >>> ${hitTestResult.extra}")
|
||||||
|
LogUtil.e("hitTestResult >>> ${mediaUrls.size}")
|
||||||
if(hitTestResult.type==0) {
|
if(hitTestResult.type==0) {
|
||||||
webView?.evaluateJavascript("document.getElementsByTagName('iframe')",
|
|
||||||
|
webView?.evaluateJavascript("document.documentElement.outerHTML",
|
||||||
object : ValueCallback<String> {
|
object : ValueCallback<String> {
|
||||||
override fun onReceiveValue(value: String?) {
|
override fun onReceiveValue(value: String?) {
|
||||||
val html = value?.replace("\\u003C", "<")
|
val html = value?.replace("\\u003C", "<")
|
||||||
onHtml(html)
|
onHtml(html, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -839,7 +842,7 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
webView!!.url,
|
webView!!.url,
|
||||||
cookie,
|
cookie,
|
||||||
object : DownFinishListener {
|
object : DownFinishListener {
|
||||||
override fun onDownFinish(path: String) {
|
override fun onDownFinish(url : String ,path: String) {
|
||||||
if (showToastPhotoSavedOrFailed) {
|
if (showToastPhotoSavedOrFailed) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
@ -1243,11 +1246,19 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open protected fun onHtml(value: String?) {
|
open protected fun onHtml(value: String?, autoCheck : Boolean) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun buildWebView(): WebView {
|
protected fun showBlock() {
|
||||||
|
binding.blocking.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun hideBlock() {
|
||||||
|
binding.blocking.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun buildWebView(): VideoEnabledWebView {
|
||||||
return VideoEnabledWebView(this)
|
return VideoEnabledWebView(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1874,10 +1885,10 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
view: WebView,
|
view: WebView,
|
||||||
request: WebResourceRequest
|
request: WebResourceRequest
|
||||||
): WebResourceResponse? {
|
): WebResourceResponse? {
|
||||||
|
|
||||||
var skipResource =
|
var skipResource =
|
||||||
(host != null) && ((request.url?.host?.contains(host!!) ?: true) == false)
|
(host != null) && ((request.url?.host?.contains(host!!) ?: true) == false)
|
||||||
if (skipResource && request.url.toString().contains("gif")) {
|
if (skipResource && request.url.toString().contains("gif")) {
|
||||||
LogUtil.e("shouldInterceptRequest request block gif resource >>> ${request.url.toString()}")
|
|
||||||
return WebResourceResponse(
|
return WebResourceResponse(
|
||||||
"text/plain", "utf-8",
|
"text/plain", "utf-8",
|
||||||
ByteArrayInputStream("".toByteArray())
|
ByteArrayInputStream("".toByteArray())
|
||||||
@ -1885,13 +1896,27 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val url = request.url.toString()
|
val url = request.url.toString()
|
||||||
|
if (url.contains("streamable.com") ||
|
||||||
|
url.contains("img-cdn.theqoo") ||
|
||||||
|
url.contains("embed/player/") ||
|
||||||
|
url.contains("dcinside.co.kr/viewimage") ||
|
||||||
|
url.contains("daumcdn.net/cafeattach") ||
|
||||||
|
url.toLowerCase(Locale.ROOT).contains(".jpg") ||
|
||||||
|
url.toLowerCase(Locale.ROOT).contains(".png") ||
|
||||||
|
url.toLowerCase(Locale.ROOT).contains(".gif") ||
|
||||||
|
url.toLowerCase(Locale.ROOT).contains(".svg") ||
|
||||||
|
url.toLowerCase(Locale.ROOT).contains(".webp")) {
|
||||||
|
mediaUrls.add(url)
|
||||||
|
LogUtil.e("mediaUrls >>>>> add(${url})")
|
||||||
|
}
|
||||||
|
|
||||||
if(!hasYoutubePlayer) {
|
if(!hasYoutubePlayer) {
|
||||||
hasYoutubePlayer = url.toLowerCase(Locale.ROOT)
|
hasYoutubePlayer = url.toLowerCase(Locale.ROOT)
|
||||||
.contains("https://www.youtube.com/s/player".toLowerCase(Locale.ROOT))
|
.contains("https://www.youtube.com/s/player".toLowerCase(Locale.ROOT))
|
||||||
}
|
}
|
||||||
if (url.contains("streamable.com")) {
|
|
||||||
mediaUrls.add(url)
|
//https://t1.daumcdn.net/cafeattach/mEr9/adc6e81a386099c4cc06f77f8b7eea15675de0d4
|
||||||
}
|
|
||||||
if (url.toLowerCase(Locale.ROOT)
|
if (url.toLowerCase(Locale.ROOT)
|
||||||
.contains("ads".toLowerCase(Locale.ROOT))) {
|
.contains("ads".toLowerCase(Locale.ROOT))) {
|
||||||
LogUtil.e("shouldInterceptRequest request url contains ads >>> ${request.url.toString()}")
|
LogUtil.e("shouldInterceptRequest request url contains ads >>> ${request.url.toString()}")
|
||||||
@ -1900,7 +1925,7 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
val adblock = adblockKeyWords.filter { url.toLowerCase(Locale.ROOT).contains(it.toLowerCase(Locale.ROOT)) }.size > 0
|
val adblock = adblockKeyWords.filter { url.toLowerCase(Locale.ROOT).contains(it.toLowerCase(Locale.ROOT)) }.size > 0
|
||||||
return if(adblock) {
|
return if(adblock) {
|
||||||
try {
|
try {
|
||||||
LogUtil.e("shouldInterceptRequest request block adblockKeyWords resource >>> ${request.url.toString()}")
|
// LogUtil.e("shouldInterceptRequest request block adblockKeyWords resource >>> ${request.url.toString()}")
|
||||||
WebResourceResponse("text/plain", "utf-8", ByteArrayInputStream("".toByteArray()))
|
WebResourceResponse("text/plain", "utf-8", ByteArrayInputStream("".toByteArray()))
|
||||||
} catch (e : Exception) {
|
} catch (e : Exception) {
|
||||||
super.shouldInterceptRequest(view, url)
|
super.shouldInterceptRequest(view, url)
|
||||||
@ -1909,7 +1934,7 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
try {
|
try {
|
||||||
val bitmap = Glide.with(this@AwesomeWebViewActivity).asBitmap().timeout(30000).diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get()
|
val bitmap = Glide.with(this@AwesomeWebViewActivity).asBitmap().timeout(30000).diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get()
|
||||||
WebResourceResponse("image/jpg", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.JPEG)).apply {
|
WebResourceResponse("image/jpg", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.JPEG)).apply {
|
||||||
LogUtil.e("shouldInterceptRequest request url down from Glide >>> ${request.url.toString()}")
|
// LogUtil.e("shouldInterceptRequest request url down from Glide >>> ${request.url.toString()}")
|
||||||
}
|
}
|
||||||
} catch (e : Exception) {
|
} catch (e : Exception) {
|
||||||
super.shouldInterceptRequest(view, url)
|
super.shouldInterceptRequest(view, url)
|
||||||
@ -1918,7 +1943,7 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
try {
|
try {
|
||||||
val bitmap = Glide.with(this@AwesomeWebViewActivity).asBitmap().timeout(30000).diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get()
|
val bitmap = Glide.with(this@AwesomeWebViewActivity).asBitmap().timeout(30000).diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get()
|
||||||
WebResourceResponse("image/png", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.PNG)).apply {
|
WebResourceResponse("image/png", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.PNG)).apply {
|
||||||
LogUtil.e("shouldInterceptRequest request url down from Glide >>> ${request.url.toString()}")
|
// LogUtil.e("shouldInterceptRequest request url down from Glide >>> ${request.url.toString()}")
|
||||||
}
|
}
|
||||||
} catch (e : Exception) {
|
} catch (e : Exception) {
|
||||||
super.shouldInterceptRequest(view, url)
|
super.shouldInterceptRequest(view, url)
|
||||||
@ -1950,6 +1975,7 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
|
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
|
||||||
|
mediaUrls.clear()
|
||||||
BroadCastManager.onPageStarted(this@AwesomeWebViewActivity, key, url)
|
BroadCastManager.onPageStarted(this@AwesomeWebViewActivity, key, url)
|
||||||
if (!url.contains("docs.google.com") && url.endsWith(".pdf")) {
|
if (!url.contains("docs.google.com") && url.endsWith(".pdf")) {
|
||||||
webView!!.loadUrl("http://docs.google.com/gview?embedded=true&url=$url")
|
webView!!.loadUrl("http://docs.google.com/gview?embedded=true&url=$url")
|
||||||
@ -1973,7 +1999,9 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
BroadCastManager.onPageFinished(this@AwesomeWebViewActivity, key, url)
|
BroadCastManager.onPageFinished(this@AwesomeWebViewActivity, key, url)
|
||||||
|
|
||||||
if (updateTitleFromHtml) binding.toolbarContent.title.text = view.title
|
if (updateTitleFromHtml) binding.toolbarContent.title.text = view.title
|
||||||
binding.toolbarContent.url.text = UrlParser.getHost(url)
|
try {
|
||||||
|
binding.toolbarContent.url.text = UrlParser.getHost(url)
|
||||||
|
}catch (e :Exception) {e.printStackTrace()}
|
||||||
requestCenterLayout()
|
requestCenterLayout()
|
||||||
|
|
||||||
if (view.canGoBack() || view.canGoForward()) {
|
if (view.canGoBack() || view.canGoForward()) {
|
||||||
@ -2006,7 +2034,7 @@ open class AwesomeWebViewActivity : AppCompatActivity(), View.OnClickListener,
|
|||||||
handler.sendEmptyMessage(MSG_CLICK_ON_URL)
|
handler.sendEmptyMessage(MSG_CLICK_ON_URL)
|
||||||
|
|
||||||
var skipResource = host!= null && ((url.contains(host!!) ?: true) == false) && (host!!.contains("google") == false)
|
var skipResource = host!= null && ((url.contains(host!!) ?: true) == false) && (host!!.contains("google") == false)
|
||||||
if (skipResource) {
|
if (skipResource || loadWithIntent) {
|
||||||
LogUtil.e("shouldOverrideUrlLoading block url $url , host >>>> $host ")
|
LogUtil.e("shouldOverrideUrlLoading block url $url , host >>>> $host ")
|
||||||
val alertDialog = AlertDialog.Builder(view.context).create()
|
val alertDialog = AlertDialog.Builder(view.context).create()
|
||||||
alertDialog.setCancelable(false)
|
alertDialog.setCancelable(false)
|
||||||
|
|||||||
@ -4,9 +4,14 @@ package kr.lunaticbum.awesomewebview.helpers;
|
|||||||
* Created by wuzongheng on 2018/2/18.
|
* Created by wuzongheng on 2018/2/18.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import static java.sql.DriverManager.println;
|
||||||
|
|
||||||
|
import android.media.MediaMetadataRetriever;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
@ -19,6 +24,11 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
import kr.lunaticbum.utils.log.LogUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图片下载的工具类
|
* 图片下载的工具类
|
||||||
@ -46,6 +56,10 @@ public class DownPicUtil {
|
|||||||
}
|
}
|
||||||
loadPic(file.getPath(), url, userAgent, referer, cookie, downFinishListener, false);
|
loadPic(file.getPath(), url, userAgent, referer, cookie, downFinishListener, false);
|
||||||
} else {
|
} else {
|
||||||
|
File file = new File(path);
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.mkdirs();
|
||||||
|
}
|
||||||
loadPic(path, url, userAgent, referer, cookie, downFinishListener, false);
|
loadPic(path, url, userAgent, referer, cookie, downFinishListener, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,24 +73,53 @@ public class DownPicUtil {
|
|||||||
}
|
}
|
||||||
loadPic(file.getPath(), url, userAgent, referer, cookie, downFinishListener, true);
|
loadPic(file.getPath(), url, userAgent, referer, cookie, downFinishListener, true);
|
||||||
} else {
|
} else {
|
||||||
|
File file = new File(path);
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.mkdirs();
|
||||||
|
}
|
||||||
loadPic(path, url, userAgent, referer, cookie, downFinishListener, true);
|
loadPic(path, url, userAgent, referer, cookie, downFinishListener, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static String toHex(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] hashString(String str, String algorithm) {
|
||||||
|
try {
|
||||||
|
MessageDigest digest = MessageDigest.getInstance(algorithm);
|
||||||
|
return digest.digest(str.getBytes(StandardCharsets.UTF_8));
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static void loadPic(final String filePath, final String url, final String userAgent, final String referer, final String cookie, final DownFinishListener downFinishListener, boolean isMp4) {
|
private static void loadPic(final String filePath, final String url, final String userAgent, final String referer, final String cookie, final DownFinishListener downFinishListener, boolean isMp4) {
|
||||||
new AsyncTask<Void,Void,String>(){
|
new AsyncTask<Void,Void,String>(){
|
||||||
String fileName;
|
String fileName;
|
||||||
InputStream is;
|
InputStream is;
|
||||||
OutputStream out;
|
OutputStream out;
|
||||||
|
private String replaceDcUrl(String origin) {
|
||||||
|
String result = origin;
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
result = result.replace(String.format("dcimg%d.",i),"dcimg2.");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
protected String doInBackground(Void... voids) {
|
protected String doInBackground(Void... voids) {
|
||||||
|
|
||||||
// 原文件名
|
// 原文件名
|
||||||
String[] split = url.split("/");
|
String[] split = url.split("/");
|
||||||
fileName = split[split.length - 1];
|
byte[] dd = hashString(url, "MD5");
|
||||||
|
fileName = dd == null ? split[split.length - 1] : toHex(dd);
|
||||||
|
|
||||||
// 创建目标文件,使用时间戳作为临时文件名,确保可以不重复
|
// 创建目标文件,使用时间戳作为临时文件名,确保可以不重复
|
||||||
String now = String.valueOf(System.currentTimeMillis());
|
String now = String.valueOf(System.currentTimeMillis());
|
||||||
@ -90,7 +133,13 @@ public class DownPicUtil {
|
|||||||
byte[] image = base64ImgHelper.decode();
|
byte[] image = base64ImgHelper.decode();
|
||||||
is = new ByteArrayInputStream(image); //处理服务器的响应结果
|
is = new ByteArrayInputStream(image); //处理服务器的响应结果
|
||||||
} else {
|
} else {
|
||||||
URL picUrl = new URL(url);
|
URL picUrl = null;
|
||||||
|
if (url.contains("dcimg")) {
|
||||||
|
picUrl = new URL(replaceDcUrl(url));
|
||||||
|
} else {
|
||||||
|
picUrl = new URL(url);
|
||||||
|
}
|
||||||
|
|
||||||
//通过图片的链接打开输入流
|
//通过图片的链接打开输入流
|
||||||
HttpURLConnection httpURLConnection = (HttpURLConnection) picUrl.openConnection();
|
HttpURLConnection httpURLConnection = (HttpURLConnection) picUrl.openConnection();
|
||||||
httpURLConnection.setConnectTimeout(10000); //设置连接超时时间
|
httpURLConnection.setConnectTimeout(10000); //设置连接超时时间
|
||||||
@ -99,13 +148,26 @@ public class DownPicUtil {
|
|||||||
httpURLConnection.setDoOutput(false); //Get请求不需要DoOutPut
|
httpURLConnection.setDoOutput(false); //Get请求不需要DoOutPut
|
||||||
httpURLConnection.setRequestMethod("GET"); //设置以Get方式请求数据
|
httpURLConnection.setRequestMethod("GET"); //设置以Get方式请求数据
|
||||||
httpURLConnection.setUseCaches(false); //不使用缓存
|
httpURLConnection.setUseCaches(false); //不使用缓存
|
||||||
|
|
||||||
//设置请求体的类型是文本类型
|
//设置请求体的类型是文本类型
|
||||||
|
|
||||||
|
// if (url.contains("dcimg")) {
|
||||||
|
//// httpURLConnection.setRequestProperty("authority", Uri.parse(url).getHost());
|
||||||
|
// httpURLConnection.setRequestProperty("Accept", "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8");
|
||||||
|
// httpURLConnection.setRequestProperty("Accept-encoding", "gzip, deflate, br, zstd");
|
||||||
|
// httpURLConnection.setRequestProperty("Sec-Fetch-Dest","image");
|
||||||
|
// httpURLConnection.setRequestProperty("Sec-Fetch-Mode","no-cors");
|
||||||
|
// httpURLConnection.setRequestProperty("Sec-Fetch-Site","cross-site");
|
||||||
|
// }
|
||||||
|
|
||||||
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(userAgent)) {
|
if (!TextUtils.isEmpty(userAgent)) {
|
||||||
httpURLConnection.setRequestProperty("User-Agent", userAgent);
|
httpURLConnection.setRequestProperty("User-Agent", userAgent);
|
||||||
}
|
}
|
||||||
if (!TextUtils.isEmpty(referer)) {
|
if (!TextUtils.isEmpty(referer)) {
|
||||||
httpURLConnection.setRequestProperty("Referer", referer);
|
httpURLConnection.setRequestProperty("Referer", referer);
|
||||||
|
println("referer>>>> " + referer);
|
||||||
}
|
}
|
||||||
if (!TextUtils.isEmpty(cookie)) {
|
if (!TextUtils.isEmpty(cookie)) {
|
||||||
httpURLConnection.setRequestProperty("Cookie", cookie);
|
httpURLConnection.setRequestProperty("Cookie", cookie);
|
||||||
@ -148,9 +210,7 @@ public class DownPicUtil {
|
|||||||
|
|
||||||
// 提取文件格式真实拓展名
|
// 提取文件格式真实拓展名
|
||||||
String extension = FormatHelper.getExtension(picFile);
|
String extension = FormatHelper.getExtension(picFile);
|
||||||
if (isMp4) {
|
|
||||||
extension = "mp4";
|
|
||||||
}
|
|
||||||
// 提取不包含拓展名的原文件名
|
// 提取不包含拓展名的原文件名
|
||||||
String[] extensions = fileName.split("\\.");
|
String[] extensions = fileName.split("\\.");
|
||||||
int splitLength = extensions.length;
|
int splitLength = extensions.length;
|
||||||
@ -160,6 +220,9 @@ public class DownPicUtil {
|
|||||||
} else {
|
} else {
|
||||||
newFileNameNoExtension = fileName;
|
newFileNameNoExtension = fileName;
|
||||||
}
|
}
|
||||||
|
if (isVideoFileByMetadata(picFile) && extension == null && isMp4) {
|
||||||
|
extension = "mp4";
|
||||||
|
}
|
||||||
|
|
||||||
// 重命名文件
|
// 重命名文件
|
||||||
if (extension == null) {
|
if (extension == null) {
|
||||||
@ -171,21 +234,24 @@ public class DownPicUtil {
|
|||||||
// 无拓展名,整个文件名递增重命名
|
// 无拓展名,整个文件名递增重命名
|
||||||
return renamePic(picFile, filePath, newFileNameNoExtension, null, MODE.MODE_INCREMENT);
|
return renamePic(picFile, filePath, newFileNameNoExtension, null, MODE.MODE_INCREMENT);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return renamePic(picFile, filePath, newFileNameNoExtension, extension, MODE.MODE_IGNORE);
|
||||||
}
|
}
|
||||||
// 支持解析的格式,使用md5文件名、真实拓展名
|
// 支持解析的格式,使用md5文件名、真实拓展名
|
||||||
String md5 = Md5Helper.getFileMD5ToString(picFile);
|
// return picFile.getPath();
|
||||||
if (TextUtils.isEmpty(md5)) {
|
// String md5 = Md5Helper.getFileMD5ToString(picFile);
|
||||||
return renamePic(picFile, filePath, newFileNameNoExtension, extension, MODE.MODE_INCREMENT);
|
// if (TextUtils.isEmpty(md5)) {
|
||||||
} else {
|
// return renamePic(picFile, filePath, newFileNameNoExtension, extension, MODE.MODE_INCREMENT);
|
||||||
return renamePic(picFile, filePath, md5.substring(0, 16), extension, MODE.MODE_IGNORE);
|
// } else {
|
||||||
}
|
// return renamePic(picFile, filePath, md5.substring(0, 16), extension, MODE.MODE_IGNORE);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(String path) {
|
protected void onPostExecute(String path) {
|
||||||
super.onPostExecute(path);
|
super.onPostExecute(path);
|
||||||
if(path!=null){
|
if(path!=null){
|
||||||
downFinishListener.onDownFinish(path);
|
downFinishListener.onDownFinish(url,path);
|
||||||
} else {
|
} else {
|
||||||
downFinishListener.onError();
|
downFinishListener.onError();
|
||||||
}
|
}
|
||||||
@ -208,6 +274,26 @@ public class DownPicUtil {
|
|||||||
MODE_OVERRIDE
|
MODE_OVERRIDE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Boolean isVideoFileByMetadata(File file) {
|
||||||
|
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||||
|
try {
|
||||||
|
retriever.setDataSource(file.getAbsolutePath());
|
||||||
|
println("retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE) >>> " + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE));
|
||||||
|
String duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
||||||
|
return duration != null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
retriever.release();
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static String renamePic(File picFile, String filePath, String newFileNameNoExtension, String extension, MODE mode) {
|
private static String renamePic(File picFile, String filePath, String newFileNameNoExtension, String extension, MODE mode) {
|
||||||
String extensionWithPoint = TextUtils.isEmpty(extension)? "": "." + extension;
|
String extensionWithPoint = TextUtils.isEmpty(extension)? "": "." + extension;
|
||||||
String newFileName = newFileNameNoExtension + extensionWithPoint;
|
String newFileName = newFileNameNoExtension + extensionWithPoint;
|
||||||
@ -262,7 +348,7 @@ public class DownPicUtil {
|
|||||||
|
|
||||||
//下载完成回调的接口
|
//下载完成回调的接口
|
||||||
public interface DownFinishListener{
|
public interface DownFinishListener{
|
||||||
void onDownFinish(String path);
|
void onDownFinish(String srcUrl ,String path);
|
||||||
void onError();
|
void onError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6,6 +6,8 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import kr.lunaticbum.utils.log.LogUtil;
|
||||||
|
|
||||||
public class FormatHelper {
|
public class FormatHelper {
|
||||||
|
|
||||||
private FormatHelper() {
|
private FormatHelper() {
|
||||||
@ -13,6 +15,7 @@ public class FormatHelper {
|
|||||||
|
|
||||||
public static String getExtension(File file) {
|
public static String getExtension(File file) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// long fileLength = file.length();
|
// long fileLength = file.length();
|
||||||
FileInputStream fileInputStream = new FileInputStream(file);
|
FileInputStream fileInputStream = new FileInputStream(file);
|
||||||
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
|
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
|
||||||
@ -81,7 +84,34 @@ public class FormatHelper {
|
|||||||
start[5] == (byte) 0x61) {
|
start[5] == (byte) 0x61) {
|
||||||
return "gif";
|
return "gif";
|
||||||
}
|
}
|
||||||
|
bufferedInputStream.reset();
|
||||||
|
start = new byte[6];
|
||||||
|
bufferedInputStream.read(start);
|
||||||
|
if (start[0] == (byte) 0x47 &&
|
||||||
|
start[1] == (byte) 0x49 &&
|
||||||
|
start[2] == (byte) 0x46 &&
|
||||||
|
start[3] == (byte) 0x38 &&
|
||||||
|
start[4] == (byte) 0x37 &&
|
||||||
|
start[5] == (byte) 0x61) {
|
||||||
|
return "gif";
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferedInputStream.reset();
|
||||||
|
start = new byte[100];
|
||||||
|
bufferedInputStream.read(start);
|
||||||
|
String xmlDeclaration = new String(start, 0, 100, "UTF-8");
|
||||||
|
LogUtil.INSTANCE.e("Path " + file.getAbsolutePath() + " ::: HEADE" + xmlDeclaration + ";");
|
||||||
|
if (xmlDeclaration.contains("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") ||
|
||||||
|
xmlDeclaration.contains("http://www.w3.org/2000/svg")) {
|
||||||
|
return "svg";
|
||||||
|
}else if (xmlDeclaration.contains("iso") &&
|
||||||
|
xmlDeclaration.contains("mp4")) {
|
||||||
|
return "mp4";
|
||||||
|
}
|
||||||
|
bufferedInputStream.reset();
|
||||||
|
|
||||||
|
|
||||||
|
LogUtil.INSTANCE.e("Path " + file.getAbsolutePath() + " ::: HEADE" + start[0] + "," + start[1] + "," + start[2] + "," + start[3] + "," + start[4] + "," + start[5] + ";");
|
||||||
bufferedInputStream.close();
|
bufferedInputStream.close();
|
||||||
fileInputStream.close();
|
fileInputStream.close();
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
|
|||||||
@ -97,5 +97,54 @@ public class VideoEnabledWebView extends WebView
|
|||||||
videoJsHelper.addJavascriptInterface(this);
|
videoJsHelper.addJavascriptInterface(this);
|
||||||
super.loadUrl(url, additionalHttpHeaders);
|
super.loadUrl(url, additionalHttpHeaders);
|
||||||
}
|
}
|
||||||
|
private boolean topReached = false;
|
||||||
|
private boolean bottomReached = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int computeVerticalScrollRange() {
|
||||||
|
|
||||||
|
int readerViewHeight = getMeasuredHeight();
|
||||||
|
|
||||||
|
int verticalScrollRange = super.computeVerticalScrollRange();
|
||||||
|
|
||||||
|
|
||||||
|
if (readerViewHeight >= verticalScrollRange) {
|
||||||
|
|
||||||
|
topReached = true;
|
||||||
|
|
||||||
|
bottomReached = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return verticalScrollRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrollChanged(int newLeft, int newTop, int oldLeft, int oldTop) {
|
||||||
|
|
||||||
|
|
||||||
|
topReached = false;
|
||||||
|
|
||||||
|
bottomReached = false;
|
||||||
|
|
||||||
|
|
||||||
|
int readerViewHeight = getMeasuredHeight();
|
||||||
|
|
||||||
|
int contentHeight = getContentHeight();
|
||||||
|
|
||||||
|
if (newTop == 0) {
|
||||||
|
|
||||||
|
|
||||||
|
topReached = true;
|
||||||
|
|
||||||
|
} else if (newTop + readerViewHeight >= contentHeight) {
|
||||||
|
|
||||||
|
|
||||||
|
bottomReached = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onScrollChanged(newLeft, newTop, oldLeft, oldTop);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,6 +82,31 @@
|
|||||||
android:visibility="invisible" /> -->
|
android:visibility="invisible" /> -->
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/blocking"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:background="#EE000000"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:visibility="visible"
|
||||||
|
app:trackThickness="10dp"
|
||||||
|
android:layout_margin="20dp"
|
||||||
|
app:trackColor="@color/finestWhite"
|
||||||
|
app:indicatorColor="@color/Color_FireBrick"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:progress="80"
|
||||||
|
app:trackCornerRadius="8dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="30dp"
|
||||||
|
android:text="저장을 위해\n리소스 모으는중..."
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
</layout>
|
</layout>
|
||||||
@ -1,13 +0,0 @@
|
|||||||
package com.thefinestartist.utils;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.test.ApplicationTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
|
||||||
*/
|
|
||||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
|
||||||
public ApplicationTest() {
|
|
||||||
super(Application.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,278 +0,0 @@
|
|||||||
package com.thefinestartist.utils.etc;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
import android.test.suitebuilder.annotation.MediumTest;
|
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
|
||||||
|
|
||||||
import kr.lunaticbum.Base;
|
|
||||||
import kr.lunaticbum.utils.preferences.PreferencesUtil;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests of the {@link PreferencesUtil} class.
|
|
||||||
*
|
|
||||||
* @author Robin Gustafsson
|
|
||||||
*/
|
|
||||||
public class PreferencesUtilTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
Base.initialize(getContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testSetGetDefaultName() {
|
|
||||||
final String expected = "TEST_DEFAULT_NAME";
|
|
||||||
|
|
||||||
PreferencesUtil.setDefaultName(expected);
|
|
||||||
String actual = PreferencesUtil.getDefaultName();
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testDifferentNames() {
|
|
||||||
final String name1 = "TEST_DIFFERENTNAMES_NAME1";
|
|
||||||
final String name2 = "TEST_DIFFERENTNAMES_NAME2";
|
|
||||||
final String key = "TEST_DIFFERENTNAMES_KEY";
|
|
||||||
final boolean value = true;
|
|
||||||
final boolean expected = false;
|
|
||||||
|
|
||||||
PreferencesUtil.put(name1, key, value);
|
|
||||||
boolean actual = PreferencesUtil.get(name2, key, expected);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreBoolean() {
|
|
||||||
final String key = "TEST_BOOLEAN";
|
|
||||||
final boolean expected = true;
|
|
||||||
final boolean defValue = false;
|
|
||||||
|
|
||||||
PreferencesUtil.put(key, expected);
|
|
||||||
boolean actual = PreferencesUtil.get(key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreBooleanNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String key = "TEST_BOOLEAN";
|
|
||||||
final boolean expected = true;
|
|
||||||
final boolean defValue = false;
|
|
||||||
|
|
||||||
PreferencesUtil.put(name, key, expected);
|
|
||||||
boolean actual = PreferencesUtil.get(name, key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreInt() {
|
|
||||||
final String key = "TEST_INT";
|
|
||||||
final int expected = 321;
|
|
||||||
final int defValue = 0;
|
|
||||||
|
|
||||||
PreferencesUtil.put(key, expected);
|
|
||||||
int actual = PreferencesUtil.get(key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreIntNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String key = "TEST_INT";
|
|
||||||
final int expected = 321;
|
|
||||||
final int defValue = 0;
|
|
||||||
|
|
||||||
PreferencesUtil.put(name, key, expected);
|
|
||||||
int actual = PreferencesUtil.get(name, key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreFloat() {
|
|
||||||
final String key = "TEST_FLOAT";
|
|
||||||
final float expected = 12.3f;
|
|
||||||
final float defValue = 0.0f;
|
|
||||||
|
|
||||||
PreferencesUtil.put(key, expected);
|
|
||||||
float actual = PreferencesUtil.get(key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreFloatNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String key = "TEST_FLOAT";
|
|
||||||
final float expected = 12.3f;
|
|
||||||
final float defValue = 0.0f;
|
|
||||||
|
|
||||||
PreferencesUtil.put(name, key, expected);
|
|
||||||
float actual = PreferencesUtil.get(name, key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreLong() {
|
|
||||||
final String key = "TEST_LONG";
|
|
||||||
final long expected = 321L;
|
|
||||||
final long defValue = 0L;
|
|
||||||
|
|
||||||
PreferencesUtil.put(key, expected);
|
|
||||||
long actual = PreferencesUtil.get(key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreLongNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String key = "TEST_LONG";
|
|
||||||
final long expected = 321L;
|
|
||||||
final long defValue = 0L;
|
|
||||||
|
|
||||||
PreferencesUtil.put(name, key, expected);
|
|
||||||
long actual = PreferencesUtil.get(name, key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreString() {
|
|
||||||
final String key = "TEST_STRING";
|
|
||||||
final String expected = "Lorem ipsum";
|
|
||||||
final String defValue = null;
|
|
||||||
|
|
||||||
PreferencesUtil.put(key, expected);
|
|
||||||
String actual = PreferencesUtil.get(key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreStringNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String key = "TEST_STRING";
|
|
||||||
final String expected = "Lorem ipsum";
|
|
||||||
final String defValue = null;
|
|
||||||
|
|
||||||
PreferencesUtil.put(name, key, expected);
|
|
||||||
String actual = PreferencesUtil.get(name, key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreStringSet() {
|
|
||||||
final String key = "TEST_STRINGSET";
|
|
||||||
final Set<String> expected = new HashSet<>();
|
|
||||||
expected.add("Lorem ipsum");
|
|
||||||
expected.add("dolor sit amet");
|
|
||||||
expected.add("consectetur adipiscing elit");
|
|
||||||
final Set<String> defValue = null;
|
|
||||||
|
|
||||||
PreferencesUtil.put(key, expected);
|
|
||||||
Set<String> actual = PreferencesUtil.get(key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testStoreStringSetNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String key = "TEST_STRINGSET";
|
|
||||||
final Set<String> expected = new HashSet<>();
|
|
||||||
expected.add("Lorem ipsum");
|
|
||||||
expected.add("dolor sit amet");
|
|
||||||
expected.add("consectetur adipiscing elit");
|
|
||||||
final Set<String> defValue = null;
|
|
||||||
|
|
||||||
PreferencesUtil.put(name, key, expected);
|
|
||||||
Set<String> actual = PreferencesUtil.get(name, key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@MediumTest
|
|
||||||
public void testStoreSerializable() {
|
|
||||||
final String key = "TEST_SERIALIZABLE";
|
|
||||||
final ArrayList<String> expected = new ArrayList<>();
|
|
||||||
expected.add("Lorem ipsum");
|
|
||||||
expected.add("dolor sit amet");
|
|
||||||
expected.add("consectetur adipiscing elit");
|
|
||||||
final ArrayList<String> defValue = new ArrayList<>();
|
|
||||||
defValue.add("Proin mollis dictum");
|
|
||||||
|
|
||||||
PreferencesUtil.put(key, expected);
|
|
||||||
ArrayList<String> actual = PreferencesUtil.get(key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@MediumTest
|
|
||||||
public void testStoreSerializableNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String key = "TEST_SERIALIZABLE";
|
|
||||||
final ArrayList<String> expected = new ArrayList<>();
|
|
||||||
expected.add("Lorem ipsum");
|
|
||||||
expected.add("dolor sit amet");
|
|
||||||
expected.add("consectetur adipiscing elit");
|
|
||||||
final ArrayList<String> defValue = new ArrayList<>();
|
|
||||||
defValue.add("Proin mollis dictum");
|
|
||||||
|
|
||||||
PreferencesUtil.put(name, key, expected);
|
|
||||||
ArrayList<String> actual = PreferencesUtil.get(name, key, defValue);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testRemove() {
|
|
||||||
final String key = "TEST_REMOVE";
|
|
||||||
final String expected = null;
|
|
||||||
|
|
||||||
PreferencesUtil.put(key, "Lorem ipsum");
|
|
||||||
PreferencesUtil.remove(key);
|
|
||||||
String actual = PreferencesUtil.get(key, expected);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testRemoveNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String key = "TEST_REMOVE";
|
|
||||||
final String expected = null;
|
|
||||||
|
|
||||||
PreferencesUtil.put(name, key, "Lorem ipsum");
|
|
||||||
PreferencesUtil.remove(name, key);
|
|
||||||
String actual = PreferencesUtil.get(name, key, expected);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testClear() {
|
|
||||||
final String[] keys = {"TEST_REMOVE_1", "TEST_REMOVE_2", "TEST_REMOVE_2"};
|
|
||||||
final String expected = null;
|
|
||||||
|
|
||||||
for (String key : keys) {
|
|
||||||
PreferencesUtil.put(key, "Lorem ipsum");
|
|
||||||
}
|
|
||||||
PreferencesUtil.clear();
|
|
||||||
for (String key : keys) {
|
|
||||||
String actual = PreferencesUtil.get(key, expected);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testClearNamed() {
|
|
||||||
final String name = "TEST_NAMED";
|
|
||||||
final String[] keys = {"TEST_REMOVE_1", "TEST_REMOVE_2", "TEST_REMOVE_2"};
|
|
||||||
final String expected = null;
|
|
||||||
|
|
||||||
for (String key : keys) {
|
|
||||||
PreferencesUtil.put(name, key, "Lorem ipsum");
|
|
||||||
}
|
|
||||||
PreferencesUtil.clear(name);
|
|
||||||
for (String key : keys) {
|
|
||||||
String actual = PreferencesUtil.get(name, key, expected);
|
|
||||||
assertEquals(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
package com.thefinestartist.utils;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To work on unit tests, switch the Test Artifact in the Build Variants view.
|
|
||||||
*/
|
|
||||||
public class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
public void addition_isCorrect() throws Exception {
|
|
||||||
assertEquals(4, 2 + 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user