onReceive() 中直接 new AlertDialog.Builder(context).show() 拋出 BadTokenException 或 WindowManager$BadTokenException。android.view.WindowManager$BadTokenException。onReceive() 參數 context 為 ReceiverRestrictedContext,不能 用於啟動 Activity 或顯示對話框。registerReceiver() 需在對應元件生命週期內,靜態註冊需在 <receiver> 標籤宣告並設定 android:exported。public class ForceOfflineReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 1. 必須用 Application Context 或啟動新 Task 的 Activity
Intent dialogIntent = new Intent(context, ForceOfflineDialogActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 關鍵!
context.startActivity(dialogIntent);
}
}
public class ForceOfflineDialogActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 設定透明主題,僅顯示對話框
setTheme(android.R.style.Theme_Translucent_NoTitleBar);
new AlertDialog.Builder(this)
.setTitle("強制下線")
.setMessage("您的帳號在別處登入,請重新登入。")
.setPositiveButton("確定", (d, w) -> {
// 跳轉登入頁
startActivity(new Intent(this, LoginActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK));
finish();
})
.setCancelable(false)
.show();
}
}
<receiver
android:name=".ForceOfflineReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.example.FORCE_OFFLINE" />
</intent-filter>
</receiver>
<activity
android:name=".ForceOfflineDialogActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:excludeFromRecents="true" />
adb logcat | grep -i forceoffline 確認廣播發送/接收。AndroidManifest.xml 是否漏寫 <receiver> 或 <activity>。Intent.FLAG_ACTIVITY_NEW_TASK 已加在啟動 Activity 的 Intent 上。遵循「BroadcastReceiver 僅負責轉發、Activity 負責 UI」原則,徹底避免 Context 權限不足導致的崩潰。