From a7df635f6689fd9f8787db99008c716879643a3d Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Fri, 27 Mar 2026 18:08:08 +0900 Subject: [PATCH] ... --- app/src/main/cpp/native_renderer.cpp | 1 + .../bums/lunatic/launcher/PhotoFilter.kt | 108 ------------------ .../launcher/helpers/ForeGroundService.kt | 36 +++--- .../launcher/home/CompletedFilesFragment.kt | 15 +-- .../lunatic/launcher/home/NeoRssActivity.kt | 4 + .../launcher/home/tokiz/TokiFragment.kt | 49 ++++++++ .../launcher/wall/MyWallpaperService.kt | 48 +++++--- app/src/main/res/layout/rss_activity.xml | 24 ++++ 8 files changed, 133 insertions(+), 152 deletions(-) delete mode 100644 app/src/main/kotlin/bums/lunatic/launcher/PhotoFilter.kt diff --git a/app/src/main/cpp/native_renderer.cpp b/app/src/main/cpp/native_renderer.cpp index b9aefaeb..7bec1697 100644 --- a/app/src/main/cpp/native_renderer.cpp +++ b/app/src/main/cpp/native_renderer.cpp @@ -93,6 +93,7 @@ Java_bums_lunatic_launcher_wall_NativeRenderer_nativeStartRenderLoop(JNIEnv* env LOGE("Could not get ANativeWindow from Surface."); return; } + ANativeWindow_setBuffersGeometry(window, 0, 0, WINDOW_FORMAT_RGBA_8888); renderer->startRenderLoop(window); ANativeWindow_release(window); } diff --git a/app/src/main/kotlin/bums/lunatic/launcher/PhotoFilter.kt b/app/src/main/kotlin/bums/lunatic/launcher/PhotoFilter.kt deleted file mode 100644 index e6e2bd3b..00000000 --- a/app/src/main/kotlin/bums/lunatic/launcher/PhotoFilter.kt +++ /dev/null @@ -1,108 +0,0 @@ -//package bums.lunatic.launcher -// -//import bums.lunatic.launcher.common.CommonActivity -//import android.Manifest -//import android.app.Activity -//import android.content.Intent -//import android.content.pm.PackageManager -//import android.graphics.Bitmap -//import android.net.Uri -//import android.os.Build -//import android.os.Bundle -//import android.provider.MediaStore -//import android.widget.Button -//import android.widget.ImageView -//import androidx.activity.result.ActivityResultLauncher -//import androidx.activity.result.contract.ActivityResultContracts -//import androidx.annotation.RequiresApi -//import androidx.appcompat.app.AppCompatActivity -//import androidx.core.app.ActivityCompat -//import androidx.core.content.ContextCompat -//import bums.lunatic.launcher.utils.Blog -// -// -//class PhotoFilter : CommonActivity() { -//// private lateinit var originalImageView: ImageView -//// private lateinit var filteredImageView: ImageView -//// private lateinit var selectImageButton: Button -//// private val PICK_IMAGE_REQUEST = 1 -//// private val PERMISSION_REQUEST_CODE = 200 -//// -//// init { -//// -//// } -//// -//// override fun onCreate(savedInstanceState: Bundle?) { -//// super.onCreate(savedInstanceState) -//// setContentView(R.layout.photo_filter) -//// -//// originalImageView = findViewById(R.id.originalImageView) -//// filteredImageView = findViewById(R.id.filteredImageView) -//// selectImageButton = findViewById(R.id.selectImageButton) -//// -//// selectImageButton.setOnClickListener { -//// Blog.LOGE("imagePickerLauncher checkPermission() ${checkPermission()}") -//// if (checkPermission()) { -//// openGallery() -//// } else { -//// requestPermission() -//// } -//// } -//// -//// imagePickerLauncher = registerForActivityResult( -//// ActivityResultContracts.GetContent(), -//// {result -> -//// Blog.LOGE("imagePickerLauncher result ${result}") -//// if (result != null) { -//// // Handle the selected image -//// FilePathUri = result; -//// try { -//// var bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), FilePathUri) -//// Blog.LOGE("imagePickerLauncher result ${result} 2") -//// originalImageView.setImageBitmap(bitmap) -//// Blog.LOGE("imagePickerLauncher result ${result} 3") -//// val filteredBitmap = applyCartoonFilter(bitmap) -//// Blog.LOGE("imagePickerLauncher result ${result} 4") -//// filteredImageView.setImageBitmap(filteredBitmap) -//// } catch (e : Exception ) { -//// e.printStackTrace(); -//// } -//// } -//// } -//// ); -//// } -//// -//// var FilePathUri : Uri? = null -//// -//// private var imagePickerLauncher : ActivityResultLauncher? = null -//// -//// -//// private fun openGallery() { -////// val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) -////// startActivityForResult(intent, PICK_IMAGE_REQUEST) -//// -//// imagePickerLauncher?.launch("image/*"); -//// Blog.LOGE("imagePickerLauncher ") -//// -//// } -//// -//// -//// @RequiresApi(Build.VERSION_CODES.TIRAMISU) -//// private fun checkPermission(): Boolean { -//// return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED -//// } -//// -//// @RequiresApi(Build.VERSION_CODES.TIRAMISU) -//// private fun requestPermission() { -//// ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_MEDIA_IMAGES), PERMISSION_REQUEST_CODE) -//// } -//// -//// override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { -//// super.onRequestPermissionsResult(requestCode, permissions, grantResults) -//// if (requestCode == PERMISSION_REQUEST_CODE) { -//// if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { -//// openGallery() -//// } -//// } -//// } -//} \ No newline at end of file diff --git a/app/src/main/kotlin/bums/lunatic/launcher/helpers/ForeGroundService.kt b/app/src/main/kotlin/bums/lunatic/launcher/helpers/ForeGroundService.kt index 9dce9a9e..9911aee4 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/helpers/ForeGroundService.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/helpers/ForeGroundService.kt @@ -202,31 +202,31 @@ class ForeGroundService : Service() { val filter = IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED) registerReceiver(bluetoothreceiver, filter) refreshFeeds() - startWallpaperTimer() +// startWallpaperTimer() startForeGround(vibrator = true) } private fun startWallpaperTimer() { - serviceScope.launch { - while (true) { - changeWallPaper() - delay(TimeUnit.MINUTES.toMillis(10)) // 10분 대기 - } - } +// serviceScope.launch { +// while (true) { +// changeWallPaper() +// delay(TimeUnit.MINUTES.toMillis(10)) // 10분 대기 +// } +// } } private fun changeWallPaper() { - val myFolderPath = File(File(getExternalFilesDir(null), "completed_torrents"),"이미지").absolutePath - - val workRequest = OneTimeWorkRequestBuilder() - .setInputData(workDataOf("FOLDER_PATH" to myFolderPath)) - .build() - - workmanager()?.enqueueUniqueWork( - "SingleWallpaperChange", - ExistingWorkPolicy.REPLACE, - workRequest - ) +// val myFolderPath = File(File(getExternalFilesDir(null), "completed_torrents"),"이미지").absolutePath +// +// val workRequest = OneTimeWorkRequestBuilder() +// .setInputData(workDataOf("FOLDER_PATH" to myFolderPath)) +// .build() +// +// workmanager()?.enqueueUniqueWork( +// "SingleWallpaperChange", +// ExistingWorkPolicy.REPLACE, +// workRequest +// ) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/CompletedFilesFragment.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/CompletedFilesFragment.kt index 79b2e7e1..50fb14ed 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/CompletedFilesFragment.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/CompletedFilesFragment.kt @@ -260,7 +260,7 @@ class CompletedFilesFragment : Fragment() { private fun showUnorganizedFilesDialog(filterType: FileFilterType) { // 사용자가 제외하고 싶어 하는 타겟 목록 - val excludedDirs = listOf(rootDir.name, "이미지", "비디오", "문서", "기타") + val excludedDirs = listOf(rootDir.name, "Images", "Videos", "Documents", "Etc") val unorganizedFiles = mutableListOf() rootDir.walkTopDown().onEnter { dir -> @@ -334,10 +334,7 @@ class CompletedFilesFragment : Fragment() { private fun showMoveDialogForFiles(filesToMove: List) { // 이동 가능한 디렉토리 목록 수집 (현재 폴더는 뺄 필요가 있다면 필터링 로직 추가 가능) - var target = arrayListOf(rootDir.name,"이미지", - "비디오", - "문서", - "기타") + var target = arrayListOf(rootDir.name,"Images", "Videos", "Documents", "Etc") val folders = rootDir.listFiles()?.filter { it.isDirectory && target.contains(it.name) }?.toMutableList() ?: mutableListOf() // 루트 폴더로 꺼내는 옵션도 추가 @@ -744,10 +741,10 @@ class CompletedFilesFragment : Fragment() { filesInRoot?.forEach { file -> val ext = file.extension.lowercase() val folderName = when { - extImages.contains(ext) -> "이미지" - extVideos.contains(ext) -> "비디오" - extDocs.contains(ext) -> "문서" - else -> "기타" + extImages.contains(ext) -> "Images" + extVideos.contains(ext) -> "Videos" + extDocs.contains(ext) -> "Documents" + else -> "Etc" } val targetDir = File(rootDir, folderName) if (!targetDir.exists()) targetDir.mkdirs() diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt index 4be2e9e2..db0dabd1 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt @@ -547,6 +547,10 @@ open class NeoRssActivity : CommonActivity() { R.id.btn_x -> TokiFragment.newInstanceX() R.id.btn_i -> TokiFragment.newInstanceI() R.id.btn_btsearch -> TokiFragment.newInstanceMagnet() +// R.id.btn_img4 -> TokiFragment.newInstanceTumblr() + R.id.btn_img3 -> TokiFragment.newInstanceTumblr() +// R.id.btn_img2 -> TokiFragment.newInstancePixiv() +// R.id.btn_img1 -> TokiFragment.newInstanceArtStation() R.id.btn_torrent -> TorrentListFragment() R.id.btn_info -> SystemStatusFragment() R.id.btn_completed_files -> CompletedFilesFragment() diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/TokiFragment.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/TokiFragment.kt index 27e16aa1..90bd7252 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/TokiFragment.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/TokiFragment.kt @@ -237,6 +237,55 @@ class TokiFragment : RemoteGestureFragment(), PagedTextViewInterface,KeyEventHan putBoolean(ARG_ENABLE_GESTURE, true) } } + + fun newInstanceTumblr(): TokiFragment = TokiFragment().apply { + arguments = Bundle().apply { + putString(ARG_TYPE, "tumblr") + putInt(ARG_LAST_NUM, 0) + putString(ARG_NAME, "www.tumblr") + putString(ARG_DOT, "com") + putBoolean(ARG_USE_NUM_URL, false) + putBoolean(ARG_ENABLE_GESTURE, true) // 이미지 스와이프 탐색을 위해 활성화 + } + } + + // 2. Pinterest: 이미지 큐레이션 및 고화질 검색 + fun newInstancePinterest(): TokiFragment = TokiFragment().apply { + arguments = Bundle().apply { + putString(ARG_TYPE, "pinterest") + putInt(ARG_LAST_NUM, 0) + putString(ARG_NAME, "www.pinterest") + putString(ARG_DOT, "com") + putBoolean(ARG_USE_NUM_URL, false) + putBoolean(ARG_ENABLE_GESTURE, true) + } + } + + // 3. Pixiv: 고화질 일러스트 및 서브컬처 이미지 + fun newInstancePixiv(): TokiFragment = TokiFragment().apply { + arguments = Bundle().apply { + putString(ARG_TYPE, "pixiv") + putInt(ARG_LAST_NUM, 0) + putString(ARG_NAME, "www.pixiv") + putString(ARG_DOT, "net") + putBoolean(ARG_USE_NUM_URL, false) + putBoolean(ARG_ENABLE_GESTURE, true) + putBoolean(ARG_PRIVATE, false) // 필요 시 로그인 정보 유지를 위해 false + } + } + + // 4. ArtStation: 전문가급 고화질 포트폴리오 사이트 + fun newInstanceArtStation(): TokiFragment = TokiFragment().apply { + arguments = Bundle().apply { + putString(ARG_TYPE, "artstation") + putInt(ARG_LAST_NUM, 0) + putString(ARG_NAME, "www.artstation") + putString(ARG_DOT, "com") + putBoolean(ARG_USE_NUM_URL, false) + putBoolean(ARG_ENABLE_GESTURE, true) + } + } + } override fun onRemoteCenterClick() { diff --git a/app/src/main/kotlin/bums/lunatic/launcher/wall/MyWallpaperService.kt b/app/src/main/kotlin/bums/lunatic/launcher/wall/MyWallpaperService.kt index be94bd10..88f7c655 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/wall/MyWallpaperService.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/wall/MyWallpaperService.kt @@ -4,6 +4,7 @@ import android.content.ContentUris import android.os.Environment import android.os.Handler import android.os.HandlerThread +import android.os.ParcelFileDescriptor import android.provider.MediaStore import android.service.wallpaper.WallpaperService import android.util.Log @@ -184,8 +185,8 @@ class MyWallpaperService : WallpaperService() { nativeRenderer?.initialize() // nativeInit() -> initialize() nativeRenderer?.setFadeDuration(1500) nativeRenderer?.setTurnPageDuration(8000) - nativeRenderer?.setAnimationMode(NativeRenderer.ANIMATION_MODE_RANDOM) - nativeRenderer?.setTransitionMode(NativeRenderer.TRANSITION_MODE_RANDOM) + nativeRenderer?.setAnimationMode(NativeRenderer.ANIMATION_MODE_PAN) + nativeRenderer?.setTransitionMode(NativeRenderer.TRANSITION_MODE_FADE) nativeRenderer?.setAnimationSpeed(2.0f) NativeRenderer.nativeSetNextMediaCallback(nextMediaCallback) @@ -213,7 +214,7 @@ class MyWallpaperService : WallpaperService() { } } } - val mediaDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "wallPapers") + val mediaDir = File(File(this@MyWallpaperService.getExternalFilesDir(null), "completed_torrents"), "Images") val supportedExtensions = listOf("mp4", "mkv", "avi", "mov","webm", "jpg", "jpeg", "png", "bmp", "webp", "gif") private val nextMediaCallback = object : NativeRenderer.NextMediaCallback { @@ -237,24 +238,37 @@ class MyWallpaperService : WallpaperService() { } } - private fun getFdFromPath(path: String): Int? { - val uri = MediaStore.Files.getContentUri("external") - val projection = arrayOf(MediaStore.Files.FileColumns._ID) - val selection = "${MediaStore.Files.FileColumns.DATA} = ?" - val selectionArgs = arrayOf(path) + private fun getFdFromPath(filePath: String): Int? { +// val uri = MediaStore.Files.getContentUri("external") +// val projection = arrayOf(MediaStore.Files.FileColumns._ID) +// val selection = "${MediaStore.Files.FileColumns.DATA} = ?" +// val selectionArgs = arrayOf(path) return 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 -> - pfd.detachFd() - } - } else null + val file = File(filePath) + if (file.exists() && file.canRead()) { + // 읽기 전용으로 ParcelFileDescriptor 열기 + val pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY) + // int형 fd 번호만 추출 + val fd = pfd.detachFd() + + // C++로 전달 + fd + } else { + Log.e(TAG, "File does not exist or is not readable: $filePath") + null } +// 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 -> +// pfd.detachFd() +// } +// } else null +// } } catch (e: Exception) { - Log.e(TAG, "Error getting FD for path: $path", e) + Log.e(TAG, "Error getting FD for path: $filePath", e) null } } diff --git a/app/src/main/res/layout/rss_activity.xml b/app/src/main/res/layout/rss_activity.xml index 44297e8e..9415d99a 100644 --- a/app/src/main/res/layout/rss_activity.xml +++ b/app/src/main/res/layout/rss_activity.xml @@ -102,6 +102,30 @@ style="@style/CommonFabStyle" android:id="@+id/btn_info" /> + + + + + + + + + + + + + + + + + + +