# DeviceInfo - Device ID 和 GAID 使用示例

## 概述
DeviceInfo 类现在提供了完整的设备标识符获取功能，包括 Android ID (Device ID) 和 Google Advertising ID (GAID)。

## 新增功能

### 1. Android ID (Device ID)
- `getAndroidId()` - 获取 Android ID

### 2. Google Advertising ID (GAID)
- `getAdvertisingId()` - 协程方式获取 GAID（推荐）
- `getAdvertisingIdSync()` - 同步方式获取 GAID（不推荐）
- `getDeviceIdentifiers()` - 获取所有标识符

### 3. 数据类
- `AdvertisingIdInfo` - GAID 信息
- `DeviceIdentifiers` - 设备标识符集合

## 使用方法

### 1. 初始化
```kotlin
import com.xyzshell.andinfo.AndInfo

// 在 Application 或 Activity 中初始化
AndInfo.init(applicationContext)

// 获取 DeviceInfo 实例
val deviceInfo = AndInfo.instance.device
```

### 2. 获取 Android ID (Device ID)

#### 基本使用
```kotlin
// 获取 Android ID
val androidId = deviceInfo.getAndroidId()
println("Android ID: $androidId")
// 输出示例: "Android ID: 9774d56d682e549c"
```

#### Android ID 特点
- **格式**: 64位十六进制字符串
- **生成时机**: 设备首次启动时随机生成
- **持久性**: 
  - 出厂重置后会改变
  - 清除应用数据不会改变
- **作用域**: 
  - Android 8.0+ 后，每个应用和用户组合都会获得不同的 Android ID
  - Android 8.0 之前，所有应用获得相同的 Android ID
- **权限**: 不需要特殊权限

#### 适用场景
```kotlin
// 1. 应用级设备标识
fun getDeviceTag(): String {
    val deviceInfo = AndInfo.instance.device
    return "device_${deviceInfo.getAndroidId()}"
}

// 2. 用户设备绑定
fun bindDeviceToUser(userId: String) {
    val deviceInfo = AndInfo.instance.device
    val androidId = deviceInfo.getAndroidId()
    // 将 androidId 与 userId 关联存储
    saveBinding(userId, androidId)
}

// 3. 设备唯一性校验
fun isNewDevice(): Boolean {
    val deviceInfo = AndInfo.instance.device
    val androidId = deviceInfo.getAndroidId()
    return !isDeviceRegistered(androidId)
}
```

### 3. 获取 GAID (Google Advertising ID)

#### 协程方式（推荐）
```kotlin
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch

// 在 Activity 或 Fragment 中
lifecycleScope.launch {
    val deviceInfo = AndInfo.instance.device
    val gaidInfo = deviceInfo.getAdvertisingId()
    
    if (gaidInfo != null) {
        println("GAID: ${gaidInfo.id}")
        println("是否限制追踪: ${gaidInfo.isLimitAdTrackingEnabled}")
        
        // 根据追踪限制状态决定是否使用
        if (!gaidInfo.isLimitAdTrackingEnabled) {
            // 用户允许广告追踪，可以使用 GAID
            sendToAnalytics(gaidInfo.id)
        } else {
            // 用户限制了广告追踪，应该尊重用户选择
            println("用户已限制广告追踪")
        }
    } else {
        // Google Play Services 不可用
        println("无法获取 GAID（设备可能没有 Google Play Services）")
    }
}
```

#### 在 ViewModel 中使用
```kotlin
class MainViewModel : ViewModel() {
    fun loadAdvertisingId() {
        viewModelScope.launch {
            val deviceInfo = AndInfo.instance.device
            val gaidInfo = deviceInfo.getAdvertisingId()
            
            gaidInfo?.let { info ->
                _advertisingId.value = info.id
                _isTrackingLimited.value = info.isLimitAdTrackingEnabled
            }
        }
    }
}
```

#### 同步方式（不推荐）
```kotlin
// ⚠️ 警告：会阻塞当前线程，不要在主线程调用
Thread {
    val deviceInfo = AndInfo.instance.device
    val gaidInfo = deviceInfo.getAdvertisingIdSync()
    
    gaidInfo?.let { info ->
        println("GAID: ${info.id}")
    }
}.start()
```

#### GAID 特点
- **格式**: UUID 格式的字符串
- **示例**: "38400000-8cf0-11bd-b23e-10b96e40000d"
- **依赖**: 需要 Google Play Services
- **用户控制**: 
  - 用户可以在设置中重置 GAID
  - 用户可以选择限制广告追踪
- **权限**: 不需要特殊权限，但需要 Google Play Services
- **线程**: 必须在后台线程调用

### 4. 获取所有设备标识符

```kotlin
// 一次性获取所有标识符
lifecycleScope.launch {
    val deviceInfo = AndInfo.instance.device
    val identifiers = deviceInfo.getDeviceIdentifiers()
    
    println("=== 设备标识符 ===")
    println("Android ID: ${identifiers.androidId}")
    
    identifiers.advertisingId?.let { gaid ->
        println("GAID: ${gaid.id}")
        println("限制追踪: ${gaid.isLimitAdTrackingEnabled}")
    } ?: run {
        println("GAID: 不可用")
    }
}
```

### 5. 完整示例：设备信息收集

```kotlin
class DeviceInfoActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        lifecycleScope.launch {
            collectDeviceInfo()
        }
    }
    
    private suspend fun collectDeviceInfo() {
        val deviceInfo = AndInfo.instance.device
        
        // 基本设备信息
        val brand = deviceInfo.brand
        val model = deviceInfo.model
        val manufacturer = deviceInfo.manufacturer
        
        // 设备标识符
        val androidId = deviceInfo.getAndroidId()
        val gaidInfo = deviceInfo.getAdvertisingId()
        
        // 显示信息
        val info = buildString {
            appendLine("=== 设备信息 ===")
            appendLine("品牌: $brand")
            appendLine("型号: $model")
            appendLine("制造商: $manufacturer")
            appendLine()
            appendLine("=== 设备标识符 ===")
            appendLine("Android ID: $androidId")
            
            if (gaidInfo != null) {
                appendLine("GAID: ${gaidInfo.id}")
                appendLine("限制追踪: ${if (gaidInfo.isLimitAdTrackingEnabled) "是" else "否"}")
            } else {
                appendLine("GAID: 不可用（可能没有 Google Play Services）")
            }
        }
        
        println(info)
        // 或显示在 UI 上
        // textView.text = info
    }
}
```

## 数据结构

### AdvertisingIdInfo
```kotlin
/**
 * 广告标识符信息数据类
 */
data class AdvertisingIdInfo(
    val id: String,                        // GAID
    val isLimitAdTrackingEnabled: Boolean  // 是否限制广告追踪
)
```

### DeviceIdentifiers
```kotlin
/**
 * 设备标识符集合数据类
 */
data class DeviceIdentifiers(
    val androidId: String,                    // Android ID
    val advertisingId: AdvertisingIdInfo?     // GAID（可能为 null）
)
```

## Android ID vs GAID 对比

| 特性 | Android ID | GAID |
|------|-----------|------|
| **格式** | 64位十六进制 | UUID |
| **示例** | 9774d56d682e549c | 38400000-8cf0-11bd-b23e-10b96e40000d |
| **依赖** | 无 | Google Play Services |
| **权限** | 无需权限 | 无需权限 |
| **重置** | 出厂重置后改变 | 用户可随时重置 |
| **作用域** | Android 8.0+ 按应用区分 | 全局统一 |
| **用户控制** | 不可控制 | 可限制追踪 |
| **适用场景** | 应用内标识、设备绑定 | 广告追踪、分析 |
| **隐私友好** | 中等 | 高（用户可控） |

## 典型应用场景

### 1. 广告归因
```kotlin
suspend fun trackAdConversion(campaignId: String) {
    val deviceInfo = AndInfo.instance.device
    val gaidInfo = deviceInfo.getAdvertisingId()
    
    if (gaidInfo != null && !gaidInfo.isLimitAdTrackingEnabled) {
        // 用户允许追踪，上报转化数据
        analyticsService.trackConversion(
            gaid = gaidInfo.id,
            campaignId = campaignId
        )
    } else {
        // 使用匿名方式或不追踪
        analyticsService.trackAnonymousConversion(campaignId)
    }
}
```

### 2. 用户设备管理
```kotlin
suspend fun registerDevice() {
    val deviceInfo = AndInfo.instance.device
    val identifiers = deviceInfo.getDeviceIdentifiers()
    
    // 注册设备信息
    val deviceProfile = DeviceProfile(
        androidId = identifiers.androidId,
        brand = deviceInfo.brand,
        model = deviceInfo.model,
        timestamp = System.currentTimeMillis()
    )
    
    saveDeviceProfile(deviceProfile)
}
```

### 3. 防作弊检测
```kotlin
suspend fun checkDeviceFraud(): Boolean {
    val deviceInfo = AndInfo.instance.device
    val androidId = deviceInfo.getAndroidId()
    
    // 检查设备是否被标记为作弊
    return fraudDetectionService.isDeviceFlagged(androidId)
}
```

### 4. A/B 测试分组
```kotlin
suspend fun getExperimentGroup(): String {
    val deviceInfo = AndInfo.instance.device
    val gaidInfo = deviceInfo.getAdvertisingId()
    
    // 使用 GAID 的哈希值进行分组
    val deviceId = gaidInfo?.id ?: deviceInfo.getAndroidId()
    val hash = deviceId.hashCode()
    
    return if (hash % 2 == 0) "GroupA" else "GroupB"
}
```

### 5. 隐私合规检查
```kotlin
suspend fun checkPrivacyCompliance(): PrivacyStatus {
    val deviceInfo = AndInfo.instance.device
    val gaidInfo = deviceInfo.getAdvertisingId()
    
    return PrivacyStatus(
        hasGooglePlayServices = gaidInfo != null,
        isTrackingLimited = gaidInfo?.isLimitAdTrackingEnabled ?: true,
        canUsePersonalizedAds = gaidInfo?.let { !it.isLimitAdTrackingEnabled } ?: false
    )
}
```

## 依赖配置

要使用 GAID 功能，需要在 `build.gradle` 中添加依赖：

```gradle
dependencies {
    // Google Play Services - Advertising ID
    implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
    
    // Kotlin Coroutines（如果项目中还没有）
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
}
```

## 注意事项

### 1. Android ID
- ⚠️ Android 8.0+ 后，每个应用获得的 Android ID 不同
- ⚠️ 出厂重置后会改变
- ⚠️ 不应用于跨应用追踪
- ✅ 适合应用内设备标识

### 2. GAID
- ⚠️ 需要 Google Play Services（国内设备可能不可用）
- ⚠️ 必须尊重用户的"限制广告追踪"设置
- ⚠️ 必须在后台线程调用
- ⚠️ 用户可以随时重置
- ✅ 适合广告归因和分析
- ✅ 符合 Google Play 政策

### 3. 隐私合规
- 📋 遵守 GDPR、CCPA 等隐私法规
- 📋 在隐私政策中说明标识符用途
- 📋 尊重用户的追踪限制选择
- 📋 提供用户删除数据的选项

### 4. 最佳实践
```kotlin
suspend fun getDeviceIdentifierForAnalytics(): String? {
    val deviceInfo = AndInfo.instance.device
    
    // 1. 优先使用 GAID（如果可用且用户允许）
    val gaidInfo = deviceInfo.getAdvertisingId()
    if (gaidInfo != null && !gaidInfo.isLimitAdTrackingEnabled) {
        return gaidInfo.id
    }
    
    // 2. 用户限制了追踪，不应该使用任何标识符
    if (gaidInfo?.isLimitAdTrackingEnabled == true) {
        return null  // 返回 null 表示不追踪
    }
    
    // 3. GAID 不可用（可能是国内设备），使用 Android ID
    // 注意：这种情况下应该获得用户明确同意
    return if (hasUserConsent()) {
        deviceInfo.getAndroidId()
    } else {
        null
    }
}
```

## 示例输出

```
=== 设备信息 ===
品牌: Samsung
型号: SM-G998B
制造商: samsung

=== 设备标识符 ===
Android ID: 9774d56d682e549c
GAID: 38400000-8cf0-11bd-b23e-10b96e40000d
限制追踪: 否
```

## 完成度

✅ **100%** - 所有功能都已实现
- Android ID (Device ID) 获取 ✅
- GAID 获取（协程方式）✅
- GAID 获取（同步方式）✅
- 追踪限制状态检测 ✅
- 综合标识符获取 ✅
- 完整的中文注释 ✅
- 详细的使用文档 ✅
- 隐私合规建议 ✅

