Skip to main content
To integrate the Spam Control SDK into your Android project, follow these steps:

Adding the Repository

First, add the repository to your project’s build.gradle file:
repositories {
    maven {
        url 'https://packagecloud.io/Wave/Wave/maven2'
    }
}
Add the sdk as a dependency in your module’s build.gradle To always get the latest version:
implementation "br.com.wave:spam-control:+"
To get the latest Minor and Patch versions:
implementation "br.com.wave:spam-control:0.+"
Current latest version: 0.13.0

Initialization

After sync, you should be able to use the SpamControl class. It contains the following methods. Context is expected as parameter in each one. They are:
  • enableSpamControl: Turns on the service. It checks for the necessary permissions and returns a EnableReturn object that represents the synchronous result. If any permission is missing, an ui will be shown asking for it. You can listen to the result in your onActivityResult and checking the SpamControl.SpamControl_RESULT requestCode. The result code will be android.app.Activity.RESULT_OK or android.app.Activity.RESULT_CANCELED. If it is RESULT_OK, the user granted the permissions and the service is turned on. If it is RESULT_CANCELED, the user denied at least one permission and enableSpamControl should be called again. If all permissions were already granted before calling this method, the ui will not be triggered and the service will start. We expect as parameters an activity, your apiKey (which we provide) and the user’s current phoneNumber. This method requires that the user has internet connection to work. The Environment parameter defines if the service will point to Staging (STG) or Production (PROD) backend. To change Environment, the enable methods need to be called again with the new Environment (after a call to disable). It is important to notice that STG and PROD apiKeys are different. The default value for this parameter is ´PROD´.
val result = SpamControl.enableSpamControl(
    activity = this,
    apiKey = "...",
    phoneNumber = "...",
    environment = SpamControl.Environment.PROD
)
when (result) {
    SpamControl.EnableReturn.Error.Connection -> { /* No connection when enabling the service */ }
    SpamControl.EnableReturn.Error.EmptyApiKey -> { /* Received apiKey is empty */ }
    SpamControl.EnableReturn.Error.EmptyPhoneNumber -> { /* Received apiKey is empty */ }
    SpamControl.EnableReturn.Success -> { /* Service is active */ }
    SpamControl.EnableReturn.AlreadyOn -> { /* Service is already on, so no action is taken */ }
    SpamControl.EnableReturn.WaitingPermissions -> { /* Waiting for user to grant permissions, listen to onActivityResult */}
}
  • enableSpamControlSilently: Turns on the service silently. It checks for the necessary permissions and returns a EnableSilentlyReturn object. If any mandatory permission is missing, the service will not be enabled. You can check by calling hasSpamControlPermissions. If all mandatory permissions were already granted before calling this method, the service will start. We expect as parameters a context, your apiKey (which we provide) and the user’s current phoneNumber. The Environment parameter defines if the service will point to Staging (STG) or Production (PROD) backend. To change Environment, the enable methods need to be called again with the new Environment (after a call to disable). It is important to notice that STG and PROD apiKeys are different. The default value for this parameter is ´PROD´
val result = SpamControl.enableSpamControlSilently(
    context = this,
    apiKey = "...",
    phoneNumber = "...",
    environment = SpamControl.Environment.PROD
)
when (result) {
    SpamControl.EnableSilentlyReturn.Error.MissingPermission -> { /* The app is still missing permissions. Please use SpamControl.enableSpamControl instead. */ }
    SpamControl.EnableSilentlyReturn.Error.EmptyApiKey -> { /* Received apiKey is empty */ }
    SpamControl.EnableSilentlyReturn.Error.EmptyPhoneNumber -> { /* Received apiKey is empty */ }
    SpamControl.EnableSilentlyReturn.AlreadyOn -> { /* Service is already on, so no action is taken */ }
    SpamControl.EnableSilentlyReturn.Success -> { /* Service is active */ }
}
  • disableSpamControl: Turns off the service. This method doesn’t revoke any granted permissions.
SpamControl.disableSpamControl(context = this)
  • isSpamControlOn: Returns true if the service is on and false if it is off.
SpamControl.isSpamControlOn(context = this)
  • getCurrentEnvironment: Returns the current environment, which is an enum. Possible values are STG and PROD.
val environment = SpamControl.getCurrentEnvironment(context = this)
  • hasSpamControlPermissions: Returns true if the app has mandatory Spam Id permission for the service to work. Returns false if it doesn’t.
SpamControl.hasSpamControlPermissions(context = this)
  • hasSpamControlOptionalPermissions: Returns true if the app has all of the optional permissions (READ_CONTACTS && READ_CALL_LOG). Returns false if at least one permission is missing.
SpamControl.hasSpamControlOptionalPermissions(context = this)
  • getCalls: Returns a list of PhoneCall objects, each representing a phone call that was registered by our service. Please note that we erase objects that are considered old from time to time.
SpamControl.getCalls(context = this)

data class PhoneCall(
    val id: Int, // Id from calls database
    val phoneNumber: String, // Call's number
    val date: String, // When the call was received
    val name: String?, // Contact's name, if it exists
    val categoryId: Int?, // Category's id, if number is categorized. Same id from Category object. See getCategories method
    val category: String?, // Category's name, if number is categorized. Same name from Category object. See getCategories method
    val isUploaded: Boolean, // If call data was uploaded to backend successfully for metrics
    val status: PhoneCallStatus, // Register what happened to the call during screening. Possible values are described below
    val direction: PhoneCallDirection, // If call was received (IN) or made (OUT)
    val databaseId: String?, // Service database's id that identified the number
)

enum class PhoneCallStatus {
    CATEGORY_FILTERED, // Blocked. Number's category is enabled.
    USER_ALLOWED_CATEGORY, // Not blocked. Number's category is disabled.
    CATEGORY_FILTERED_PREFIX, // Blocked. Number has a prefix related to a category that is enabled.
    CATEGORY_NOT_MAPPED, // Blocked. Number is identified by SpamControl, but doesn't have a category.
    MANUAL_BLOCK, // Blocked. Number was manually blocked by the user.
    NOT_IN_DATABASE, // Not blocked. Number is not identified by SpamControl.
    RELIABLE_NUMBER, // Not blocked. Number was manually unblocked by the user.
    ALLOWED_CONTACT, // Not blocked. Number is a user's contact.
    BLOCKED_PRIVATE_NUMBER, // Blocked. Number is private, not accessible.
    ALLOWED_PENDING_PAYMENT, // Not blocked. User is missing payment.
    UNDEFINED, // Status was not mapped

    NORMAL, // Deprecated. This value is not used for new calls and will be removed soon. Use NOT_IN_DATABASE instead
    SPAM, // Deprecated. This value is not used for new calls and will be removed soon. Use USER_ALLOWED_CATEGORY instead
    RELIABLE, // Deprecated. This value is not used for new calls and will be removed soon. Use RELIABLE_NUMBER instead
    BLOCKED; // Deprecated. This value is not used for new calls and will be removed soon. Use CATEGORY_FILTERED instead

    // Returns true if the call was blocked by SpamControl based on status (call.status.isBlocked()).
    fun isBlocked(): Boolean
}
  • deleteCalls: Deletes all registered calls from our registry. Returns a DeleteCallsReturn object.
val result = SpamControl.deleteCalls(context = this)
when (result) {
    SpamControl.DeleteCallsReturn.Error.Unknown -> { /* Something wrong happened */ }
    SpamControl.DeleteCallsReturn.Error.NoCallsToDelete -> { /* There are no calls to be deleted */ }
    SpamControl.DeleteCallsReturn.Success -> { /* Deleted successfully */ }
}
  • getUserSpamNumbers: Returns a list of UserSpamPhoneNumber objects, each representing a specific number that the user manually blocked or allowed receiving calls from.
SpamControl.getUserSpamNumbers(context = this)

data class UserSpamPhoneNumber(
    val phoneNumber: String, // Blocked/Unblocked number.
    val name: String?, // Number's contact name.
    val categoryId: Int?, // Number's category.
    val isBlocked: Boolean, // True if blocked and false if unblocked
    val date: Date? // The date when blocked or unblocked
)
  • blockNumber: Blocks a number. Pass the number as a trimmed number only string. Returns a BlockReturn object.
val result = SpamControl.blockNumber(context = this, number = "...")
when (result) {
    SpamControl.BlockReturn.Error.Unknown -> { /* Something wrong happened */ }
    SpamControl.BlockReturn.Error.NumberLengthSmall -> { /* The provided number is not accepted for being too small. The is a `minLength` field inside this data class representing the current minimum length. It is set as 3 */ }
    SpamControl.BlockReturn.Error.NumberLengthLong -> { /* The provided number is not accepted for being too long. The is a `maxLength` field inside this data class representing the current maximum length. It is set as 14 */ }
    SpamControl.BlockReturn.Success -> { /* Number blocked successfully */ }
}
  • unblockNumber: Unblocks a number. Pass the number as a trimmed number only string. Returns a UnblockReturn object.
val result = SpamControl.unblockNumber(context = this, number = "...")
when (result) {
    SpamControl.UnblockReturn.Error.Unknown -> { /* Something wrong happened */ }
    SpamControl.UnblockReturn.Error.NumberIsNotBlocked -> { /* The provided number is not currently blocked */ }
    SpamControl.UnblockReturn.Success -> { /* Number unblocked successfully */ }
}
  • getCategories: Returns a list of Category objects, each representing a category of phone numbers that can be all blocked/unblocked at once
SpamControl.getCategories(context = this)

data class Category(
    val id: Int, // Id from categories database
    val category: String?, // Category's name
    val description: String?, // Category's description
    val isBlocked: Int?, // True if blocked and false if unblocked
    val regex: String?, // Category's regex, usually used to block numbers by prefix
    val icon: String?, // Category's icon for ui
)
  • blockCategory: Blocks future calls from any number inside a specific spam category
SpamControl.blockCategory(context = this, categoryId = ...)
  • unblockCategory: Unblocks future calls from any number inside a specific spam category
SpamControl.unblockCategory(context = this, categoryId = ...)
  • isNumberBlocked: Returns a Boolean that corresponds if the number is blocked or not. Please note that this method will return null if the current number is not in the user’s call history.
SpamControl.isNumberBlocked(context = this, number = ...)

Minimum Android Version

Our current minSdkVersion is 24.

Required Permissions

The SDK will require the following permissions to function correctly:
  • INTERNET Since the block list is dynamic and needs to be downloaded from a server.
  • ACCESS_NETWORK_STATE To check if there is wifi or 4g connectivity before enabling the service.
  • READ_CONTACTS Provides access to the user’s contact list. Without this permission, it is impossible to block a call from a contact. (api 29+)
  • READ_CALL_LOG Provides access to the user’s call history. We use this data, like if a call was rejected or answered, as well as the call duration, to improve our spam detection.
  • POST_NOTIFICATIONS: So we can trigger notifications from time to time to let the user know how many blocks happened
  • Default dialer To allow the SDK to detect incoming calls (api 24 to 28).
  • Default spam app To allow the SDK to detect incoming calls (api 29+).