首页 > 代码库 > Android相机应用开发实例

Android相机应用开发实例

   在学习直接调用本地相机获取照片之前,我想最好还是根据Android给的相机API自己开发一个简单的相机,对于相机的运作过程有一个基本的了解。

 

  第一步,建立SurfaceView显示预览(拍照之前)

  activity_main.xml文件定义FrameLayout布局,用一个button来实施拍照行为

  

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"    >    <SurfaceView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/surfaceView"        android:layout_gravity="center" />    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:visibility="visible"        android:id="@+id/shot_button_layout"        >        <Button            android:id="@+id/button"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentRight="true"            android:layout_alignParentBottom="true"            android:text="@string/shot"            android:layout_marginRight="10dp"            android:layout_marginBottom="10dp"/>        </RelativeLayout></FrameLayout>

  onCreate方法布局全屏和添加回调函数,其中的button点击动作为拍摄照片

@Override    protected void onCreate(Bundle savedInstanceState) {        requestWindowFeature(Window.FEATURE_NO_TITLE); //此方法必须在super.onCreate方法之前调用        super.onCreate(savedInstanceState);        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏显示        setContentView(R.layout.activity_main);        button = (Button) findViewById(R.id.button);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mCamera.takePicture(null, null, new MyPictureCallback());            }        });        mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);        mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        //获取手机分辨率        Display display = getWindowManager().getDefaultDisplay(); //Activity#getWindowManager()        Point size = new Point();        display.getSize(size);        mSurfaceView.getHolder().setFixedSize(size.x,size.y);        mSurfaceView.getHolder().setKeepScreenOn(true);        mSurfaceView.getHolder().addCallback(new SurfaceCallback());    }

  重要的一个步骤就是处理SurfaceView的显示与更新。

private final class SurfaceCallback implements SurfaceHolder.Callback{        @Override        public void surfaceCreated(SurfaceHolder holder) {            mCamera = Camera.open();            Camera.Parameters parameters = mCamera.getParameters();            mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();            Camera.Size mPreviewSize = mSupportedPreviewSizes.get(mSupportedPreviewSizes.size()-1);            parameters.setPreviewSize(mPreviewSize.width,mPreviewSize.height);            parameters.setPreviewFrameRate(5);            if(parameters.getSupportedPreviewFormats().contains(ImageFormat.JPEG)){                parameters.setPreviewFormat(ImageFormat.JPEG);            }            parameters.setPictureFormat(ImageFormat.JPEG);            parameters.setPictureSize(1024, 768);            parameters.setJpegQuality(80);            mCamera.setParameters(parameters);            try {                mCamera.setPreviewDisplay(holder);                mCamera.startPreview();            } catch (IOException e) {                e.printStackTrace();            }            Log.v(LOG_TAG,"Camera parameters are: "+parameters.flatten());        }        @Override        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        }        @Override        public void surfaceDestroyed(SurfaceHolder holder) {            if (mCamera != null){                mCamera.release();                mCamera =null;            }        }    }

   

   第二步,实现拍照与照片数据的保存(保存在sd卡里的CameraDemo/目录下)。

private final class MyPictureCallback implements Camera.PictureCallback {        @Override        public void onPictureTaken(byte[] data, Camera camera) {            SavePictureTask savePictureTask = new SavePictureTask();            savePictureTask.execute(data);              mCamera.startPreview();        }    }

  建立上边代码中的SavePictureTask异步处理类。

public class SavePictureTask extends AsyncTask<byte[],Void,Void>{    @Override    protected Void doInBackground(byte[]... params) {        File path = new File(getSDPath()+"/CameraDemo");        if (!path.exists()) {            path.mkdirs();        }        // 创建文件        Calendar calendar = Calendar.getInstance();        String filename = ""+calendar.get(Calendar.YEAR)+calendar.get(Calendar.MONTH)+                calendar.get(Calendar.DAY_OF_MONTH)+Integer.toString((int) System.currentTimeMillis()) + ".jpg";        File picture = new File(path+"/"+filename);  //这里是全路径        try {            FileOutputStream out = new FileOutputStream(picture);            out.write(params[0]);            out.close();        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    public String getSDPath(){        File sdDir = null;        boolean sdCardExist = Environment.getExternalStorageState()                .equals(android.os.Environment.MEDIA_MOUNTED);   //判断sd卡是否存在        if   (sdCardExist)        {            sdDir = Environment.getExternalStorageDirectory();//获取跟目录        }        return sdDir.toString();    }}

  实现一个简单拍照功能的相机难度不大,但是所给API的模式还需进一步理解。这个相机的自动对焦功能实现的不是太好,有待于改进,这里就不贴代码了,以后需要深入学习的。完整代码等我更新到github上会贴出地址。

 

Android相机应用开发实例