Android無需許可權調起系統相機拍照

語言: CN / TW / HK

在進行一些小型APP的開發,或者是對拍照介面沒有自定義要求時,我們可以用調起系統相機的方式快速完成拍照需求

和不需讀寫許可權進行讀寫操作的方案一樣,都是通過Intent啟動系統的activity讓使用者進行操作,系統再將使用者操作的結果告訴我們,因為過程對APP是完全透明的,所以不會侵犯使用者隱私。

有兩種方法可以調起系統相機拍照獲取圖片,我們先講比較簡單的一種

1、直接獲取使用者拍照結果

``` val launcher = registerForActivityResult(ActivityResultContracts.TakePicturePreview()) {bitmap-> bitmap ?: return@registerForActivityResult vm.process(bitmap) }

launcher.launch("image/*") 這個在舊版本的API中就等於 startActivityForResult(Intent(MediaStore.ACTION_IMAGE_CAPTURE),CODE) ```

等到使用者完成拍照,返回我們的activity時,我們就可以得到一張經過壓縮的bitmap。這個方法很簡單,它的缺點就是獲得的bitmap畫素太低了,如果對圖片畫素有要求的話需要使用第二種方法

2、使用者拍照之後指定相機將未壓縮的圖片存放到我們指定的目錄

``` var uri: Uri? = null

val launcher = registerForActivityResult(ActivityResultContracts.TakePicture()) { if(it){ uri?.let { it1 -> vm.process(it1) } } }

val picture = File(externalCacheDir?.path, "picture") picture.mkdirs() uri = FileProvider.getUriForFile( this, "${BuildConfig.APPLICATION_ID}.fileprovider", File(picture, "cache") ) launcher.launch(uri) ``` 這裡我逐行進行解釋: 1. 首先,我們需要指定拍攝的照片要存到哪,所以我們先指定圖片的存放路徑為externalCacheDir.path/picture/cache 注意這張圖片在檔案系統中的名字就叫做cache了(沒有檔案字尾)。 2. 然後我們通過FileProvider構建一個有授權的Uri給系統相機,相機程式拿到我們的臨時授權,才有許可權將檔案存放到APP的私有目錄。 3. 系統相機拍照完成之後就會走到回撥,如果resultCode為RESULT_OK才說明使用者成功拍照並儲存圖片了。這樣我們就能得到一張系統相機拍出來的原圖的Uri,這樣我們就可以用這張圖片去處理業務了。

注意:使用方法二需要用到FileProvider,所以我們還要在AndroidManifest裡宣告 <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider> @xml/provider_paths是我們授權訪問的檔案路徑,這裡我寫的是 <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="."/> </paths>

關於這個"path.xml",其實還有一些可以補充說明的,後面有空會補上,這裡我簡單說明一下:

因為我們建立臨時檔案的時候,檔案指定的目錄是externalCacheDir?.path,對應的path就是external-cache-path,表示我們要臨時授權的目錄是externalCacheDir,如果檔案目錄指定的是其他路徑,那path節點也需要改成代表對應資料夾的節點,這樣其他應用才能訪問到我們APP的私有目錄