# 设备信息收集和上传使用指南

## 概述
本功能提供了完整的设备信息收集、序列化、加密和上传功能。所有信息收集都是异步并发执行，性能优化且不会阻塞主线程。

## 功能特性

### 1. 信息收集模块
自动收集以下 24 类设备信息：
- CPU 信息
- GPU 信息
- 屏幕信息
- 内存信息
- 磁盘信息
- 网络信息
- 电池信息
- 设备信息
- 应用信息
- 系统信息
- 定位信息
- 相机信息
- 传感器信息
- 系统属性
- 蓝牙信息
- WiFi 信息
- NFC 信息
- USB 信息
- 构建信息
- DRM 信息
- 输入设备信息
- Device ID
- GAID

### 2. 数据处理流程
1. **异步收集** - 并发收集所有信息，提高性能
2. **JSON 序列化** - 将所有信息转换为 JSON 格式
3. **AES 加密** - 使用 AES 加密保护数据
4. **HTTP POST** - 发送加密数据到服务器
5. **响应处理** - 解析服务器响应

## 使用方法

### 1. 基本使用

```kotlin
import androidx.lifecycle.lifecycleScope
import com.xyzshell.andinfo.AndInfo
import com.xyzshell.andinfo.collector.DeviceInfoCollector
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 初始化 AndInfo
        AndInfo.init(applicationContext)
        
        // 收集并上传设备信息
        uploadDeviceInfo()
    }
    
    private fun uploadDeviceInfo() {
        lifecycleScope.launch {
            val collector = DeviceInfoCollector(applicationContext)
            
            collector.collectAndUpload { message, error ->
                if (error != null) {
                    // 上传失败
                    runOnUiThread {
                        Toast.makeText(
                            this@MainActivity,
                            "上传失败: ${error.message}",
                            Toast.LENGTH_LONG
                        ).show()
                    }
                } else {
                    // 上传成功
                    runOnUiThread {
                        Toast.makeText(
                            this@MainActivity,
                            "上传成功: $message",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }
            }
        }
    }
}
```

### 2. 仅收集信息（不上传）

```kotlin
lifecycleScope.launch {
    val collector = DeviceInfoCollector(applicationContext)
    
    // 仅收集信息，不上传
    val deviceInfo = collector.collectAllInfo()
    
    // 转换为 JSON 查看
    val json = collector.gson.toJson(deviceInfo)
    println("设备信息: $json")
}
```

### 3. 在 ViewModel 中使用

```kotlin
class DeviceInfoViewModel : ViewModel() {
    private val _uploadStatus = MutableLiveData<UploadStatus>()
    val uploadStatus: LiveData<UploadStatus> = _uploadStatus
    
    fun uploadDeviceInfo(context: Context) {
        viewModelScope.launch {
            _uploadStatus.value = UploadStatus.Loading
            
            val collector = DeviceInfoCollector(context)
            
            collector.collectAndUpload { message, error ->
                if (error != null) {
                    _uploadStatus.postValue(UploadStatus.Error(error.message ?: "上传失败"))
                } else {
                    _uploadStatus.postValue(UploadStatus.Success(message ?: "上传成功"))
                }
            }
        }
    }
}

sealed class UploadStatus {
    object Loading : UploadStatus()
    data class Success(val message: String) : UploadStatus()
    data class Error(val message: String) : UploadStatus()
}
```

### 4. 带进度显示的上传

```kotlin
class UploadActivity : AppCompatActivity() {
    private lateinit var progressDialog: ProgressDialog
    
    private fun uploadWithProgress() {
        // 显示进度对话框
        progressDialog = ProgressDialog(this).apply {
            setMessage("正在收集设备信息...")
            setCancelable(false)
            show()
        }
        
        lifecycleScope.launch {
            val collector = DeviceInfoCollector(applicationContext)
            
            // 更新进度
            progressDialog.setMessage("正在上传...")
            
            collector.collectAndUpload { message, error ->
                runOnUiThread {
                    progressDialog.dismiss()
                    
                    if (error != null) {
                        AlertDialog.Builder(this@UploadActivity)
                            .setTitle("上传失败")
                            .setMessage(error.message)
                            .setPositiveButton("确定", null)
                            .show()
                    } else {
                        AlertDialog.Builder(this@UploadActivity)
                            .setTitle("上传成功")
                            .setMessage(message)
                            .setPositiveButton("确定", null)
                            .show()
                    }
                }
            }
        }
    }
}
```

### 5. 定时自动上传

```kotlin
class AutoUploadService : Service() {
    private val uploadInterval = 24 * 60 * 60 * 1000L // 24小时
    private val handler = Handler(Looper.getMainLooper())
    
    private val uploadRunnable = object : Runnable {
        override fun run() {
            uploadDeviceInfo()
            handler.postDelayed(this, uploadInterval)
        }
    }
    
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        handler.post(uploadRunnable)
        return START_STICKY
    }
    
    private fun uploadDeviceInfo() {
        CoroutineScope(Dispatchers.IO).launch {
            val collector = DeviceInfoCollector(applicationContext)
            
            collector.collectAndUpload { message, error ->
                if (error != null) {
                    Log.e("AutoUpload", "上传失败: ${error.message}")
                } else {
                    Log.i("AutoUpload", "上传成功: $message")
                }
            }
        }
    }
    
    override fun onDestroy() {
        handler.removeCallbacks(uploadRunnable)
        super.onDestroy()
    }
    
    override fun onBind(intent: Intent?): IBinder? = null
}
```

## API 接口说明

### 请求格式

**URL**: `https://api.xyzshell.com/api/mobile/checker/save`

**Method**: POST

**Content-Type**: application/json

**请求体**:
```json
{
  "encrypted": "AES加密后的Base64字符串"
}
```

**加密前的数据格式**:
```json
{
  "cpuInfo": "{\"processorName\":\"ARM\",\"cores\":8}",
  "gpuInfo": "{\"vendor\":\"Qualcomm\",\"renderer\":\"Adreno 650\"}",
  "screenInfo": "{\"width\":1080,\"height\":2400}",
  "memoryInfo": "{\"totalMem\":8589934592}",
  "diskInfo": "{\"totalSpace\":128000000000}",
  "networkInfo": "{}",
  "batteryInfo": "{\"level\":85,\"status\":3}",
  "deviceInfo": "{\"brand\":\"Samsung\",\"model\":\"SM-G998B\"}",
  "appInfo": "{}",
  "systemInfo": "{\"androidVersion\":\"13\",\"sdkInt\":33}",
  "locationInfo": "{\"gpsSupported\":true}",
  "cameraInfo": "{\"cameraCount\":4}",
  "sensorInfo": "{\"sensorCount\":20}",
  "propsInfo": "{}",
  "bluetoothInfo": "{\"supported\":true,\"enabled\":true}",
  "wifiInfo": "{}",
  "nfcInfo": "{\"supported\":true}",
  "usbInfo": "{\"hostSupported\":true}",
  "buildInfo": "{\"trebleEnabled\":true}",
  "deviceId": "9774d56d682e549c",
  "deviceName": "Samsung SM-G998B",
  "drmInfo": "{\"supportedSchemes\":2}",
  "inputInfo": "{\"deviceCount\":3}",
  "gaid": "38400000-8cf0-11bd-b23e-10b96e40000d"
}
```

### 响应格式

**成功响应**:
```json
{
  "data": null,
  "message": "设备信息保存成功",
  "status": "Success"
}
```

**失败响应**:
```json
{
  "data": null,
  "message": "错误详情信息",
  "status": "Fail"
}
```

## 数据模型

### DeviceInfoRequest
```kotlin
data class DeviceInfoRequest(
    val cpuInfo: String,           // CPU信息JSON
    val gpuInfo: String,           // GPU信息JSON
    val screenInfo: String,        // 屏幕信息JSON
    val memoryInfo: String,        // 内存信息JSON
    val diskInfo: String,          // 磁盘信息JSON
    val networkInfo: String,       // 网络信息JSON
    val batteryInfo: String,       // 电池信息JSON
    val deviceInfo: String,        // 设备信息JSON
    val appInfo: String,           // 应用信息JSON
    val systemInfo: String,        // 系统信息JSON
    val locationInfo: String,      // 定位信息JSON
    val cameraInfo: String,        // 相机信息JSON
    val sensorInfo: String,        // 传感器信息JSON
    val propsInfo: String,         // 系统属性JSON
    val bluetoothInfo: String,     // 蓝牙信息JSON
    val wifiInfo: String,          // WiFi信息JSON
    val nfcInfo: String,           // NFC信息JSON
    val usbInfo: String,           // USB信息JSON
    val buildInfo: String,         // 构建信息JSON
    val deviceId: String,          // 设备ID
    val deviceName: String,        // 设备名称
    val drmInfo: String,           // DRM信息JSON
    val inputInfo: String,         // 输入信息JSON
    val gaid: String               // Google广告ID
)
```

### EncryptedRequest
```kotlin
data class EncryptedRequest(
    val encrypted: String  // AES加密后的Base64字符串
)
```

### ApiResponse
```kotlin
data class ApiResponse(
    val data: Any?,       // 响应数据
    val message: String,  // 响应消息
    val status: String    // 状态: "Success" 或 "Fail"
)
```

## 加密说明

### AES 加密
- **算法**: AES/ECB/PKCS5Padding
- **密钥**: "e67cbcee5e573d1b" (16字节)
- **编码**: Base64 (NO_WRAP)

### 加密示例
```kotlin
val webService = WebService()
val plainText = """{"test": "data"}"""
val encrypted = webService.encrypt(plainText)
println("加密结果: $encrypted")
```

## 权限要求

根据收集的信息类型，可能需要以下权限：

```xml
<!-- 必需权限 -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- 可选权限（用于获取更多信息） -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
```

## 性能优化

### 1. 并发收集
所有信息收集都是并发执行：
```kotlin
// 使用协程并发收集
val cpuInfoDeferred = async { collectCpuInfo() }
val gpuInfoDeferred = async { collectGpuInfo() }
// ... 其他信息并发收集
```

### 2. 异常处理
每个收集方法都有完善的异常处理：
```kotlin
private suspend fun collectCpuInfo(): String = withContext(Dispatchers.Default) {
    try {
        // 收集逻辑
    } catch (e: Exception) {
        "{}"  // 返回空JSON对象
    }
}
```

### 3. 线程调度
- 信息收集：使用 `Dispatchers.Default` 或 `Dispatchers.IO`
- 加密操作：使用 `Dispatchers.Default`
- 网络请求：使用 `Dispatchers.IO`

## 错误处理

### 常见错误及解决方案

1. **网络错误**
```kotlin
// 错误: java.net.UnknownHostException
// 解决: 检查网络连接和URL是否正确
```

2. **加密错误**
```kotlin
// 错误: 加密失败
// 解决: 检查密钥长度是否为16/24/32字节
```

3. **序列化错误**
```kotlin
// 错误: JSON解析失败
// 解决: 确保所有收集方法返回有效的JSON字符串
```

## 注意事项

1. **隐私合规**：
   - 确保用户知情并同意收集设备信息
   - 遵守 GDPR、CCPA 等隐私法规
   - 在隐私政策中说明数据用途

2. **网络使用**：
   - 建议在 WiFi 环境下上传
   - 可以添加网络类型检测

3. **频率控制**：
   - 不要频繁上传
   - 建议每天或每周上传一次

4. **错误重试**：
   - 失败时可以实现重试机制
   - 保存失败的数据，下次再试

## 完整示例

```kotlin
class DeviceCheckActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_device_check)
        
        // 初始化
        AndInfo.init(applicationContext)
        
        // 检查权限后上传
        if (checkPermissions()) {
            uploadDeviceInfo()
        } else {
            requestPermissions()
        }
    }
    
    private fun uploadDeviceInfo() {
        lifecycleScope.launch {
            try {
                val collector = DeviceInfoCollector(applicationContext)
                
                // 显示加载对话框
                val dialog = ProgressDialog(this@DeviceCheckActivity)
                dialog.setMessage("正在收集设备信息...")
                dialog.show()
                
                collector.collectAndUpload { message, error ->
                    runOnUiThread {
                        dialog.dismiss()
                        
                        if (error != null) {
                            showErrorDialog(error.message ?: "上传失败")
                        } else {
                            showSuccessDialog(message ?: "上传成功")
                        }
                    }
                }
            } catch (e: Exception) {
                runOnUiThread {
                    showErrorDialog("发生错误: ${e.message}")
                }
            }
        }
    }
    
    private fun showSuccessDialog(message: String) {
        AlertDialog.Builder(this)
            .setTitle("成功")
            .setMessage(message)
            .setPositiveButton("确定", null)
            .show()
    }
    
    private fun showErrorDialog(message: String) {
        AlertDialog.Builder(this)
            .setTitle("失败")
            .setMessage(message)
            .setPositiveButton("确定", null)
            .setNegativeButton("重试") { _, _ ->
                uploadDeviceInfo()
            }
            .show()
    }
    
    private fun checkPermissions(): Boolean {
        // 检查必要权限
        return true
    }
    
    private fun requestPermissions() {
        // 请求权限
    }
}
```

## 总结

本功能提供了完整的设备信息收集和上传解决方案：
- ✅ 异步并发收集，性能优化
- ✅ 完整的24类设备信息
- ✅ AES 加密保护数据
- ✅ 完善的错误处理
- ✅ 简单易用的 API
- ✅ 详细的中文注释

