...
This commit is contained in:
parent
428b16cda2
commit
2a25b49baa
@ -54,6 +54,9 @@
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
@ -101,6 +104,10 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".helpers.BluetoothManager"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".wall.MyWallpaperService"
|
||||
android:label="Bums Live Wallpaper"
|
||||
|
||||
@ -83,4 +83,23 @@ function check2() {
|
||||
}
|
||||
}
|
||||
}
|
||||
check2();
|
||||
check2();
|
||||
|
||||
fetch("https://dv-m.nhmembers.co.kr/nhpot/common/saveCertInf.ajax",{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
})
|
||||
|
||||
if (document.querySelectorAll('[class^="w-full flex"]').length > 1) {
|
||||
document.querySelectorAll('[class^="w-full flex"]').forEach(function (e) {
|
||||
|
||||
|
||||
var description = ""
|
||||
if(e.querySelector('[class^="pb-2 w-100 text-gray-500"]')){
|
||||
description = e.querySelector('[class^="pb-2 w-100 text-gray-500"]').textContent.replace(/\s+/g, ' ').trim();
|
||||
}
|
||||
console.log(description)
|
||||
})
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
video-item ::> <div class="img-area">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a onclick="sendEvent('Cover Click','Main List Movie','201882')" href="/movie/ipzz-574-201882" data-link="https://images.ijavtorrent.com/data/covers/201882.jpg"> <img sizes="
|
||||
(max-width: 1536px) 480px,
|
||||
(max-width: 1920px) 620px,
|
||||
(min-width: 1921px) 800px,
|
||||
" src="https://images.ijavtorrent.com/data/covers/201882.jpg" alt="IPZZ-574 I Didn't Know About My Wife's Twisted Sexual Habits... My Beloved Wife, Who Is Usually Kind, Was A Masochistic Slave Trained By A Sadistic Neighbor. Kana Momonogi" title="IPZZ-574 I Didn't Know About My Wife's Twisted Sexual Habits... My Beloved Wife, Who Is Usually Kind, Was A Masochistic Slave Trained By A Sadistic Neighbor. Kana Momonogi" class="lazy mw-100" style="" srcset="
|
||||
https://images.ijavtorrent.com/data/covers/201882.jpg?width=480 480w,
|
||||
https://images.ijavtorrent.com/data/covers/201882.jpg?width=620 620w,
|
||||
https://images.ijavtorrent.com/data/covers/201882.jpg?width=800 800w,
|
||||
"> </a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="name">
|
||||
<a onclick="sendEvent('movie-click','Main List Movie','201882')" href="/movie/ipzz-574-201882"> <span>ipzz-574 i didn't know about my wife's twisted sexual habits... my beloved wife, who is usually kind, was a masochistic slave trained by a sadistic neighbor. kana momonogi</span> </a>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<a onclick="sendEvent('movie-click','Main List Movie','201882')" href="/movie/ipzz-574-201882"> 08/07/2025 </a> | <i class="fas fa-eye"></i> <span class="pageview-value">4260</span> | <i class="fa fa-fw fa-download"></i> <span class="download-value">2602</span>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<div class="badge badge-info" data-toggle="popover" data-html="true" data-content="<div><img src='https://images.ijavtorrent.com/data/actresses/451.jpg?v=772750732' alt='Kana Momonogi' style='width: 150px; height: 150px;'></div>" data-original-title="" title="">
|
||||
<a href="/actress/kana-momonogi-451"> <i class="fas fa-info"></i> Kana Momonogi </a> <img src="https://images.ijavtorrent.com/data/actresses/451.jpg?v=772750732" class="d-none">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="badge badge-warning">
|
||||
<a href="/?editorrate=6"><i class="fab fa-hotjar"></i> 6</a>
|
||||
</div>
|
||||
<div class="badge badge-warning">
|
||||
<a href="/tag/top-5-daily-2483">Top 5 Daily</a>
|
||||
</div>
|
||||
<div class="badge badge-secondary">
|
||||
<a href="/tag/cuckold-112">Cuckold</a>
|
||||
</div>
|
||||
<div class="badge badge-secondary">
|
||||
<a href="/tag/nasty-hardcore-85">Nasty, Hardcore</a>
|
||||
</div>
|
||||
<div class="badge badge-secondary">
|
||||
<a href="/tag/sm-95">SM</a>
|
||||
</div>
|
||||
<div class="badge badge-secondary">
|
||||
<a href="/tag/solowork-1">Solowork</a>
|
||||
</div>
|
||||
<div class="badge badge-secondary">
|
||||
<a href="/tag/married-woman-19">Married Woman</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="btn btn-sm btn-warning">
|
||||
<a onclick="sendEvent('Screenshot-Click','Main List Movie','201882')" href="https://images.ijavtorrent.com/data/screenshots/201882.jpg" data-featherlight="image" target="_blank"> <i class="far fa-images"></i> Screenshot </a>
|
||||
</div>
|
||||
<div class="btn btn-sm btn-outline-primary movie-like-button" data-movie-id="201882">
|
||||
<i class="fas fa-heart"></i> <span class="like-value">0</span>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-sm mt-2">
|
||||
<tbody>
|
||||
<tr style="vertical-align: middle">
|
||||
2025-07-23 11:22:20.062 26023-26023 Lunatic bums.lunatic.launcher E <td><a onclick="sendEvent('Torrent Click','Main List Movie','201882')" href="/download/463171" rel="nofollow" class="download-click-track"><i class="fa fa-fw fa-download"></i> Download</a> <a onclick="sendEvent('Magnet Click','Main List Movie','201882')" href="magnet:?xt=urn:btih:8c64238f2bfd260a6793b3b8ec97aad93e4d1dd8&amp;dn=IPZZ-574%E3%80%90%E7%A0%B4%E5%A3%8A%E7%89%88%E3%80%91%E4%BF%BA%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E5%A6%BB%E3%81%AE%E6%AD%AA%E3%82%93%E3%81%A0%E6%80%A7%E7%99%96%E2%80%A6%20%E6%99%AE%E6%AE%B5%E5%84%AA%E3%81%97%E3%81%84%E6%9C%80%E6%84%9B%E3%81%AE%E5%A6%BB%E3%81%AF%E3%83%89S%E9%9A%A3%E4%BA%BA%E3%81%AB%E8%AA%BF%E6%95%99%E6%B8%88%E3%81%AE%E3%83%9E%E3%82%BE%E5%A5%B4%E2%97%8F%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82%20%E6%A1%83%E4%B9%83%E6%9C%A8%E3%81%8B%E3%81%AA&amp;tr=http%3A%2F%2Fsukebei.tracker.wf%3A8888%2Fannounce&amp;tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&amp;tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce" rel="nofollow" class="magnet-click-track"><i class="fa fa-fw fa-magnet" rel="nofollow"></i> Magnet</a></td>
|
||||
<td><i class="fas fa-weight-hanging"></i> 3.4gb</td>
|
||||
<td><strong>S:</strong> 41</td>
|
||||
<td><strong>L:</strong> 667</td>
|
||||
<td><i class="far fa-calendar-alt"></i> 23/07/25</td>
|
||||
<td><span class="badge badge-info">Decen</span></td>
|
||||
</tr>
|
||||
<tr style="vertical-align: middle">
|
||||
<td><a onclick="sendEvent('Torrent Click','Main List Movie','201882')" href="/download/459739" rel="nofollow" class="download-click-track"><i class="fa fa-fw fa-download"></i> Download</a> <a onclick="sendEvent('Magnet Click','Main List Movie','201882')" href="magnet:?xt=urn:btih:6a020162885ec725961eeca6ccb15153586f09d3&amp;dn=%5BHD%2F720p%5D%20IPZZ-574%20%E4%BF%BA%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E5%A6%BB%E3%81%AE%E6%AD%AA%E3%82%93%E3%81%A0%E6%80%A7%E7%99%96%E2%80%A6%20%E6%99%AE%E6%AE%B5%E5%84%AA%E3%81%97%E3%81%84%E6%9C%80%E6%84%9B%E3%81%AE%E5%A6%BB%E3%81%AF%E3%83%89S%E9%9A%A3%E4%BA%BA%E3%81%AB%E8%AA%BF%E6%95%99%E6%B8%88%E3%81%AE%E3%83%9E%E3%82%BE%E5%A5%B4%E2%97%8F%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82%20%E6%A1%83%E4%B9%83%E6%9C%A8%E3%81%8B%E3%81%AA&amp;tr=http%3A%2F%2Fsukebei.tracker.wf%3A8888%2Fannounce&amp;tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&amp;tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce" rel="nofollow" class="magnet-click-track"><i class="fa fa-fw fa-magnet" rel="nofollow"></i> Magnet</a></td>
|
||||
<td><i class="fas fa-weight-hanging"></i> 1.3gb</td>
|
||||
<td><strong>S:</strong> 30</td>
|
||||
<td><strong>L:</strong> 6</td>
|
||||
<td><i class="far fa-calendar-alt"></i> 22/07/25</td>
|
||||
</tr>
|
||||
<tr style="vertical-align: middle">
|
||||
2025-07-23 11:22:20.062 26023-26023 Lunatic bums.lunatic.launcher E <td><a onclick="sendEvent('Torrent Click','Main List Movie','201882')" href="/download/460809" rel="nofollow" class="download-click-track"><i class="fa fa-fw fa-download"></i> Download</a> <a onclick="sendEvent('Magnet Click','Main List Movie','201882')" href="magnet:?xt=urn:btih:cb582ed50fb3d342c2c668d2a33f7b143e1f1b03&amp;dn=%2B%2B%2B%20%5BFHDC%5D%20IPZZ-574%20%E4%BF%BA%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E5%A6%BB%E3%81%AE%E6%AD%AA%E3%82%93%E3%81%A0%E6%80%A7%E7%99%96%E2%80%A6%20%E6%99%AE%E6%AE%B5%E5%84%AA%E3%81%97%E3%81%84%E6%9C%80%E6%84%9B%E3%81%AE%E5%A6%BB%E3%81%AF%E3%83%89S%E9%9A%A3%E4%BA%BA%E3%81%AB%E8%AA%BF%E6%95%99%E6%B8%88%E3%81%AE%E3%83%9E%E3%82%BE%E5%A5%B4%E2%97%8F%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82%20%E6%A1%83%E4%B9%83%E6%9C%A8%E3%81%8B%E3%81%AA&amp;tr=http%3A%2F%2Fsukebei.tracker.wf%3A8888%2Fannounce&amp;tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&amp;tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&amp;tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce" rel="nofollow" class="magnet-click-track"><i class="fa fa-fw fa-magnet" rel="nofollow"></i> Magnet</a></td>
|
||||
<td><i class="fas fa-weight-hanging"></i> 5.3gb</td>
|
||||
<td><strong>S:</strong> 60</td>
|
||||
<td><strong>L:</strong> 23</td>
|
||||
<td><i class="far fa-calendar-alt"></i> 22/07/25</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<div class="text-right">
|
||||
<a href="/movie/ipzz-574-201882"> more torrents >> </a>
|
||||
</div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="mb-4">
|
||||
</div>
|
||||
@ -291,6 +291,180 @@ if (port) {
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[class^="code-block"]')) {
|
||||
document.querySelectorAll('[class^="code-block"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('.ad-template')) {
|
||||
document.querySelectorAll('.ad-template').forEach(function (e) {
|
||||
e.remove()
|
||||
})
|
||||
}
|
||||
if (document.querySelectorAll('[class^="popupBanner_w popupOpen"]')) {
|
||||
document.querySelectorAll('[class^="popupBanner_w popupOpen"]').forEach(function (e) {
|
||||
e.remove()
|
||||
})
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('iframe')) {
|
||||
document.querySelectorAll('iframe').forEach(function (e) {
|
||||
if (e.getAttribute("src") != null && (e.getAttribute("src").search("ads") > -1 || e.getAttribute("src").search("coupang") > -1)) {
|
||||
e.remove()
|
||||
}
|
||||
})
|
||||
}
|
||||
if (location.href.search("x.com") > -1) {
|
||||
var mainClass = document.querySelector('section').className
|
||||
|
||||
document.querySelector('section').querySelectorAll('div[class="'+ mainClass +'"]').forEach(function (e) {
|
||||
if (e.hasAttribute("data-testid") && e.querySelector('video')) {
|
||||
e.querySelectorAll('[poster]').forEach(function (e) {
|
||||
|
||||
})
|
||||
console.log(e.innerHTML)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[data-banner^="coupang-"]')) {
|
||||
document.querySelectorAll('[data-banner^="coupang-"]').forEach(e => e.remove())
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[id^="mobonDivBanner"]')) {
|
||||
document.querySelectorAll('[id^="mobonDivBanner"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[id^="pnlTopAd"]')) {
|
||||
document.querySelectorAll('[id^="pnlTopAd"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[class^="ad-tag"]')) {
|
||||
document.querySelectorAll('[class^="ad-tag"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[class^="science-banner-area"]')) {
|
||||
document.querySelectorAll('[class^="science-banner-area"]').forEach(e=> e.remove())
|
||||
}
|
||||
if (location.href.search("torrentzota") > -1 && document.querySelectorAll('a')) {
|
||||
document.querySelectorAll('a').forEach(function (e) {
|
||||
if (e.getAttribute('href') != null && e.getAttribute('href').startsWith("/adver-")) {
|
||||
e.remove()
|
||||
}
|
||||
}
|
||||
)
|
||||
if(document.querySelectorAll('[class^="py-4 flex flex-row border-b topic-item"]').length > 1) {
|
||||
var datas = []
|
||||
document.querySelectorAll('[class^="py-4 flex flex-row border-b topic-item"]').forEach(function (e) {
|
||||
var title = ""
|
||||
var link = ""
|
||||
e.querySelectorAll("a").forEach(function (e){
|
||||
if(e.getAttribute("class") === "item-link"){
|
||||
title = e.getAttribute('title')
|
||||
}
|
||||
if(e.getAttribute("class") === "item-link"){
|
||||
link = e.getAttribute('href')
|
||||
if (link.length > 0) {
|
||||
link = location.protocol + '//' + location.hostname + link
|
||||
}
|
||||
}
|
||||
})
|
||||
var description = e.querySelector('.flex-none w-16 text-center').textContent + e.querySelector('.badge badge-third w-auto px-1 flex-none mr-2 float-left').textContent
|
||||
var md = e.querySelector(".flex-none w-14 text-center hidden md:block").textContent
|
||||
|
||||
let todayYear = new Date().getFullYear();
|
||||
let now = new Date();
|
||||
let hh = String(now.getHours()).padStart(2, '0'); // 시 (2자리)
|
||||
let mm = String(now.getMinutes()).padStart(2, '0'); // 분 (2자리)
|
||||
let ss = String(now.getSeconds()).padStart(2, '0'); // 초 (2자리)
|
||||
|
||||
let time = `${hh}:${mm}:${ss}`;
|
||||
let combinedStr = todayYear + "-" + md + " " + time;
|
||||
let dateObj = new Date(combinedStr);
|
||||
|
||||
datas.push({
|
||||
"title" : title,
|
||||
"description" : description,
|
||||
"originPage" : link,
|
||||
"pubDate" : dateObj.getTime(),
|
||||
"category" : "TORRENT"
|
||||
});
|
||||
})
|
||||
if(datas.length > 0) {
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: datas,
|
||||
currentPage : location.href
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
if (document.querySelectorAll('[class^="w-full flex"]').length > 1) {
|
||||
var datas = []
|
||||
document.querySelectorAll('[class^="w-full flex"]').forEach(function (e) {
|
||||
var thumbnail = ""
|
||||
e.querySelectorAll("img").forEach(function (e){
|
||||
if(e.getAttribute("class") === "border"){
|
||||
thumbnail = e.getAttribute('src')
|
||||
}
|
||||
})
|
||||
|
||||
var title = ""
|
||||
var link = ""
|
||||
e.querySelectorAll("a").forEach(function (e){
|
||||
if(e.getAttribute("class") === "item-link"){
|
||||
title = e.getAttribute('title')
|
||||
}
|
||||
if(e.getAttribute("class") === "item-link"){
|
||||
link = e.getAttribute('href')
|
||||
if (link.length > 0) {
|
||||
link = location.protocol + '//' + location.hostname + link
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
var description = ""
|
||||
var time = ""
|
||||
var md = ""
|
||||
if(e.querySelector('[class^="pb-2 w-100 text-gray-500"]')){
|
||||
description = e.querySelector('[class^="pb-2 w-100 text-gray-500"]').textContent.replace(/\s+/g, ' ').trim();
|
||||
md = description.split(" ")[1].trim();
|
||||
time = description.split(" ")[2].trim();
|
||||
description = description.split(" ")[0].trim();
|
||||
}
|
||||
console.log(link)
|
||||
console.log(thumbnail)
|
||||
console.log(title)
|
||||
console.log(description)
|
||||
console.log(md)
|
||||
console.log(time)
|
||||
|
||||
|
||||
|
||||
let todayYear = new Date().getFullYear();
|
||||
let combinedStr = todayYear + "-" + md + " " + time;
|
||||
let dateObj = new Date(combinedStr);
|
||||
|
||||
datas.push({
|
||||
"title" : title,
|
||||
"description" : description,
|
||||
"originPage" : link,
|
||||
"thumbnail" : thumbnail,
|
||||
"pubDate" : dateObj.getTime(),
|
||||
"category" : "TORRENT"
|
||||
});
|
||||
})
|
||||
if(datas.length > 0) {
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: datas,
|
||||
currentPage : location.href
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').length > 1) {
|
||||
var datas = []
|
||||
@ -440,18 +614,4 @@ function gotoNext() {
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
//
|
||||
// if (document.readyState === "complete" || document.readyState === "interactive") {
|
||||
// reportCookiesToNative();
|
||||
// } else {
|
||||
// window.addEventListener("DOMContentLoaded", reportCookiesToNative);
|
||||
// }
|
||||
// function reportCookiesToNative() {
|
||||
// // 모든 쿠키를 읽어 네이티브로 전달
|
||||
// sendMessage({type: "MSG", cookies: "DOMContentLoaded try to cookies send"});
|
||||
// window.cookies.getAll({url: window.location.href}).then((cookies) => {
|
||||
// // 쿠키 데이터를 네이티브(Android)로 전송
|
||||
// sendMessage({type: "Cookies", cookies: cookies});
|
||||
// });
|
||||
// }
|
||||
}
|
||||
@ -46,6 +46,7 @@ import android.view.WindowInsets
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.core.view.ViewCompat
|
||||
@ -62,6 +63,7 @@ import bums.lunatic.launcher.tokiz.Novels
|
||||
import bums.lunatic.launcher.common.CommonActivity
|
||||
import bums.lunatic.launcher.databinding.LauncherActivityBinding
|
||||
import bums.lunatic.launcher.feeds.WidgetHost
|
||||
import bums.lunatic.launcher.helpers.BluetoothManager
|
||||
import bums.lunatic.launcher.helpers.Constants.Companion.KEY_STATUS_BAR
|
||||
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
||||
import bums.lunatic.launcher.helpers.Constants.Companion.widgetHostId
|
||||
@ -72,7 +74,9 @@ import bums.lunatic.launcher.home.RssViewBuilder
|
||||
import bums.lunatic.launcher.model.RssData
|
||||
import bums.lunatic.launcher.model.RssDataType
|
||||
import bums.lunatic.launcher.tokiz.Comics
|
||||
import bums.lunatic.launcher.tokiz.Twitter
|
||||
import bums.lunatic.launcher.tokiz.Webtoons
|
||||
import bums.lunatic.launcher.tokiz.Zota
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import bums.lunatic.launcher.utils.FeedParseManager
|
||||
import bums.lunatic.launcher.utils.getJ
|
||||
@ -115,6 +119,7 @@ import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.jvm.java
|
||||
|
||||
|
||||
internal class LauncherActivity : CommonActivity() {
|
||||
@ -130,41 +135,40 @@ internal class LauncherActivity : CommonActivity() {
|
||||
return sRuntime
|
||||
}
|
||||
|
||||
private var mWorkManager: WorkManager? = null
|
||||
|
||||
var isOpendFold = false
|
||||
val qDayPeriod = 60L * 8L
|
||||
|
||||
@JvmStatic var lActivity: LauncherActivity? = null
|
||||
@JvmStatic var appWidgetManager: AppWidgetManager? = null
|
||||
@JvmStatic var appWidgetHost: WidgetHost? = null
|
||||
fun refreshDeviceData()
|
||||
{
|
||||
|
||||
mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
SMS_WORK_TAG,
|
||||
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<RecentSmsGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(SMS_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(RecentCallGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
RecentCallGetter.TAG,
|
||||
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<RecentCallGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(RecentCallGetter.TAG)
|
||||
.build())
|
||||
|
||||
mWorkManager?.cancelAllWorkByTag(ContactInfoGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
ContactInfoGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<ContactInfoGetter>(12, TimeUnit.HOURS)
|
||||
.addTag(ContactInfoGetter.TAG)
|
||||
.build())
|
||||
|
||||
mWorkManager?.enqueue(OneTimeWorkRequest.from(AppInfoGetter::class.java))
|
||||
|
||||
}
|
||||
// fun refreshDeviceData()
|
||||
// {
|
||||
//
|
||||
// mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
|
||||
// mWorkManager?.enqueueUniquePeriodicWork(
|
||||
// SMS_WORK_TAG,
|
||||
// ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
// PeriodicWorkRequestBuilder<RecentSmsGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||
// .addTag(SMS_WORK_TAG)
|
||||
// .build())
|
||||
// mWorkManager?.cancelAllWorkByTag(RecentCallGetter.TAG)
|
||||
// mWorkManager?.enqueueUniquePeriodicWork(
|
||||
// RecentCallGetter.TAG,
|
||||
// ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
// PeriodicWorkRequestBuilder<RecentCallGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||
// .addTag(RecentCallGetter.TAG)
|
||||
// .build())
|
||||
//
|
||||
// mWorkManager?.cancelAllWorkByTag(ContactInfoGetter.TAG)
|
||||
// mWorkManager?.enqueueUniquePeriodicWork(
|
||||
// ContactInfoGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
// PeriodicWorkRequestBuilder<ContactInfoGetter>(12, TimeUnit.HOURS)
|
||||
// .addTag(ContactInfoGetter.TAG)
|
||||
// .build())
|
||||
//
|
||||
// mWorkManager?.enqueue(OneTimeWorkRequest.from(AppInfoGetter::class.java))
|
||||
//
|
||||
// }
|
||||
|
||||
// fun runWeatherGetter() {
|
||||
// Executors.newSingleThreadScheduledExecutor().schedule({
|
||||
@ -172,92 +176,14 @@ internal class LauncherActivity : CommonActivity() {
|
||||
// }, 200L, TimeUnit.MILLISECONDS)
|
||||
// }
|
||||
|
||||
fun getCal() {
|
||||
Executors.newSingleThreadScheduledExecutor().schedule({
|
||||
mWorkManager?.enqueue(OneTimeWorkRequest.from(CalendarGetter::class.java))
|
||||
}, 5, TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
val defaultDelay = 10L
|
||||
|
||||
fun refreshFeeds() {
|
||||
mWorkManager?.cancelAllWork()
|
||||
mWorkManager?.cancelAllWorkByTag(RuliWebGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
RuliWebGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<RuliWebGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(RuliWebGetter.TAG)
|
||||
.build())
|
||||
|
||||
mWorkManager?.cancelAllWorkByTag(FEDDS_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
FEDDS_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<NewsFeedsGetter>(PrefLong.shortTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(FEDDS_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(YT_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
YT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<YoutubeGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(YT_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(REDDIT_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
REDDIT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<RedditGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(REDDIT_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(FM_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
FM_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<FmKoreaGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(FM_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<DotaxGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(COMIC2_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(ClienGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
ClienGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<ClienGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(ClienGetter.TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(DCGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
DCGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<DCGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(DCGetter.TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(TheQooGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
TheQooGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<TheQooGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(TheQooGetter.TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(ArcaGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
ArcaGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<ArcaGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(ArcaGetter.TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(LocationGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
LocationGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<LocationGetter>(PrefLong.locationTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(LocationGetter.TAG)
|
||||
.build())
|
||||
}
|
||||
// fun getCal() {
|
||||
// Executors.newSingleThreadScheduledExecutor().schedule({
|
||||
// mWorkManager?.enqueue(OneTimeWorkRequest.from(CalendarGetter::class.java))
|
||||
// }, 5, TimeUnit.SECONDS)
|
||||
// }
|
||||
|
||||
|
||||
|
||||
fun workmanager() : WorkManager? {
|
||||
if (mWorkManager == null && lActivity != null) {
|
||||
mWorkManager = WorkManager.getInstance(lActivity!!)
|
||||
}
|
||||
return mWorkManager
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -305,15 +231,6 @@ internal class LauncherActivity : CommonActivity() {
|
||||
when(ev.keyCode) {
|
||||
KEYCODE_BUTTON_Y->{
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
String(Base64.getMimeDecoder().decode("aHR0cHM6Ly9qYXZtb3N0LnRvL2xhdGVzdC11cGRhdGVzCg==".toByteArray())).getJ().let { doc -> FeedParseManager.parse(doc){Blog.LOGE(it)} }
|
||||
}
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
String.format(String(Base64.getMimeDecoder().decode("aHR0cHM6Ly9qYXZtb3N0LnRvL3NlYXJjaC9tb3ZpZS8lcw==".toByteArray())),"").getJ().let { doc -> FeedParseManager.parse(doc){Blog.LOGE(it)} }
|
||||
}
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
String.format(String(Base64.getMimeDecoder().decode("aHR0cHM6Ly9rcjcxLnNvZ2lybC5zby8/cz0lcw==".toByteArray())),"").getJ().let { doc -> FeedParseManager.parse(doc){Blog.LOGE(it)} }
|
||||
}
|
||||
}
|
||||
KEYCODE_BUTTON_X->{
|
||||
|
||||
@ -332,11 +249,7 @@ internal class LauncherActivity : CommonActivity() {
|
||||
}
|
||||
}
|
||||
KEYCODE_BUTTON_B->{
|
||||
// RssViewBuilder(lActivity!!)
|
||||
// .setRssId("https://jav.guru")
|
||||
// .webViewJavaScriptEnabled(true)
|
||||
// .showIconClose(true).showIconBack(false).showProgressBar(true).backPressToClose(false).webViewMixedContentMode(1)
|
||||
// .show("https://jav.guru")
|
||||
|
||||
}
|
||||
KEYCODE_DPAD_DOWN->{
|
||||
|
||||
@ -411,7 +324,6 @@ internal class LauncherActivity : CommonActivity() {
|
||||
}
|
||||
|
||||
fun onClickCenterButton() {
|
||||
|
||||
WorkersDb.getRealm().apply {
|
||||
writeBlocking {
|
||||
delete(
|
||||
@ -584,7 +496,7 @@ internal class LauncherActivity : CommonActivity() {
|
||||
installSplashScreen()
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||
lActivity = this
|
||||
mWorkManager = WorkManager.getInstance(this)
|
||||
|
||||
DynamicColors.applyToActivityIfAvailable(this)
|
||||
|
||||
|
||||
@ -594,9 +506,6 @@ internal class LauncherActivity : CommonActivity() {
|
||||
|
||||
binding = LauncherActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
appWidgetManager = AppWidgetManager.getInstance(applicationContext)
|
||||
appWidgetHost = WidgetHost(applicationContext, widgetHostId)
|
||||
appWidgetHost?.startListening()
|
||||
HeadsetActionButtonReceiver.register(this)
|
||||
|
||||
|
||||
@ -617,6 +526,9 @@ internal class LauncherActivity : CommonActivity() {
|
||||
handleBackPress()
|
||||
updateLocationService()
|
||||
binding.feeds.isChecked = true
|
||||
|
||||
val intent = Intent(this, BluetoothManager::class.java)
|
||||
ContextCompat.startForegroundService(this, intent)
|
||||
}
|
||||
|
||||
fun showContents(id : Int) {
|
||||
@ -641,6 +553,16 @@ internal class LauncherActivity : CommonActivity() {
|
||||
.replace(R.id.fragment_container, Comics())
|
||||
.commit()
|
||||
}
|
||||
R.id.zota ->{
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.fragment_container, Zota())
|
||||
.commit()
|
||||
}
|
||||
R.id.twitter ->{
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.fragment_container, Twitter())
|
||||
.commit()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@ -665,7 +587,6 @@ internal class LauncherActivity : CommonActivity() {
|
||||
override fun onDestroy() {
|
||||
|
||||
|
||||
appWidgetHost?.stopListening()
|
||||
try {
|
||||
sRuntime?.shutdown()
|
||||
sRuntime = null
|
||||
@ -689,8 +610,6 @@ internal class LauncherActivity : CommonActivity() {
|
||||
@RequiresApi(Build.VERSION_CODES.O_MR1)
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
refreshFeeds()
|
||||
// blutoothManager?.getPairedDevices()
|
||||
Blog.LOGE("LauncherActivity onResume")
|
||||
}
|
||||
|
||||
@ -746,6 +665,9 @@ internal class LauncherActivity : CommonActivity() {
|
||||
currentFragment.doNextPage()
|
||||
}
|
||||
}
|
||||
is Novels -> {
|
||||
currentFragment.actionNextEvent(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -2,6 +2,10 @@ package bums.lunatic.launcher.helpers
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.content.BroadcastReceiver
|
||||
@ -9,8 +13,33 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
|
||||
import bums.lunatic.launcher.R
|
||||
import bums.lunatic.launcher.home.GeckoWeb
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import bums.lunatic.launcher.workers.ArcaGetter
|
||||
import bums.lunatic.launcher.workers.ClienGetter
|
||||
import bums.lunatic.launcher.workers.DCGetter
|
||||
import bums.lunatic.launcher.workers.DotaxGetter
|
||||
import bums.lunatic.launcher.workers.DotaxGetter.Companion.COMIC2_WORK_TAG
|
||||
import bums.lunatic.launcher.workers.FmKoreaGetter
|
||||
import bums.lunatic.launcher.workers.FmKoreaGetter.Companion.FM_WORK_TAG
|
||||
import bums.lunatic.launcher.workers.LocationGetter
|
||||
import bums.lunatic.launcher.workers.NewsFeedsGetter
|
||||
import bums.lunatic.launcher.workers.NewsFeedsGetter.Companion.FEDDS_WORK_TAG
|
||||
import bums.lunatic.launcher.workers.RedditGetter
|
||||
import bums.lunatic.launcher.workers.RedditGetter.Companion.REDDIT_WORK_TAG
|
||||
import bums.lunatic.launcher.workers.RuliWebGetter
|
||||
import bums.lunatic.launcher.workers.TheQooGetter
|
||||
import bums.lunatic.launcher.workers.YoutubeGetter
|
||||
import bums.lunatic.launcher.workers.YoutubeGetter.Companion.YT_WORK_TAG
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -22,7 +51,7 @@ import okhttp3.ResponseBody
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
class BluetoothManager {
|
||||
class BluetoothManager : Service() {
|
||||
|
||||
enum class BLUETOOTH_STATE(val statestr: String) {
|
||||
ENABLED("enabledBlutooth"),
|
||||
@ -30,50 +59,61 @@ class BluetoothManager {
|
||||
NOT_SUPPORT("notSupport")
|
||||
}
|
||||
|
||||
lateinit var context: Context
|
||||
var blueToothAdapter:BluetoothAdapter? = null
|
||||
private var mWorkManager: WorkManager? = null
|
||||
|
||||
constructor(context: Context) {
|
||||
this.context = context
|
||||
}
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
// init {
|
||||
// this.context = context
|
||||
// }
|
||||
|
||||
fun initBluetoothAdapter(){
|
||||
if ( blueToothAdapter == null ){
|
||||
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as android.bluetooth.BluetoothManager
|
||||
blueToothAdapter = bluetoothManager.getAdapter()
|
||||
val NOTIF_ID = 830721
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Blog.LOGE("onCreate")
|
||||
mWorkManager = WorkManager.getInstance(this)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
startForeground(NOTIF_ID, createNotification(this))
|
||||
}
|
||||
val filter = IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)
|
||||
registerReceiver(bluetoothreceiver, filter)
|
||||
refreshFeeds()
|
||||
// GeckoWeb(applicationContext).apply {
|
||||
// loadUrl("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=")
|
||||
// }
|
||||
}
|
||||
|
||||
fun register(){
|
||||
if (context == null) return
|
||||
context.registerReceiver(bluetoothreceiver, addFilterAction())
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
Blog.LOGE("intent >>> ${intent}")
|
||||
return null
|
||||
}
|
||||
private val CHANNEL_ID = "ble_service_channel"
|
||||
private val CHANNEL_NAME = "BLE 서비스"
|
||||
|
||||
fun createNotification(context: Context): Notification {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
CHANNEL_NAME,
|
||||
NotificationManager.IMPORTANCE_HIGH // 중요도 낮게 (필요시 변경)
|
||||
)
|
||||
val notificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
return NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setContentTitle("BLE 서비스")
|
||||
.setContentText("실행중입니다.")
|
||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||
.setSmallIcon(R.drawable.ic_b)
|
||||
.setOngoing(true) // 사용자가 알림을 스와이프로 지울 수 없게 만듦
|
||||
.build()
|
||||
}
|
||||
|
||||
fun unregister(){
|
||||
if (context == null) return
|
||||
context.unregisterReceiver(bluetoothreceiver)
|
||||
}
|
||||
|
||||
//페어링된 디바이스 정보 가져오기
|
||||
|
||||
fun getPairedDevices() {
|
||||
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as android.bluetooth.BluetoothManager
|
||||
val bluetoothManager = applicationContext.getSystemService(Context.BLUETOOTH_SERVICE) as android.bluetooth.BluetoothManager
|
||||
blueToothAdapter = bluetoothManager.adapter
|
||||
if (ActivityCompat.checkSelfPermission(context,Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) return
|
||||
if (ActivityCompat.checkSelfPermission(applicationContext,Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) return
|
||||
var pairedDevices = blueToothAdapter?.bondedDevices
|
||||
if (pairedDevices?.size ?: 0 > 0) {
|
||||
pairedDevices?.forEach { i ->
|
||||
//bondState : 12 (페어링 등록된 상태)
|
||||
//bondState : 10 (페어링 등록 안됨)
|
||||
// BLog.LOGE("getPairedDevices() / name : ${i.name}")
|
||||
// BLog.LOGE("getPairedDevices() / bondState : ${i.bondState}")
|
||||
val isConnected = isConnected(i)
|
||||
if(PrefString.carName.get().length > 2 && i.name.equals(PrefString.carName.get()) && isConnected != PrefBoolean.isConnectedCar.get()) {
|
||||
PrefBoolean.isConnectedCar.set(isConnected)
|
||||
@ -83,6 +123,84 @@ class BluetoothManager {
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshFeeds() {
|
||||
mWorkManager?.cancelAllWork()
|
||||
mWorkManager?.cancelAllWorkByTag(RuliWebGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
RuliWebGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<RuliWebGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(RuliWebGetter.TAG)
|
||||
.build())
|
||||
|
||||
mWorkManager?.cancelAllWorkByTag(FEDDS_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
FEDDS_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<NewsFeedsGetter>(PrefLong.shortTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(FEDDS_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(YT_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
YT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<YoutubeGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(YT_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(REDDIT_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
REDDIT_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<RedditGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(REDDIT_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(FM_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
FM_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<FmKoreaGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(FM_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<DotaxGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(COMIC2_WORK_TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(ClienGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
ClienGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<ClienGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(ClienGetter.TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(DCGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
DCGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<DCGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(DCGetter.TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(TheQooGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
TheQooGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<TheQooGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(TheQooGetter.TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(ArcaGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
ArcaGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<ArcaGetter>(PrefLong.midTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(ArcaGetter.TAG)
|
||||
.build())
|
||||
mWorkManager?.cancelAllWorkByTag(LocationGetter.TAG)
|
||||
mWorkManager?.enqueueUniquePeriodicWork(
|
||||
LocationGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
PeriodicWorkRequestBuilder<LocationGetter>(PrefLong.locationTimePeriod.get(), TimeUnit.MINUTES)
|
||||
.addTag(LocationGetter.TAG)
|
||||
.build())
|
||||
}
|
||||
|
||||
|
||||
fun workmanager() : WorkManager? {
|
||||
if (mWorkManager == null && lActivity != null) {
|
||||
mWorkManager = WorkManager.getInstance(lActivity!!)
|
||||
}
|
||||
return mWorkManager
|
||||
}
|
||||
|
||||
fun sendToI(boolean: Boolean) {
|
||||
if (PrefString.telegramSendTarget.get().length > 5) {
|
||||
@ -94,20 +212,10 @@ class BluetoothManager {
|
||||
"${PrefString.carName.get()}의 시동이 꺼졌다요."
|
||||
}}"
|
||||
//7068729507
|
||||
// OkHttp 클라이언트 객체 생성
|
||||
val client = OkHttpClient.Builder()
|
||||
val response: Response = OkHttpClient.Builder()
|
||||
.connectionPool(ConnectionPool(5, 60, TimeUnit.SECONDS))
|
||||
.build()
|
||||
|
||||
// GET 요청 객체 생성
|
||||
val builder: Request.Builder = Request.Builder().url(url)
|
||||
.addHeader("Content-Type", "application/json").get()
|
||||
|
||||
val request: Request = builder.build()
|
||||
|
||||
// BLog.LOGE("sendToI telegram before request ")
|
||||
// OkHttp 클라이언트로 GET 요청 객체 전송
|
||||
val response: Response = client.newCall(request).execute()
|
||||
.build().newCall(Request.Builder().url(url)
|
||||
.addHeader("Content-Type", "application/json").get().build()).execute()
|
||||
if (response.isSuccessful()) {
|
||||
// 응답 받아서 처리
|
||||
val body: ResponseBody? = response.body()
|
||||
|
||||
@ -29,7 +29,7 @@ enum class PrefLong(val def : Long) : PrefKey<Long> {
|
||||
maxQueryCount(18L);
|
||||
override fun set(value : Long) { PrefHelper.putLong(this.name, value) }
|
||||
override fun get(def : Long?) : Long {
|
||||
val value = PrefHelper.getLong(this.name, def ?: this.def) ?: this.def
|
||||
val value = Math.max(15,PrefHelper.getLong(this.name, def ?: this.def) ?: this.def)
|
||||
|
||||
// Blog.LOGE("$name : $value")
|
||||
|
||||
|
||||
@ -286,6 +286,7 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
|
||||
fun downloadImage(context: Context, url: Uri) {
|
||||
Blog.LOGE("url.lastPathSegment ${url.lastPathSegment}")
|
||||
val fileName = url.lastPathSegment ?: "${SimpleDateFormat("yyyyMMddHHmmsss")}.jpg"
|
||||
val request = DownloadManager.Request(url)
|
||||
request.setTitle(fileName)
|
||||
@ -687,9 +688,13 @@ class GeckoWeb : BWebview {
|
||||
var nUrl = url
|
||||
Blog.LOGE("url >>>> ${url}")
|
||||
if (url.endsWith("=")) {
|
||||
nUrl = String(java.util.Base64.getMimeDecoder().decode(url.toByteArray()))
|
||||
param?.let {
|
||||
nUrl = nUrl.plus(param)
|
||||
try {
|
||||
nUrl = String(java.util.Base64.getMimeDecoder().decode(url.toByteArray()))
|
||||
param?.let {
|
||||
nUrl = nUrl.plus(param)
|
||||
}
|
||||
}catch (e: Exception) {
|
||||
nUrl = url
|
||||
}
|
||||
} else if (url.startsWith("http") == false) {
|
||||
nUrl = lastDomain
|
||||
|
||||
@ -50,7 +50,6 @@ import bums.lunatic.launcher.common.letTrue
|
||||
import bums.lunatic.launcher.databinding.LauncherHomeBinding
|
||||
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
||||
import bums.lunatic.launcher.home.adapters.RssItemAdapter
|
||||
import bums.lunatic.launcher.home.adapters.RssItemAdapter.Companion.rssList
|
||||
import bums.lunatic.launcher.home.adapters.SwipeToDeleteCallback
|
||||
import bums.lunatic.launcher.model.RssData
|
||||
import bums.lunatic.launcher.model.RssDataType
|
||||
@ -101,7 +100,7 @@ internal class RssHome : Fragment() {
|
||||
fun rssStateVote() = (lasted?.filter { it.vote == true }?.size ?: -1) == (lasted?.size ?: 0)
|
||||
var lasted: ArrayList<RssData> = arrayListOf()
|
||||
var infosJob: Job? = null
|
||||
var rssId = ""
|
||||
// var rssId = ""
|
||||
lateinit var mRssAdapter: RssItemAdapter
|
||||
|
||||
var mRssDataResult: RealmResults<RssData>? = null
|
||||
@ -336,25 +335,32 @@ internal class RssHome : Fragment() {
|
||||
builder.show()
|
||||
}
|
||||
|
||||
|
||||
var currentRss : RssData? = null
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
fun openGecko(rssData: RssData? = null) {
|
||||
binding.layoutRssSummary.root.visibility = View.GONE
|
||||
if (rssData?.category()?.equals(RssDataType.PRIVATE) == false && rssData?.originPage?.isNotEmpty() == true) {
|
||||
rssData?.originPage?.let {
|
||||
rssData?.let { rss ->
|
||||
currentRss = rss
|
||||
binding.geckoWeb.privateMode = false
|
||||
rssId = it
|
||||
targetList.clear()
|
||||
var setString = hashSetOf<String>()
|
||||
setString.addAll(rssList)
|
||||
setString.removeAll { it.equals(rssId) }
|
||||
targetList.addAll(setString)
|
||||
binding.geckoWeb.loadUrl(rssId)
|
||||
appendReadCount(rss, 1, false)
|
||||
rss?.originPage?.let { rssId->
|
||||
synchronized(lasted) {
|
||||
if (lasted.isNotEmpty()) {
|
||||
lasted.removeAll { target -> target.originPage.equals(rssId) }
|
||||
}
|
||||
}
|
||||
binding.geckoWeb.loadUrl(rssId)
|
||||
}
|
||||
}
|
||||
} else if (rssData?.category()?.equals(RssDataType.PRIVATE) == true){
|
||||
rssData?.let {
|
||||
binding.geckoWeb.privateMode = true
|
||||
lasted.removeAll { target -> target.originPage.equals(it.originPage) }
|
||||
synchronized(lasted) {
|
||||
if (lasted.isNotEmpty()) {
|
||||
lasted.removeAll { target -> target.originPage.equals(it.originPage) }
|
||||
}
|
||||
}
|
||||
appendReadCount(it, 1, false)
|
||||
Blog.LOGE("removeFirst >>> ${Gson().toJson(it)}")
|
||||
binding.layoutRssSummary.title.tag = it
|
||||
@ -477,11 +483,13 @@ internal class RssHome : Fragment() {
|
||||
if (binding.geckoWeb.isVisible) {
|
||||
WorkersDb.getRealm().apply {
|
||||
writeBlocking {
|
||||
val result = query<RssData>().query("originPage == $0", rssId).find()
|
||||
if (result.size > 0) {
|
||||
result.forEach {
|
||||
if (it.vote) {
|
||||
it.vote = false
|
||||
currentRss?.originPage?.let {
|
||||
val result = query<RssData>().query("originPage == $0", it).find()
|
||||
if (result.size > 0) {
|
||||
result.forEach {
|
||||
if (it.vote) {
|
||||
it.vote = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -552,45 +560,40 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
fun vote() {
|
||||
Blog.LOGE("Arrow Center Click")
|
||||
WorkersDb.getRealm().apply {
|
||||
writeBlocking {
|
||||
val result = query<RssData>().query(
|
||||
if (imageView) "thumbnail == $0" else "originPage == $0",
|
||||
rssId
|
||||
).find()
|
||||
if (result.size > 0) {
|
||||
result.forEach { it.vote = true }
|
||||
currentRss?.originPage.let {
|
||||
Blog.LOGE("Arrow Center Click")
|
||||
WorkersDb.getRealm().apply {
|
||||
writeBlocking {
|
||||
val result = query<RssData>().query(
|
||||
if (imageView) "thumbnail == $0" else "originPage == $0",
|
||||
it
|
||||
).find()
|
||||
if (result.size > 0) {
|
||||
result.forEach { it.vote = true }
|
||||
}
|
||||
}
|
||||
}
|
||||
doNextPage()
|
||||
}
|
||||
doNextPage()
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
fun doNextPage() {
|
||||
WorkersDb.getRealm().apply {
|
||||
writeBlocking {
|
||||
val result = query<RssData>().query(
|
||||
if (imageView) "thumbnail == $0" else "originPage == $0",
|
||||
rssId
|
||||
).find()
|
||||
if (result.size > 0) {
|
||||
result.forEach {
|
||||
it.read = it.read + nomoreShowCount
|
||||
currentRss?.originPage.let {
|
||||
WorkersDb.getRealm().apply {
|
||||
writeBlocking {
|
||||
val result = query<RssData>().query(
|
||||
if (imageView) "thumbnail == $0" else "originPage == $0",
|
||||
it
|
||||
).find()
|
||||
if (result.size > 0) {
|
||||
result.forEach { it.read = it.read + nomoreShowCount }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
targetList.removeAll { it.equals(rssId) }
|
||||
if (targetList.size > 0) {
|
||||
rssId = targetList.removeFirst()
|
||||
binding.geckoWeb.loadUrl(rssId)
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "없어 끄자", Toast.LENGTH_LONG).show()
|
||||
binding.geckoWeb.visibility = View.GONE
|
||||
}
|
||||
openGecko(randomOrNull())
|
||||
}
|
||||
|
||||
fun clearJob(job: Job?) {
|
||||
@ -616,7 +619,7 @@ internal class RssHome : Fragment() {
|
||||
.query(
|
||||
"category != $0 AND category != $1 ",
|
||||
RssDataType.PRIVATE.name,
|
||||
RssDataType.REDDIT_NSFW.name
|
||||
RssDataType.TORRENT.name
|
||||
)
|
||||
.query("vote != $0", true).find()
|
||||
)
|
||||
@ -634,12 +637,14 @@ internal class RssHome : Fragment() {
|
||||
flow.collect { changes: ResultsChange<RssData> ->
|
||||
// when (changes) {
|
||||
// is InitialResults -> {
|
||||
commandHandler.removeCallbacks(infoUpdate)
|
||||
WorkersDb.getRealm().apply {
|
||||
lasted.clear()
|
||||
lasted.addAll(copyFromRealm(changes.list))
|
||||
synchronized(lasted) {
|
||||
commandHandler.removeCallbacks(infoUpdate)
|
||||
WorkersDb.getRealm().apply {
|
||||
lasted.clear()
|
||||
lasted.addAll(copyFromRealm(changes.list))
|
||||
}
|
||||
commandHandler.post(infoUpdate)
|
||||
}
|
||||
commandHandler.post(infoUpdate)
|
||||
// }
|
||||
//
|
||||
// is UpdatedResults -> {
|
||||
@ -714,9 +719,13 @@ internal class RssHome : Fragment() {
|
||||
|
||||
fun queryInfos(
|
||||
keywords: List<String>,
|
||||
includeVote : Boolean = false,
|
||||
includeRead : Boolean = false
|
||||
) {
|
||||
beforeQuery()
|
||||
var rQ = getRealm().query<RssData>().sort("pubDate", Sort.DESCENDING)
|
||||
var rQ = getRealm().query<RssData>().sort("read", Sort.ASCENDING)
|
||||
if (!includeRead) { rQ = rQ.query("read == $0", 0)}
|
||||
if (!includeVote) { rQ = rQ.query("vote != $0", true)}
|
||||
// 사용 예시
|
||||
val (queryStr, queryArgs) = buildMultiFieldOrQuery(
|
||||
listOf("title", "description"),
|
||||
|
||||
@ -61,7 +61,7 @@ internal class RssItemAdapter (
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
val dateFormat = SimpleDateFormat("a HH:mm / yy - MM - dd")
|
||||
val emptyDate = " - "
|
||||
var rssList: ArrayList<String> = ArrayList()
|
||||
// var rssList: ArrayList<String> = ArrayList()
|
||||
val webViewListener = object : WebViewListener() {
|
||||
override fun onCustomMenuClick(menuCode: String?) {
|
||||
super.onCustomMenuClick(menuCode)
|
||||
@ -188,51 +188,60 @@ internal class RssItemAdapter (
|
||||
|
||||
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
||||
override fun onBindViewHolder(holder: RssHolder, position: Int) {
|
||||
val rssData = rssDataItemLis[position]
|
||||
if (rssData.pubDate() > 1000L) {
|
||||
holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
|
||||
} else {
|
||||
holder.view.date.text = emptyDate
|
||||
}
|
||||
|
||||
|
||||
holder.view.title.text = "".plus(if(rssData.vote) " * " else "").plus(rssData.title().plus("[R:${rssData.read}]"))
|
||||
holder.view.desc.text = rssData.description()
|
||||
|
||||
var param = holder.view.circlePreview.layoutParams
|
||||
holder.view.circlePreview.layoutParams = ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
|
||||
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
|
||||
Picasso.get().cancelRequest(holder.view.circlePreview)
|
||||
|
||||
if(rssData.thumbnailUrl()?.length ?: 0 > 6) {
|
||||
Picasso.get().load(rssData.thumbnailUrl().replace("&","&").toUri()).into(holder.view.circlePreview)
|
||||
} else if (rssData.category().getResId() > 0 ) {
|
||||
holder.view.circlePreview.setImageResource(rssData.category().getResId())
|
||||
} else {
|
||||
holder.view.circlePreview.setImageDrawable(null)
|
||||
}
|
||||
|
||||
holder.itemView.tag = rssData
|
||||
holder.itemView.setOnClickListener(dateViewClick)
|
||||
holder.itemView.setOnTouchListener(object : View.OnTouchListener{
|
||||
override fun onTouch(
|
||||
v: View,
|
||||
event: MotionEvent
|
||||
): Boolean {
|
||||
if (event.device != null && event.device.name != null && (event.device.name?.contains("JX-12",true) == true|| event.device.name?.equals("J06",true) == true)) {
|
||||
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
||||
return true//mSimpleFingerGestures.onTouch(v,event)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
if (rssDataItemLis.isNotEmpty() && rssDataItemLis.size > position) {
|
||||
val rssData = rssDataItemLis[position]
|
||||
if (rssData.pubDate() > 1000L) {
|
||||
holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
|
||||
} else {
|
||||
holder.view.date.text = emptyDate
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
holder.view.title.text = "".plus(if (rssData.vote) " * " else "")
|
||||
.plus(rssData.title().plus("[R:${rssData.read}]"))
|
||||
holder.view.desc.text = rssData.description()
|
||||
|
||||
var param = holder.view.circlePreview.layoutParams
|
||||
holder.view.circlePreview.layoutParams =
|
||||
ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
|
||||
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
|
||||
Picasso.get().cancelRequest(holder.view.circlePreview)
|
||||
|
||||
if (rssData.thumbnailUrl()?.length ?: 0 > 6) {
|
||||
Picasso.get().load(rssData.thumbnailUrl().replace("&", "&").toUri())
|
||||
.into(holder.view.circlePreview)
|
||||
} else if (rssData.category().getResId() > 0) {
|
||||
holder.view.circlePreview.setImageResource(rssData.category().getResId())
|
||||
} else {
|
||||
holder.view.circlePreview.setImageDrawable(null)
|
||||
}
|
||||
|
||||
holder.itemView.tag = rssData
|
||||
holder.itemView.setOnClickListener(dateViewClick)
|
||||
holder.itemView.setOnTouchListener(object : View.OnTouchListener {
|
||||
override fun onTouch(
|
||||
v: View,
|
||||
event: MotionEvent
|
||||
): Boolean {
|
||||
if (event.device != null && event.device.name != null && (event.device.name?.contains(
|
||||
"JX-12",
|
||||
true
|
||||
) == true || event.device.name?.equals("J06", true) == true)
|
||||
) {
|
||||
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
||||
return true//mSimpleFingerGestures.onTouch(v,event)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
// v.setOnLongClickListener {
|
||||
// WorkersDb.getRealm().apply {
|
||||
// copyFromRealm(rss)
|
||||
// }
|
||||
// }
|
||||
holder.itemView.setOnLongClickListener(mLongClickListener)
|
||||
holder.itemView.setOnLongClickListener(mLongClickListener)
|
||||
}
|
||||
}
|
||||
|
||||
var layoutManager : LinearLayoutManager? = null
|
||||
@ -242,24 +251,29 @@ internal class RssItemAdapter (
|
||||
this.recyclerView = recyclerView
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun updateData(newList: List<RssData>) {
|
||||
try {
|
||||
DiffUtil.calculateDiff(RssItemDiffUtil(rssDataItemLis, newList)).apply {
|
||||
// DiffUtil.calculateDiff(RssItemDiffUtil(rssDataItemLis, newList)).apply {
|
||||
//
|
||||
// }.dispatchUpdatesTo(this).apply {
|
||||
// val visibleItemCount = (layoutManager?.findLastVisibleItemPosition() ?: 0) - (layoutManager?.findFirstVisibleItemPosition() ?: 0)
|
||||
// val first = layoutManager?.findLastVisibleItemPosition() ?: 0
|
||||
// if (visibleItemCount > 0) {
|
||||
// this@RssItemAdapter.notifyItemRangeChanged(first, visibleItemCount)
|
||||
//// recyclerView?.scrollToPosition(0)
|
||||
// }
|
||||
// }
|
||||
synchronized(rssDataItemLis) {
|
||||
rssDataItemLis.clear()
|
||||
rssDataItemLis.addAll(newList)
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
|
||||
}.dispatchUpdatesTo(this).apply {
|
||||
val visibleItemCount = (layoutManager?.findLastVisibleItemPosition() ?: 0) - (layoutManager?.findFirstVisibleItemPosition() ?: 0)
|
||||
val first = layoutManager?.findLastVisibleItemPosition() ?: 0
|
||||
if (visibleItemCount > 0) {
|
||||
this@RssItemAdapter.notifyItemRangeChanged(first, visibleItemCount)
|
||||
// recyclerView?.scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
rssDataItemLis.clear()
|
||||
rssDataItemLis.addAll(newList)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
rssList.clear()
|
||||
rssList.addAll(newList.map { it.originPage() })
|
||||
}
|
||||
// CoroutineScope(Dispatchers.IO).launch {
|
||||
// rssList.clear()
|
||||
// rssList.addAll(newList.map { it.originPage() })
|
||||
// }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
@ -7,10 +7,9 @@ import bums.lunatic.launcher.helpers.PrefHelper
|
||||
enum class RssDataType {
|
||||
NO_DATA,
|
||||
PRIVATE,
|
||||
TORRENT,
|
||||
YOUTUBE,
|
||||
NEWSFEED,
|
||||
// GURU,
|
||||
// MOST,
|
||||
TAGS,
|
||||
REDDIT,
|
||||
REDDIT_NSFW,
|
||||
|
||||
@ -54,9 +54,11 @@ import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||
import bums.lunatic.launcher.tokiz.view.PagedTextLayout
|
||||
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
|
||||
import bums.lunatic.launcher.databinding.BooktokiBinding
|
||||
import bums.lunatic.launcher.home.toast
|
||||
import bums.lunatic.launcher.tokiz.data.model.FakeSession
|
||||
import bums.lunatic.launcher.tokiz.data.model.FakeSessions
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import bums.lunatic.launcher.workers.WorkersDb
|
||||
import com.google.gson.Gson
|
||||
import io.realm.kotlin.Realm
|
||||
import io.realm.kotlin.UpdatePolicy
|
||||
@ -130,7 +132,7 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
|
||||
abstract var lastNumber : Int
|
||||
abstract val webcontentsName : String
|
||||
abstract val afterDot : String
|
||||
fun getLastedDoamin(): String {
|
||||
open fun getLastedDoamin(): String {
|
||||
return String.format("https://%s%d.%s", webcontentsName , lastNumber, afterDot)
|
||||
}
|
||||
val OnTouchListener = object : OnTouchListener {
|
||||
@ -454,6 +456,12 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface {
|
||||
"SHOWVIEWER" -> {
|
||||
binding.progress.visibility = GONE
|
||||
}
|
||||
"PRIVATES"->{
|
||||
lPortMessage.privates?.let {
|
||||
requireContext().toast("Received Msg privates form ${lPortMessage.currentPage} data => ${it?.size ?: 0}")
|
||||
WorkersDb.insertBulkData(it)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
|
||||
}
|
||||
|
||||
185
app/src/main/kotlin/bums/lunatic/launcher/tokiz/Twitter.kt
Normal file
185
app/src/main/kotlin/bums/lunatic/launcher/tokiz/Twitter.kt
Normal file
@ -0,0 +1,185 @@
|
||||
package bums.lunatic.launcher.tokiz
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.text.InputType
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.RelativeSizeSpan
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.OnTouchListener
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.View.inflate
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
||||
import bums.lunatic.launcher.R
|
||||
import bums.lunatic.launcher.tokiz.common.PairArray
|
||||
import bums.lunatic.launcher.tokiz.common.TouchArea
|
||||
import bums.lunatic.launcher.tokiz.common.colorz
|
||||
import bums.lunatic.launcher.tokiz.common.getIndex
|
||||
import bums.lunatic.launcher.tokiz.common.typesfacez
|
||||
import bums.lunatic.launcher.tokiz.data.HistoryManager
|
||||
import bums.lunatic.launcher.tokiz.data.model.ContentsPageInfo
|
||||
import bums.lunatic.launcher.tokiz.data.model.ContentsCollection
|
||||
import bums.lunatic.launcher.tokiz.data.model.PageInfosJ
|
||||
import bums.lunatic.launcher.tokiz.data.model.HistoryItem
|
||||
import bums.lunatic.launcher.tokiz.data.model.LastInfo
|
||||
import bums.lunatic.launcher.tokiz.data.model.PortMessage
|
||||
import bums.lunatic.launcher.tokiz.data.model.ReaderConfig
|
||||
import bums.lunatic.launcher.tokiz.dialog.DefaultList
|
||||
import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||
import bums.lunatic.launcher.tokiz.view.PagedTextLayout
|
||||
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
|
||||
import bums.lunatic.launcher.databinding.BooktokiBinding
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import com.google.gson.Gson
|
||||
import io.realm.kotlin.Realm
|
||||
import io.realm.kotlin.UpdatePolicy
|
||||
import io.realm.kotlin.ext.copyFromRealm
|
||||
import io.realm.kotlin.ext.query
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.mozilla.gecko.util.ThreadUtils
|
||||
import org.mozilla.geckoview.GeckoResult
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.MediaSession
|
||||
import org.mozilla.geckoview.WebExtension
|
||||
import org.mozilla.geckoview.WebExtension.MessageDelegate
|
||||
import org.mozilla.geckoview.WebExtension.PortDelegate
|
||||
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
|
||||
import org.mozilla.geckoview.WebRequestError
|
||||
import java.lang.System.currentTimeMillis
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.List
|
||||
import kotlin.collections.MutableList
|
||||
import kotlin.collections.arrayListOf
|
||||
import kotlin.collections.first
|
||||
import kotlin.collections.isNotEmpty
|
||||
import kotlin.collections.last
|
||||
import kotlin.collections.sortBy
|
||||
import kotlin.random.Random
|
||||
import kotlin.text.contains
|
||||
import kotlin.text.endsWith
|
||||
import kotlin.text.equals
|
||||
import kotlin.text.replace
|
||||
import kotlin.text.split
|
||||
import kotlin.text.startsWith
|
||||
import kotlin.text.toInt
|
||||
import kotlin.text.toRegex
|
||||
import kotlin.text.trim
|
||||
|
||||
|
||||
class Twitter : BaseToki(), PagedTextViewInterface {
|
||||
|
||||
override val contentsType = "twitter"
|
||||
override var lastNumber : Int = 143
|
||||
override val webcontentsName : String = "twitter"
|
||||
override val afterDot = "com"
|
||||
override fun getLastedDoamin(): String {
|
||||
return String.format("https://%s.%s", webcontentsName, afterDot)
|
||||
}
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
loadLastInfo()
|
||||
}
|
||||
|
||||
override fun onTouch(touchArea: TouchArea) {
|
||||
Blog.LOGD(log = "onTouch ${touchArea}")
|
||||
when (touchArea) {
|
||||
TouchArea.Center -> {
|
||||
|
||||
}
|
||||
|
||||
TouchArea.Right -> {
|
||||
actionNextEvent()
|
||||
}
|
||||
|
||||
TouchArea.Left -> {
|
||||
actionPrevEvent()
|
||||
}
|
||||
|
||||
TouchArea.DoubleRight -> {
|
||||
actionNextEvent(true)
|
||||
}
|
||||
|
||||
TouchArea.DoubleLeft -> {
|
||||
actionPrevEvent(true)
|
||||
}
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun onLongClick() {
|
||||
Blog.LOGD(log = "onLongClick")
|
||||
|
||||
}
|
||||
|
||||
override fun onSwipeLeft(count: Int) {
|
||||
Blog.LOGD(log = "onSwipeLeft ${count}")
|
||||
actionNextEvent(count > 1)
|
||||
|
||||
}
|
||||
|
||||
override fun onSwipeRight(count: Int) {
|
||||
Blog.LOGD(log = "onSwipeRight ${count}")
|
||||
actionPrevEvent(count > 1)
|
||||
}
|
||||
|
||||
override fun onSwipeUp(touchCount: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onSwipeDown(touchCount: Int) {
|
||||
if (touchCount == 2) {
|
||||
if (binding.pagedLayer.isVisible) {
|
||||
binding.pagedLayer.visibility = GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTimeoverTouch() {
|
||||
|
||||
}
|
||||
}
|
||||
182
app/src/main/kotlin/bums/lunatic/launcher/tokiz/Zota.kt
Normal file
182
app/src/main/kotlin/bums/lunatic/launcher/tokiz/Zota.kt
Normal file
@ -0,0 +1,182 @@
|
||||
package bums.lunatic.launcher.tokiz
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.text.InputType
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.RelativeSizeSpan
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.OnTouchListener
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.View.inflate
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
||||
import bums.lunatic.launcher.R
|
||||
import bums.lunatic.launcher.tokiz.common.PairArray
|
||||
import bums.lunatic.launcher.tokiz.common.TouchArea
|
||||
import bums.lunatic.launcher.tokiz.common.colorz
|
||||
import bums.lunatic.launcher.tokiz.common.getIndex
|
||||
import bums.lunatic.launcher.tokiz.common.typesfacez
|
||||
import bums.lunatic.launcher.tokiz.data.HistoryManager
|
||||
import bums.lunatic.launcher.tokiz.data.model.ContentsPageInfo
|
||||
import bums.lunatic.launcher.tokiz.data.model.ContentsCollection
|
||||
import bums.lunatic.launcher.tokiz.data.model.PageInfosJ
|
||||
import bums.lunatic.launcher.tokiz.data.model.HistoryItem
|
||||
import bums.lunatic.launcher.tokiz.data.model.LastInfo
|
||||
import bums.lunatic.launcher.tokiz.data.model.PortMessage
|
||||
import bums.lunatic.launcher.tokiz.data.model.ReaderConfig
|
||||
import bums.lunatic.launcher.tokiz.dialog.DefaultList
|
||||
import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||
import bums.lunatic.launcher.tokiz.view.PagedTextLayout
|
||||
import bums.lunatic.launcher.tokiz.view.PagedTextViewInterface
|
||||
import bums.lunatic.launcher.databinding.BooktokiBinding
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import com.google.gson.Gson
|
||||
import io.realm.kotlin.Realm
|
||||
import io.realm.kotlin.UpdatePolicy
|
||||
import io.realm.kotlin.ext.copyFromRealm
|
||||
import io.realm.kotlin.ext.query
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.mozilla.gecko.util.ThreadUtils
|
||||
import org.mozilla.geckoview.GeckoResult
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.MediaSession
|
||||
import org.mozilla.geckoview.WebExtension
|
||||
import org.mozilla.geckoview.WebExtension.MessageDelegate
|
||||
import org.mozilla.geckoview.WebExtension.PortDelegate
|
||||
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
|
||||
import org.mozilla.geckoview.WebRequestError
|
||||
import java.lang.System.currentTimeMillis
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.List
|
||||
import kotlin.collections.MutableList
|
||||
import kotlin.collections.arrayListOf
|
||||
import kotlin.collections.first
|
||||
import kotlin.collections.isNotEmpty
|
||||
import kotlin.collections.last
|
||||
import kotlin.collections.sortBy
|
||||
import kotlin.random.Random
|
||||
import kotlin.text.contains
|
||||
import kotlin.text.endsWith
|
||||
import kotlin.text.equals
|
||||
import kotlin.text.replace
|
||||
import kotlin.text.split
|
||||
import kotlin.text.startsWith
|
||||
import kotlin.text.toInt
|
||||
import kotlin.text.toRegex
|
||||
import kotlin.text.trim
|
||||
|
||||
|
||||
class Zota : BaseToki(), PagedTextViewInterface {
|
||||
|
||||
override val contentsType = "Torrent"
|
||||
override var lastNumber : Int = 143
|
||||
override val webcontentsName : String = "torrentzota"
|
||||
override val afterDot = "com"
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
loadLastInfo()
|
||||
}
|
||||
|
||||
override fun onTouch(touchArea: TouchArea) {
|
||||
Blog.LOGD(log = "onTouch ${touchArea}")
|
||||
when (touchArea) {
|
||||
TouchArea.Center -> {
|
||||
|
||||
}
|
||||
|
||||
TouchArea.Right -> {
|
||||
actionNextEvent()
|
||||
}
|
||||
|
||||
TouchArea.Left -> {
|
||||
actionPrevEvent()
|
||||
}
|
||||
|
||||
TouchArea.DoubleRight -> {
|
||||
actionNextEvent(true)
|
||||
}
|
||||
|
||||
TouchArea.DoubleLeft -> {
|
||||
actionPrevEvent(true)
|
||||
}
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun onLongClick() {
|
||||
Blog.LOGD(log = "onLongClick")
|
||||
|
||||
}
|
||||
|
||||
override fun onSwipeLeft(count: Int) {
|
||||
Blog.LOGD(log = "onSwipeLeft ${count}")
|
||||
actionNextEvent(count > 1)
|
||||
|
||||
}
|
||||
|
||||
override fun onSwipeRight(count: Int) {
|
||||
Blog.LOGD(log = "onSwipeRight ${count}")
|
||||
actionPrevEvent(count > 1)
|
||||
}
|
||||
|
||||
override fun onSwipeUp(touchCount: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onSwipeDown(touchCount: Int) {
|
||||
if (touchCount == 2) {
|
||||
if (binding.pagedLayer.isVisible) {
|
||||
binding.pagedLayer.visibility = GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTimeoverTouch() {
|
||||
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,8 @@ import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.RectF
|
||||
import android.media.MediaCodec
|
||||
import android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar
|
||||
import android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar
|
||||
import android.media.MediaExtractor
|
||||
import android.media.MediaFormat
|
||||
import android.renderscript.Allocation
|
||||
@ -18,6 +20,8 @@ import android.util.DisplayMetrics
|
||||
import android.view.SurfaceHolder
|
||||
import android.view.WindowManager
|
||||
import bums.lunatic.launcher.R
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
|
||||
class MyWallpaperService : WallpaperService() {
|
||||
@ -51,6 +55,8 @@ class MyWallpaperService : WallpaperService() {
|
||||
screenWidth = metrics.widthPixels
|
||||
screenHeight = metrics.heightPixels
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun onSurfaceCreated(holder: SurfaceHolder) {
|
||||
@ -98,6 +104,7 @@ class RenderThread(
|
||||
private var renderStartY = 0f
|
||||
private var maxOffset = 0f
|
||||
private var moveXAxis = false
|
||||
private var keyFrameRate = 60
|
||||
|
||||
override fun run() {
|
||||
try {
|
||||
@ -110,9 +117,16 @@ class RenderThread(
|
||||
for (i in 0 until trackCount) {
|
||||
val format = getTrackFormat(i)
|
||||
val mime = format.getString(MediaFormat.KEY_MIME) ?: ""
|
||||
|
||||
if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
|
||||
keyFrameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE)
|
||||
} else {
|
||||
keyFrameRate = 60
|
||||
}
|
||||
if (mime.startsWith("video/")) {
|
||||
videoTrackIndex = i
|
||||
selectTrack(i)
|
||||
|
||||
videoWidth = format.getInteger(MediaFormat.KEY_WIDTH)
|
||||
videoHeight = format.getInteger(MediaFormat.KEY_HEIGHT)
|
||||
break
|
||||
@ -144,8 +158,8 @@ class RenderThread(
|
||||
}
|
||||
renderWidth = videoWidth * scale
|
||||
renderHeight = videoHeight * scale
|
||||
renderStartX = (screenWidth - renderWidth) / 2f
|
||||
renderStartY = (screenHeight - renderHeight) / 2f
|
||||
renderStartX = 0f;//(screenWidth - renderWidth) / 2f
|
||||
renderStartY = 0f;//(screenHeight - renderHeight) / 2f
|
||||
|
||||
moveXAxis = renderWidth > screenWidth
|
||||
maxOffset = if (moveXAxis) renderWidth - screenWidth else if (renderHeight > screenHeight) renderHeight - screenHeight else 0f
|
||||
@ -161,9 +175,12 @@ class RenderThread(
|
||||
if (inputBuffer != null) {
|
||||
val sampleSize = extractor?.readSampleData(inputBuffer, 0) ?: -1
|
||||
if (sampleSize < 0) {
|
||||
codec?.queueInputBuffer(
|
||||
inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
|
||||
isEOS = true
|
||||
// codec?.queueInputBuffer(
|
||||
// inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
|
||||
// isEOS = true
|
||||
extractor?.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC)
|
||||
isEOS = false // false로 재설정해서 계속 받게
|
||||
continue
|
||||
} else {
|
||||
val pts = extractor?.sampleTime ?: 0L
|
||||
codec?.queueInputBuffer(inputBufferIndex, 0, sampleSize, pts, 0)
|
||||
@ -176,13 +193,35 @@ class RenderThread(
|
||||
val outputBufferIndex = codec?.dequeueOutputBuffer(bufferInfo, 10000) ?: -1
|
||||
if (outputBufferIndex >= 0) {
|
||||
val outputBuffer = codec?.getOutputBuffer(outputBufferIndex)
|
||||
Blog.LOGE("codec.outputFormat >>> ${codec?.outputFormat}")
|
||||
if (bufferInfo.size > 0 && outputBuffer != null) {
|
||||
val yuvData = ByteArray(bufferInfo.size)
|
||||
outputBuffer.get(yuvData)
|
||||
val format = codec?.outputFormat
|
||||
|
||||
val bitmap = convertYUVToBitmap(yuvData, videoWidth, videoHeight)
|
||||
val colorFormat = format?.getInteger(MediaFormat.KEY_COLOR_FORMAT) ?: /*기본값*/0
|
||||
val stride = format?.getInteger(MediaFormat.KEY_STRIDE) ?: videoWidth
|
||||
val sliceHeight = format?.getInteger(MediaFormat.KEY_SLICE_HEIGHT) ?: videoHeight
|
||||
// outputBuffer.get(yuvData)
|
||||
val expectedSize = videoWidth * videoHeight * 3 / 2
|
||||
val yuvData = ByteArray(expectedSize)
|
||||
val rawYUV = ByteArray(bufferInfo.size)
|
||||
outputBuffer.get(rawYUV)
|
||||
outputBuffer.position(0)
|
||||
|
||||
// 포맷별 변환
|
||||
val nv21Data = when (colorFormat) {
|
||||
COLOR_FormatYUV420SemiPlanar -> nv12ToNv21(rawYUV, videoWidth, videoHeight)
|
||||
COLOR_FormatYUV420Planar -> i420ToNv21(rawYUV, videoWidth, videoHeight)
|
||||
else -> rawYUV // 이미 NV21 등
|
||||
}
|
||||
|
||||
// NV21 데이터 → Bitmap
|
||||
val bitmap = convertYUVToBitmap(nv21Data, videoWidth, videoHeight)
|
||||
// outputBuffer.get(yuvData, 0, minOf(bufferInfo.size, expectedSize))
|
||||
// getYUVDataWithStride(outputBuffer, videoWidth, videoHeight, stride, height)
|
||||
// val bitmap = convertYUVToBitmap(yuvData, videoWidth, videoHeight)
|
||||
|
||||
// 6. 왕복 이동 애니메이션 offset 계산
|
||||
// Blog.LOGE("maxOffset >>> $maxOffset , offset >>> $offset , direction >> $direction , keyFrameRate >>> $keyFrameRate")
|
||||
if (maxOffset > 0f) {
|
||||
offset += direction * speed
|
||||
if (offset < 0f) { offset = 0f; direction = 1 }
|
||||
@ -215,7 +254,7 @@ class RenderThread(
|
||||
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
|
||||
// 필요하다면 포맷 변경 처리
|
||||
}
|
||||
sleep(1000L/45L) // 약 30fps
|
||||
sleep(1000L / keyFrameRate) // 약 30fps
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -229,13 +268,17 @@ class RenderThread(
|
||||
}
|
||||
|
||||
private fun convertYUVToBitmap(yuvByteArray: ByteArray, width: Int, height: Int): Bitmap {
|
||||
val yuvType = Type.Builder(rs, Element.U8(rs)).setX(yuvByteArray.size)
|
||||
// YUV420の場合, 바이트 수는 width * height * 3 / 2 여야 함
|
||||
val minSize = width * height * 3 / 2
|
||||
val realData = if (yuvByteArray.size >= minSize) yuvByteArray.copyOf(minSize) else yuvByteArray
|
||||
|
||||
val yuvType = Type.Builder(rs, Element.U8(rs)).setX(minSize)
|
||||
val inAllocation = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT)
|
||||
|
||||
val rgbaType = Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height)
|
||||
val outAllocation = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT)
|
||||
|
||||
inAllocation.copyFrom(yuvByteArray)
|
||||
inAllocation.copyFrom(realData)
|
||||
yuvToRgb?.setInput(inAllocation)
|
||||
yuvToRgb?.forEach(outAllocation)
|
||||
|
||||
@ -247,4 +290,91 @@ class RenderThread(
|
||||
|
||||
return bitmap
|
||||
}
|
||||
|
||||
private fun getYUVDataWithStride(
|
||||
buffer: ByteBuffer,
|
||||
width: Int,
|
||||
height: Int,
|
||||
stride: Int,
|
||||
sliceHeight: Int
|
||||
): ByteArray {
|
||||
val yuvData = ByteArray(width * height * 3 / 2)
|
||||
// Y plane 복사
|
||||
for (y in 0 until height) {
|
||||
buffer.position(y * stride)
|
||||
buffer.get(yuvData, y * width, width)
|
||||
}
|
||||
// UV plane... (NV21 등 포맷 따라 별도 구현 필요)
|
||||
// 이 영역은 포맷에 따라 다름, 기본은 Y만 참고!
|
||||
return yuvData
|
||||
}
|
||||
|
||||
// NV12 to NV21 변환
|
||||
fun nv12ToNv21(nv12: ByteArray, width: Int, height: Int): ByteArray {
|
||||
val frameSize = width * height
|
||||
val nv21 = ByteArray(frameSize * 3 / 2)
|
||||
|
||||
// Y는 그대로 복사
|
||||
System.arraycopy(nv12, 0, nv21, 0, frameSize)
|
||||
|
||||
// UV를 VU로 뒤집어서 복사
|
||||
var i = 0
|
||||
while (i < frameSize / 2 - 1) {
|
||||
nv21[frameSize + i] = nv12[frameSize + i + 1]
|
||||
nv21[frameSize + i + 1] = nv12[frameSize + i]
|
||||
i += 2
|
||||
}
|
||||
return nv21
|
||||
}
|
||||
|
||||
// I420(YUV420Planar) to NV21 변환
|
||||
fun i420ToNv21(i420: ByteArray, width: Int, height: Int): ByteArray {
|
||||
val frameSize = width * height
|
||||
val qFrameSize = frameSize / 4
|
||||
val nv21 = ByteArray(frameSize * 3 / 2)
|
||||
|
||||
// Y 복사
|
||||
System.arraycopy(i420, 0, nv21, 0, frameSize)
|
||||
|
||||
// VU interleave
|
||||
val u = frameSize
|
||||
val v = frameSize + qFrameSize
|
||||
|
||||
for (i in 0 until qFrameSize) {
|
||||
nv21[frameSize + i * 2] = i420[v + i] // V
|
||||
nv21[frameSize + i * 2 + 1] = i420[u + i] // U
|
||||
}
|
||||
return nv21
|
||||
}
|
||||
fun i420ToNv21WithStride(src: ByteBuffer, width: Int, height: Int, stride: Int, sliceHeight: Int): ByteArray {
|
||||
val frameSize = width * height
|
||||
val qFrameSize = frameSize / 4
|
||||
val nv21 = ByteArray(frameSize * 3 / 2)
|
||||
|
||||
// 1. Y plane 복사
|
||||
for (y in 0 until height) {
|
||||
src.position(y * stride)
|
||||
src.get(nv21, y * width, width)
|
||||
}
|
||||
|
||||
// 2. U/V plane 복사, 각각 stride/2씩 적용
|
||||
val uOffsetBuf = sliceHeight * stride
|
||||
val vOffsetBuf = uOffsetBuf + (sliceHeight / 2) * (stride / 2)
|
||||
|
||||
for (y in 0 until height/2) {
|
||||
src.position(uOffsetBuf + y * (stride / 2))
|
||||
src.get(nv21, frameSize + y * width, width/2) // 임시: U만
|
||||
|
||||
src.position(vOffsetBuf + y * (stride / 2))
|
||||
for (x in 0 until width/2) {
|
||||
// NV21 순서: V, U
|
||||
val v = src.get()
|
||||
val u = nv21[frameSize + y * width + x] // U
|
||||
nv21[frameSize + y * width + x*2] = v
|
||||
nv21[frameSize + y * width + x*2 + 1] = u
|
||||
}
|
||||
}
|
||||
|
||||
return nv21
|
||||
}
|
||||
}
|
||||
@ -77,12 +77,12 @@ class DCGetter : BaseGetter {
|
||||
Blog.LOGE("realWork() ${this::class.simpleName}")
|
||||
temp.clear()
|
||||
// https://m.dcinside.com/board/singlebungle1472
|
||||
//"https://m.dcinside.com/board/programming",
|
||||
//"https://m.dcinside.com/board/reading",
|
||||
var urls = arrayListOf(
|
||||
"https://m.dcinside.com",
|
||||
"https://m.dcinside.com/board/singlebungle1472",
|
||||
"https://m.dcinside.com/board/programming",
|
||||
"https://m.dcinside.com/board/cartoon",
|
||||
"https://m.dcinside.com/board/reading",
|
||||
"https://m.dcinside.com/board/hit",
|
||||
"https://m.dcinside.com/board/dcbest"
|
||||
)
|
||||
|
||||
BIN
app/src/main/res/drawable/ic_b.png
Normal file
BIN
app/src/main/res/drawable/ic_b.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 565 B |
@ -59,6 +59,17 @@
|
||||
android:id="@+id/comics"
|
||||
style="@style/tabItem"
|
||||
android:layout_height="match_parent"/>
|
||||
<androidx.appcompat.widget.AppCompatRadioButton
|
||||
android:text="zota"
|
||||
android:id="@+id/zota"
|
||||
style="@style/tabItem"
|
||||
android:layout_height="match_parent"/>
|
||||
<androidx.appcompat.widget.AppCompatRadioButton
|
||||
android:text="twitter"
|
||||
android:visibility="gone"
|
||||
android:id="@+id/twitter"
|
||||
style="@style/tabItem"
|
||||
android:layout_height="match_parent"/>
|
||||
<Button
|
||||
android:text="hidden"
|
||||
android:id="@+id/hidden"
|
||||
|
||||
@ -1,36 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/colorInputLayout"
|
||||
android:layout_width="@dimen/oneNinetySix"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="inpout text"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/colorInputLayout"
|
||||
android:layout_width="@dimen/oneNinetySix"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="inpout text"
|
||||
android:orientation="horizontal"
|
||||
app:boxBackgroundColor="?attr/colorSurface"
|
||||
app:endIconMode="clear_text"
|
||||
android:gravity="right"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:ignore="MissingConstraints">
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
app:boxBackgroundColor="?attr/colorSurface"
|
||||
app:endIconMode="clear_text"
|
||||
android:gravity="right"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="text" />
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<CheckBox
|
||||
android:padding="0dp"
|
||||
android:text="PRIVATE MODE"
|
||||
android:textColor="@color/white"
|
||||
android:text="add Vote"
|
||||
android:textColor="@color/black"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:id="@+id/parivate_mode"
|
||||
android:checked="true"
|
||||
android:id="@+id/add_vote"
|
||||
android:checked="false"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<CheckBox
|
||||
android:padding="0dp"
|
||||
android:text="Add Read"
|
||||
android:textColor="@color/black"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:id="@+id/add_read"
|
||||
android:checked="false"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="text" />
|
||||
<CheckBox
|
||||
android:padding="0dp"
|
||||
android:text="PRIVATE"
|
||||
android:textColor="@color/black"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:id="@+id/parivate_mode"
|
||||
android:checked="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
BIN
app/src/main/res/raw/sm2.mp4
Normal file
BIN
app/src/main/res/raw/sm2.mp4
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user