控制摄像头拍照
現(xiàn)在的智能手機(jī)和平板電腦一般都會(huì)提供攝像頭拍照功能。在Android中提供了專門(mén)用于處理攝像頭相關(guān)事件的類,即android.hardware包中的Camera類。Camera類沒(méi)有構(gòu)造方法,可以通過(guò)其提供的open()方法打開(kāi)攝像頭。打開(kāi)攝像頭后,可以通過(guò)Camera.Parameters類處理攝像頭的拍照參數(shù)。拍照參數(shù)設(shè)置完成后,可以調(diào)用startPreview()方法預(yù)覽拍照畫(huà)面,也可以調(diào)用takePicture()方法進(jìn)行拍照。結(jié)束程序時(shí),可以調(diào)用Camera類的stopPreview()方法結(jié)束預(yù)覽,并調(diào)用release()方法釋放攝像頭資源。Camera類常用的方法如表10.9所示。
表10.9 Camera類常用的方法
下面通過(guò)一個(gè)實(shí)例來(lái)說(shuō)明控制攝像頭拍照的具體過(guò)程。
實(shí)例 實(shí)現(xiàn)控制攝像頭拍照功能
在Android Studio中創(chuàng)建Module,名稱為“Camera”,在該Module中實(shí)現(xiàn)本實(shí)例,具體步驟如下。
(1)修改布局文件activity_main.xml,首先將默認(rèn)添加的布局管理器修改為幀布局管理器,然后將TextView組件刪除,再添加一個(gè)SurfaceView組件(用于顯示攝像頭預(yù)覽畫(huà)面),最后添加一個(gè)預(yù)覽按鈕和一個(gè)拍照按鈕。具體代碼請(qǐng)參見(jiàn)光盤(pán)。
(2)打開(kāi)MainActivity類,該類繼承Activity,然后在該類中,定義所需的成員變量,關(guān)鍵代碼如下:
01 private Camera camera; //定義相機(jī)對(duì)象 02 private boolean isPreview = false; //定義非預(yù)覽狀態(tài)
(3)在MainActivity類的onCreate()方法中,首先設(shè)置全屏顯示,然后判斷手機(jī)是否安裝SD卡,關(guān)鍵代碼如下:
01 //設(shè)置全屏顯示
02 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
03 WindowManager.LayoutParams.FLAG_FULLSCREEN);
04 if (!Environment.getExternalStorageState().equals( //判斷手機(jī)是否安裝SD卡
05 Environment.MEDIA_MOUNTED)) {
06 Toast.makeText(this, "請(qǐng)安裝SD卡!", Toast.LENGTH_SHORT).show(); // 提示安裝SD卡
07 }
(4)獲取SurfaceView組件與SurfaceHolder對(duì)象,用于顯示攝像頭預(yù)覽,關(guān)鍵代碼如下:
01 //獲取SurfaceView組件,用于顯示攝像頭預(yù)覽 02 SurfaceView sv = (SurfaceView) findViewById(R.id.surfaceView); 03 final SurfaceHolder sh = sv.getHolder(); //獲取SurfaceHolder對(duì)象 04 //設(shè)置該SurfaceHolder自己不維護(hù)緩沖 05 sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 06 ImageButton preview = (ImageButton) findViewById(R.id.preview); //獲取“預(yù)覽”按鈕 07 ImageButton takePicture = (ImageButton) findViewById(R.id.takephoto); //獲取“拍照”按鈕
(5)為預(yù)覽按鈕添加單擊事件監(jiān)聽(tīng)器,實(shí)現(xiàn)攝像頭的預(yù)覽功能,關(guān)鍵代碼如下:
01 preview.setOnClickListener(new View.OnClickListener() { //實(shí)現(xiàn)攝像頭預(yù)覽功能
02 @Override
03 public void onClick(View v) {
04 // 如果攝像頭為非預(yù)覽模式,則打開(kāi)相機(jī)
05 if (!isPreview) {
06 camera = Camera.open(); /打開(kāi)相機(jī)
07 isPreview = true; //設(shè)置為預(yù)覽狀態(tài)
08 }
09 try {
10 camera.setPreviewDisplay(sh); //設(shè)置用于顯示預(yù)覽的SurfaceView
11 Camera.Parameters parameters = camera.getParameters(); //獲取相機(jī)參數(shù)
12 parameters.setPictureFormat(PixelFormat.JPEG); //指定圖片為JPEG圖片
13 parameters.set("jpeg-quality", 80); //設(shè)置圖片的質(zhì)量
14 camera.setParameters(parameters); //重新設(shè)置相機(jī)參數(shù)
15 camera.startPreview(); //開(kāi)始預(yù)覽
16 camera.autoFocus(null); //設(shè)置自動(dòng)對(duì)焦
17 } catch (IOException e) { //輸出異常信息
18 e.printStackTrace();
19 }
20 }
21 });
(6)在MainActivity中,創(chuàng)建實(shí)現(xiàn)重新預(yù)覽的方法resetCamera(),在該方法中,當(dāng)isPreview變量的值為真時(shí),調(diào)用攝像頭的startPreview()方法開(kāi)啟預(yù)覽,具體代碼如下:
01 private void resetCamera() { //創(chuàng)建resetCamera()方法,實(shí)現(xiàn)重新預(yù)覽功能
02 if (!isPreview) { //如果為非預(yù)覽模式
03 camera.startPreview(); //開(kāi)啟預(yù)覽
04 isPreview = true;
05 }
06 }
(8)實(shí)現(xiàn)拍照的回調(diào)接口,在重寫(xiě)的onPictureTaken()方法中,首先根據(jù)拍照所得的數(shù)據(jù)創(chuàng)建位圖,然后保存所拍攝的圖片,再把保存的圖片文件插入到系統(tǒng)圖庫(kù),最后通知圖庫(kù)更新,具體代碼如下:
01
02 //實(shí)現(xiàn)將照片保存到系統(tǒng)圖庫(kù)中
03 final Camera.PictureCallback jpeg = new Camera.PictureCallback() { //照片回調(diào)函數(shù)
04 @Override
05 public void onPictureTaken(byte[] data, Camera camera) {
06 // 根據(jù)拍照所得的數(shù)據(jù)創(chuàng)建位圖
07 final Bitmap bm = BitmapFactory.decodeByteArray(data, 0,
08 data.length);
09 camera.stopPreview(); //停止預(yù)覽
10 isPreview = false; //設(shè)置為非預(yù)覽狀態(tài)
11 //獲取sd卡根目錄
12 File appDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/Camera/");
13 if (!appDir.exists()) { //如果該目錄不存在
14 appDir.mkdir(); //創(chuàng)建該目錄
15 }
16 //將獲取的當(dāng)前系統(tǒng)時(shí)間設(shè)置為照片名稱
17 String fileName = System.currentTimeMillis() + ".jpg";
18 File file = new File(appDir, fileName); //創(chuàng)建文件對(duì)象
19 try { //保存拍到的圖片
20 FileOutputStream fos = new FileOutputStream(file); //創(chuàng)建一個(gè)文件輸出流對(duì)象
21 //將圖片內(nèi)容壓縮為JPEG格式輸出到輸出流對(duì)象中
22 bm.compress(Bitmap.CompressFormat.JPEG, 100, fos);
23 //將緩沖區(qū)中的數(shù)據(jù)全部寫(xiě)出到輸出流中
24 fos.flush();
25 fos.close(); //關(guān)閉文件輸出流對(duì)象
26 } catch (FileNotFoundException e) {
27 e.printStackTrace();
28 } catch (IOException e) {
29 e.printStackTrace();
30 }
31 //將照片插入到系統(tǒng)圖庫(kù)
32 try {
33 MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(),
34 file.getAbsolutePath(), fileName, null);
35 } catch (FileNotFoundException e) {
36 e.printStackTrace();
37 }
38 //最后通知圖庫(kù)更新
39 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
40 Uri uri = Uri.fromFile(file);
41 intent.setData(uri);
42 MainActivity.this.sendBroadcast(intent); //這個(gè)廣播的目的就是更新圖庫(kù)
43 Toast.makeText(MainActivity.this, "照片保存至:" + file, Toast.LENGTH_LONG).show();
44 resetCamera(); //調(diào)用重新預(yù)覽resetCamera()方法
45 }
46 };
(9)在onCreate()方法中,為拍照按鈕添加單擊事件監(jiān)聽(tīng)器,實(shí)現(xiàn)攝像頭的拍照功能,關(guān)鍵代碼如下:
01 takePicture.setOnClickListener(new View.OnClickListener() {
02 @Override
03 public void onClick(View v) {
04 if (camera != null) { //相機(jī)不為空
05 camera.takePicture(null, null, jpeg); //進(jìn)行拍照
06 }
07 }
08 });
(10)重寫(xiě)Activity的onPause()方法,用于當(dāng)暫停Activity時(shí),停止預(yù)覽并釋放攝像頭資源,具體代碼如下:
01 @Override
02 protected void onPause() {
03 if (camera != null) { //如果攝像頭不為空
04 camera.stopPreview(); //停止預(yù)覽
05 camera.release(); //釋放資源
06 }
07 super.onPause();
08 }
(11)由于本程序需要訪問(wèn)SD卡和控制攝像頭,所以需要在AndroidManifest.xml文件中賦予程序訪問(wèn)SD卡和控制攝像頭的權(quán)限,關(guān)鍵代碼如下:
01 <!-- 授予程序可以向SD卡中保存文件的權(quán)限 --> 02 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 03 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 04 <!-- 授予程序使用攝像頭的權(quán)限 --> 05 <uses-permission android:name="android.permission.CAMERA"/> 06 <uses-feature android:name="android.hardware.camera.autofocus"/> 07 <uses-feature android:name="android.hardware.camera"/>
(12)在AndroidManifest.xml文件的<activity>標(biāo)記中添加screenOrientation屬性,設(shè)置其橫屏顯示,關(guān)鍵代碼如下:
android:screenOrientation="landscape"
(13)在工具欄中找到下拉列表框,選擇要運(yùn)行的應(yīng)用(這里為Camera),再單擊右側(cè)的按鈕,在顯示的界面中,單擊預(yù)覽按鈕,啟動(dòng)攝像頭,單擊拍照按鈕進(jìn)行拍照,如圖10.9所示。
圖10.9 預(yù)覽與拍照
說(shuō)明:本實(shí)例需要攝像頭硬件的支持,這里我們使用真機(jī)測(cè)試。讀者需要在手機(jī)中手動(dòng)開(kāi)啟攝像頭權(quán)限與sd卡讀寫(xiě)權(quán)限。
本文來(lái)自明日科技出版的《零基礎(chǔ)學(xué)Android》,轉(zhuǎn)載請(qǐng)注明出處!!!
總結(jié)
- 上一篇: 浙江移动营业厅APP
- 下一篇: 小技巧:通过“Apple 支持”应用更改