📜 ⬆️ ⬇️

Working with the camera in Android

Working with the camera on the phone has always been of interest to me. How does all this work ... And now I got a phone with Android in my hands. I did not fail to try to figure it out. That's what happened in the end.

Consider a small program that allows you to take pictures.

All operations are performed using the Camera class.
It is necessary to have a variable
Camera camera; 

and initialize it
 camera = Camera.open(); 

After completing the camera work
 camera.release(); 

otherwise, the camera will remain blocked and inaccessible to other applications.

For normal applications such as cameras, initialization is best done in onResume , and release in onPause .
')
A prerequisite for working with the camera is to create a preview window (preview). This window must be an object of the class Surface and SurfaceView is suitable for display on the screen.
Announce
 SurfaceView preview; 

To set a preview, you must call the setPreviewDisplay method, the parameter of which is an object of the class SurfaceHolder .
 SurfaceHolder surfaceHolder; surfaceHolder = preview.getHolder(); camera.setPreviewDisplay(surfaceHolder); 

To enable the preview display, call
 camera.startPreview(); 

If this is not done, the camera will not be able to take pictures.

Actually in order to take a picture, you must call the method
 void takePicture(Camera.ShutterCalback shutter, Camera.PictureCallback raw, Camera.PictureCallback postview, Camera.PictureCallback jpg); 

With the help of parameters (by the way, any of them can be null) different event handlers are set:

The call to takePicture can be placed directly into the button's onClick handler - in this case, photographing will take place immediately after clicking on it, but you can also use pre-autofocus.
In this case, the Camera.AutoFocusCallback handler is specified , in which you need to implement the method
 public void onAutoFocus(boolean paramBoolean, Camera paramCamera); 

Then after calling the handler for the camera.autoFocus () button in the handler, the handler will be called once, in which we will already make a decision about a good focus and the need to take a picture.

You can set SurfaceHolder.Callbac k to work with SurfaceHolder
surfaceHolder.addCallback();

In this case, you must implement the methods
 public void surfaceCreated(SurfaceHolder holder); public void surfaceChanged(SurfaceHolder holder, int format, int width, int height); public void surfaceDestroyed(SurfaceHolder holder); 

Using them, the application will be informed that Surface has been successfully created if it has been changed or that it has been deleted.

The size of our preview can be changed during the program:
 LayoutParams lp = preview.getLayoutParams(); lp.width =  ; lp.height =  ; preview.setLayoutParams(lp); 

For a camera application, it's best to set the screen layout as
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Otherwise, we will have, for example, in surfaceCreated to check the location of the screen and rotate the preview using, for example, camera.setDisplayOrientation(0) .
This is not very convenient, because it takes some time to rotate the screen. At this point, the onPause and onResume call occurs, and Surface is recreated.

It is also possible to declare a Camera.PreviewCallback handler, with the help of which by implementing the method
 void onPreviewFrame(byte[] paramArrayOfByte, Camera paramCamera); 

You can receive and process each frame displayed in the preview.

And the last important point. Most often it turns out that the SurfaceView aspect ratio is different from the aspect ratio in the preview camera. Therefore, in order to avoid image distortions on the screen, it is necessary to correct the size of the displayed preview window.

I almost forgot. Add permission to manifest
 <uses-permission android:name="android.permission.CAMERA" /> 


MainScreen.java
 package test.camera; import android.app.Activity; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.view.View; import android.hardware.Camera; import android.hardware.Camera.Size; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class MainScreen extends Activity implements SurfaceHolder.Callback, View.OnClickListener, Camera.PictureCallback, Camera.PreviewCallback, Camera.AutoFocusCallback { private Camera camera; private SurfaceHolder surfaceHolder; private SurfaceView preview; private Button shotBtn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //  ,       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //  ,     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); //    requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); //  SurfaceView   SurfaceView01 preview = (SurfaceView) findViewById(R.id.SurfaceView01); surfaceHolder = preview.getHolder(); surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //    Button01 shotBtn = (Button) findViewById(R.id.Button01); shotBtn.setText("Shot"); shotBtn.setOnClickListener(this); } @Override protected void onResume() { super.onResume(); camera = Camera.open(); } @Override protected void onPause() { super.onPause(); if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.release(); camera = null; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); camera.setPreviewCallback(this); } catch (IOException e) { e.printStackTrace(); } Size previewSize = camera.getParameters().getPreviewSize(); float aspect = (float) previewSize.width / previewSize.height; int previewSurfaceWidth = preview.getWidth(); int previewSurfaceHeight = preview.getHeight(); LayoutParams lp = preview.getLayoutParams(); //     preview,     if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) { //   camera.setDisplayOrientation(90); lp.height = previewSurfaceHeight; lp.width = (int) (previewSurfaceHeight / aspect); ; } else { //  camera.setDisplayOrientation(0); lp.width = previewSurfaceWidth; lp.height = (int) (previewSurfaceWidth / aspect); } preview.setLayoutParams(lp); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void onClick(View v) { if (v == shotBtn) { //      //     //camera.takePicture(null, null, null, this); camera.autoFocus(this); } } @Override public void onPictureTaken(byte[] paramArrayOfByte, Camera paramCamera) { //   jpg   /sdcard/CameraExample/ //   - System.currentTimeMillis() try { File saveDir = new File("/sdcard/CameraExample/"); if (!saveDir.exists()) { saveDir.mkdirs(); } FileOutputStream os = new FileOutputStream(String.format("/sdcard/CameraExample/%d.jpg", System.currentTimeMillis())); os.write(paramArrayOfByte); os.close(); } catch (Exception e) { } //  ,   ,   .    paramCamera.startPreview(); } @Override public void onAutoFocus(boolean paramBoolean, Camera paramCamera) { if (paramBoolean) { //   ,   paramCamera.takePicture(null, null, null, this); } } @Override public void onPreviewFrame(byte[] paramArrayOfByte, Camera paramCamera) { //    ,   preview } } 


main.xml
 <?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/FrameLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <SurfaceView android:id="@+id/SurfaceView01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </SurfaceView> <Button android:text="@+id/Button01" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </Button> </FrameLayout> 


AndroidManifest.xml
 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.camera" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true"> <activity android:name=".MainScreen" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest> 


The program was debugged and tested on the phone LG Optimus One P500.

When writing, the following sources of information were used:

  1. developer.android.com/reference/android/hardware/Camera.html
  2. Shawn Van Every. Android Media Pro: Developing Graphics, Music, Video and Rich Media Apps for Smartphones and Tablets. Apress 2009.
  3. developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html


Download the project at the link: perezalil here zalil.ru/30377379

Source: https://habr.com/ru/post/112272/


All Articles