android调用相册和摄像头,Android8.3调用摄像头和相册
我們平時在使用QQ或微信的時候經常要和別人分享圖片,這些圖片可以是用手機攝像頭拍的,也可以是從相冊中選取的。類似這樣的功能實在是太常見了,幾乎在每個應用程序中都會有,那么本節我們就學習一下調用攝像頭和相冊方面的知識。
8.3.1 ? ?調用攝像頭拍照
先來看看攝像頭方面的知識,現在很多的應用都會要求用戶上傳一張圖片來作為頭像,這時攝像頭拍張照是最簡單快捷的。下面就讓我們通過一個例子來學習一下如何才能在應用程序里調用手機的攝像頭進行拍照。
新建一個CameraAlbumTest項目,然后修改activity_main.xml中的代碼,如下所示:
可以看到,布局文件中只有兩個控件一個Button和一個ImageView。BUtton適用于打開攝像頭進行拍照的,而ImageView則是用于將拍到的圖片顯示出來。
然后開始編寫調用攝像頭的具體邏輯,修改mainActivity中的代碼,如下所示:
上述代碼稍微有點復雜,我們來仔細分析一下。在MainActivity中要做的第一件事自然是分別獲取到Button和ImageView的實例,并給Button注冊上點擊事件,然后在Button的點擊事件里開始處理調用攝像頭的邏輯,我們重點看一下這部代碼。
首先這里創建了一個File,對象,用于存放攝像頭拍下的圖片,這里我們把圖片命名為output_image.jpg,并將它存放在手機SD卡的應用關聯緩存目錄下。什么叫做應用關聯緩存目錄啦?就是指SD卡中專門存放當前應用緩存數據的位置,調用getExternalCacheDir()方法可以得到這個目錄,具體的路徑是/sdcard/Android/data//cache。name為什么要使用應用關聯目錄存放圖片啦?因為從Android6.0系統開始,讀寫SD卡被列為了危險權限,如果將圖片存放在SD卡的任何其他目錄,都要進行運行時權限處理才行,而使用應關聯目錄則可以跳過這一步。
接著會進行一個判斷,如果運行設備的系統版本低于Android7.0就調用formFile()方法將File對象轉換成Uri對象,這個Uri對象標識這output_image.jpg這張圖片的本地真實路徑。否則就調用FileProvider的getUriForFile()方法將File對象轉換成一個封裝過得Uri對象。getUriForFile()方法接收3各參數,第一個參數要求傳入Context對象,第二個參數可以是任意唯一的字符串,第三個參數真是我們剛剛創建的File對象。之所以要進行這樣一層轉換,是因為從Android7.0系統開始,直接使用本地真實路勁Uri被認為是不安全的,會拋出一個FileUriExposedException異常。而FileProvider則是一種特殊的內容提供者,他是用了和內存提供器類似的機制來對數據進行保護,可以選擇性地保護,可以選擇性地將封裝過得Uri共享給外部,從而提高了應用的安全性。
接下來構建出一個Intent對象,并將這個Intent的action指定為android.media.action.IMAGE_CAPTURE,再調用Inten的putExtra()方法來指定圖片的輸出地址,這里填入剛剛得到的Uri對象,最后調用startActivityForResult()來啟動活動。由于我們使用的是一個隱士Intent,系統會找出能夠響應這個Intent的活動啟動,這樣照相機程序就會被打開,拍下的照片將會輸出到output_image.jpg中。
注意,剛才我們是使用startActivityForResult()來啟動活動的,因此拍完照后會有結果返回到onActivityResult()方法中。如果發現拍照成功,就可以調用BitmapFactory的decodeStream()方法將output_image.jpg這張照片解析成Bitmap對象,然后把它設置到ImageView中顯示出來。
不過現在還沒結束,剛才提到了內容提供器,那么我們自然要在AndroidManifest.xml中內容提供器進行注冊了,如下所示:(不多說,直接上代碼)
其實,android:name屬性的值是固定的,android:authorities屬性的之必須要和剛才FileProvider.getUriForFile()方法中第二個參數一致。另外,這里還有標簽的內部使用來指定Uri的共享路徑,并引入了一個@xml/file_paths資源。當然,這個資源現在還是不存在的,下面我們就來創建它。
右擊res目錄---->NEW----->File,創建一個file_paths.xml文件。然后修改file_paths.xml文件中的內容,如下所示:
其中,external-path就是用來指定Uri共享的,name屬性的值可以隨便填,path屬性的值表示共享的的具體路徑。這里設置空值就表示將整個SD卡進行共享,當然你也可以僅共享我們存放output_image.jpg這張圖片的路徑。
另外還有一點要注意,在Android4.4系統之前,訪問SD卡的應用關聯目錄也是要聲明權限的,從4.4系統開始不再需要權限聲明。那么我們為了能夠兼容老版本系統的手機,還需要在AndroidManifest.xml中聲明一下訪問SD卡的權限
這樣代碼就編寫完了,現在將程序運行運行到手機上。
8.3.2 從相冊中選擇照片
雖然調用攝像頭拍照既方便又快捷,但我們并不是每次都需要去當場拍以后在那個照片的,因為每個人的手機相冊里應該存在許許多多張照片,直接從相冊里選取一張現在照片回避打開相機拍照更加常用。一個優秀的應用程序應該講這兩種選擇方式都提供給用戶,由用戶決定使用哪一種。下面我們就來看一下,如何才能實現從相冊中選擇照片的功能。
還是在CameraAlbumTest項目的基礎上進行修改,編輯activity_main.xml文件,在布局中添加一個按鈕用于從相冊選擇照片,代碼如圖所示:
可以看到,在Choose_From_Album按鈕的點擊事件里我們現實進行了一個運行權限處理,動態申請WRITE_EXTERNAL_STORAGE這個危險權限。為什么需要申請證券西安啦?因為相冊中的照片都是存在SD卡上,我們要從SD卡中讀取照片就需要申請這個權限。WRITE_EXTERNAL_STORAGE表示同時授予程序對SD卡讀寫能力。
當用戶授予了權限申請之后,會調用openAlbum()方法,這里我們先是構建出了一個Intent對象,并將它的action指定為android.intent.action.GET_CONTENT.接著給這個Intent對象設置一些必要參數,然后調用startActivityForResult()方法就可以打開相冊程序選擇照片了。注意在調用startActivityForResult()方法的時候,我們個誒第二個參數傳入的值變成了CHOOSE_PHoto的case圖片,接下來的邏輯就比較復雜了,首先為了兼容新老版本的手機,我們做了一個判斷,如果是4.4及以上系統的手機就調用handleImageOnKiKat()方法來處理圖片,否則就調用handleImageBeforeKitke()方法來處理圖片。之所以要這樣做,是因為Android系統從4.4版本開始,選取相冊中的圖片不再返回圖片真實的Uri了,而是一個封裝過的Uri,因此如果是4.4版本以上的手機就需要對這個Uri進行解析才行。
那么handleImageOnKiKat()方法中的邏輯基本是如何解析這個封裝過的Uri了。這里有好幾種判斷情況,如果返回的Uri是document類型的話,那就取出document id進行處理,如果不是的話,那么就是用普通的方式處理。另外,如果Uri的authority是media格式的話,document id還需要再進行一次解析,要通過字符串分隔的方式取出后半部分才能得到真正的數字id。取出的id用于構建新的Uri和條件語句,然后把這些值作為參數傳入到getImagePath()方法當中,就可以獲取到圖片的真實路徑了。拿到圖片的路徑之后,在調用disPlayImage()方法將圖片顯示在界面上。
相比于handleImageOnKikAT()方法,handleImageBeforeKiKat()方法中的邏輯就要簡單很多了,因為它的Uri是沒有封裝過的,不需要任何解析,直接將Uri傳入到getImagePath()方法當中就能獲取到圖片的真實路徑了,最后同樣是調用displayImage()方法來讓圖片顯示到界面上。
現在將程序重新運行到手機上,然后點擊一下choose From Album按鈕,首先會彈出權限申請對象畫框,如圖8.14所示。
點擊允許之后就會打開手機相冊,如圖8.15所示:
然后隨意選擇一張照片,回到我們程序的界面,選中的照片應該就會顯示出來了,如圖8.16所示。
調用攝像頭拍照以及從相冊中選取照片很多Android應用都會帶有的功能,現在你已經將這兩種技術學會了,將來工作中需要開發類似的功能,相信你一定會輕松完成。不過目前我們現實還不算完美,因為有些照片經過裁剪之后體積仍然很大,直接加載到內存中又可能會導致程序崩潰。更好的做好是根據項目的需求先對照片進行適當的壓縮,然后再加載到內存中。至于如何對照片進行壓縮,就要開眼你查閱資料的能力了,這里就不再展開進行講解了。
總結
以上是生活随笔為你收集整理的android调用相册和摄像头,Android8.3调用摄像头和相册的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑各类快捷键及运行命令大全
- 下一篇: 排队论模型