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