...
This commit is contained in:
@@ -52,7 +52,7 @@ internal class LunaticLauncher : Application() {
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
} else {
|
||||
dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
|
||||
// dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
|
||||
}
|
||||
mHourlyLogWriter = HourlyLogWriter(dir)
|
||||
val cacheSize = 1024L * 1024 * 1024 // 60MB
|
||||
|
||||
@@ -384,7 +384,7 @@ class GeckoWeb : BWebview {
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
} else {
|
||||
dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
|
||||
// dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
|
||||
}
|
||||
val outputFile = File(dir, "${url?.host ?: "UnKnown"}_scraped_${SimpleDateFormat("yyyyMMdd-HHmm").format(Date())}.md")
|
||||
outputFile.writeText(markdownText, Charsets.UTF_8)
|
||||
|
||||
@@ -127,7 +127,7 @@ object CommonUtils {
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
} else {
|
||||
dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
|
||||
// dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
|
||||
}
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package bums.lunatic.launcher.wall
|
||||
|
||||
import android.content.ContentUris
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.provider.MediaStore
|
||||
import android.service.wallpaper.WallpaperService
|
||||
import android.view.SurfaceHolder
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import java.io.File
|
||||
|
||||
class MyWallpaperService : WallpaperService() {
|
||||
@@ -19,6 +22,7 @@ class MyWallpaperService : WallpaperService() {
|
||||
private var running = false
|
||||
private var nativeRenderer: NativeRenderer? = null
|
||||
private var mediaFiles: List<File> = emptyList()
|
||||
private var currentMediaIndex = -1
|
||||
|
||||
private val frameDelayMs = 16L // 약 60fps
|
||||
|
||||
@@ -27,12 +31,89 @@ class MyWallpaperService : WallpaperService() {
|
||||
|
||||
private val renderRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (!running) return
|
||||
nativeRenderer?.nativeRender()
|
||||
if (!running || holder.surface == null) return
|
||||
nativeRenderer?.nativeRender(holder.surface)
|
||||
handler.postDelayed(this, frameDelayMs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadMediaFiles() {
|
||||
val mediaDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "wallPapers")
|
||||
val supportedExtensions = videoExtensions + imageExtensions
|
||||
mediaFiles = if (mediaDir.exists() && mediaDir.isDirectory) {
|
||||
mediaDir.listFiles()?.filter { supportedExtensions.contains(it.extension.lowercase()) }?.toList() ?: emptyList()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
// --- 디버깅 로그 추가 ---
|
||||
Blog.LOGE("MyWallpaperService", "Found ${mediaFiles.size} media files.")
|
||||
|
||||
if (mediaFiles.isNotEmpty()) {
|
||||
currentMediaIndex = 0
|
||||
val firstFilePath = mediaFiles[currentMediaIndex].absolutePath
|
||||
Blog.LOGE("MyWallpaperService", "Attempting to load initial media: $firstFilePath")
|
||||
|
||||
getFdFromPath(firstFilePath)?.let { fd ->
|
||||
Blog.LOGE("MyWallpaperService", "Successfully got fd ($fd) for initial media. Calling nativeSetCurrentMedia.")
|
||||
nativeRenderer?.nativeSetCurrentMedia(fd)
|
||||
} ?: run {
|
||||
// 'let' 블록이 실행되지 않으면 fd가 null이라는 의미
|
||||
Blog.LOGE("MyWallpaperService", "Failed to get fd for initial media: $firstFilePath")
|
||||
}
|
||||
|
||||
if (mediaFiles.size > 1) {
|
||||
// Preload 로직도 동일하게 로그 추가 가능
|
||||
val nextFilePath = mediaFiles[1].absolutePath
|
||||
Blog.LOGE("MyWallpaperService", "Attempting to preload next media: $nextFilePath")
|
||||
getFdFromPath(nextFilePath)?.let { fd ->
|
||||
Blog.LOGE("MyWallpaperService", "Successfully got fd ($fd) for preload. Calling nativeStartNextPreload.")
|
||||
nativeRenderer?.nativeStartNextPreload(fd)
|
||||
} ?: run {
|
||||
Blog.LOGE("MyWallpaperService", "Failed to get fd for preload media: $nextFilePath")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Blog.LOGE("MyWallpaperService", "Media files list is empty. No media will be loaded.")
|
||||
}
|
||||
}
|
||||
|
||||
private val nextMediaCallback = object : NativeRenderer.NextMediaCallback {
|
||||
override fun onNextMediaRequested() {
|
||||
if (mediaFiles.isEmpty()) return
|
||||
currentMediaIndex = (currentMediaIndex + 1) % mediaFiles.size
|
||||
// 다음 파일 예비 로딩 시에도 파일 디스크립터를 전달
|
||||
getFdFromPath(mediaFiles[currentMediaIndex].absolutePath)?.let { fd ->
|
||||
nativeRenderer?.nativeStartNextPreload(fd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 파일 경로로 MediaStore를 쿼리하여 File Descriptor를 얻는 함수
|
||||
private fun getFdFromPath(path: String): Int? {
|
||||
var fileDescriptor: Int? = null
|
||||
val uri = MediaStore.Files.getContentUri("external")
|
||||
val projection = arrayOf(MediaStore.Files.FileColumns._ID)
|
||||
val selection = "${MediaStore.Files.FileColumns.DATA} = ?"
|
||||
val selectionArgs = arrayOf(path)
|
||||
|
||||
try {
|
||||
contentResolver.query(uri, projection, selection, selectionArgs, null)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
|
||||
val fileUri = ContentUris.withAppendedId(uri, id)
|
||||
contentResolver.openFileDescriptor(fileUri, "r")?.use { pfd ->
|
||||
fileDescriptor = pfd.detachFd() // 중요: fd 소유권을 네이티브로 넘기기 위해 detach
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return fileDescriptor
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(surfaceHolder: SurfaceHolder) {
|
||||
super.onCreate(surfaceHolder)
|
||||
holder = surfaceHolder
|
||||
@@ -41,11 +122,16 @@ class MyWallpaperService : WallpaperService() {
|
||||
override fun onSurfaceCreated(holder: SurfaceHolder) {
|
||||
super.onSurfaceCreated(holder)
|
||||
nativeRenderer = NativeRenderer()
|
||||
nativeRenderer?.nativeInit(holder.surface)
|
||||
nativeRenderer?.nativeInit()
|
||||
|
||||
handlerThread = HandlerThread("NativeRenderThread").apply { start() }
|
||||
handler = Handler(handlerThread.looper)
|
||||
running = true
|
||||
|
||||
// 콜백 등록 및 최초 미디어 로딩
|
||||
nativeRenderer?.nativeSetNextMediaCallback(nextMediaCallback)
|
||||
loadMediaFiles()
|
||||
|
||||
running = true
|
||||
handler.post(renderRunnable)
|
||||
}
|
||||
|
||||
@@ -57,17 +143,6 @@ class MyWallpaperService : WallpaperService() {
|
||||
super.onSurfaceDestroyed(holder)
|
||||
}
|
||||
|
||||
private fun loadMediaFiles() {
|
||||
val mediaDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "wallpapers")
|
||||
val supportedExtensions = videoExtensions + imageExtensions
|
||||
mediaFiles = if (mediaDir.exists() && mediaDir.isDirectory) {
|
||||
mediaDir.listFiles()?.filter { supportedExtensions.contains(it.extension.lowercase()) }?.toList() ?: emptyList()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val mediaPaths = mediaFiles.map { it.absolutePath }
|
||||
nativeRenderer?.nativeSetMediaList(mediaPaths.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,25 @@ import android.view.Surface
|
||||
|
||||
class NativeRenderer {
|
||||
|
||||
interface NextMediaCallback {
|
||||
fun onNextMediaRequested()
|
||||
}
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("native_renderer")
|
||||
}
|
||||
}
|
||||
|
||||
external fun nativeInit(surface: Surface?): Boolean
|
||||
external fun nativeInit(): Boolean
|
||||
external fun nativeDestroy()
|
||||
external fun nativeRender()
|
||||
external fun nativeSetMediaList(paths: Array<String?>?)
|
||||
external fun nativeRender(surface: Surface)
|
||||
// ...
|
||||
// external fun nativeSetCurrentMedia(path: String) // 기존 코드
|
||||
external fun nativeSetCurrentMedia(fd: Int) // 수정
|
||||
|
||||
}
|
||||
// external fun nativeStartNextPreload(path: String) // 기존 코드
|
||||
external fun nativeStartNextPreload(fd: Int) // 수정
|
||||
// ...
|
||||
external fun nativeSetNextMediaCallback(callback: NextMediaCallback)
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class LocationUpdateService : Service(), LocationListener {
|
||||
try {
|
||||
//////-1002450229641
|
||||
val url = PrefString.locationApi.get()
|
||||
Blog.LOGE("LocationLog ${url}")
|
||||
// Blog.LOGE("LocationLog ${url}")
|
||||
if (url.length > 10) {
|
||||
val client = OkHttpClient.Builder()
|
||||
.connectionPool(ConnectionPool(5, 60, TimeUnit.SECONDS))
|
||||
@@ -84,7 +84,7 @@ class LocationUpdateService : Service(), LocationListener {
|
||||
)
|
||||
val request: Request = builder.build()
|
||||
|
||||
Blog.LOGE("telegram before request ")
|
||||
// Blog.LOGE("telegram before request ")
|
||||
// OkHttp 클라이언트로 GET 요청 객체 전송
|
||||
val response: Response = client.newCall(request).execute()
|
||||
if (response.isSuccessful()) {
|
||||
|
||||
Reference in New Issue
Block a user