開發者在廣播接收器中嘗試顯示 AlertDialog,導致程序崩潰。發現將導入包從 android.support.v7.app.AlertDialog 改為 android.app.AlertDialog 後問題解決,疑惑兼容包反而失效的原因。
關鍵點:BroadcastReceiver.onReceive() 接收的 Context 是 ReceiverRestrictedContext(受限上下文),非 Activity Context。
| 類別 | 包路徑 | 構造函數要求 | 適用 Context |
|---|---|---|---|
| 系統原生 | android.app.AlertDialog | new AlertDialog.Builder(Context) | 任意 Context(含受限上下文) |
| 兼容包 | androidx.appcompat.app.AlertDialog (v7 旧包) | new AlertDialog.Builder(Context) | 必須為 Activity 或 ContextThemeWrapper |
AppCompat 版 AlertDialog 內部需要訪問主題屬性(如 alertDialogTheme、colorAccent 等),這要求 Context 能正確解析主題資源。ReceiverRestrictedContext 為安全考慮,禁用了主題解析相關功能,導致兼容包構建失敗。
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 直接使用 android.app.AlertDialog
new android.app.AlertDialog.Builder(context)
.setTitle("提示")
.setMessage("收到廣播")
.setPositiveButton("確定", null)
.show(); // 安全,不依賴主題解析
}
}
廣播接收器不應直接彈窗,應啟動透明 Activity 或全屏對話框 Activity:
// AndroidManifest.xml
// Receiver 中
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, DialogActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 必須標記
context.startActivity(i);
}
// 僅在確保有 Activity 可用時使用(如有序廣播中)
ContextThemeWrapper wrapper = new ContextThemeWrapper(context, R.style.AppTheme);
new androidx.appcompat.app.AlertDialog.Builder(wrapper)
.setTitle("標題")
.show();
AlertDialog 體驗良好onReceive 必須在 10 秒內完成,耗時操作啟動 ServiceonResume 註冊,onPause 註銷,防洩漏android:permission 或 sendBroadcast(intent, permission)兼包 AlertDialog 失效的根因是 ReceiverRestrictedContext 無法滿足 AppCompat 主題解析需求。系統原生 AlertDialog 因不依賴複雜主題而能正常工作。但從架構規範角度,廣播接收器不應直接承載 UI 交互,正確做法是啟動承載對話框的 Activity。理解 Context 類型差異、Dialog 實現機制、組件職責邊界,是 Android 進階開發的必修課。