Android開發(fā)教程之調(diào)用攝像頭功能的方法詳解
本文實例講述了Android調(diào)用攝像頭功能的方法。分享給大家供大家參考,具體如下:
我們要調(diào)用攝像頭的拍照功能,顯然
第一步必須加入調(diào)用攝像頭硬件的權(quán)限,拍完照后我們要將圖片保存在SD卡中,必須加入SD卡讀寫權(quán)限,所以第一步,我們應(yīng)該在Android清單文件中加入以下代碼
攝像頭權(quán)限:
<uses-permission android:name="android.permission.CAMERA"/>
SD卡讀寫權(quán)限:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
第二步,要將攝像頭捕獲的圖像實時地顯示在手機上。
我們是用SurfaceView這個視圖組件來實現(xiàn)的,因此在main.xml中加入下列代碼
<SurfaceView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/surfaceview" />
第三步,設(shè)置窗口的顯示方式
首先獲得當(dāng)前窗口
Window window = getWindow();//得到窗口
接著設(shè)置沒有標(biāo)題
requestWindowFeature(Window.FEATURE_NO_TITLE);//沒有標(biāo)題
接著設(shè)置全屏
當(dāng)然,我們在拍照過程中,屏幕必須一致處于高亮狀態(tài),因此接著加入下面代碼
至此,我們將窗口的顯示方式規(guī)定死了,然后才能設(shè)置窗口上顯示的組件(順序非常重要)
setContentView(R.layout.main);
第四步,設(shè)置SurficeView顯示控件的屬性
找到surficeView
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
設(shè)置它的像素為800x600
surfaceView.getHolder().setFixedSize(800, 480); //下面設(shè)置surfaceView不維護自己的緩沖區(qū),而是等待屏幕的渲染引擎將內(nèi)容推送到用戶面前 surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
第五步,就是為surficeView加入回調(diào)方法(callBack)
surfaceView.getHolder().addCallback(new SurfaceCallback());
上面的回調(diào)類是我們自己定義的,代碼如下
private class SurfaceCallback implements SurfaceHolder.Callback{ @Override public void surfaceCreated(SurfaceHolder holder) { try { camera = Camera.open();//打開硬件攝像頭,這里導(dǎo)包得時候一定要注意是android.hardware.Camera WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);//得到窗口管理器 Display display = wm.getDefaultDisplay();//得到當(dāng)前屏幕 Camera.Parameters parameters = camera.getParameters();//得到攝像頭的參數(shù) parameters.setPreviewSize(display.getWidth(), display.getHeight());//設(shè)置預(yù)覽照片的大小 parameters.setPreviewFrameRate(3);//設(shè)置每秒3幀 parameters.setPictureFormat(PixelFormat.JPEG);//設(shè)置照片的格式 parameters.setJpegQuality(85);//設(shè)置照片的質(zhì)量 parameters.setPictureSize(display.getHeight(), display.getWidth());//設(shè)置照片的大小,默認(rèn)是和 屏幕一樣大 camera.setParameters(parameters); camera.setPreviewDisplay(surfaceView.getHolder());//通過SurfaceView顯示取景畫面 camera.startPreview();//開始預(yù)覽 isPreview = true;//設(shè)置是否預(yù)覽參數(shù)為真 } catch (IOException e) { Log.e(TAG, e.toString()); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } @Override public void surfaceDestroyed(SurfaceHolder holder) { if(camera!=null){ if(isPreview){//如果正在預(yù)覽 camera.stopPreview(); camera.release(); } } } }
第六步,我們必須對按鍵事件進行監(jiān)聽,如是拍照還是聚焦,代碼如下
public boolean onKeyDown(int keyCode, KeyEvent event) {//處理按鍵事件 if(camera!=null&&event.getRepeatCount()==0)//代表只按了一下 { switch(keyCode){ case KeyEvent.KEYCODE_BACK://如果是搜索鍵 camera.autoFocus(null);//自動對焦 break; case KeyEvent.KEYCODE_DPAD_CENTER://如果是中間鍵 camera.takePicture(null, null, new TakePictureCallback());//將拍到的照片給第三個對象中,這里的TakePictureCallback()是自己定義的,在下面的代碼中 break; } } return true;//阻止事件往下傳遞,否則按搜索鍵會變成系統(tǒng)默認(rèn)的 }
private final class TakePictureCallback implements PictureCallback{ public void onPictureTaken(byte[] data, Camera camera) { try { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg"); FileOutputStream outputStream = new FileOutputStream(file); bitmap.compress(CompressFormat.JPEG, 100, outputStream); outputStream.close(); camera.stopPreview(); camera.startPreview();//處理完數(shù)據(jù)之后可以預(yù)覽 } catch (Exception e) { Log.e(TAG, e.toString()); } } }
注意,代碼中有兩個回調(diào)類,一個是SurfaceCallback(),另外一個是TakePictureCallback(),初學(xué)者可能一時難以理解,通俗地講,前者是用來監(jiān)視surficeView這個暫時存放圖片數(shù)據(jù)的顯示控件的,根據(jù)它的顯示情況調(diào)用不同的方法,包括surfaceCreated(),surfaceChanged(),surfaceDestroyed(),也就不難理解為什么會有這三個回調(diào)方法了(注意,在surfaceDestroyed()方法中必須釋放攝像頭,詳細(xì)代碼參見上方)。TakePictureCallback()是為了監(jiān)視是否拍照而設(shè)計的接口,期中也僅有一個方法,camera將拍照得到的數(shù)據(jù)傳入方法,我們便可以對拍照得到的數(shù)據(jù)進行進一步處理了。
至此,簡單的拍照功能介紹完畢!
package cn.camera.rxm; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Calendar; import java.util.Locale; import org.apache.commons.logging.Log; import android.text.format.DateFormat; import android.util.*; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.os.Environment; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; //import android.widget.Toast; public class MycamActivity extends Activity { private Preview mPreview; private Camera mCamera; Bitmap CameraBitmap; SurfaceHolder mHolder; private static final int OPTION_SNAPSHOT = 0; private static final int OPTION_STOPCAMERA = 1; private View viewStart; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LayoutInflater flater = this.getLayoutInflater(); viewStart = flater.inflate(R.layout.main, null); setContentView(viewStart); Button btn1 = (Button)findViewById(R.id.button1); btn1.setOnClickListener( new OnClickListener(){ public void onClick(View v){ mPreview = new Preview(getBaseContext()); setContentView(mPreview); }; } ); } public boolean onCreateOptionsMenu(Menu menu){ // menu.add(0, OPTION_SNAPSHOT, 0, R.string.take); // menu.add(0, OPTION_STOPCAMERA, 1, R.string.back); // return true;//super.onCreateOptionsMenu(menu); } public boolean onOptionsItemSelected(MenuItem item) { // int itemId = item.getItemId(); // switch(itemId){ case OPTION_SNAPSHOT: //拍攝照片 mCamera.takePicture(null, null, jpegCallback); try { Thread.sleep(4000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } mCamera.startPreview(); break; case OPTION_STOPCAMERA: mPreview = null; setContentView(viewStart); break; } return true; } private PictureCallback jpegCallback = new PictureCallback(){ // public void onPictureTaken(byte[] data, Camera camera) { try { String name = new DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg"; FileOutputStream fileout = new FileOutputStream("/mnt/sdcard/sdcard/DCIM/"+ name); System.out.println(name); fileout.write(data,0,data.length); fileout.flush(); fileout.close(); } catch (IOException e) { // TODO: handle exception System.out.println(e); } } }; class Preview extends SurfaceView implements SurfaceHolder.Callback { Preview(Context context) { super(context); mHolder=getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { mCamera=Camera.open(); try { mCamera.setPreviewDisplay(holder); } catch(IOException exception) { mCamera.release(); mCamera=null; } } public void surfaceDestroyed(SurfaceHolder holder) { mCamera.stopPreview(); mCamera.release(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // TODO Auto-generated method stub Camera.Parameters parameters=mCamera.getParameters(); parameters.setPictureFormat(PixelFormat.JPEG); parameters.setPreviewSize(1024, 1024); mCamera.setParameters(parameters); mCamera.setDisplayOrientation(90); mCamera.startPreview(); } } }
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android文件操作技巧匯總》、《Android編程開發(fā)之SD卡操作方法匯總》、《Android開發(fā)入門與進階教程》、《Android資源操作技巧匯總》、《Android視圖View技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對大家Android程序設(shè)計有所幫助。
相關(guān)文章
Android Activity之間相互調(diào)用與傳遞參數(shù)的原理與用法分析
這篇文章主要介紹了Android Activity之間相互調(diào)用與傳遞參數(shù)的原理與用法,較為詳細(xì)的分析了Android組件的構(gòu)成以及Activity的創(chuàng)建、調(diào)用、切換等相關(guān)操作技巧,需要的朋友可以參考下2016-08-08Android中ListView異步加載圖片錯位、重復(fù)、閃爍問題分析及解決方案
在Android所有系統(tǒng)自帶的控件當(dāng)中,ListView這個控件算是用法比較復(fù)雜的了,關(guān)鍵是用法復(fù)雜也就算了,它還經(jīng)常會出現(xiàn)一些稀奇古怪的問題,讓人非常頭疼,下面通過本篇文章給大家分享Android中ListView異步加載圖片錯位、重復(fù)、閃爍問題分析及解決方案,需要朋友可以參考2015-08-08android 仿微信demo——登錄功能實現(xiàn)(移動端)
本篇文章主要介紹了微信小程序-閱讀小程序?qū)嵗╠emo),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望能給你們提供幫助2021-06-06Android 仿日歷翻頁、仿htc時鐘翻頁、數(shù)字翻頁切換效果
這篇文章主要介紹了Android 仿日歷翻頁、仿htc時鐘翻頁、數(shù)字翻頁切換效果,需要的朋友可以參考下2017-07-07android 上傳aar到私有maven服務(wù)器的示例
這篇文章主要介紹了android 上傳aar到私有maven服務(wù)器,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11