From 178cccd93fe1979488c5223d94b0b916767a1344 Mon Sep 17 00:00:00 2001 From: Moez Bhatti Date: Tue, 9 Feb 2021 23:09:05 -0500 Subject: [PATCH] Add support for Call Blocker --- .../moez/QKSMS/blocking/BlockingManager.kt | 2 + .../blocking/CallBlockerBlockingClient.kt | 84 +++++++++++++++++++ .../java/com/moez/QKSMS/util/Preferences.kt | 1 + .../java/com/moez/QKSMS/common/Navigator.kt | 9 ++ .../manager/BlockingManagerController.kt | 4 + .../manager/BlockingManagerPresenter.kt | 26 ++++++ .../blocking/manager/BlockingManagerState.kt | 1 + .../blocking/manager/BlockingManagerView.kt | 1 + .../layout/blocking_manager_controller.xml | 8 ++ presentation/src/main/res/values/strings.xml | 2 + 10 files changed, 138 insertions(+) create mode 100644 data/src/main/java/com/moez/QKSMS/blocking/CallBlockerBlockingClient.kt diff --git a/data/src/main/java/com/moez/QKSMS/blocking/BlockingManager.kt b/data/src/main/java/com/moez/QKSMS/blocking/BlockingManager.kt index 23d9e758..633a22f3 100644 --- a/data/src/main/java/com/moez/QKSMS/blocking/BlockingManager.kt +++ b/data/src/main/java/com/moez/QKSMS/blocking/BlockingManager.kt @@ -12,6 +12,7 @@ import javax.inject.Singleton @Singleton class BlockingManager @Inject constructor( private val prefs: Preferences, + private val callBlockerBlockingClient: CallBlockerBlockingClient, private val callControlBlockingClient: CallControlBlockingClient, private val qksmsBlockingClient: QksmsBlockingClient, private val shouldIAnswerBlockingClient: ShouldIAnswerBlockingClient @@ -19,6 +20,7 @@ class BlockingManager @Inject constructor( private val client: BlockingClient get() = when (prefs.blockingManager.get()) { + Preferences.BLOCKING_MANAGER_CB -> callBlockerBlockingClient Preferences.BLOCKING_MANAGER_SIA -> shouldIAnswerBlockingClient Preferences.BLOCKING_MANAGER_CC -> callControlBlockingClient else -> qksmsBlockingClient diff --git a/data/src/main/java/com/moez/QKSMS/blocking/CallBlockerBlockingClient.kt b/data/src/main/java/com/moez/QKSMS/blocking/CallBlockerBlockingClient.kt new file mode 100644 index 00000000..8cb4ada1 --- /dev/null +++ b/data/src/main/java/com/moez/QKSMS/blocking/CallBlockerBlockingClient.kt @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2020 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.blocking + +import android.content.Context +import android.content.Intent +import android.database.Cursor +import android.net.Uri +import androidx.core.database.getStringOrNull +import com.moez.QKSMS.common.util.extensions.isInstalled +import com.moez.QKSMS.extensions.map +import com.moez.QKSMS.util.tryOrNull +import io.reactivex.Completable +import io.reactivex.Single +import java.util.ArrayList +import javax.inject.Inject + +class CallBlockerBlockingClient @Inject constructor( + private val context: Context +) : BlockingClient { + + class LookupResult(cursor: Cursor) { + val blockReason: String? = cursor.getStringOrNull(0) + } + + override fun isAvailable(): Boolean = context.isInstalled("com.cuiet.blockCalls") + + override fun getClientCapability() = BlockingClient.Capability.BLOCK_WITH_PERMISSION + + override fun getAction(address: String): Single = Single.fromCallable { + val uri = Uri.parse("content://com.cuiet.blockCalls.ContProvBlockCalls/lookup/is.blocked.lookup") + val blockReason = tryOrNull { + context.contentResolver.query(uri, arrayOf("result"), "incomingNumber", + arrayOf(address), null) + ?.use { cursor -> cursor.map(::LookupResult) } + ?.find { result -> result.blockReason != null } + }?.blockReason + + when (blockReason) { + "true" -> BlockingClient.Action.Block() + else -> BlockingClient.Action.Unblock + } + } + + override fun block(addresses: List): Completable = Completable.fromCallable { + val arrayList = ArrayList() + arrayList.addAll(addresses) + val intent = Intent("com.cuiet.blockCalls.ADD_NUMBERS") + intent.putStringArrayListExtra("addresses", arrayList) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(intent) + } + + override fun unblock(addresses: List): Completable = Completable.fromCallable { + val arrayList = ArrayList() + arrayList.addAll(addresses) + val intent = Intent("com.cuiet.blockCalls.REMOVE_NUMBERS") + intent.putStringArrayListExtra("addresses", arrayList) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(intent) + } + + override fun openSettings() { + val intent = Intent("com.cuiet.blockCalls.OPEN_SETTINGS") + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(intent) + } +} diff --git a/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt b/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt index 919fab27..d7711f3b 100644 --- a/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt +++ b/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt @@ -75,6 +75,7 @@ class Preferences @Inject constructor( const val BLOCKING_MANAGER_QKSMS = 0 const val BLOCKING_MANAGER_CC = 1 const val BLOCKING_MANAGER_SIA = 2 + const val BLOCKING_MANAGER_CB = 3 } // Internal diff --git a/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt b/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt index 0a7cba9c..b0659c99 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt @@ -191,6 +191,15 @@ class Navigator @Inject constructor( } } + /** + * Launch the Play Store and display the Call Blocker listing + */ + fun installCallBlocker() { + val url = "https://play.google.com/store/apps/details?id=com.cuiet.blockCalls" + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + startActivityExternal(intent) + } + /** * Launch the Play Store and display the Call Control listing */ diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerController.kt index ed64b1d5..7c0b392c 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerController.kt @@ -44,6 +44,9 @@ class BlockingManagerController : QkController = activityResumedSubject override fun qksmsClicked(): Observable<*> = qksms.clicks() + override fun callBlockerClicked(): Observable<*> = callBlocker.clicks() override fun callControlClicked(): Observable<*> = callControl.clicks() override fun siaClicked(): Observable<*> = shouldIAnswer.clicks() diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerPresenter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerPresenter.kt index 1ef5d91f..09b748bc 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerPresenter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerPresenter.kt @@ -3,6 +3,7 @@ package com.moez.QKSMS.feature.blocking.manager import android.content.Context import com.moez.QKSMS.R import com.moez.QKSMS.blocking.BlockingClient +import com.moez.QKSMS.blocking.CallBlockerBlockingClient import com.moez.QKSMS.blocking.CallControlBlockingClient import com.moez.QKSMS.blocking.QksmsBlockingClient import com.moez.QKSMS.blocking.ShouldIAnswerBlockingClient @@ -21,6 +22,7 @@ import javax.inject.Inject class BlockingManagerPresenter @Inject constructor( private val analytics: AnalyticsManager, + private val callBlocker: CallBlockerBlockingClient, private val callControl: CallControlBlockingClient, private val context: Context, private val conversationRepo: ConversationRepository, @@ -30,6 +32,7 @@ class BlockingManagerPresenter @Inject constructor( private val shouldIAnswer: ShouldIAnswerBlockingClient ) : QkPresenter(BlockingManagerState( blockingManager = prefs.blockingManager.get(), + callBlockerInstalled = callBlocker.isAvailable(), callControlInstalled = callControl.isAvailable(), siaInstalled = shouldIAnswer.isAvailable() )) { @@ -42,6 +45,12 @@ class BlockingManagerPresenter @Inject constructor( override fun bindIntents(view: BlockingManagerView) { super.bindIntents(view) + view.activityResumed() + .map { callBlocker.isAvailable() } + .distinctUntilChanged() + .autoDisposable(view.scope()) + .subscribe { available -> newState { copy(callBlockerInstalled = available) } } + view.activityResumed() .map { callControl.isAvailable() } .distinctUntilChanged() @@ -64,6 +73,23 @@ class BlockingManagerPresenter @Inject constructor( prefs.blockingManager.set(Preferences.BLOCKING_MANAGER_QKSMS) } + view.callBlockerClicked() + .filter { + val installed = callBlocker.isAvailable() + if (!installed) { + analytics.track("Install Call Blocker") + navigator.installCallBlocker() + } + + val enabled = prefs.blockingManager.get() == Preferences.BLOCKING_MANAGER_CB + installed && !enabled + } + .autoDisposable(view.scope()) + .subscribe { + analytics.setUserProperty("Blocking Manager", "Call Blocker") + prefs.blockingManager.set(Preferences.BLOCKING_MANAGER_CB) + } + view.callControlClicked() .filter { val installed = callControl.isAvailable() diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerState.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerState.kt index 2663caf0..169add4b 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerState.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerState.kt @@ -2,6 +2,7 @@ package com.moez.QKSMS.feature.blocking.manager data class BlockingManagerState( val blockingManager: Int = 0, + val callBlockerInstalled: Boolean = false, val callControlInstalled: Boolean = false, val siaInstalled: Boolean = false ) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerView.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerView.kt index 7318e53a..dd871e17 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/manager/BlockingManagerView.kt @@ -8,6 +8,7 @@ interface BlockingManagerView : QkViewContract { fun activityResumed(): Observable<*> fun qksmsClicked(): Observable<*> + fun callBlockerClicked(): Observable<*> fun callControlClicked(): Observable<*> fun siaClicked(): Observable<*> diff --git a/presentation/src/main/res/layout/blocking_manager_controller.xml b/presentation/src/main/res/layout/blocking_manager_controller.xml index 03575c7b..b85e2877 100644 --- a/presentation/src/main/res/layout/blocking_manager_controller.xml +++ b/presentation/src/main/res/layout/blocking_manager_controller.xml @@ -37,6 +37,14 @@ app:summary="@string/blocking_manager_qksms_summary" app:title="@string/blocking_manager_qksms_title" /> + + Blocking Manager QKSMS Built-in blocking functionality in QKSMS + Call Blocker + Call Blocker is a program that blocks unwanted calls, call centers, spam, robocalls, telemarketing, private calls, hidden calls, anonymous calls, strangers, etc. Call Control Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers Should I Answer?