...
This commit is contained in:
parent
f7f71ca195
commit
2f63f8550a
@ -120,7 +120,9 @@ dependencies {
|
|||||||
// implementation("org.opencv:opencv-android:4.11.0")
|
// implementation("org.opencv:opencv-android:4.11.0")
|
||||||
// build.gradle에 추가
|
// build.gradle에 추가
|
||||||
// implementation ("com.github.aeonSolutions:FloatingActionButtonMenuDrag:1.1")
|
// implementation ("com.github.aeonSolutions:FloatingActionButtonMenuDrag:1.1")
|
||||||
|
implementation("io.github.junkfood02.youtubedl-android:library:0.17.4")
|
||||||
|
implementation("io.github.junkfood02.youtubedl-android:ffmpeg:0.17.4")
|
||||||
|
implementation("io.github.junkfood02.youtubedl-android:aria2c:0.17.4")
|
||||||
|
|
||||||
|
|
||||||
implementation ("androidx.media:media:1.7.0")
|
implementation ("androidx.media:media:1.7.0")
|
||||||
|
|||||||
@ -79,6 +79,7 @@
|
|||||||
android:stateNotNeeded="true"
|
android:stateNotNeeded="true"
|
||||||
android:enableOnBackInvokedCallback="true"
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
|
android:extractNativeLibs="true"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
@ -136,7 +137,7 @@
|
|||||||
<!-- </activity>-->
|
<!-- </activity>-->
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".helpers.BluetoothManager"
|
android:name=".helpers.ForeGroundService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<service
|
<service
|
||||||
@ -169,16 +170,16 @@
|
|||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
<!-- <activity-->
|
<activity
|
||||||
<!-- android:name=".settings.SettingsActivity"-->
|
android:name=".settings.SettingsActivity"
|
||||||
<!-- android:label="@string/lunar_settings"-->
|
android:label="@string/lunar_settings"
|
||||||
<!-- android:launchMode="singleTask"-->
|
android:launchMode="singleTask"
|
||||||
<!-- android:excludeFromRecents="true"-->
|
android:excludeFromRecents="true"
|
||||||
<!-- android:exported="true">-->
|
android:exported="true">
|
||||||
<!-- <intent-filter>-->
|
<intent-filter>
|
||||||
<!-- <action android:name="android.intent.action.APPLICATION_PREFERENCES" />-->
|
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
|
||||||
<!-- </intent-filter>-->
|
</intent-filter>
|
||||||
<!-- </activity>-->
|
</activity>
|
||||||
<!-- <activity-->
|
<!-- <activity-->
|
||||||
<!-- android:name=".behavior.Behavior"-->
|
<!-- android:name=".behavior.Behavior"-->
|
||||||
<!-- android:label="@string/lunar_settings"-->
|
<!-- android:label="@string/lunar_settings"-->
|
||||||
@ -269,15 +270,17 @@
|
|||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/file_paths" />
|
android:resource="@xml/file_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
<!-- <service android:name=".receiver.NLService"-->
|
|
||||||
<!-- android:label="@string/app_name"-->
|
<service android:name=".receiver.NLService"
|
||||||
<!-- android:enabled="true"-->
|
android:label="@string/app_name"
|
||||||
<!-- android:exported="true"-->
|
android:enabled="true"
|
||||||
<!-- android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">-->
|
android:exported="true"
|
||||||
<!-- <intent-filter>-->
|
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||||
<!-- <action android:name="android.service.notification.NotificationListenerService" />-->
|
<intent-filter>
|
||||||
<!-- </intent-filter>-->
|
<action android:name="android.service.notification.NotificationListenerService" />
|
||||||
<!-- </service>-->
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
<!-- <service android:name="bums.lunatic.launcher.workers.LocationUpdateService" />-->
|
<!-- <service android:name="bums.lunatic.launcher.workers.LocationUpdateService" />-->
|
||||||
|
|
||||||
<!-- <receiver android:name=".LauncherActivity$EndCallReceiver"-->
|
<!-- <receiver android:name=".LauncherActivity$EndCallReceiver"-->
|
||||||
|
|||||||
@ -253,9 +253,16 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
if (port) {
|
if (port) {
|
||||||
sendMessage({type: "MSG", msg: "connect prot"});
|
sendMessage({type: "MSG", msg: "connect prot"});
|
||||||
time1 = setTimeout(autoScrollAndSave(false), 3500)
|
time1 = setTimeout(autoScrollAndSave(false), 3500)
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
document.addEventListener('touchstart', function(e) {
|
||||||
|
console.log('터치 시작');
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('touchend', function(e) {
|
||||||
|
autoScrollAndSave()
|
||||||
|
});
|
||||||
|
|
||||||
function scrollToLazyImg(fastMode) {
|
function scrollToLazyImg(fastMode) {
|
||||||
(function(autoScrollAndSave){
|
(function(autoScrollAndSave){
|
||||||
@ -346,12 +353,16 @@ function isNewerThanOneDay(dateStr) {
|
|||||||
function autoScrollAndSave(senContents) {
|
function autoScrollAndSave(senContents) {
|
||||||
// 도메인에 맞는 handler 실행
|
// 도메인에 맞는 handler 실행
|
||||||
const matchedRule = domainRules.find(rule => rule.test(location.href));
|
const matchedRule = domainRules.find(rule => rule.test(location.href));
|
||||||
|
try {
|
||||||
if (matchedRule) {
|
if (matchedRule) {
|
||||||
matchedRule.handler();
|
matchedRule.handler();
|
||||||
}
|
}
|
||||||
|
}catch (e) { }
|
||||||
|
|
||||||
|
try {
|
||||||
// 공통 광고 요소 제거는 항상 실행
|
// 공통 광고 요소 제거는 항상 실행
|
||||||
handleCommon();
|
handleCommon();
|
||||||
window.scrollTo({ top: 2, behavior: 'smooth' });
|
}catch (e) { }
|
||||||
if (mainContentsEl == null) {
|
if (mainContentsEl == null) {
|
||||||
mainContentsEl = document.body.outerHTML
|
mainContentsEl = document.body.outerHTML
|
||||||
}
|
}
|
||||||
@ -545,7 +556,11 @@ function handleCommon() {
|
|||||||
|
|
||||||
gotoNext()
|
gotoNext()
|
||||||
}
|
}
|
||||||
window.scrollTo({ top: 2, behavior: 'smooth' });
|
if (window.scrollY < 5) {
|
||||||
|
console.log("window.scrollY >>> " + window.scrollY)
|
||||||
|
window.scrollTo({ top: 5, behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
function handleToreentZota() {
|
function handleToreentZota() {
|
||||||
if (location.href.search("torrentzota") > -1 && document.querySelectorAll('a')) {
|
if (location.href.search("torrentzota") > -1 && document.querySelectorAll('a')) {
|
||||||
@ -759,13 +774,26 @@ function handleDoctorsnews() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleDcinside() {
|
function handleDcinside() {
|
||||||
|
try {
|
||||||
document.querySelectorAll(
|
document.querySelectorAll(
|
||||||
'[id^="view_btn_area"], [class^="trend-rank"], [class^="view-btm-con"], [class^="md-tit-box"], [class^="gall-detail-lst"], [class^="outside-search-box"], [class^="footer ftlong"], [class^="adv-group"], li[style^="cursor:default;"], [id^="div_adnmore_area"]'
|
'[id^="view_btn_area"], [class^="trend-rank"], [class^="view-btm-con"], [class^="md-tit-box"], [class^="gall-detail-lst"], [class^="outside-search-box"], [class^="footer ftlong"], [class^="adv-group"], li[style^="cursor:default;"], [id^="div_adnmore_area"]'
|
||||||
).forEach(e => e.remove());
|
).forEach(e => e.remove());
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
try {
|
||||||
document.querySelectorAll('div[class^="imgwrap"]').forEach(function (e) {
|
document.querySelectorAll('div[class^="imgwrap"]').forEach(function (e) {
|
||||||
try {e.style.backgroundColor = 'red';} catch (e) {}
|
try {e.style.backgroundColor = 'red';} catch (e) {}
|
||||||
})
|
})
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
document.querySelectorAll('div[class^="imgwrap"]')[0].click()
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
mainContentsEl = document.querySelector('div[class="container"]');
|
mainContentsEl = document.querySelector('div[class="container"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,13 +22,11 @@ package bums.lunatic.launcher
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.SearchManager
|
import android.app.SearchManager
|
||||||
import android.appwidget.AppWidgetManager
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Rect
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@ -49,89 +47,50 @@ import android.view.PointerIcon
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Button
|
|
||||||
import android.widget.HorizontalScrollView
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy
|
|
||||||
import androidx.work.OneTimeWorkRequest
|
|
||||||
import androidx.work.PeriodicWorkRequestBuilder
|
|
||||||
import androidx.work.WorkManager
|
|
||||||
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
|
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
|
||||||
import bums.lunatic.launcher.apps.AppDrawer
|
import bums.lunatic.launcher.apps.AppDrawer
|
||||||
import bums.lunatic.launcher.tokiz.Novels
|
|
||||||
import bums.lunatic.launcher.common.CommonActivity
|
import bums.lunatic.launcher.common.CommonActivity
|
||||||
import bums.lunatic.launcher.databinding.LauncherActivityBinding
|
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.KEY_STATUS_BAR
|
||||||
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
||||||
import bums.lunatic.launcher.helpers.Constants.Companion.widgetHostId
|
import bums.lunatic.launcher.helpers.ForeGroundService
|
||||||
import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver
|
import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver
|
||||||
import bums.lunatic.launcher.helpers.PrefHelper.putString
|
|
||||||
import bums.lunatic.launcher.helpers.PrefLong
|
|
||||||
import bums.lunatic.launcher.home.GeckoWeb
|
|
||||||
import bums.lunatic.launcher.home.RssHome
|
import bums.lunatic.launcher.home.RssHome
|
||||||
import bums.lunatic.launcher.home.RssViewBuilder
|
import bums.lunatic.launcher.home.RssViewBuilder
|
||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.model.RssDataType
|
import bums.lunatic.launcher.model.RssDataType
|
||||||
|
import bums.lunatic.launcher.receiver.NLService
|
||||||
|
import bums.lunatic.launcher.settings.SettingsActivity
|
||||||
import bums.lunatic.launcher.tokiz.Comics
|
import bums.lunatic.launcher.tokiz.Comics
|
||||||
import bums.lunatic.launcher.tokiz.Magnet
|
import bums.lunatic.launcher.tokiz.Magnet
|
||||||
|
import bums.lunatic.launcher.tokiz.Novels
|
||||||
import bums.lunatic.launcher.tokiz.Perplexity
|
import bums.lunatic.launcher.tokiz.Perplexity
|
||||||
import bums.lunatic.launcher.tokiz.Twitter
|
import bums.lunatic.launcher.tokiz.Twitter
|
||||||
import bums.lunatic.launcher.tokiz.Webtoons
|
import bums.lunatic.launcher.tokiz.Webtoons
|
||||||
import bums.lunatic.launcher.tokiz.Zota
|
import bums.lunatic.launcher.tokiz.Zota
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import bums.lunatic.launcher.utils.FeedParseManager
|
|
||||||
import bums.lunatic.launcher.utils.getJ
|
|
||||||
import bums.lunatic.launcher.workers.AppInfoGetter
|
|
||||||
import bums.lunatic.launcher.workers.ArcaGetter
|
|
||||||
import bums.lunatic.launcher.workers.CalendarGetter
|
|
||||||
import bums.lunatic.launcher.workers.ClienGetter
|
|
||||||
import bums.lunatic.launcher.workers.ContactInfoGetter
|
|
||||||
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.RecentCallGetter
|
|
||||||
import bums.lunatic.launcher.workers.RecentSmsGetter
|
|
||||||
import bums.lunatic.launcher.workers.RecentSmsGetter.Companion.SMS_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.WorkersDb
|
import bums.lunatic.launcher.workers.WorkersDb
|
||||||
import bums.lunatic.launcher.workers.YoutubeGetter
|
|
||||||
import bums.lunatic.launcher.workers.YoutubeGetter.Companion.YT_WORK_TAG
|
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
|
import com.yausername.ffmpeg.FFmpeg
|
||||||
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
|
import com.yausername.youtubedl_android.YoutubeDLException
|
||||||
import io.realm.kotlin.ext.query
|
import io.realm.kotlin.ext.query
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kr.lunaticbum.utils.ui.DisplayUtil
|
import kr.lunaticbum.utils.ui.DisplayUtil
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import org.mozilla.geckoview.ExperimentDelegate
|
import org.mozilla.geckoview.ExperimentDelegate
|
||||||
import org.mozilla.geckoview.GeckoResult
|
import org.mozilla.geckoview.GeckoResult
|
||||||
import org.mozilla.geckoview.GeckoRuntime
|
import org.mozilla.geckoview.GeckoRuntime
|
||||||
import org.mozilla.geckoview.GeckoRuntimeSettings
|
import org.mozilla.geckoview.GeckoRuntimeSettings
|
||||||
import java.util.Base64
|
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlin.jvm.java
|
|
||||||
|
|
||||||
|
|
||||||
open class LauncherActivity : CommonActivity() {
|
open class LauncherActivity : CommonActivity() {
|
||||||
@ -209,7 +168,8 @@ open class LauncherActivity : CommonActivity() {
|
|||||||
Blog.LOGE("onConfigurationChanged newConfig?.screenWidthDp >> ${newConfig?.screenWidthDp}")
|
Blog.LOGE("onConfigurationChanged newConfig?.screenWidthDp >> ${newConfig?.screenWidthDp}")
|
||||||
Blog.LOGE("onConfigurationChanged newConfig?.screenHeightDp >> ${newConfig?.screenHeightDp}")
|
Blog.LOGE("onConfigurationChanged newConfig?.screenHeightDp >> ${newConfig?.screenHeightDp}")
|
||||||
isOpendFold = (newConfig.screenWidthDp * 1.1f) > newConfig.screenHeightDp
|
isOpendFold = (newConfig.screenWidthDp * 1.1f) > newConfig.screenHeightDp
|
||||||
|
val nullCursor = PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL)
|
||||||
|
binding.root.setPointerIcon(nullCursor)
|
||||||
}
|
}
|
||||||
// override fun onKeyClick(keyCode: Int): Boolean {
|
// override fun onKeyClick(keyCode: Int): Boolean {
|
||||||
// when (keyCode) {
|
// when (keyCode) {
|
||||||
@ -533,15 +493,24 @@ open class LauncherActivity : CommonActivity() {
|
|||||||
@SuppressLint("NewApi", "MissingPermission")
|
@SuppressLint("NewApi", "MissingPermission")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
installSplashScreen()
|
installSplashScreen()
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
try {
|
||||||
|
YoutubeDL.getInstance().init(this)
|
||||||
|
FFmpeg.getInstance().init(this);
|
||||||
|
} catch (e: YoutubeDLException) {
|
||||||
|
Blog.LOGE("failed to initialize youtubedl-android", e)
|
||||||
|
}
|
||||||
|
val intent = Intent(this, ForeGroundService::class.java)
|
||||||
|
this.startForegroundService(intent)
|
||||||
|
|
||||||
|
val nlService = Intent(this, NLService::class.java)
|
||||||
|
this.startService(nlService)
|
||||||
|
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||||
lActivity = this
|
lActivity = this
|
||||||
|
|
||||||
DynamicColors.applyToActivityIfAvailable(this)
|
DynamicColors.applyToActivityIfAvailable(this)
|
||||||
|
|
||||||
|
|
||||||
settingsPrefs = getSharedPreferences(PREFS_SETTINGS, 0)
|
settingsPrefs = getSharedPreferences(PREFS_SETTINGS, 0)
|
||||||
// AppCompatDelegate.setDefaultNightMode(settingsPrefs.getInt(KEY_APPLICATION_THEME, MODE_NIGHT_FOLLOW_SYSTEM))
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
binding = LauncherActivityBinding.inflate(layoutInflater)
|
binding = LauncherActivityBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
@ -553,8 +522,8 @@ open class LauncherActivity : CommonActivity() {
|
|||||||
updateLocationService()
|
updateLocationService()
|
||||||
|
|
||||||
|
|
||||||
val intent = Intent(this, BluetoothManager::class.java)
|
|
||||||
ContextCompat.startForegroundService(this, intent)
|
|
||||||
showContents(binding.feeds.id)
|
showContents(binding.feeds.id)
|
||||||
binding.floatingActionMenu.setOnMenuButtonClickListener { v->
|
binding.floatingActionMenu.setOnMenuButtonClickListener { v->
|
||||||
Blog.LOGE("v >> ${v}")
|
Blog.LOGE("v >> ${v}")
|
||||||
@ -622,6 +591,10 @@ open class LauncherActivity : CommonActivity() {
|
|||||||
.replace(R.id.fragment_container, Magnet())
|
.replace(R.id.fragment_container, Magnet())
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
|
R.id.setting ->{
|
||||||
|
startActivity(Intent(this, SettingsActivity::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
binding.floatingActionMenu.close(false)
|
binding.floatingActionMenu.close(false)
|
||||||
|
|||||||
@ -2,9 +2,9 @@ package bums.lunatic.launcher.helpers
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Notification
|
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.bluetooth.BluetoothAdapter
|
import android.bluetooth.BluetoothAdapter
|
||||||
import android.bluetooth.BluetoothDevice
|
import android.bluetooth.BluetoothDevice
|
||||||
@ -17,12 +17,13 @@ import android.os.Build
|
|||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
import androidx.work.PeriodicWorkRequestBuilder
|
import androidx.work.PeriodicWorkRequestBuilder
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
import bums.lunatic.launcher.LauncherActivity
|
||||||
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
|
import bums.lunatic.launcher.LauncherActivity.Companion.lActivity
|
||||||
import bums.lunatic.launcher.R
|
import bums.lunatic.launcher.R
|
||||||
import bums.lunatic.launcher.home.GeckoWeb
|
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import bums.lunatic.launcher.workers.ArcaGetter
|
import bums.lunatic.launcher.workers.ArcaGetter
|
||||||
import bums.lunatic.launcher.workers.ClienGetter
|
import bums.lunatic.launcher.workers.ClienGetter
|
||||||
@ -51,8 +52,11 @@ import okhttp3.ResponseBody
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
class BluetoothManager : Service() {
|
class ForeGroundService : Service() {
|
||||||
|
companion object {
|
||||||
|
val ACTION_SENDMSG = "ACTION_SEND_TO_LOVE"
|
||||||
|
val EXTRA_MSGKEY = "SEND_MSG"
|
||||||
|
}
|
||||||
enum class BLUETOOTH_STATE(val statestr: String) {
|
enum class BLUETOOTH_STATE(val statestr: String) {
|
||||||
ENABLED("enabledBlutooth"),
|
ENABLED("enabledBlutooth"),
|
||||||
DISABLED("disableBlutooth"),
|
DISABLED("disableBlutooth"),
|
||||||
@ -67,44 +71,71 @@ class BluetoothManager : Service() {
|
|||||||
super.onCreate()
|
super.onCreate()
|
||||||
Blog.LOGE("onCreate")
|
Blog.LOGE("onCreate")
|
||||||
mWorkManager = WorkManager.getInstance(this)
|
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)
|
val filter = IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)
|
||||||
registerReceiver(bluetoothreceiver, filter)
|
registerReceiver(bluetoothreceiver, filter)
|
||||||
refreshFeeds()
|
refreshFeeds()
|
||||||
// GeckoWeb(applicationContext).apply {
|
|
||||||
// loadUrl("https://arca.live/b/live")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
Blog.LOGE("intent >>> ${intent}")
|
Blog.LOGE("onStartCommand >>> ${intent}")
|
||||||
return null
|
if (ACTION_SENDMSG.equals(intent?.action)) {
|
||||||
|
intent?.getStringExtra(EXTRA_MSGKEY)?.let {
|
||||||
|
sendToI(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startForeGround()
|
||||||
|
return START_STICKY
|
||||||
}
|
}
|
||||||
private val CHANNEL_ID = "ble_service_channel"
|
|
||||||
private val CHANNEL_NAME = "BLE 서비스"
|
|
||||||
|
|
||||||
fun createNotification(context: Context): Notification {
|
fun startForeGround() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val channel = NotificationChannel(
|
val channel = NotificationChannel(
|
||||||
CHANNEL_ID,
|
CHANNEL_ID,
|
||||||
CHANNEL_NAME,
|
"BLE 서비스 채널",
|
||||||
NotificationManager.IMPORTANCE_HIGH // 중요도 낮게 (필요시 변경)
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
)
|
)
|
||||||
val notificationManager =
|
val manager = getSystemService(NotificationManager::class.java)
|
||||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
manager.createNotificationChannel(channel)
|
||||||
notificationManager.createNotificationChannel(channel)
|
|
||||||
}
|
}
|
||||||
return NotificationCompat.Builder(context, CHANNEL_ID)
|
val intent = Intent(this, LauncherActivity::class.java).apply {
|
||||||
|
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
|
}
|
||||||
|
|
||||||
|
val pendingIntent = PendingIntent.getActivity(
|
||||||
|
this,
|
||||||
|
0,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||||
|
)
|
||||||
|
|
||||||
|
startForeground(NOTIF_ID, NotificationCompat.Builder(this, CHANNEL_ID)
|
||||||
.setContentTitle("BLE 서비스")
|
.setContentTitle("BLE 서비스")
|
||||||
.setContentText("실행중입니다.")
|
.setContentText("실행중입니다.")
|
||||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
.setSmallIcon(R.drawable.ic_b)
|
.setSmallIcon(R.drawable.ic_b)
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.addAction(android.R.drawable.ic_btn_speak_now,"퇴근", makeSendMsgAction(0,"돼지 퇴근했다요~!"))
|
||||||
|
.addAction(android.R.drawable.ic_btn_speak_now,"버스 탐", makeSendMsgAction(1,"돼지 버스 탔다요~!"))
|
||||||
|
.addAction(android.R.drawable.ic_btn_speak_now,"버스 내림", makeSendMsgAction(2,"돼지 버스 내린다요~!"))
|
||||||
.setOngoing(true) // 사용자가 알림을 스와이프로 지울 수 없게 만듦
|
.setOngoing(true) // 사용자가 알림을 스와이프로 지울 수 없게 만듦
|
||||||
.build()
|
.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun makeSendMsgAction(code : Int, msg : String) : PendingIntent {
|
||||||
|
val actionIntent = Intent(this, ForeGroundService::class.java).apply {
|
||||||
|
action = ACTION_SENDMSG
|
||||||
|
putExtra(EXTRA_MSGKEY, msg) // 전달할 데이터
|
||||||
|
}
|
||||||
|
return PendingIntent.getService(this, code, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE )
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
|
Blog.LOGE("onBind intent >>> ${intent}")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
private val CHANNEL_ID = "ble_service_channel"
|
||||||
|
private val CHANNEL_NAME = "BLE 서비스"
|
||||||
|
|
||||||
|
|
||||||
//페어링된 디바이스 정보 가져오기
|
//페어링된 디바이스 정보 가져오기
|
||||||
fun getPairedDevices() {
|
fun getPairedDevices() {
|
||||||
@ -192,6 +223,14 @@ class BluetoothManager : Service() {
|
|||||||
PeriodicWorkRequestBuilder<LocationGetter>(PrefLong.locationTimePeriod.get(), TimeUnit.MINUTES)
|
PeriodicWorkRequestBuilder<LocationGetter>(PrefLong.locationTimePeriod.get(), TimeUnit.MINUTES)
|
||||||
.addTag(LocationGetter.TAG)
|
.addTag(LocationGetter.TAG)
|
||||||
.build())
|
.build())
|
||||||
|
mWorkManager?.cancelAllWorkByTag(ServiceWatchdogWorker.TAG)
|
||||||
|
mWorkManager?.enqueueUniquePeriodicWork(
|
||||||
|
ServiceWatchdogWorker.TAG,
|
||||||
|
ExistingPeriodicWorkPolicy.REPLACE,
|
||||||
|
PeriodicWorkRequestBuilder<ServiceWatchdogWorker>(15, TimeUnit.MINUTES)
|
||||||
|
.addTag(ServiceWatchdogWorker.TAG)
|
||||||
|
.build())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,6 +241,21 @@ class BluetoothManager : Service() {
|
|||||||
return mWorkManager
|
return mWorkManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendToI(msg: String) {
|
||||||
|
if (PrefString.telegramSendTarget.get().length > 5) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
OkHttpClient.Builder()
|
||||||
|
.connectionPool(ConnectionPool(5, 60, TimeUnit.SECONDS))
|
||||||
|
.build().newCall(Request.Builder().url("https://api.telegram.org/bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w/sendMessage?chat_id=${PrefString.telegramSendTarget.get()}&text=${msg}")
|
||||||
|
.addHeader("Content-Type", "application/json").get().build()).execute()?.let { response ->
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
val body: ResponseBody? = response.body()
|
||||||
|
if (body != null) { }
|
||||||
|
} else Blog.LOGE("sendToI telegram Error Occurred")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fun sendToI(boolean: Boolean) {
|
fun sendToI(boolean: Boolean) {
|
||||||
if (PrefString.telegramSendTarget.get().length > 5) {
|
if (PrefString.telegramSendTarget.get().length > 5) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
@ -251,6 +305,13 @@ class BluetoothManager : Service() {
|
|||||||
return BLUETOOTH_STATE.NOT_SUPPORT.statestr
|
return BLUETOOTH_STATE.NOT_SUPPORT.statestr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun stopService(name: Intent?): Boolean {
|
||||||
|
Blog.LOGE("stopService ${name}")
|
||||||
|
val intent = Intent(this, ForeGroundService::class.java)
|
||||||
|
ContextCompat.startForegroundService(this, intent)
|
||||||
|
return super.stopService(name)
|
||||||
|
}
|
||||||
|
|
||||||
//add Receive action
|
//add Receive action
|
||||||
private fun addFilterAction(): IntentFilter {
|
private fun addFilterAction(): IntentFilter {
|
||||||
val stateFilter = IntentFilter()
|
val stateFilter = IntentFilter()
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package bums.lunatic.launcher.helpers
|
||||||
|
|
||||||
|
import android.app.ActivityManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.work.Worker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
|
||||||
|
class ServiceWatchdogWorker(
|
||||||
|
private val context: Context,
|
||||||
|
workerParams: WorkerParameters
|
||||||
|
) : Worker(context, workerParams) {
|
||||||
|
|
||||||
|
companion object{
|
||||||
|
val TAG = "ServiceWatchdogWorker"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doWork(): Result {
|
||||||
|
val isServiceRunning = isServiceRunning(ForeGroundService::class.java)
|
||||||
|
if (!isServiceRunning) {
|
||||||
|
val intent = Intent(context, ForeGroundService::class.java)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
context.startForegroundService(intent)
|
||||||
|
} else {
|
||||||
|
context.startService(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
fun isServiceRunning(serviceClass: Class<*>): Boolean {
|
||||||
|
val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||||
|
return manager.getRunningServices(Int.MAX_VALUE)
|
||||||
|
.any { it.service.className == serviceClass.name }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -40,6 +40,7 @@ import androidx.core.net.toUri
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
||||||
import bums.lunatic.launcher.R
|
import bums.lunatic.launcher.R
|
||||||
|
import bums.lunatic.launcher.model.others.Button
|
||||||
import bums.lunatic.launcher.tokiz.data.model.PortMessage
|
import bums.lunatic.launcher.tokiz.data.model.PortMessage
|
||||||
import bums.lunatic.launcher.tokiz.view.BWebview
|
import bums.lunatic.launcher.tokiz.view.BWebview
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
@ -47,6 +48,9 @@ import bums.lunatic.launcher.utils.CommonUtils
|
|||||||
import bums.lunatic.launcher.workers.WorkersDb
|
import bums.lunatic.launcher.workers.WorkersDb
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter
|
import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter
|
||||||
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
|
import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||||
|
import com.yausername.youtubedl_android.YoutubeDLResponse
|
||||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -54,6 +58,7 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kr.lunaticbum.utils.service.ServiceUtil.getSystemService
|
import kr.lunaticbum.utils.service.ServiceUtil.getSystemService
|
||||||
|
import kr.lunaticbum.utils.service.ServiceUtil.layoutInflater
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
@ -61,6 +66,7 @@ import org.json.JSONObject
|
|||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.mozilla.gecko.util.ThreadUtils
|
import org.mozilla.gecko.util.ThreadUtils
|
||||||
|
import org.mozilla.gecko.util.ThreadUtils.runOnUiThread
|
||||||
import org.mozilla.geckoview.ExperimentDelegate
|
import org.mozilla.geckoview.ExperimentDelegate
|
||||||
import org.mozilla.geckoview.GeckoResult
|
import org.mozilla.geckoview.GeckoResult
|
||||||
import org.mozilla.geckoview.GeckoSession
|
import org.mozilla.geckoview.GeckoSession
|
||||||
@ -76,6 +82,7 @@ import java.io.FileOutputStream
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
class GeckoWeb : BWebview {
|
class GeckoWeb : BWebview {
|
||||||
constructor(context: Context?) : super(context) {
|
constructor(context: Context?) : super(context) {
|
||||||
@ -84,7 +91,7 @@ class GeckoWeb : BWebview {
|
|||||||
var decoViews = arrayListOf<View>()
|
var decoViews = arrayListOf<View>()
|
||||||
override fun setVisibility(visibility: Int) {
|
override fun setVisibility(visibility: Int) {
|
||||||
super.setVisibility(visibility)
|
super.setVisibility(visibility)
|
||||||
decoViews.filter { it != null && it.id > -1 }.forEach { it.visibility = visibility }
|
decoViews.filter { it != null && it.id > -1 && it.id != R.id.dl_video }.forEach { it.visibility = visibility }
|
||||||
}
|
}
|
||||||
interface OnSave {
|
interface OnSave {
|
||||||
fun saved()
|
fun saved()
|
||||||
@ -448,6 +455,153 @@ class GeckoWeb : BWebview {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun checkIfDownloadable(url: String) {
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
runOnUiThread {
|
||||||
|
decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let {
|
||||||
|
it.setOnClickListener {}
|
||||||
|
it.visibility = View.GONE
|
||||||
|
}}}
|
||||||
|
Blog.LOGE("checkIfDownloadable ${url}")
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
try {
|
||||||
|
val videoInfo = YoutubeDL.getInstance().getInfo(url)
|
||||||
|
// videoInfo 가 null 아니고, 필요한 키(예: title, url 등)가 있으면 다운로드 가능
|
||||||
|
Blog.LOGE("checkIfDownloadable ${url}\n videoInfo : ${videoInfo}")
|
||||||
|
var canVideoDown = videoInfo != null && !videoInfo.title.isNullOrEmpty()
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
runOnUiThread {
|
||||||
|
decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let {
|
||||||
|
it.setOnClickListener {
|
||||||
|
videoDlownLoad(url)
|
||||||
|
}
|
||||||
|
it.visibility = if (canVideoDown){View.VISIBLE} else{View.GONE}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Blog.LOGE("checkIfDownloadable ${url} ${e}")
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
runOnUiThread {
|
||||||
|
decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let {
|
||||||
|
it.setOnClickListener {}
|
||||||
|
it.visibility = View.GONE
|
||||||
|
}}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun replaceDcUrl(origin: String): String {
|
||||||
|
var result = origin
|
||||||
|
for (i in 0..19) {
|
||||||
|
result = result.replace(String.format("dcimg%d.", i), "dcimg2.")
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copyToClipboard(text: String?) {
|
||||||
|
if (text == null) return
|
||||||
|
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val clip = ClipData.newPlainText("Media URL", text)
|
||||||
|
clipboard.setPrimaryClip(clip)
|
||||||
|
Toast.makeText(context, "주소가 복사되었습니다.", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun getFormatList(url: String): List<String> = withContext(Dispatchers.IO) {
|
||||||
|
val command = YoutubeDLRequest(lastedUrl!!)
|
||||||
|
command.addOption("--list-formats", url)
|
||||||
|
val output = YoutubeDL.getInstance().execute(command)
|
||||||
|
// output.stdout에 포맷 리스트가 문자열로 들어있음
|
||||||
|
// 줄 단위로 분리 후 리턴
|
||||||
|
Blog.LOGE("output.out >>> ${output.out}")
|
||||||
|
return@withContext output.out.split("\n").filter { it.isNotBlank() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showFormatSelectionDialog(formats: List<String>, onFormatSelected: (String) -> Unit) {
|
||||||
|
val builder = AlertDialog.Builder(context)
|
||||||
|
builder.setTitle("포맷 선택")
|
||||||
|
builder.setItems(formats.toTypedArray()) { _, which ->
|
||||||
|
onFormatSelected(formats[which])
|
||||||
|
}
|
||||||
|
builder.setNegativeButton("취소", null)
|
||||||
|
builder.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lateinit var progressDialog: AlertDialog
|
||||||
|
fun showProgressDialog() {
|
||||||
|
val dialogView = layoutInflater.inflate(R.layout.progress_dialog, null)
|
||||||
|
val progressBar = dialogView.findViewById<ProgressBar>(R.id.progressBar)
|
||||||
|
val textProgress = dialogView.findViewById<TextView>(R.id.textProgress)
|
||||||
|
val btn = dialogView.findViewById<android.widget.Button>(R.id.dl_cancel)
|
||||||
|
progressDialog = AlertDialog.Builder(context)
|
||||||
|
.setTitle("다운로드 중...")
|
||||||
|
.setView(dialogView)
|
||||||
|
.setCancelable(false)
|
||||||
|
.create()
|
||||||
|
progressDialog.show()
|
||||||
|
|
||||||
|
// UI 업데이트 함수 예 (나중에 실행)
|
||||||
|
fun updateProgress(progress: Int, est : Long, str : String) {
|
||||||
|
runOnUiThread {
|
||||||
|
progressBar.progress = progress
|
||||||
|
textProgress.text = "$progress%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun dismissProgressDialog() {
|
||||||
|
progressDialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun downloadVideo(processId : String,url: String, updateProgress: (Float, Long, String) -> Unit) = withContext(Dispatchers.IO) {
|
||||||
|
val youtubeDLDir = File(
|
||||||
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
|
||||||
|
"youtubedl-android"
|
||||||
|
)
|
||||||
|
val command = YoutubeDLRequest(url)
|
||||||
|
command.addOption("-o", youtubeDLDir.getAbsolutePath() + "/%(title)s.%(ext)s");
|
||||||
|
var process = YoutubeDL.getInstance().execute(command,processId) { progress, est , str ->
|
||||||
|
updateProgress(progress, est, str)
|
||||||
|
}
|
||||||
|
return@withContext process
|
||||||
|
}
|
||||||
|
|
||||||
|
fun videoDlownLoad(videoUrl : String) {
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
try {
|
||||||
|
showProgressDialog()
|
||||||
|
var res: YoutubeDLResponse? = null
|
||||||
|
val processId = UUID.randomUUID().toString()
|
||||||
|
res = downloadVideo(processId, videoUrl) { progress , time , str->
|
||||||
|
runOnUiThread {
|
||||||
|
val pb =
|
||||||
|
progressDialog.findViewById<ProgressBar>(R.id.progressBar)
|
||||||
|
val tv =
|
||||||
|
progressDialog.findViewById<TextView>(R.id.textProgress)
|
||||||
|
pb?.progress = progress.toInt()
|
||||||
|
val btn = progressDialog.findViewById<android.widget.Button>(R.id.dl_cancel)
|
||||||
|
tv?.text = "$progress%\n$str"
|
||||||
|
btn?.setOnClickListener {
|
||||||
|
progressDialog?.dismiss()
|
||||||
|
YoutubeDL.getInstance().destroyProcessById(processId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dismissProgressDialog()
|
||||||
|
Toast.makeText(context, "다운로드 완료", Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
progressDialog?.dismiss()
|
||||||
|
Toast.makeText(context, "오류: ${e.message}", Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var dialog : Dialog? = null
|
var dialog : Dialog? = null
|
||||||
fun getFilterF() = String(java.util.Base64.getMimeDecoder().decode("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=".toByteArray()))
|
fun getFilterF() = String(java.util.Base64.getMimeDecoder().decode("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=".toByteArray()))
|
||||||
var currentTitle = ""
|
var currentTitle = ""
|
||||||
@ -474,21 +628,7 @@ class GeckoWeb : BWebview {
|
|||||||
|
|
||||||
super.onFirstContentfulPaint(session)
|
super.onFirstContentfulPaint(session)
|
||||||
}
|
}
|
||||||
fun replaceDcUrl(origin: String): String {
|
|
||||||
var result = origin
|
|
||||||
for (i in 0..19) {
|
|
||||||
result = result.replace(String.format("dcimg%d.", i), "dcimg2.")
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copyToClipboard(text: String?) {
|
|
||||||
if (text == null) return
|
|
||||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
val clip = ClipData.newPlainText("Media URL", text)
|
|
||||||
clipboard.setPrimaryClip(clip)
|
|
||||||
Toast.makeText(context, "주소가 복사되었습니다.", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onExternalResponse(session: GeckoSession, response: WebResponse) {
|
override fun onExternalResponse(session: GeckoSession, response: WebResponse) {
|
||||||
Blog.LOGE("response >>> ${response.uri} ")
|
Blog.LOGE("response >>> ${response.uri} ")
|
||||||
@ -504,6 +644,7 @@ class GeckoWeb : BWebview {
|
|||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
|
.addHeader("Referer", lastedUrl)
|
||||||
.addHeader("User-Agent", "Mozilla/5.0")
|
.addHeader("User-Agent", "Mozilla/5.0")
|
||||||
// 필요시 Referer, 쿠키 등 헤더 추가
|
// 필요시 Referer, 쿠키 등 헤더 추가
|
||||||
.build()
|
.build()
|
||||||
@ -531,6 +672,7 @@ class GeckoWeb : BWebview {
|
|||||||
super.onExternalResponse(session, response)
|
super.onExternalResponse(session, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onContextMenu(
|
override fun onContextMenu(
|
||||||
session: GeckoSession,
|
session: GeckoSession,
|
||||||
screenX: Int,
|
screenX: Int,
|
||||||
@ -539,18 +681,11 @@ class GeckoWeb : BWebview {
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
if (element.baseUri?.contains("youtube") == true) {
|
if (element.baseUri?.contains("youtube") == true) {
|
||||||
copyToClipboard(lastedUrl)
|
lastedUrl?.let { videoUrl ->
|
||||||
loadUrl("https://ko.savefrom.net/227lt/#url=${lastedUrl}")
|
lastedUrl?.let {
|
||||||
// copyToClipboard(lastedUrl)
|
videoDlownLoad(it)
|
||||||
// Dialog(context)?.let { dialog ->
|
}
|
||||||
// val popupWebView = GeckoWeb(context).apply {
|
}
|
||||||
// loadUrl(lastedUrl!!.replace("https://","https://ss"))
|
|
||||||
// this.dialog = dialog
|
|
||||||
// }
|
|
||||||
// dialog.setCanceledOnTouchOutside(true)
|
|
||||||
// dialog.setContentView(popupWebView)
|
|
||||||
// dialog.show()
|
|
||||||
// }
|
|
||||||
} else {
|
} else {
|
||||||
Blog.LOGE("onContextMenu:: x = ${x}, y = ${y} , element = ${Gson().toJson(element)}")
|
Blog.LOGE("onContextMenu:: x = ${x}, y = ${y} , element = ${Gson().toJson(element)}")
|
||||||
if (element.type == GeckoSession.ContentDelegate.ContextElement.TYPE_IMAGE) {
|
if (element.type == GeckoSession.ContentDelegate.ContextElement.TYPE_IMAGE) {
|
||||||
@ -723,6 +858,7 @@ class GeckoWeb : BWebview {
|
|||||||
} else {
|
} else {
|
||||||
lastedUrl = url
|
lastedUrl = url
|
||||||
}
|
}
|
||||||
|
checkIfDownloadable(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -735,6 +871,8 @@ class GeckoWeb : BWebview {
|
|||||||
it.tag = currentTitle
|
it.tag = currentTitle
|
||||||
it.text = url
|
it.text = url
|
||||||
}
|
}
|
||||||
|
}else if (it.id == R.id.reload) {
|
||||||
|
it.setOnClickListener { session.reload() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -625,6 +625,8 @@ internal class RssHome : Fragment() {
|
|||||||
(activity as? LauncherActivity)?.let { activity ->
|
(activity as? LauncherActivity)?.let { activity ->
|
||||||
binding.geckoWeb.decoViews.add(activity.findViewById<TextView>(R.id.current_address))
|
binding.geckoWeb.decoViews.add(activity.findViewById<TextView>(R.id.current_address))
|
||||||
binding.geckoWeb.decoViews.add(activity.findViewById<ImageButton>(R.id.back))
|
binding.geckoWeb.decoViews.add(activity.findViewById<ImageButton>(R.id.back))
|
||||||
|
binding.geckoWeb.decoViews.add(activity.findViewById<ImageButton>(R.id.reload))
|
||||||
|
binding.geckoWeb.decoViews.add(activity.findViewById<ImageButton>(R.id.dl_video))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package bums.lunatic.launcher.receiver
|
package bums.lunatic.launcher.receiver
|
||||||
|
|
||||||
|
import android.app.Notification
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -13,9 +14,11 @@ import android.service.notification.NotificationListenerService
|
|||||||
import android.service.notification.StatusBarNotification
|
import android.service.notification.StatusBarNotification
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
|
import bums.lunatic.launcher.helpers.ForeGroundService
|
||||||
import bums.lunatic.launcher.model.CurrentPlayItem
|
import bums.lunatic.launcher.model.CurrentPlayItem
|
||||||
import bums.lunatic.launcher.model.NotificationItem
|
import bums.lunatic.launcher.model.NotificationItem
|
||||||
import bums.lunatic.launcher.utils.BitmapConverter
|
import bums.lunatic.launcher.utils.BitmapConverter
|
||||||
|
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.UpdatePolicy
|
||||||
import io.realm.kotlin.ext.query
|
import io.realm.kotlin.ext.query
|
||||||
@ -29,7 +32,6 @@ class NLService : NotificationListenerService() {
|
|||||||
super.onCreate()
|
super.onCreate()
|
||||||
nlservicereciver = NLServiceReceiver()
|
nlservicereciver = NLServiceReceiver()
|
||||||
val filter = IntentFilter()
|
val filter = IntentFilter()
|
||||||
// filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE")
|
|
||||||
registerReceiver(nlservicereciver, filter)
|
registerReceiver(nlservicereciver, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,130 +40,54 @@ class NLService : NotificationListenerService() {
|
|||||||
unregisterReceiver(nlservicereciver)
|
unregisterReceiver(nlservicereciver)
|
||||||
}
|
}
|
||||||
|
|
||||||
val skips = arrayListOf("com.wssyncmldm")
|
|
||||||
@RequiresApi(Build.VERSION_CODES.S)
|
@RequiresApi(Build.VERSION_CODES.S)
|
||||||
override fun onNotificationPosted(sbn: StatusBarNotification) {
|
override fun onNotificationPosted(sbn: StatusBarNotification) {
|
||||||
// BLog.LOGE("NLService********** onNotificationPosted")
|
Blog.LOGE("onNotificationPosted ${sbn}")
|
||||||
// BLog.LOGE("NLServiceID :" + sbn.id + "\t${sbn.notification.tickerText}\t" + sbn.packageName)
|
val notification = sbn.notification
|
||||||
// sbn.notification.extras.keySet().forEach {
|
val extras = notification.extras
|
||||||
// BLog.LOGE("NLService********** keySet >> ${it} ${sbn.notification.extras.get(it)}")
|
when (sbn.packageName){
|
||||||
// }
|
"com.kakao.talk" -> {
|
||||||
try {
|
|
||||||
if (sbn.id != 0 && (sbn.packageName.contains(".") || sbn.packageName.contains("android")) && sbn.packageName.length > 0) {
|
|
||||||
NotificationItem().apply {
|
|
||||||
notiId = sbn.id
|
|
||||||
pkgName = sbn.packageName
|
|
||||||
title = sbn.notification?.extras?.getString("android.title") ?: ""
|
|
||||||
subtext = sbn.notification?.extras?.getString("android.subText") ?: ""
|
|
||||||
selfDisplayName = sbn.notification?.extras?.getString("android.selfDisplayName") ?: ""
|
|
||||||
tikerMsg = sbn.notification?.tickerText?.toString() ?: ""
|
|
||||||
postTime = sbn.postTime
|
|
||||||
var uniq = title ?: subtext ?: selfDisplayName ?: tikerMsg ?: ""
|
|
||||||
uniq_id = "${sbn.id}_${sbn.packageName}_${if (uniq.length > 3) uniq.substring(0,3) else uniq}"
|
|
||||||
// BLog.LOGE("NLService********** enqueue TelegramBotGetter ${true == "bumssavor".equals(title)}")
|
|
||||||
// BLog.LOGE("NLService********** enqueue TelegramBotGetter ${(true == "org.telegram.messenger".equals(pkgName))}")
|
|
||||||
// BLog.LOGE("NLService********** enqueue TelegramBotGetter ${sbn.notification?.extras?.getString("android.text")?.startsWith("/") == true}")
|
|
||||||
}.apply {
|
|
||||||
if (skips.contains(pkgName)) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// WorkersDb.insertNoti(this)
|
|
||||||
// BLog.LOGE("NLService********** onNotificationPosted ${Gson().toJson(this)}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e : Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (sbn.packageName.contains("youtube")) {
|
|
||||||
val m = getSystemService<MediaSessionManager>()!!
|
|
||||||
val component = ComponentName(this, NLService::class.java)
|
|
||||||
val sessions = m.getActiveSessions(component)
|
|
||||||
sessions.forEach { session ->
|
|
||||||
WorkersDb.getRealm().writeBlocking {
|
|
||||||
// Blog.LOGE("session.playbackState >>> ${session.playbackState}")
|
|
||||||
if (session.playbackState != null) {
|
|
||||||
if (session.playbackState?.isActive == true && session.playbackState?.state?.equals(
|
|
||||||
STATE_PLAYING
|
|
||||||
) == true
|
|
||||||
) {
|
|
||||||
session.playbackState?.state
|
|
||||||
val result = query<CurrentPlayItem>().find()
|
|
||||||
var current: CurrentPlayItem? = null
|
|
||||||
if (result.size > 0) {
|
|
||||||
current = result.first()
|
|
||||||
} else {
|
|
||||||
current = CurrentPlayItem()
|
|
||||||
copyToRealm(current, UpdatePolicy.ALL)
|
|
||||||
}
|
|
||||||
if (session?.metadata?.containsKey(MediaMetadata.METADATA_KEY_ALBUM_ART) == true) {
|
|
||||||
current.albumArt = BitmapConverter.BitmapToString(
|
|
||||||
session.metadata?.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
current.albumArt = ""
|
|
||||||
}
|
|
||||||
current.title =
|
|
||||||
session?.metadata?.getString(MediaMetadata.METADATA_KEY_TITLE)
|
|
||||||
current.artists =
|
|
||||||
session?.metadata?.getString(MediaMetadata.METADATA_KEY_ARTIST)
|
|
||||||
} else {
|
|
||||||
delete(query<CurrentPlayItem>().find())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val title = extras.getString(Notification.EXTRA_TITLE) ?: ""
|
||||||
|
val text = extras.getCharSequence(Notification.EXTRA_TEXT)?.toString() ?: ""
|
||||||
|
val bigText = extras.getCharSequence(Notification.EXTRA_BIG_TEXT)?.toString() ?: ""
|
||||||
|
val extraInfo = extras.getCharSequence(Notification.EXTRA_INFO_TEXT)?.toString() ?: ""
|
||||||
|
val subText = extras.getCharSequence(Notification.EXTRA_SUB_TEXT)?.toString() ?: ""
|
||||||
|
val conversationTitle = extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE)?.toString() ?: ""
|
||||||
|
val summaryText = extras.getCharSequence(Notification.EXTRA_SUMMARY_TEXT)?.toString() ?: ""
|
||||||
|
val verificationText = extras.getCharSequence(Notification.EXTRA_VERIFICATION_TEXT)?.toString() ?: ""
|
||||||
|
|
||||||
|
Blog.LOGE("title >> ${title} text >> ${text} bigText >> ${bigText} extraInfo >> ${extraInfo} subText >> ${subText} conversationTitle >> ${conversationTitle} summaryText >> ${summaryText} verificationText >> ${verificationText}")
|
||||||
|
|
||||||
}
|
|
||||||
}}catch (e : Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
// val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
|
|
||||||
// i.putExtra("notification_event", "onNotificationPosted :" + sbn.packageName + "\n")
|
|
||||||
// sendBroadcast(i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNotificationRemoved(sbn: StatusBarNotification) {
|
override fun onNotificationRemoved(sbn: StatusBarNotification) {
|
||||||
//// BLog.LOGE("NLService********** onNOtificationRemoved")
|
Blog.LOGE("onNotificationPosted ${sbn}")
|
||||||
//// BLog.LOGE("NLService ID :" + sbn.id + "\t" + sbn.notification.tickerText + "\t" + sbn.packageName)
|
if (sbn.packageName == "bums.lunatic.launcher" && sbn.id == 830721) {
|
||||||
// var uniq_id = "${sbn.id}_${sbn.packageName}"
|
// 포그라운드 알림이 사라짐 감지
|
||||||
// try {
|
Blog.LOGE("NotificationListener", "포그라운드 알림 제거 감지")
|
||||||
// WorkersDb.getRealm()?.apply {
|
|
||||||
// this.writeBlocking {
|
// 서비스 재시작 시도
|
||||||
//// delete(query<NotificationItem>().query("pkgName == $0", sbn.packageName).find())
|
val intent = Intent(this, ForeGroundService::class.java)
|
||||||
// }
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
// }
|
startForegroundService(intent)
|
||||||
// }catch (e : Exception){e.printStackTrace()}
|
} else {
|
||||||
//// val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
|
startService(intent)
|
||||||
//// i.putExtra("notification_event", "onNotificationRemoved :" + sbn.packageName + "\n")
|
}
|
||||||
//// sendBroadcast(i)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal inner class NLServiceReceiver : BroadcastReceiver() {
|
internal inner class NLServiceReceiver : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent) {
|
override fun onReceive(context: Context?, intent: Intent) {
|
||||||
// BLog.LOGE("NLService intent >>> ${intent.action}")
|
|
||||||
if (intent.getStringExtra("command") == "clearall") {
|
if (intent.getStringExtra("command") == "clearall") {
|
||||||
this@NLService.cancelAllNotifications()
|
this@NLService.cancelAllNotifications()
|
||||||
} else if (intent.getStringExtra("command") == "list") {
|
} else if (intent.getStringExtra("command") == "list") {
|
||||||
// val i1 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
|
|
||||||
// i1.putExtra("notification_event", "=====================")
|
|
||||||
// sendBroadcast(i1)
|
|
||||||
var i = 1
|
|
||||||
for (sbn in this@NLService.activeNotifications) {
|
|
||||||
// BLog.LOGE("NLService sbn >>> ${sbn.packageName} , ${Gson().toJson(sbn.notification.extras.keySet())}")
|
|
||||||
// val i2 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
|
|
||||||
// i2.putExtra("notification_event", i.toString() + " " + sbn.packageName + "\n")
|
|
||||||
// sendBroadcast(i2)
|
|
||||||
// i++
|
|
||||||
}
|
|
||||||
// val i3 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
|
|
||||||
// i3.putExtra("notification_event", "===== Notification List ====")
|
|
||||||
// sendBroadcast(i3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package bums.lunatic.launcher.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.GestureDetector
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.ScaleGestureDetector
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
class ZoomImageView(context: Context, attrs: AttributeSet) : AppCompatImageView(context, attrs),
|
||||||
|
ScaleGestureDetector.OnScaleGestureListener, GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
|
||||||
|
|
||||||
|
private var scaleFactor = 1.0f
|
||||||
|
private val scaleGestureDetector = ScaleGestureDetector(context, this)
|
||||||
|
private val gestureDetector = GestureDetector(context, this)
|
||||||
|
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
scaleGestureDetector.onTouchEvent(event)
|
||||||
|
gestureDetector.onTouchEvent(event)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScaleGestureDetector callbacks
|
||||||
|
override fun onScale(detector: ScaleGestureDetector): Boolean {
|
||||||
|
scaleFactor *= detector.scaleFactor
|
||||||
|
scaleFactor = scaleFactor.coerceIn(1.0f, 4.0f)
|
||||||
|
scaleX = scaleFactor
|
||||||
|
scaleY = scaleFactor
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScaleBegin(detector: ScaleGestureDetector) = true
|
||||||
|
override fun onScaleEnd(detector: ScaleGestureDetector) {}
|
||||||
|
|
||||||
|
// GestureDetector callbacks (클릭, 터치 등)
|
||||||
|
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
|
||||||
|
performClick() // 클릭 이벤트 발생
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun performClick(): Boolean {
|
||||||
|
super.performClick()
|
||||||
|
// 추가로 클릭 시 동작할 코드 넣기
|
||||||
|
if (hasOnClickListeners()) {
|
||||||
|
callOnClick()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDown(e: MotionEvent) = true
|
||||||
|
override fun onShowPress(e: MotionEvent) {}
|
||||||
|
override fun onSingleTapUp(e: MotionEvent) = true
|
||||||
|
override fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float) = false
|
||||||
|
override fun onLongPress(e: MotionEvent) {}
|
||||||
|
override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float) = false
|
||||||
|
override fun onDoubleTap(e: MotionEvent) = true
|
||||||
|
override fun onDoubleTapEvent(e: MotionEvent) = true
|
||||||
|
}
|
||||||
BIN
app/src/main/res/drawable/dl_vid.png
Normal file
BIN
app/src/main/res/drawable/dl_vid.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 530 B |
@ -36,12 +36,27 @@
|
|||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
tools:ignore="ContentDescription"
|
tools:ignore="ContentDescription"
|
||||||
android:layout_height="40dp" />
|
android:layout_height="40dp" />
|
||||||
|
<ImageButton
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/fragment_container"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/back"
|
||||||
|
android:id="@+id/reload"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:background="@null"
|
||||||
|
android:src="@drawable/ic_refresh"
|
||||||
|
android:tint="@color/white"
|
||||||
|
android:foregroundTint="@color/white"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:layout_height="40dp" />
|
||||||
<TextView
|
<TextView
|
||||||
android:text="asdasdsadasd"
|
android:text="asdasdsadasd"
|
||||||
android:id="@+id/current_address"
|
android:id="@+id/current_address"
|
||||||
app:layout_constraintTop_toTopOf="@id/back"
|
app:layout_constraintTop_toTopOf="@id/back"
|
||||||
app:layout_constraintRight_toLeftOf="@id/share"
|
app:layout_constraintRight_toLeftOf="@id/dl_video"
|
||||||
app:layout_constraintLeft_toRightOf="@id/back"
|
app:layout_constraintLeft_toRightOf="@id/reload"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="@dimen/_12sp"
|
android:textSize="@dimen/_12sp"
|
||||||
@ -49,6 +64,21 @@
|
|||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="40dp"/>
|
android:layout_height="40dp"/>
|
||||||
|
<ImageButton
|
||||||
|
app:layout_constraintTop_toTopOf="@id/back"
|
||||||
|
app:layout_constraintRight_toLeftOf="@id/share"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:id="@+id/dl_video"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:background="@null"
|
||||||
|
android:tint="@color/white"
|
||||||
|
android:foregroundTint="@color/white"
|
||||||
|
android:src="@drawable/dl_vid"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:layout_height="40dp" />
|
||||||
<ImageButton
|
<ImageButton
|
||||||
app:layout_constraintTop_toTopOf="@id/back"
|
app:layout_constraintTop_toTopOf="@id/back"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
@ -140,5 +170,13 @@
|
|||||||
android:onClick="floatClick"
|
android:onClick="floatClick"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="20dp"/>
|
android:layout_height="20dp"/>
|
||||||
|
<bums.lunatic.launcher.view.FloatingActionButton
|
||||||
|
app:fab_label="setting"
|
||||||
|
android:id="@+id/setting"
|
||||||
|
app:fab_showShadow="true"
|
||||||
|
app:fab_size="mini"
|
||||||
|
android:onClick="floatClick"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="20dp"/>
|
||||||
</bums.lunatic.launcher.view.FloatingActionMenu>
|
</bums.lunatic.launcher.view.FloatingActionMenu>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@ -49,7 +49,7 @@
|
|||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
<ImageView
|
<bums.lunatic.launcher.view.ZoomImageView
|
||||||
app:layout_constraintTop_toBottomOf="@id/date"
|
app:layout_constraintTop_toBottomOf="@id/date"
|
||||||
android:alpha="0.05"
|
android:alpha="0.05"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
@ -78,7 +78,7 @@
|
|||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
<ImageView
|
<bums.lunatic.launcher.view.ZoomImageView
|
||||||
app:layout_constraintTop_toBottomOf="@id/desc"
|
app:layout_constraintTop_toBottomOf="@id/desc"
|
||||||
android:id="@+id/screen"
|
android:id="@+id/screen"
|
||||||
android:alpha="0.05"
|
android:alpha="0.05"
|
||||||
|
|||||||
29
app/src/main/res/layout/progress_dialog.xml
Normal file
29
app/src/main/res/layout/progress_dialog.xml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||||
|
android:layout_width="250dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:max="100"
|
||||||
|
android:progress="0" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textProgress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="0%" />
|
||||||
|
<Button
|
||||||
|
android:text="다운로드 취소"
|
||||||
|
android:gravity="center"
|
||||||
|
android:id="@+id/dl_cancel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
</LinearLayout>
|
||||||
Loading…
x
Reference in New Issue
Block a user