注意:原文章標題為「JAVA 實現鏈表試題」,但內容實為 Android 開發實戰避坑筆記。本文依實際內容重寫並補充 2024 年最新適配要點。
Android 碎片化嚴重:系統版本 (API 21~34)、廠商 ROM (MIUI, ColorOS, HarmonyOS, OneUI)、硬體差異、權限政策頻繁變更。本文彙總 6 大類高頻坑位,附根因分析、修復代碼與最佳實踐,助你少踩坑、快交付。
設置 colorPrimary 為帶透明度的顏色 (如 #80FF0000),App 啟動崩潰:
java.lang.RuntimeException: A TaskDescription's primary color should be opaque
ActivityManager.TaskDescription 構造函數強制檢查 Color.alpha(color) == 255,用於近期任務列表顯示,不支援半透明。
- @color/primary_opaque
- @color/primary_dark_opaque
API 21+ CookieManager 預設 acceptThirdPartyCookies = false,導致 WebView 無法讀取第三方域 Cookie (如嵌入 H5 登錄態)。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
}
// 同步 Cookie 到原生網絡層 (OkHttp/Retrofit)
CookieManager.getInstance().setCookie(url, cookieString);
CookieSyncManager.getInstance().sync(); // API 21- 已棄用但兼容
最佳實踐:避免跨域 Cookie 依賴,改用 Token Header 或原生登錄態同步方案。
華為自研 BASTET (Battery Saving Technology) 機制:基於耗電量、用戶行為、應用類別智能清理。預設策略激進,甚至新安裝應用默認「不允許後台」。
// 跳轉華為電池優化設置
Intent intent = new Intent();
intent.setClassName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity");
startActivity(intent);
Service.startForeground() + 通知欄,系統不敢輕易殺。NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("正在播放").setSmallIcon(R.drawable.ic_notif)
.setContentIntent(pendingIntent).setOngoing(true);
startForeground(NOTIFICATION_ID, builder.build());
同一 App 不同進程 (:remote) 中,Service 註冊網絡變化廣播 (CONNECTIVITY_CHANGE):
華為/部分 ROM 對非前台進程的隱式廣播進行優化攔截,CONNECTIVITY_ACTION 在 Android 7.0+ 已廢棄靜態註冊,動態註冊亦受限。
// 1. NetworkCallback API (API 21+ 推薦)
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
cm.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
@Override public void onAvailable(Network network) { /* 已連網 */ }
@Override public void onLost(Network network) { /* 斷網 */ }
});
// 2. WorkManager 週期性檢查 (延遲容忍場景)
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED).build();
PeriodicWorkRequest request = new PeriodicWorkRequest.Builder(NetworkCheckWorker.class, 15, TimeUnit.MINUTES)
.setConstraints(constraints).build();
WorkManager.getInstance(context).enqueue(request);
從資源獲取 Drawable 後修改顏色/Alpha,導致**全應用**所有使用該資源的地方同步變色。
Resources.getDrawable() 返回同一 ConstantState 實例,內部共享狀態。
// 方式 1: mutate() 破壞共享狀態 (API 1+) Drawable d = ContextCompat.getDrawable(context, R.drawable.ic_icon).mutate(); d.setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN); // 方式 2: 新建實例 (API 23+) Drawable d = ResourcesCompat.getDrawable(res, R.drawable.ic_icon, theme).mutate();
| 坑位 | 現象 | 修復/規避 |
|---|---|---|
| 8.0+ 通知渠道 | 無 Channel 通知不顯示 | NotificationManager.createNotificationChannel() (API 26+) |
| 9.0+ 明文流量 | HTTP 請求失敗 | android:usesCleartextTraffic="true" 或全 HTTPS |
| 10+ 儲存權限 | 外部存儲讀寫受限 | Scoped Storage: MediaStore / SAF / requestLegacyExternalStorage (臨時) |
| 11+ 套件可見性 | queryIntentActivities 返回空 | <queries> 清單聲明需查詢的包/意圖 |
| 12+ 藍牙權限 | 掃描/連接需新權限 | BLUETOOTH_SCAN, BLUETOOTH_CONNECT (API 31+) |
| 13+ 通知權限 | 通知需用戶授權 | POST_NOTIFICATIONS 運行時請求 (API 33+) |
| 14+ 前台服務類型 | 缺類型崩潰 | foregroundServiceType="mediaPlayback|location|..." (API 34+) |
minSdk 24+ (Android 7.0) 可棄用大量兼容代碼,compileSdk/targetSdk 34 強制適配最新政策。dependencyVerification + OWASP Dependency Check 防供應鏈攻擊。Android 開發的本質是「在約束中尋找確定性」。建立團隊級避坑知識庫、自動化驗證體系、漸進式現代化技術棧,才能在碎片化浪潮中穩健前行。