用戶希望在用戶未響應權限彈窗時「暫停主線程」,待用戶點擊後繼續執行。這在 Android 中不可行且極其危險:
Thread.sleep()、wait()、CountDownLatch.await() 等均會阻塞主線程,導致界面凍結,權限彈窗無法顯示或響應,形成死鎖。Android 6.0+ 動態權限機制本身就是異步的,應遵循「請求 → 回調 → 處理」流程:
private static final int REQ_PERM = 100;
public void requestCameraPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQ_PERM);
} else {
// 已授權,直接執行業務
doCameraWork();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQ_PERM) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
doCameraWork(); // 用戶同意
} else {
// 用戶拒絕:提示說明、引導去設置頁、或降級處理
showPermissionDeniedDialog();
}
}
}
如 PermissionsDispatcher、RxPermissions,支持鏈式調用、Kotlin 協程,自動處理「不再提示」邏輯。
| 誤區 | 正確認知 |
|---|---|
| 用 while 循環輪詢權限狀態 | 阻塞主線程,導致 ANR,彈窗無法顯示 |
| 在子線程請求權限 | requestPermissions 必須在主線程調用,否則崩潰 |
| 以為權限彈窗是同步的 | 彈窗由系統進程管理,回調異步觸發 |
永遠不要嘗試阻塞 Android 主線程。權限申請天然是異步流程,請在 onRequestPermissionsResult 或封裝庫的回調中編寫後續業務邏輯。這才是健壯、用戶體驗良好的應用架構。