diff --git a/app/src/main/java/com/github/cvzi/screenshottile/services/ScreenshotAccessibilityService.kt b/app/src/main/java/com/github/cvzi/screenshottile/services/ScreenshotAccessibilityService.kt index 6e536822c..97104315f 100644 --- a/app/src/main/java/com/github/cvzi/screenshottile/services/ScreenshotAccessibilityService.kt +++ b/app/src/main/java/com/github/cvzi/screenshottile/services/ScreenshotAccessibilityService.kt @@ -174,6 +174,12 @@ class ScreenshotAccessibilityService : AccessibilityService() { private var packageFilterMode = PackageNameFilterMode.BLACKLIST private val packageFilterNameList: HashSet = HashSet() private var lastPackageName: CharSequence = "" + + /** + * Get the package name of the last foreground application + */ + fun getForegroundPackageName(): String = lastPackageName.toString() + private var prefManager = App.getInstance().prefManager private var lastClickTime = 0L private val doubleClickThreshold = 300L // milliseconds @@ -1035,12 +1041,17 @@ class ScreenshotAccessibilityService : AccessibilityService() { } override fun onAccessibilityEvent(event: AccessibilityEvent) { - if (packageFilterEnabled && - event.isFullScreen && + if (event.isFullScreen && event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && event.packageName != lastPackageName ) { - lastPackageName = event.packageName + if (event.packageName != packageName) { + lastPackageName = event.packageName + } + + if (!packageFilterEnabled) { + return + } if (packageFilterTempForceShow) { // Temporary show floating button despite filter until the next app change but at least 60s diff --git a/app/src/main/java/com/github/cvzi/screenshottile/utils/Utils.kt b/app/src/main/java/com/github/cvzi/screenshottile/utils/Utils.kt index 7af21db61..125ca8af1 100644 --- a/app/src/main/java/com/github/cvzi/screenshottile/utils/Utils.kt +++ b/app/src/main/java/com/github/cvzi/screenshottile/utils/Utils.kt @@ -451,9 +451,93 @@ fun formatFileName(fileNamePattern: String, date: Date): String { while (fileName.contains("%random%")) { fileName = fileName.replaceFirst("%random%", UUID.randomUUID().toString()) } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && (fileName.contains("%app%") || fileName.contains("%package%"))) { + val service = ScreenshotAccessibilityService.instance + val packageName = service?.getForegroundPackageName() ?: "" + fileName = fileName.replace("%package%", sanitizeFilename(packageName)) + if (fileName.contains("%app%")) { + val appLabel = resolveAppLabel(packageName) + fileName = fileName.replace("%app%", sanitizeFilename(appLabel)) + } + } return fileName } +private fun resolveAppLabel(packageName: String): String { + if (packageName.isBlank()) { + return "" + } + + val context = App.getInstance() + val pm = context.packageManager + + // Try launcher activity + try { + val launchIntent = pm.getLaunchIntentForPackage(packageName) + if (launchIntent != null) { + val resolveInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + pm.resolveActivity( + launchIntent, + PackageManager.ResolveInfoFlags.of(0) + ) + } else { + @Suppress("DEPRECATION") + pm.resolveActivity(launchIntent, 0) + } + + resolveInfo?.let { + val label = it.loadLabel(pm)?.toString() + if (!label.isNullOrBlank()) { + return label + } + } + } + } catch (_: Exception) { + // no-op + } + + // Try ApplicationInfo + try { + val appInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + pm.getApplicationInfo( + packageName, + PackageManager.ApplicationInfoFlags.of(0) + ) + } else { + @Suppress("DEPRECATION") + pm.getApplicationInfo(packageName, 0) + } + + val label = pm.getApplicationLabel(appInfo)?.toString() + if (!label.isNullOrBlank()) { + return label + } + } catch (_: Exception) { + // no-op + } + + // Fallback + return shortPackageName(packageName) +} + +/** + * Get last part of package name + */ +private fun shortPackageName(pkg: String): String { + val parts = pkg.split('.') + return when { + parts.size >= 2 -> parts.takeLast(2).joinToString(".") + else -> pkg + } +} + +/** + * Remove characters that are not allowed in filenames + */ +private fun sanitizeFilename(name: String): String { + return name.replace(Regex("[\\\\/:*?\"<>|]"), "_") +} + /** * Cut cutOutRect from bitmap and return new bitmap, * return old bitmap if cutOutRect is null or malformed diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 7806bb73b..4f7dea946 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -62,7 +62,9 @@ +%randint% - a random number\n +%app% - name of the foreground app\n +%package% - package name of the foreground app]]> Tile action Tile long-press action Floating button action diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 426ca7e04..a87c58c57 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -62,7 +62,9 @@ +%randint% - случайное число\n +%app% - название приложения на переднем плане\n +%package% - имя пакета приложения на переднем плане]]> Действие плитки Действие при длительном нажатии на плитку Действие плавающей кнопки diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 69558f70a..b5e90d853 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -62,7 +62,9 @@ +%randint% - a random number\n +%app% - name of the foreground app\n +%package% - package name of the foreground app]]> ‌Tile action ‌Tile long-press action ‌Floating button action