Exploring Android Camera-start, androidcamera
Exploring Android Camera
Camera plays an important role in mobile phones. No matter the QR code, photos, and recognition, cameras are indispensable. This article will comprehensively analyze Camera in Android.
Permission town building:
<uses-permission android:name="android.permission.CAMERA"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-feature android:name="android.hardware.camera"/>
Call System Camera
Using the system-defined Intent Action, we can easily use all apps that implement the Camera function.
ACTION_IMAGE_CAPTURE
This action is the most common action that calls the System Camera.
The usage is as follows:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
With such an Action, we can call all apps that declare Camera.
So how do I receive the image? We naturally need to use the startActivityForResult method.
Here we will first look at the simplest:
We are:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); }
In the onActivityResult method, the image is obtained using the data parameter:
/*** Get the image through data */Bundle extras = data. getExtras (); Bitmap bitmap = (Bitmap) extras. get ("data"); mImageViewShow. setImageBitmap (bitmap );
However, the pixels of mobile phones are so high now. If the pictures are too big, will the data be too big and FC? Don't worry, Android has long considered it, so the data is not a complete picture at all,It's just a thumbnail.. Therefore, you cannot use this method to obtain the source image. But we can do this. We can specify an EXTRA_OUTPUT of the MediaStore class to specify the location where the image is saved, which is equivalent to creating a temporary file. In onActivityResult, we can directly read the temporary file instead of using data to obtain the image.
Specify EXTRA_OUTPUT:
String tempPath = Environment.getExternalStorageDirectory().getPath();mFilePath = tempPath + "/" + "test1.png";
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);Uri photoUri = Uri.fromFile(new File(mFilePath));intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);startActivityForResult(intent, CAMERA_CODE1);
OnActivityResult:
/*** Get the image through the temporary path */FileInputStream FD = null; Bitmap bitmap = null; try {FD = new FileInputStream (mFilePath); bitmap = BitmapFactory. decodeStream (FS);} catch (FileNotFoundException e) {e. printStackTrace ();} finally {if (FS! = Null) {try {fs. close ();} catch (IOException e) {e. printStackTrace ();}}}
In this way, we can get the complete picture. Later, you can display the image. When displaying the image, you also need to consider the processing of the big image to avoid the problems caused by the image size. For details, refer to the following:
Http://blog.csdn.net/eclipsexys/article/details/44459771
I will not go into details here. If your App only requires a very simple shooting function, it is enough to call the system Intent, but most of the time it is impossible. So let's take a look at how to customize Camera.
Custom Camera
According to Google Android Doc, the following steps are required to customize a Camera:
1. Check whether Camera exists and grant related permissions to AndroidManifest. xml;
2. Create a Camera Preview class inherited from SurfaceView and implemented the SurfaceHolder interface;
3. Create a new Camera Preview layout file;
4. Set a photo listening event, such as clicking a button event;
5. Take a photo and save the image to the device;
6. Release Camera.
It looks complicated. So let's step by step.
First, we create a Camera preview interface:
<RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" android: layout_width = "match_parent" android: layout_height = "match_parent"> <LinearLayout android: id = "@ + id/ll" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: layout_alignParentTop = "true" android: orientation = "horizontal"> <Button android: id = "@ + id/btn_switch_camera" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_weight = "1" android: gravity = "center" android: onClick = "switchCamera" android: text = ""/> <Button android: id = "@ + id/btn_capture" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_weight = "1" android: gravity = "center" android: onClick = "capture" android: text = ""/> </LinearLayout> <SurfaceView android: id = "@ + id/sv_camera" android: layout_width = "match_parent" android: layout_height = "match_parent" android: layout_below = "@ id/ll" android: text = "camera"/> </RelativeLayout>
It is very simple. There is a surfaceview under two buttons:
Then, we create an Activity to display the preview of Camera:
There must be SurfaceView in this Activity. Therefore, SurfaceView's set of things is naturally indispensable. If you don't understand it, please make up your mind.
So what do we need to do in this Activity? Two things:
The Camera of Android is exclusive. If multiple calls are made, an exception is thrown. Therefore, we need to bind the lifecycle of Camera to the lifecycle of the Activity:
Camera Initialization is very simple:
/*** Initialize the camera ** @ return Camera */private Camera getCamera () {camera; try {Camera = camera. open ();} catch (Exception e) {camera = null;} return camera ;}
Releasing a camera is also very simple:
/*** Release camera Resources */private void releaseCamera () {if (mCamera! = Null) {mCamera. setPreviewCallback (null); mCamera. stopPreview (); mCamera. release (); mCamera = null ;}}
Now let's take a look at how to set the camera image to SurfaceView for preview:
/*** Preview the camera content in SurfaceView ** @ param camera Camera * @ param holder SurfaceHolder */private void setStartPreview (camera, SurfaceHolder holder) {try {camera. setPreviewDisplay (holder); camera. setDisplayOrientation (90); camera. startPreview ();} catch (IOException e) {e. printStackTrace ();}}
Nima, isn't it very simple? A camera method has automatically associated SurfaceView for us.
PS here you need to pay attention to this method camera. setDisplayOrientation (90). Through this method, we can adjust the camera angle. Otherwise, the default is landscape screen, and the image will display a strange one. Of course, even if you set 90, the image may be strange, because you have not correctly scaled the image, and the proportion is incorrect.
Through the settings above, we can preview the image content of the camera normally. Now we can take a photo.
Alas, it's really easy to take a photo, just one sentence:
mCamera.takePicture(null, null, mPictureCallback);
Of course, in order to work with the camera, we need to make some settings, set the camera parameters, and set a callback for the action after the camera:
Parameters:
Camera. parameters params = mCamera. getParameters (); params. setPictureFormat (ImageFormat. JPEG); params. setPreviewSize (800,400); params. setFocusMode (Camera. parameters. FOCUS_MODE_AUTO); mCamera. setParameters (params); // use the autofocus function mCamera. autoFocus (new Camera. autoFocusCallback () {@ Override public void onAutoFocus (boolean success, Camera camera) {mCamera. takePicture (null, null, mPictureCallback );}});
Callback:
/*** Camera callback, using data [] to keep image data information */Camera. pictureCallback mPictureCallback = new Camera. pictureCallback () {@ Override public void onPictureTaken (byte [] data, Camera camera) {File pictureFile = getOutputMediaFile (); if (pictureFile = null) {return ;} try {FileOutputStream fos = new FileOutputStream (pictureFile); fos. write (data); fos. close (); Intent intent = new Intent (CustomCamera. this, CameraResult. class); intent. putExtra ("picPath", pictureFile. getAbsolutePath (); startActivity (intent); CustomCamera. this. finish ();} catch (IOException e) {e. printStackTrace ();}}};
In the callback, we pass the captured image address to the ImageView for display. This completes camera shooting and image display.
Process image deformation
Because we have created a SurfaceView in the layout, and we have made match_parent between them, the image will certainly be stretched during preview. So how to deal with these variants?
We can change the SurfaceView size. In the Android API Demo, Google also provides us with an example like this:
Path:
Android-22/legacy/ApiDemos/src/com/example/android/apis/graphics/CameraPreview. java
Google solves the deformation problem by setting a new size to adapt to the size of the preview area,I don't understand the source code or the Demo for foreign affairs..
Custom Image Capture
It sounds very tall. In fact, it's really simple. You just need to use a FrameLayout to pack the SurfaceView for Preview. What do you want to add next, add it directly in FrameLayout, like this:
<FrameLayout android: layout_width = "match_parent" android: layout_height = "match_parent" android: layout_below = "@ id/ll"> <SurfaceView android: id = "@ + id/sv_camera" android: layout_width = "match_parent" android: layout_height = "match_parent" android: text = "Photo area"/> <ImageView android: layout_width = "match_parent" android: layout_height = "match_parent" android: scaleType = "center" android: src = "@ drawable/demo"/> </FrameLayout>
Besides ImageView and ViewPager, you can even create a interchangeable watermark camera. Isn't it very simple, and everything you add is operable, plus animation, color, done in minutes.
Above.
After starting, we will start running.
To download the code, please go to the world's largest pear dating community:
Https://github.com/xuyisheng/CameraGuide
Subsequent chapters will also be updated in this repo.