很多的 Android App 中都有使用相機拍攝用戶頭像的功能。大部分開發(fā)者都會使用MediaStore.ACTION_IMAGE_CAPTURE
來滿足這一需求。這可以節(jié)省很多時間,不需要單獨開發(fā)相機UI,直接調(diào)用系統(tǒng)相機;不需要向系統(tǒng)請求 Camera 權限。正如官方文檔里面說的那樣,Taking Photos Simply。然而在最近的一次的測試中,我發(fā)現(xiàn)并沒有那么簡單。因為運行了幾年的代碼竟然發(fā)生了 Crash。具體的 log 如下:
java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE cat=[android.intent.category.DEFAULT] flg=0x3 cmp=com.google.android.GoogleCamera/com.android.camera.activity.CaptureActivity clip={text/uri-list U:content://com.imzhiqiang.example.fileprovider/imageCache/tmp_avatar.jpg} (has extras) } from ProcessRecord{bf70afd 18107:com.imzhiqiang.example/u0a108} (pid=18107, uid=10108) with revoked permission android.permission.CAMERA
看上去是因為沒有處理運行時權限導致的 Crash。Interesting! 我并沒有在 manifest 文件中聲明 Camera 的權限,為什么會出現(xiàn)沒有處理 Camera 運行時權限的問題呢?隨后我想到了可能是引用的 library 中聲明了該權限。在 Android Studio 中查看了 Merged Manifest,果然是這樣。圖中深色背景的權限是我自己聲明的,下面的權限是第三方的 library 聲明的。
然而這和 Intent 又有什么關系?使用 ACTION_IMAGE_CAPTURE 不是可以避免請求 Camera 權限嗎?經(jīng)過幾番周折過后,最后終于在官方文檔中找到了答案。
雖然很難理解 Google 這樣的做法,不過總算找到了問題的根本所在。在對 Camera 權限進行正確的處理后,終于正常運行了。
結論
- 如果沒有在 manifest 文件中聲明 Camera 權限,使用 ACTION_IMAGE_CAPTURE 不需要對 Camera 權限做運行時權限處理,代碼正常運行。如果聲明了就必須要做權限處理。
- 使用 Intent 的 action 時,一定要仔細閱讀官方文檔,避免類似的風險。
- 引用第三方 library 時,除了熟悉其內(nèi)部原理和源碼外,還要注意它在 manifest 文件中添加的東西。
擴展閱讀