# Android 授权管理（License SDK）

**模块**：`com.xuqm:sdk-license` · **最低 Android 版本**：API 24 (Android 7.0)

License SDK 用于设备授权注册与验证，所有平台（Android / iOS / 鸿蒙）共用同一个 License Key。

---

## 快速接入

### 1. 添加依赖

```kotlin
// app/build.gradle.kts
dependencies {
    implementation("com.xuqm:sdk-license:0.4.2")
}
```

### 2. 放置 License 文件

从租户平台下载 `.xuqmlicense` 加密文件，放入 app 的 assets 目录：

```
app/src/main/assets/xuqm/license.xuqm
```

SDK 会按以下顺序查找文件：
1. `assets/xuqm/license.xuqm`
2. `assets/xuqm/` 目录下第一个 `.xuqmlicense` 文件

### 3. 检查授权

SDK **无需手动初始化**，首次调用 `checkLicense()` 时自动读取并解密 License 文件。

```kotlin
LicenseSDK.checkLicense { isValid ->
    if (isValid) {
        // 授权通过，允许使用
    } else {
        // 授权失败，提示用户
    }
}
```

---

## API 说明

### checkLicense

检查设备授权状态。首次调用时自动完成：读取 License 文件 → 解密 → 注册/验证设备 → 缓存结果。

```kotlin
// 回调方式
LicenseSDK.checkLicense { isValid ->
    // true: 授权通过  false: 授权失败
}

// 协程方式
lifecycleScope.launch {
    val isValid = LicenseSDK.checkLicense()
}
```

**内部逻辑**：
1. 检查本地缓存（默认 10 分钟有效期）
2. 缓存有效 → 直接返回 `true`
3. 缓存过期或无缓存：
   - 有 Token → 调用验证接口
   - 无 Token 或验证失败 → 调用注册接口
4. 网络异常且缓存曾成功 → 返回 `true`（离线模式）
5. 网络异常且无缓存 → 返回 `false`

---

## 设备唯一码

SDK 自动选择设备唯一码，优先级如下：

| 优先级 | 来源 | 稳定性 |
|--------|------|--------|
| 1 | ANDROID_ID | 同一签名 + 设备 + 用户不变，重装不变 |
| 2 | 持久化 UUID | 首次生成后持久化存储 |

**保持不变**的场景：App 重启、App 重装（同一签名）、系统升级

**会变化**的场景：恢复出厂设置、更换签名重新安装

---

## 离线模式

SDK 支持离线使用：
- 首次激活需要网络连接
- 激活成功后，缓存有效期内（默认 10 分钟）可离线使用
- 网络异常时，若缓存曾经成功验证，继续返回授权通过

---

## 数据存储

| 数据 | 存储方式 | 说明 |
|------|----------|------|
| deviceId | EncryptedSharedPreferences | AES-256 加密 |
| token | EncryptedSharedPreferences | AES-256 加密 |
| 授权状态 | EncryptedSharedPreferences | AES-256 加密 |
| fallback UUID | SharedPreferences | ANDROID_ID 不可用时使用 |

---

## AppKey 变更

当 License 文件中的 AppKey 与已存储的不一致时，SDK 会自动：
1. 清除所有旧数据（Token、deviceId、状态）
2. 使用新 AppKey 重新注册

---

## 完整示例

```kotlin
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // 无需初始化代码，SDK 自动读取 License 文件
    }
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        LicenseSDK.checkLicense { isValid ->
            runOnUiThread {
                if (isValid) {
                    // 进入主界面
                } else {
                    Toast.makeText(this, "授权验证失败", Toast.LENGTH_LONG).show()
                    finish()
                }
            }
        }
    }
}
```

---

## 常见问题

**Q: checkLicense 返回 false 怎么办？**
A: 检查以下几点：
- License 文件是否放在 `assets/xuqm/` 目录
- 文件名是否为 `license.xuqm` 或以 `.xuqmlicense` 结尾
- 设备是否有网络连接（首次激活需要网络）
- License 是否已过期或被管理员禁用

**Q: 不同平台可以用同一个 License 吗？**
A: 可以。所有平台共用同一个 AppKey，设备数量统一计算。

**Q: 设备被禁用后如何恢复？**
A: 由租户管理员在租户平台的授权管理页面重新激活该设备，App 端无需额外操作，下次 `checkLicense` 会自动恢复正常。
