Unity SDK - 数据隐私

文件

遵守数据隐私法

通过通知 Singular 用户同意 GDPR、CCPA 和其他消费者隐私法规的选择,实施符合隐私法规的数据收集。

当用户同意或拒绝与第三方共享其信息时,使用 Singular 的隐私方法来传达他们的选择。这将确保遵守《加州消费者隐私法案》(CCPA)等法规,并使合作伙伴尊重用户的隐私偏好。

了解更多信息:有关Singular如何处理隐私同意的详细信息,请参阅用户隐私和限制数据共享


限制数据共享

控制第三方数据共享

通知Singular用户是否同意使用LimitDataSharing 方法与第三方合作伙伴共享个人数据。

方法签名

SingularSDK.LimitDataSharing(bool shouldLimitDataSharing)

参数

  • false:用户已选择并同意共享其数据
  • true: true:用户已退出,不同意共享其数据

重要:虽然此方法是可选的,但它会影响属性数据的共享。一些合作伙伴只有在明确通知用户已选择加入时,才会共享完整的属性信息。

使用示例

C#
using UnityEngine;
using Singular;

public class PrivacyManager : MonoBehaviour
{
    // User has opted in to share their data
    public void OnUserOptedInToDataSharing()
    {
        SingularSDK.LimitDataSharing(false);
        Debug.Log("Data sharing enabled");
    }

    // User has opted out and declined to share their data
    public void OnUserOptedOutOfDataSharing()
    {
        SingularSDK.LimitDataSharing(true);
        Debug.Log("Data sharing limited");
    }

    // Example: Set based on user preference
    public void HandlePrivacyConsent(bool userConsented)
    {
        // Pass inverse: false = opted in, true = opted out
        SingularSDK.LimitDataSharing(!userConsented);

        Debug.Log($"Data sharing: {(userConsented ? "Enabled" : "Limited")}");
    }
}

如何使用

Singular 在用户隐私回邮中使用此设置,并将其传递给需要遵守法规的合作伙伴。


GDPR 合规方法

管理用户跟踪同意和控制SDK功能,以符合GDPR(通用数据保护条例)和其他隐私法规。

跟踪同意管理

跟踪同意

通过向 Singular 服务器发送 GDPR 选入事件,记录用户对跟踪的明确同意。

方法签名

SingularSDK.TrackingOptIn()

何时使用

  • GDPR 合规性:当用户明确同意在受 GDPR 监管的地区进行跟踪时调用
  • 同意记录:在 Singular 系统中将用户标记为已提供 GDPR 同意
  • 默认行为:如果没有此调用,SDK 会继续跟踪,但不会明确记录同意信息
C#
using UnityEngine;
using Singular;

public class GDPRManager : MonoBehaviour
{
    // User accepted tracking consent
    public void OnUserAcceptedTracking()
    {
        SingularSDK.TrackingOptIn();
        Debug.Log("User opted in to tracking");
    }

    // Example: Call after consent dialog
    public void ShowGDPRConsentDialog()
    {
        // Your consent dialog UI logic here
        // ...

        // If user accepts:
        OnUserAcceptedTracking();
    }
}

跟踪控制方法

停止所有跟踪

完全禁用当前用户在此设备上的所有 SDK 跟踪活动。

方法签名

SingularSDK.StopAllTracking()

严重警告:此方法会永久禁用 SDK,直到调用ResumeAllTracking() 。禁用状态会在应用程序重启时持续存在,只能通过编程方式逆转。

行为

  • 立即生效:立即停止所有跟踪、事件报告和数据收集功能
  • 持续状态:即使在应用程序关闭和重新打开后也会保持禁用状态
  • 无法自动重置:必须明确调用ResumeAllTracking() 才能重新启用
C#
using UnityEngine;
using Singular;

public class TrackingController : MonoBehaviour
{
    // User declined all tracking
    public void OnUserDeclinedTracking()
    {
        SingularSDK.StopAllTracking();
        Debug.Log("All tracking stopped");

        // Optionally store preference
        PlayerPrefs.SetInt("tracking_enabled", 0);
        PlayerPrefs.Save();
    }

    // Example: Handle user opt-out from settings menu
    public void HandlePrivacySettingsChange(bool trackingEnabled)
    {
        if (!trackingEnabled)
        {
            SingularSDK.StopAllTracking();
            Debug.Log("Privacy settings: Tracking disabled");
        }
    }
}

恢复所有跟踪

在使用StopAllTracking() 停止跟踪后重新启用跟踪。

方法签名

SingularSDK.ResumeAllTracking()

使用案例

  • 同意更改:用户更改隐私偏好并选择恢复跟踪
  • 隐私设置:用户通过应用程序设置菜单更新同意
  • 地区合规性:当用户转移到非监管区域时重新启用跟踪功能
C#
using UnityEngine;
using Singular;

public class TrackingController : MonoBehaviour
{
    // User opted back in to tracking
    public void OnUserResumedTracking()
    {
        SingularSDK.ResumeAllTracking();
        Debug.Log("Tracking resumed");

        // Optionally update stored preference
        PlayerPrefs.SetInt("tracking_enabled", 1);
        PlayerPrefs.Save();
    }

    // Example: Handle consent update from settings
    public void HandlePrivacySettingsChange(bool trackingEnabled)
    {
        if (trackingEnabled)
        {
            SingularSDK.ResumeAllTracking();
            Debug.Log("Privacy settings: Tracking enabled");
        }
    }
}

IsAllTrackingStopped

检查当前用户是否已禁用跟踪功能。

方法签名

bool SingularSDK.IsAllTrackingStopped()

返回 返回 返回 返回值值值值

  • true:当前已通过StopAllTracking()停止跟踪
  • false:跟踪处于活动状态(从未停止或恢复
C#
using UnityEngine;
using UnityEngine.UI;
using Singular;

public class PrivacySettingsUI : MonoBehaviour
{
    public Toggle trackingToggle;
    public Text statusText;

    void Start()
    {
        // Check current tracking status on startup
        UpdatePrivacyUI();
    }

    // Check current tracking status
    public bool IsTrackingEnabled()
    {
        return !SingularSDK.IsAllTrackingStopped();
    }

    // Example: Display privacy status in settings
    public string GetPrivacyStatusText()
    {
        if (SingularSDK.IsAllTrackingStopped())
        {
            return "Tracking: Disabled";
        }
        else
        {
            return "Tracking: Enabled";
        }
    }

    // Example: Sync UI with tracking state
    public void UpdatePrivacyUI()
    {
        bool isStopped = SingularSDK.IsAllTrackingStopped();

        if (trackingToggle != null)
        {
            trackingToggle.isOn = !isStopped;
        }

        if (statusText != null)
        {
            statusText.text = GetPrivacyStatusText();
        }

        Debug.Log($"Current tracking state: {(isStopped ? "Stopped" : "Active")}");
    }

    // Handle toggle change from UI
    public void OnTrackingToggleChanged(bool enabled)
    {
        if (enabled)
        {
            SingularSDK.ResumeAllTracking();
        }
        else
        {
            SingularSDK.StopAllTracking();
        }

        UpdatePrivacyUI();
    }
}

儿童隐私保护

13 岁以下用户跟踪

通知 Singular 用户未满 13 周岁,以遵守 COPPA(儿童在线隐私保护法案)和其他儿童隐私法规。

方法签名

SingularSDK.TrackingUnder13()

合规要求

  • COPPA 合规性:收集美国 13 岁以下儿童数据的应用程序必须遵守
  • 有年龄限制的内容:当用户在注册或年龄验证时表明自己未满 13 岁时使用
  • 限制跟踪:限制数据收集,以遵守儿童隐私保护法
C#
using UnityEngine;
using Singular;

public class COPPAManager : MonoBehaviour
{
    // User identified as under 13
    public void OnUserUnder13()
    {
        SingularSDK.TrackingUnder13();
        Debug.Log("COPPA mode enabled for user under 13");
    }
    
    // Example: Call after age verification
    public void OnAgeVerified(int userAge)
    {
        if (userAge < 13)
        {
            SingularSDK.TrackingUnder13();
            Debug.Log("COPPA restrictions applied");
            
            // Also limit advertising identifiers
            SingularSDK.SetLimitAdvertisingIdentifiers(true);
        }
    }
}

重要提示:在确定用户未满 13 周岁后尽早调用此方法,最好是在应用程序初始化期间或年龄验证后立即调用。这样可确保所有后续跟踪都遵守儿童隐私保护法规。


设置广告标识符限制

在混合受众应用程序的 SDK 初始化后,限制广告标识符(Android 上为 GAID,iOS 上为 IDFA)的收集和使用。

方法签名

SingularSDK.SetLimitAdvertisingIdentifiers(bool isEnabled)

参数

  • true:启用限制广告标识符模式(限制收集
  • false:禁用有限广告标识符模式:禁用有限广告标识符模式(正常收集

使用案例

  • 混合受众应用程序:同时为成人和儿童服务的应用程序,其年龄在应用程序启动后确定
  • 动态隐私控制:根据用户操作或访问内容调整跟踪
  • 运行时限制:在初始 SDK 设置后应用广告标识符限制
C#
using UnityEngine;
using Singular;

public class AdvertisingIdentifierManager : MonoBehaviour
{
    // Limit advertising identifiers after initialization
    public void EnableLimitedMode()
    {
        SingularSDK.SetLimitAdvertisingIdentifiers(true);
        Debug.Log("Advertising identifiers limited");
    }
    
    // Example: Mixed audience app with age gate
    public void OnKidsModeSwitched(bool isKidsMode)
    {
        if (isKidsMode)
        {
            SingularSDK.SetLimitAdvertisingIdentifiers(true);
            Debug.Log("Advertising identifiers limited for kids mode");
        }
        else
        {
            SingularSDK.SetLimitAdvertisingIdentifiers(false);
            Debug.Log("Advertising identifiers unrestricted for adult mode");
        }
    }
    
    // Example: Content-based restrictions
    public void OnViewingChildrensContent()
    {
        SingularSDK.SetLimitAdvertisingIdentifiers(true);
        Debug.Log("Ad identifiers restricted for children's content");
    }
    
    // Example: Combined with TrackingUnder13
    public void OnAgeVerified(int age)
    {
        if (age < 13)
        {
            SingularSDK.TrackingUnder13();
            SingularSDK.SetLimitAdvertisingIdentifiers(true);
            Debug.Log("Full COPPA restrictions applied");
        }
    }
}

配置替代方案:如果您在 SDK 启动前就知道隐私要求,也可以在 SDK 初始化期间通过设置 Singular SDK 配置中的limitAdvertisingIdentifiers 属性来限制广告标识符。

配置属性

在 SDK 初始化期间为预先知道隐私要求的应用程序设置广告标识符限制。

C#
using UnityEngine;
using Singular;

public class SDKInitializer : MonoBehaviour
{
    void Start()
    {
        // Get reference to SingularSDK component
        var singularSDK = GetComponent<SingularSDK>();
        
        // Limit advertising identifiers at initialization
        singularSDK.limitAdvertisingIdentifiers = true;
        
        // Initialize SDK
        if (!singularSDK.InitializeOnAwake)
        {
            SingularSDK.InitializeSingularSDK();
        }
    }
}

实施最佳实践

完整隐私管理示例

实施全面的隐私控制,尊重用户偏好并遵守法规。

C#
using UnityEngine;
using Singular;

public class ComprehensivePrivacyManager : MonoBehaviour
{
    private const string PREF_USER_CONSENT = "privacy_user_consent";
    private const string PREF_DATA_SHARING = "privacy_data_sharing";

    void Start()
    {
        // Initialize privacy settings on app start
        InitializePrivacySettings();
    }

    /// <summary>
    /// Initialize privacy settings on app startup based on stored preferences
    /// </summary>
    public void InitializePrivacySettings()
    {
        bool hasUserConsent = GetUserConsent();
        bool allowDataSharing = GetDataSharingPreference();

        // Apply stored tracking preference
        if (hasUserConsent)
        {
            SingularSDK.TrackingOptIn();
            SingularSDK.ResumeAllTracking();
            Debug.Log("Privacy initialized: Tracking enabled with consent");
        }
        else
        {
            SingularSDK.StopAllTracking();
            Debug.Log("Privacy initialized: Tracking disabled");
        }

        // Set data sharing preference (inverse logic)
        SingularSDK.LimitDataSharing(!allowDataSharing);

        Debug.Log($"Privacy initialized: consent={hasUserConsent}, sharing={allowDataSharing}");
    }

    /// <summary>
    /// User accepts tracking via consent dialog
    /// </summary>
    public void OnUserAcceptedTracking()
    {
        SaveUserConsent(true);

        SingularSDK.TrackingOptIn();
        SingularSDK.ResumeAllTracking();

        Debug.Log("User accepted tracking");
    }

    /// <summary>
    /// User declines tracking
    /// </summary>
    public void OnUserDeclinedTracking()
    {
        SaveUserConsent(false);

        SingularSDK.StopAllTracking();

        Debug.Log("User declined tracking");
    }

    /// <summary>
    /// User updates data sharing preference
    /// </summary>
    /// <param name="enabled">True to enable data sharing, false to limit it</param>
    public void SetDataSharingEnabled(bool enabled)
    {
        SaveDataSharingPreference(enabled);

        // Note: LimitDataSharing uses inverse logic
        // false = data sharing enabled, true = data sharing limited
        SingularSDK.LimitDataSharing(!enabled);

        Debug.Log($"Data sharing: {(enabled ? "Enabled" : "Limited")}");
    }

    /// <summary>
    /// Check if tracking is currently enabled
    /// </summary>
    /// <returns>True if tracking is active, false if stopped</returns>
    public bool IsTrackingEnabled()
    {
        return !SingularSDK.IsAllTrackingStopped();
    }

    /// <summary>
    /// Get current privacy status as readable text
    /// </summary>
    /// <returns>Human-readable tracking status</returns>
    public string GetPrivacyStatus()
    {
        bool isEnabled = !SingularSDK.IsAllTrackingStopped();
        bool dataSharingEnabled = GetDataSharingPreference();

        return $"Tracking: {(isEnabled ? "Enabled" : "Disabled")}\n" +
               $"Data Sharing: {(dataSharingEnabled ? "Enabled" : "Limited")}";
    }

    // Private helper methods for PlayerPrefs storage

    private bool GetUserConsent()
    {
        return PlayerPrefs.GetInt(PREF_USER_CONSENT, 0) == 1;
    }

    private void SaveUserConsent(bool consent)
    {
        PlayerPrefs.SetInt(PREF_USER_CONSENT, consent ? 1 : 0);
        PlayerPrefs.Save();
    }

    private bool GetDataSharingPreference()
    {
        return PlayerPrefs.GetInt(PREF_DATA_SHARING, 0) == 1;
    }

    private void SaveDataSharingPreference(bool enabled)
    {
        PlayerPrefs.SetInt(PREF_DATA_SHARING, enabled ? 1 : 0);
        PlayerPrefs.Save();
    }
}

最佳实践

  • 持久存储:使用 PlayerPrefs 或安全存储解决方案保存用户首选项
  • 尽早初始化:尽可能在 SDK 初始化之前应用隐私设置
  • UI 同步:使用IsAllTrackingStopped()保持设置 UI 与实际 SDK 状态同步
  • 清晰沟通:在应用设置中提供清晰、易用的隐私控制
  • 反向逻辑:请记住,LimitDataSharing(false) 意味着启用数据共享,而true 则意味着限制数据共享
  • 合规文档:保留用户何时以及如何提供或撤销同意的记录