核心 API
int currentApi = Build.VERSION.SDK_INT; // 編譯時常量,運行時取值
// Build.VERSION_CODES.LOLLIPOP = 21, M = 23, N = 24, O = 26, P = 28, Q = 29, R = 30, S = 31, T = 33, U = 34
三種實現模式
| 模式 | 代碼示例 | 優點 | 缺點 |
| 運行時判斷 (最常用) | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
doMarshmallowPlus();
} else {
doLegacy();
}
| 簡單直觀、無反射、編譯期檢查 | 代碼分支隨版本增多 |
| 反射調用 | try {
Method m = clazz.getMethod("newApiMethod");
m.invoke(obj);
} catch (NoSuchMethodException e) {
clazz.getMethod("oldApiMethod").invoke(obj);
}
| 不需編譯時依賴高版本 API | 性能差、易崩、混淆後失效 |
| 版本專用類隔離 (推薦大項目) | // VersionedImpl.java
interface ApiImpl { void doWork(); }
class ApiImplV23 implements ApiImpl { ... } // 只引用 API 23+
class ApiImplBase implements ApiImpl { ... } // 兼容舊版
// 工廠
ApiImpl getImpl() {
if (SDK_INT >= 23) return new ApiImplV23();
return new ApiImplBase();
}
| 代碼隔離、無運行時判斷分支、利於測試 | 類數量增加 |
註解輔助(僅文檔/靜態分析)
@RequiresApi(api = Build.VERSION_CODES.M)
void newApiMethod() { ... }
@SuppressLint("NewApi") // 告訴 Lint 我已做版本判斷
void caller() {
if (SDK_INT >= M) newApiMethod();
}
常見版本分水嶺
| 版本 | API | 關鍵特性 |
| 5.0 | 21 | Material Design、ART、JobScheduler |
| 6.0 | 23 | 運行時權限、Doze、指紋 API |
| 7.0 | 24 | 多窗口、JIT/AOT 混合、FileProvider 必須 |
| 8.0 | 26 | 通知通道、Picture-in-Picture、自適應圖標 |
| 10 | 29 | 分區存儲、暗黑模式、5G API |
| 12 | 31 | 隱私儀表板、精確鬧鐘權限、exported 強制 |
**優先用「運行時判斷 + @RequiresApi」**,代碼清晰、Lint 能檢測遺漏。大型項目引入「版本專用類隔離」,將高版本 API 依賴物理隔離在單獨類中,杜絕「誤在低版本調用高版本 API」導致的 NoSuchMethodError。