One, foreword
Recently, my former colleague and gay friend Dai Lao asked me for my old demo that could take photos without any delay. He looked through my demo project folder and found it was a bit real
In addition, programmers do not like to see the features of the code they wrote before, so they decided to encapsulate this function, for the convenience of others, of course, but also for their own convenience
The origin of this function is still the card swiping attendance machine we made before. When checking attendance, we need to take attendance pictures, so we need to take photos
At first, I just used the conventional Camera takePicture method to get photos, but it would appear in the actual application and the speed of taking photos would be slow
At that time I also went to the scene to see the usage, director complained that the film is slow with me and show me for a moment, is indeed a caton, of course, it is easy to understand, I reluctantly explained to her that you don’t use mobile phones will also pause, need to focus on mobile phones, this is so
The person in charge told me that such and such attendance machine took pictures without stopping ah, very fast, my first reaction is that it should be a Windows machine
It turned out to be an Android machine, so I was lost in thought
I don’t know about any of us, but it was a pretty good idea to copy it, and that’s where we started exploring android cameras
As I wrote in the title, in order to achieve my stuck shooting, I use the SurfaceView+Camera mode, through the Camera preview to the SurfaceView, and then through the Camera setPreviewCallback function to call the current frame of the picture, there will be no stuck
Second, the effect drawing
After clicking Take a picture, you can get the BitMap object of the current frame and save it to the local path
Three, function realization
(a) how to use
Let’s start by looking at the layout file a SurfaceView for displaying the camera’s image in real time and a text field for ImageView for displaying and saving the image
<? The XML version = "1.0" encoding = "utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent" tools:context=".MainActivity"> <SurfaceView android:id="@+id/surfaceview" android:layout_width="320dp" android:layout_height="240dp" /> <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" Android :layout_height="wrap_content"> <Button android:id="@+id/btn_take_photo" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_pic_dir" Android :text=" " android:textSize="14sp" android:textColor="#000000" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:background="#000000" android:id="@+id/img_pic" android:layout_width="160dp" android:layout_height="120dp" /> </LinearLayout> </LinearLayout>Copy the code
Using the encapsulated CameraTakeManager, you pass in three parameters: the Activity object, the surfaceView control object, and a custom callback
The two functions onSuccess of the callback return the image and BitMap object to save
OnFail Returns failure information
manager = new CameraTakeManager(this, previewView, new CameraTakeListener() { @Override public void onSuccess(File bitmapFile, Bitmap mBitmap) { imgPic.setImageBitmap(mBitmap); Tvpicdir.settext (" image path: "+ bitmapfile.getPath ()); } @Override public void onFail(String error) { LogUtil.e(error); }});Copy the code
By clicking the button used to get the photo, enter the CameraTakeManager callback
@OnClick({R.id.btn_take_photo}) public void onClick(View view) { switch (view.getId()) { case R.id.btn_take_photo: /** click takePhoto */ manager.takephoto (); break; }}Copy the code
(2) the code of implementation
A custom SurfaceViewCallback class implements the SurfaceHolder.callback interface
Start by opening a preview of the camera in the surfaceChanged callback
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (previewing) {
mCamera.stopPreview();
previewing = false;
}
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
previewing = true;
setCameraDisplayOrientation(activity, mCurrentCamIndex, mCamera);
} catch (Exception e) {
}
}
Copy the code
The Camera setPreviewCallback function is implemented in the surfaceCreated callback to get the callback for each frame of the Camera
CanTake variable is used to determine whether the current frame needs to be photographed. When it is true, the image of the current frame is taken, a bitmap is generated, and a picture file is compressed and saved locally, and the data is called back to the interface
Realize the camera function
@Override public void surfaceCreated(SurfaceHolder holder) { if (! hasSurface) { hasSurface = true; mCamera = openFrontFacingCameraGingerbread(); If (mCamera == null){listener.onFail(" No camera available "); return; } mCamera.setPreviewCallback(new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] bytes, Camera camera) { if (canTake) { getSurfacePic(bytes, camera); canTake = false; }}}); }}Copy the code
Four, conclusion
Here even if completed, skills are not fine, I hope you give more suggestions, I will be the first time to improve, remember to give me praise oh
At the end of the post github source address github.com/Giftedcat/C…