# 设备信息收集和上传使用指南 ## 概述 本功能提供了完整的设备信息收集、序列化、加密和上传功能。所有信息收集都是异步并发执行,性能优化且不会阻塞主线程。 ## 功能特性 ### 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() val uploadStatus: LiveData = _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 ``` ## 性能优化 ### 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 - ✅ 详细的中文注释