SDK do Android - Privacidade de dados

Conformidade com leis de privacidade de dados

Implemente a coleta de dados em conformidade com a privacidade notificando o Singular sobre as escolhas de consentimento dos usuários para GDPR, CCPA e outras regulamentações de privacidade do consumidor.

Quando os usuários consentem ou recusam o compartilhamento de suas informações com terceiros, utilize os métodos de privacidade do Singular para comunicar essa escolha. Isso garante a conformidade com regulamentações como a California Consumer Privacy Act (CCPA) e permite que os parceiros respeitem as preferências de privacidade do usuário.

Saiba mais: Consulte Privacidade do usuário e limitação do compartilhamento de dados para obter informações detalhadas sobre como o Singular processa o consentimento de privacidade.


Limitar o compartilhamento de dados

Controlar o compartilhamento de dados com terceiros

Notifique o Singular sobre se os usuários consentiram em compartilhar seus dados pessoais com parceiros terceirizados usando o método limitDataSharing .

Assinatura do método:

public static void limitDataSharing(boolean shouldLimitDataSharing);

Parâmetros:

  • false: O usuário optou por participar e consentiu em compartilhar seus dados
  • true: O usuário optou por não participar e não consente em compartilhar seus dados

Importante: Embora opcional, este método afeta o compartilhamento de dados de atribuição. Alguns parceiros só compartilham informações completas de atribuição quando são notificados explicitamente de que os usuários optaram por participar.

Exemplos de uso

Kotlin Java
// User has opted in to share their data
Singular.limitDataSharing(false)

// User has opted out and declined to share their data
Singular.limitDataSharing(true)

// Example: Set based on user preference
fun handlePrivacyConsent(userConsented: Boolean) {
    // Pass inverse: false = opted in, true = opted out
    Singular.limitDataSharing(!userConsented)

    Log.d("Privacy", "Data sharing: ${if (userConsented) "Enabled" else "Limited"}")
}

Como funciona:

O Singular usa essa configuração em postbacks de privacidade do usuário e a repassa para os parceiros que a exigem para conformidade regulatória.


Limitação do compartilhamento de dados por evento

Substituir o compartilhamento de dados em um único evento

Você pode substituir a configuração global limitDataSharing para um único evento ou chamada de receita personalizada passando o atributo Attributes.sngAttrLimitDataSharing junto com os demais argumentos do evento. Isso é útil quando o usuário atualiza o consentimento de forma simultânea a uma ação e deseja que esse evento específico reflita a nova escolha imediatamente, sem alterar a configuração global do SDK para os eventos subsequentes.

Valores aceitos:

  • false: O usuário optou por participar apenas neste evento
  • true: O usuário optou por não participar apenas neste evento

Importante: O atributo deve ser um Boolean . Entradas que não sejam booleanas são ignoradas e a requisição recorre à configuração global limitDataSharing . Em qualquer caso, o atributo é removido dos argumentos do evento antes do envio da requisição, de modo que nunca aparece no payload do evento.

Exemplos de uso

Kotlin Java
// Example 1: Standard event, opt out only for this event
val args = JSONObject()
    .put(Attributes.sngAttrLimitDataSharing.toString(), true)
    .put("order_id", "12345")

Singular.event("checkout_completed", args.toString())

// Example 2: Custom revenue, opt in only for this event
val attributes = mutableMapOf<String, Any>().apply {
    put(Attributes.sngAttrLimitDataSharing.toString(), false)
    put("sku", "premium_monthly")
}

Singular.customRevenue("premium_purchase", "USD", 9.99, attributes)

Como funciona:

Quando um valor booleano válido é fornecido, o SDK remove o atributo dos argumentos do evento e o grava no campo data_sharing_options.limit_data_sharing da requisição — substituindo a configuração global limitDataSharing apenas para essa requisição. A configuração global e o resultado de getLimitDataSharing não são modificados, de modo que os eventos subsequentes que não fornecerem o atributo continuarão a usar a escolha global.


Métodos de conformidade com o GDPR

Gerencie o consentimento de rastreamento do usuário e controle a funcionalidade do SDK para estar em conformidade com o GDPR (Regulamento Geral sobre a Proteção de Dados) e outras regulamentações de privacidade.

Gerenciamento de consentimento de rastreamento

trackingOptIn

Registre o consentimento explícito do usuário para rastreamento enviando um evento de opt-in do GDPR para os servidores do Singular.

Assinatura do método:

Singular.trackingOptIn()

Quando usar:

  • Conformidade com o GDPR: Chame quando os usuários consentirem explicitamente o rastreamento em regiões regulamentadas pelo GDPR
  • Registro de consentimento: Marca os usuários como tendo fornecido consentimento do GDPR nos sistemas do Singular
  • Comportamento padrão: Sem essa chamada, o SDK continua rastreando, mas não registra o consentimento de forma específica
Kotlin Java
// User accepted tracking consent
Singular.trackingOptIn()

// Example: Call after consent dialog
fun onUserAcceptedTracking() {
    Singular.trackingOptIn()
    Log.d("GDPR", "User opted in to tracking")
}

Métodos de controle de rastreamento

stopAllTracking

Desative completamente todas as atividades de rastreamento do SDK para o usuário atual neste dispositivo.

Assinatura do método:

Singular.stopAllTracking()

Aviso crítico: Este método desativa o SDK permanentemente até que resumeAllTracking() seja chamado. O estado desativado persiste após reinicializações do app e só pode ser revertido por programação.

Comportamento:

  • Efeito imediato: Interrompe todo o rastreamento, o envio de eventos e a coleta de dados instantaneamente
  • Estado persistente: Permanece desativado mesmo após o app ser fechado e reaberto
  • Sem reinicialização automática: É preciso chamar explicitamente resumeAllTracking() para reativar
Kotlin Java
// User declined all tracking
Singular.stopAllTracking()

// Example: Handle user opt-out
fun onUserDeclinedTracking() {
    Singular.stopAllTracking()
    Log.d("Privacy", "All tracking stopped")

    // Optionally store preference
    saveUserTrackingPreference(false)
}

resumeAllTracking

Reative o rastreamento depois que ele foi interrompido com stopAllTracking() .

Assinatura do método:

Singular.resumeAllTracking()

Casos de uso:

  • Alteração do consentimento: O usuário altera as preferências de privacidade e opta novamente pelo rastreamento
  • Configurações de privacidade: O usuário atualiza o consentimento por meio do menu de configurações do app
  • Conformidade regional: Reativa o rastreamento quando o usuário muda para regiões não regulamentadas
Kotlin Java
// User opted back in to tracking
Singular.resumeAllTracking()

// Example: Handle consent update
fun onUserResumedTracking() {
    Singular.resumeAllTracking()
    Log.d("Privacy", "Tracking resumed")

    // Optionally update stored preference
    saveUserTrackingPreference(true)
}

isAllTrackingStopped

Verifique se o rastreamento foi desativado para o usuário atual.

Assinatura do método:

public static boolean isAllTrackingStopped();

Retorna:

  • true: O rastreamento está atualmente interrompido por stopAllTracking()
  • false: O rastreamento está ativo (nunca foi interrompido ou foi retomado)

Retorna false se o SDK não tiver sido inicializado, independentemente de qualquer estado de rastreamento anterior. Sempre confirme que Singular.init() foi concluído antes de confiar nesse valor e interprete false como "não interrompido ou ainda não inicializado", e não como "rastreando ativamente".

Kotlin Java
// Check current tracking status
val isTrackingStopped = Singular.isAllTrackingStopped()

// Example: Display privacy status in settings
fun getPrivacyStatusText(): String {
    return if (Singular.isAllTrackingStopped()) {
        "Tracking: Disabled"
    } else {
        "Tracking: Enabled"
    }
}

// Example: Sync UI with tracking state
fun updatePrivacyToggle() {
    val isStopped = Singular.isAllTrackingStopped()
    privacyToggle.isChecked = !isStopped
    Log.d("Privacy", "Current tracking state: ${if (isStopped) "Stopped" else "Active"}")
}

Proteção da privacidade infantil

trackingUnder13

Notifique o Singular de que o usuário tem menos de 13 anos para estar em conformidade com a COPPA (Lei de Proteção da Privacidade Online de Crianças) e outras regulamentações de privacidade infantil.

Assinatura do método:

Singular.trackingUnder13()

Requisitos de conformidade:

  • Conformidade com a COPPA: Necessário para apps que coletam dados de crianças menores de 13 anos nos Estados Unidos
  • Conteúdo com restrição de idade: Use quando os usuários se identificarem como menores de 13 anos durante o registro ou a verificação de idade
  • Rastreamento restrito: Limita a coleta de dados para estar em conformidade com as leis de proteção da privacidade infantil
Kotlin Java
// User identified as under 13
Singular.trackingUnder13()

// Example: Call after age verification
fun onAgeVerified(userAge: Int) {
    if (userAge < 13) {
        Singular.trackingUnder13()
        Log.d("Privacy", "COPPA mode enabled for user under 13")
    }
}

Importante: Chame este método o quanto antes após determinar que o usuário tem menos de 13 anos, idealmente durante a inicialização do app ou imediatamente após a verificação de idade. Isso garante que todo o rastreamento subsequente respeite as regulamentações de privacidade infantil.


setLimitAdvertisingIdentifiers

Restrinja a coleta e o uso de identificadores de publicidade (GAID no Android) após a inicialização do SDK em apps de audiência mista.

Assinatura do método:

public static void setLimitAdvertisingIdentifiers(boolean enabled);

Parâmetros:

  • enabled: Passe true para limitar a coleta do identificador de publicidade; false para restaurar a coleta normal.

Não confunda com a variante em tempo de configuração. O método em tempo de execução Singular.setLimitAdvertisingIdentifiers(boolean) exige um argumento booleano, enquanto o método em tempo de configuração SingularConfig.withLimitAdvertisingIdentifiers() não recebe argumentos e ativa o limite incondicionalmente. Chamar o método em tempo de execução sem argumentos não compila.

Casos de uso:

  • Apps de audiência mista: Apps que atendem tanto adultos quanto crianças, em que a idade é determinada após o lançamento do app
  • Controles de privacidade dinâmicos: Ajuste o rastreamento com base nas ações do usuário ou no conteúdo acessado
  • Restrições em tempo de execução: Aplique as limitações do identificador de publicidade após a configuração inicial do SDK
Kotlin Java
// Limit advertising identifiers after initialization
Singular.setLimitAdvertisingIdentifiers(true)

// Example: Mixed audience app with age gate
fun onKidsModeSwitched(isKidsMode: Boolean) {
    if (isKidsMode) {
        Singular.setLimitAdvertisingIdentifiers(true)
        Log.d("Privacy", "Advertising identifiers limited for kids mode")
    }
}

// Example: Content-based restrictions
fun onViewingChildrensContent() {
    Singular.setLimitAdvertisingIdentifiers(true)
    Log.d("Privacy", "Ad identifiers restricted for children's content")
}

Alternativa de configuração: Você também pode limitar os identificadores de publicidade durante a inicialização do SDK usando SingularConfig.withLimitAdvertisingIdentifiers() se conhecer os requisitos de privacidade antes do início do SDK.

Método de configuração

Defina as limitações dos identificadores de publicidade durante a inicialização do SDK para apps que conhecem os requisitos de privacidade antecipadamente.

Kotlin Java
// Limit advertising identifiers at initialization
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
    .withLimitAdvertisingIdentifiers()

Singular.init(applicationContext, config)

Boas práticas de implementação

Exemplo completo de gerenciamento de privacidade

Implemente controles de privacidade abrangentes que respeitem as preferências do usuário e estejam em conformidade com as regulamentações.

Kotlin Java
class PrivacyManager(private val context: Context) {

    private val prefs = context.getSharedPreferences("privacy_prefs", Context.MODE_PRIVATE)

    // Initialize privacy settings on app start
    fun initializePrivacy() {
        val hasUserConsent = getUserConsent()
        val allowDataSharing = getDataSharingPreference()
        val userAge = getUserAge()

        // Apply stored preferences
        if (hasUserConsent) {
            Singular.trackingOptIn()
            Singular.resumeAllTracking()
        } else {
            Singular.stopAllTracking()
        }

        // Set data sharing preference
        Singular.limitDataSharing(!allowDataSharing)

        // Handle children's privacy
        if (userAge > 0 && userAge < 13) {
            Singular.trackingUnder13()
            Singular.setLimitAdvertisingIdentifiers(true)
        }

        Log.d("Privacy", "Initialized: consent=$hasUserConsent, sharing=$allowDataSharing, age=$userAge")
    }

    // User accepts tracking via consent dialog
    fun userAcceptedTracking() {
        saveUserConsent(true)
        Singular.trackingOptIn()
        Singular.resumeAllTracking()
        Log.d("Privacy", "User accepted tracking")
    }

    // User declines tracking
    fun userDeclinedTracking() {
        saveUserConsent(false)
        Singular.stopAllTracking()
        Log.d("Privacy", "User declined tracking")
    }

    // User updates data sharing preference
    fun setDataSharingEnabled(enabled: Boolean) {
        saveDataSharingPreference(enabled)
        // Note: limitDataSharing uses inverse logic
        Singular.limitDataSharing(!enabled)
        Log.d("Privacy", "Data sharing: ${if (enabled) "Enabled" else "Limited"}")
    }

    // Handle age verification result
    fun onAgeVerified(age: Int) {
        saveUserAge(age)
        if (age < 13) {
            Singular.trackingUnder13()
            Singular.setLimitAdvertisingIdentifiers(true)
            Log.d("Privacy", "COPPA restrictions applied for user under 13")
        }
    }

    // Get current tracking status
    fun isTrackingEnabled(): Boolean {
        return !Singular.isAllTrackingStopped()
    }

    // Private helper methods
    private fun getUserConsent(): Boolean {
        return prefs.getBoolean("user_consent", false)
    }

    private fun saveUserConsent(consent: Boolean) {
        prefs.edit().putBoolean("user_consent", consent).apply()
    }

    private fun getDataSharingPreference(): Boolean {
        return prefs.getBoolean("data_sharing", false)
    }

    private fun saveDataSharingPreference(enabled: Boolean) {
        prefs.edit().putBoolean("data_sharing", enabled).apply()
    }

    private fun getUserAge(): Int {
        return prefs.getInt("user_age", 0)
    }

    private fun saveUserAge(age: Int) {
        prefs.edit().putInt("user_age", age).apply()
    }
}

Boas práticas:

  • Armazenamento persistente: Salve as preferências do usuário no SharedPreferences ou em armazenamento seguro
  • Inicialização antecipada: Aplique as configurações de privacidade antes da inicialização do SDK sempre que possível
  • Sincronização da UI: Mantenha a UI de configurações sincronizada com o estado real do SDK usando isAllTrackingStopped()
  • Comunicação clara: Forneça controles de privacidade claros e acessíveis nas configurações do app
  • Verificação de idade: Implemente uma verificação de idade robusta para apps voltados a crianças
  • Controles combinados: Para usuários menores de 13 anos, aplique tanto trackingUnder13() quanto setLimitAdvertisingIdentifiers(true)