From 51ceb5feffb8975707cc3b0b170f93e33afa9ce6 Mon Sep 17 00:00:00 2001 From: Andrin Bertschi Date: Thu, 7 Dec 2023 16:27:37 +0100 Subject: [PATCH 1/7] Remove unused imports --- .../java/ch/abertschi/adfree/presenter/SettingsPresenter.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/java/ch/abertschi/adfree/presenter/SettingsPresenter.kt b/app/src/main/java/ch/abertschi/adfree/presenter/SettingsPresenter.kt index d658c19..566dfb8 100644 --- a/app/src/main/java/ch/abertschi/adfree/presenter/SettingsPresenter.kt +++ b/app/src/main/java/ch/abertschi/adfree/presenter/SettingsPresenter.kt @@ -11,12 +11,9 @@ import ch.abertschi.adfree.ad.AdObservable import ch.abertschi.adfree.plugin.AdPlugin import ch.abertschi.adfree.plugin.PluginHandler import ch.abertschi.adfree.view.setting.SettingsView -import io.reactivex.Observable -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.schedulers.Schedulers import org.jetbrains.anko.AnkoLogger import org.jetbrains.anko.collections.forEachWithIndex -import java.util.concurrent.TimeUnit + /** From 5f1c7d3643ef66362560281c38226c0fe56ba4ea Mon Sep 17 00:00:00 2001 From: Andrin Bertschi Date: Thu, 7 Dec 2023 16:27:57 +0100 Subject: [PATCH 2/7] accuradio: inspect bigContentView and tickerView Apart from contentView, also inspect bigContentView and tickerView. --- .../adfree/detector/AccuradioDetector.kt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/ch/abertschi/adfree/detector/AccuradioDetector.kt b/app/src/main/java/ch/abertschi/adfree/detector/AccuradioDetector.kt index bc3a01f..a0eae4b 100644 --- a/app/src/main/java/ch/abertschi/adfree/detector/AccuradioDetector.kt +++ b/app/src/main/java/ch/abertschi/adfree/detector/AccuradioDetector.kt @@ -55,10 +55,9 @@ class AccuradioDetector : AdDetectable, AnkoLogger, AbstractNotificationDetector } } - override fun flagAsAdvertisement(payload: AdPayload): Boolean { + + private fun inspectContentViews(contentView: RemoteViews?): Boolean { try { - val contentView = payload.statusbarNotification?.notification?.contentView - info(payload) if (contentView != null) { val actions = extractObject(contentView, "mActions") as List<*>? if (actions != null) { @@ -88,4 +87,18 @@ class AccuradioDetector : AdDetectable, AnkoLogger, AbstractNotificationDetector } return false } + + override fun flagAsAdvertisement(payload: AdPayload): Boolean { + info(payload) + val contentView = payload.statusbarNotification?.notification?.contentView + val bigView = payload.statusbarNotification?.notification?.bigContentView + val tickerView = payload.statusbarNotification?.notification?.tickerView + + for (v in listOf(contentView, bigView, tickerView)) { + if (inspectContentViews(v)) { + return true; + } + } + return false; + } } \ No newline at end of file From 89137c395e0103a87a79cf8d1592f9a78b9f0193 Mon Sep 17 00:00:00 2001 From: Andrin Bertschi Date: Thu, 7 Dec 2023 16:51:46 +0100 Subject: [PATCH 3/7] introduce new field in text repository --- .../ch/abertschi/adfree/model/TextRepository.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/main/java/ch/abertschi/adfree/model/TextRepository.kt b/app/src/main/java/ch/abertschi/adfree/model/TextRepository.kt index e753e6e..5957cb1 100644 --- a/app/src/main/java/ch/abertschi/adfree/model/TextRepository.kt +++ b/app/src/main/java/ch/abertschi/adfree/model/TextRepository.kt @@ -39,6 +39,7 @@ class TextRepository : AnkoLogger { private val context: Context private val ID_KEY: String = "k_" private val ID_KEYS: String = "keys" + private val ID_USE_REFLECTION_FOR_MATCH = "_use_reflection" private var dataEntries: ArrayList @@ -56,6 +57,8 @@ class TextRepository : AnkoLogger { return sharedPreferences.getStringSet(ID_KEYS, HashSet()) } + + private fun getEntryByFormattedKey(key: String): TextRepositoryData? { var dataStr: String = sharedPreferences.getString(key, null) ?: return null return TextRepositoryData.deserialzeFromString(dataStr) @@ -72,6 +75,18 @@ class TextRepository : AnkoLogger { return entries } + /* + * Boolean to indicate if a generic reflection based + * approach should be used to find a matching text entry in all fields of the payload + */ + fun useReflectionForMatch(): Boolean { + return sharedPreferences.getBoolean(ID_USE_REFLECTION_FOR_MATCH, false) + } + + fun setReflectionForMatch(useIt: Boolean) { + sharedPreferences.edit().putBoolean(ID_USE_REFLECTION_FOR_MATCH, useIt).apply() + } + fun getAllEntries(): ArrayList { return ArrayList(dataEntries) } From e7109c5a6a145409e7b03a895a6711f87bcadd2e Mon Sep 17 00:00:00 2001 From: Andrin Bertschi Date: Thu, 7 Dec 2023 16:52:17 +0100 Subject: [PATCH 4/7] add comments --- .../ch/abertschi/adfree/detector/AccuradioDetector.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/ch/abertschi/adfree/detector/AccuradioDetector.kt b/app/src/main/java/ch/abertschi/adfree/detector/AccuradioDetector.kt index a0eae4b..ff30b6b 100644 --- a/app/src/main/java/ch/abertschi/adfree/detector/AccuradioDetector.kt +++ b/app/src/main/java/ch/abertschi/adfree/detector/AccuradioDetector.kt @@ -89,10 +89,10 @@ class AccuradioDetector : AdDetectable, AnkoLogger, AbstractNotificationDetector } override fun flagAsAdvertisement(payload: AdPayload): Boolean { - info(payload) - val contentView = payload.statusbarNotification?.notification?.contentView - val bigView = payload.statusbarNotification?.notification?.bigContentView - val tickerView = payload.statusbarNotification?.notification?.tickerView + // XXX: Support old deprecated fields + val contentView = payload.statusbarNotification.notification?.contentView + val bigView = payload.statusbarNotification.notification?.bigContentView + val tickerView = payload.statusbarNotification.notification?.tickerView for (v in listOf(contentView, bigView, tickerView)) { if (inspectContentViews(v)) { From 1921a8ed8f515cf3d1f7da7b18d6fe06277eb7f8 Mon Sep 17 00:00:00 2001 From: Andrin Bertschi Date: Thu, 7 Dec 2023 16:52:29 +0100 Subject: [PATCH 5/7] userdef. text detector: implement new mode mode uses a simple serialization approach and checks all fields in payload if they contain the user defined elements. --- .../detector/UserDefinedTextDetector.kt | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/ch/abertschi/adfree/detector/UserDefinedTextDetector.kt b/app/src/main/java/ch/abertschi/adfree/detector/UserDefinedTextDetector.kt index e7f9e13..8c9764a 100644 --- a/app/src/main/java/ch/abertschi/adfree/detector/UserDefinedTextDetector.kt +++ b/app/src/main/java/ch/abertschi/adfree/detector/UserDefinedTextDetector.kt @@ -4,6 +4,7 @@ import android.app.Notification import android.os.Bundle import ch.abertschi.adfree.model.TextRepository import ch.abertschi.adfree.model.TextRepositoryData +import com.thoughtworks.xstream.XStream import org.jetbrains.anko.AnkoLogger import org.jetbrains.anko.warn import java.util.* @@ -38,8 +39,9 @@ class UserDefinedTextDetector(private val repo: TextRepository) : AdDetectable, } } - override fun flagAsAdvertisement(payload: AdPayload): Boolean { - val extras = payload.statusbarNotification?.notification?.extras + // Use a fixed approach and search for predefined fields + private fun flagAsAdvertisementFixed(payload: AdPayload): Boolean { + val extras = payload.statusbarNotification.notification?.extras val title = extractString(extras, Notification.EXTRA_TITLE) val subTitle = extractString(extras, Notification.EXTRA_SUB_TEXT) @@ -59,6 +61,28 @@ class UserDefinedTextDetector(private val repo: TextRepository) : AdDetectable, return false; } + private fun flagAsAdvertisementDynamic(payload: AdPayload): Boolean { + /* + * XXX: This implementation is inefficient but simple. + * Will a reflection approach be better? + */ + val str = XStream().toXML(payload)!!.toLowerCase() + for (entry in payload.matchedTextDetectorEntries) { + for (entryLine in entry.content) { + if (entryLine.trim().isEmpty()) { + continue + } + if (str.contains(entryLine.trim().toLowerCase())) { + return true + } + } + } + return false + } + override fun flagAsAdvertisement(payload: AdPayload) = + if (repo.useReflectionForMatch()) flagAsAdvertisementDynamic(payload) + else flagAsAdvertisementFixed(payload) + override fun getMeta(): AdDetectorMeta = AdDetectorMeta( "User defined text", "flag a notification based on the presence of text", false, From 3d6dc17b86003d591150db22198b5316374fb098 Mon Sep 17 00:00:00 2001 From: Andrin Bertschi Date: Fri, 8 Dec 2023 20:25:43 +0100 Subject: [PATCH 6/7] userdef. text: use both fixed and dynamic detector --- .../ch/abertschi/adfree/detector/UserDefinedTextDetector.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/ch/abertschi/adfree/detector/UserDefinedTextDetector.kt b/app/src/main/java/ch/abertschi/adfree/detector/UserDefinedTextDetector.kt index 8c9764a..1d180e9 100644 --- a/app/src/main/java/ch/abertschi/adfree/detector/UserDefinedTextDetector.kt +++ b/app/src/main/java/ch/abertschi/adfree/detector/UserDefinedTextDetector.kt @@ -80,8 +80,7 @@ class UserDefinedTextDetector(private val repo: TextRepository) : AdDetectable, return false } override fun flagAsAdvertisement(payload: AdPayload) = - if (repo.useReflectionForMatch()) flagAsAdvertisementDynamic(payload) - else flagAsAdvertisementFixed(payload) + flagAsAdvertisementFixed(payload) || flagAsAdvertisementDynamic(payload) override fun getMeta(): AdDetectorMeta = AdDetectorMeta( "User defined text", "flag a notification based on the presence of text", From d58404c2d9a3ff46297ed9a2ac0cef26db9f0f6e Mon Sep 17 00:00:00 2001 From: Andrin Bertschi Date: Fri, 8 Dec 2023 22:52:57 +0100 Subject: [PATCH 7/7] Prepare for release 3.2 --- CHANGELOG.md | 5 +++++ app/build.gradle | 4 ++-- metadata/en-US/changelogs/42.txt | 3 +++ metadata/en-US/full_description.txt | 2 +- metadata/en-US/short_description.txt | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 metadata/en-US/changelogs/42.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 767a834..c610ada 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ # Changelog / Ad-Free + +### v3.2/42 (2023-12-08) +- Improve Accuradio Detector to support bigContentView, tickerView and contentView (#93, thanks to @unseenlarks) +- Use generic reflection approach UserDefinedText Detector to search for user defined ad texts + ### v3.1/41 - Fix bug with local music plugin: folder selection diff --git a/app/build.gradle b/app/build.gradle index d2ca3b9..f9b1011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "ch.abertschi.adfree" minSdkVersion 23 targetSdkVersion 27 - versionCode 41 - versionName "3.1" + versionCode 42 + versionName "3.2" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true } diff --git a/metadata/en-US/changelogs/42.txt b/metadata/en-US/changelogs/42.txt new file mode 100644 index 0000000..3430405 --- /dev/null +++ b/metadata/en-US/changelogs/42.txt @@ -0,0 +1,3 @@ +### v3.2/42 (2023-12-08) +- Improve Accuradio Detector to support bigContentView, tickerView and contentView (#93, thanks to @unseenlarks) +- Use generic reflection approach UserDefinedText Detector to search for user defined ad texts diff --git a/metadata/en-US/full_description.txt b/metadata/en-US/full_description.txt index 56e3862..be30be5 100644 --- a/metadata/en-US/full_description.txt +++ b/metadata/en-US/full_description.txt @@ -1,4 +1,4 @@ -ad-free is an ad audio blocker for Android. +Ad-free is an ad audio blocker for Android. This app is a research project attempting to show flaws in the way how audio advertisement is shown on Android. It is a proof-of-concept of a diff --git a/metadata/en-US/short_description.txt b/metadata/en-US/short_description.txt index b6e1b67..b28d208 100644 --- a/metadata/en-US/short_description.txt +++ b/metadata/en-US/short_description.txt @@ -1 +1 @@ -ad-free is a modularized audio ad blocker for Spotify and more on Android. +Ad-free is a modularized audio ad blocker for Spotify and more on Android.