1. Create a New Android Application Project
2. Creating the layout of the main
We are going to make a very simple layout xml for the CameraDemo
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/btn_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/layout_area"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:background="#000">
<ImageView
android:id="@+id/btn_flash"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:padding="5dp"
android:src="@drawable/ic_action_flash_off" />
<ImageView
android:id="@+id/btn_switch"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:padding="5dp"
android:src="@drawable/ic_action_switch_camera" />
</RelativeLayout>
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/layout_area1"
android:layout_below="@+id/layout_area" />
<RelativeLayout
android:id="@+id/layout_area1"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:background="#000">
<ImageView
android:id="@+id/btn_exit"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_action_remove" />
<com.melnykov.fab.FloatingActionButton
android:id="@+id/btn_take_photo"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:src="@drawable/ic_action_camera" />
<ImageView
android:id="@+id/btn_lib"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_margin="5dp"
android:src="@drawable/ic_library_cam" />
</RelativeLayout>
</RelativeLayout>
</FrameLayout>
3. Creating the source code
package com.example.tb_laota.camerademo;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;
import com.melnykov.fab.FloatingActionButton;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import butterknife.ButterKnife;
import butterknife.InjectView;
/**
* Created by tb_laota on 10/30/2015.
*/
public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback {
Camera camera;
@InjectView(R.id.surfaceView)
SurfaceView surfaceView;
@InjectView(R.id.btn_take_photo)
FloatingActionButton btn_take_photo;
SurfaceHolder surfaceHolder;
PictureCallback jpegCallback;
ShutterCallback shutterCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_activity);
ButterKnife.inject(this);
surfaceHolder = surfaceView.getHolder();
// Install a surfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
surfaceHolder.addCallback(this);
//deprecated setting, but required on android versions prior to 3.0
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
btn_take_photo.setOnClickListener(new FloatingActionButton.OnClickListener() {
@Override
public void onClick(View v) {
captureImage();
}
});
jpegCallback = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outputStream = null;
File file_image = getDirc();
if (!file_image.exists() && !file_image.mkdirs()) {
Toast.makeText(getApplication(), "Can't create directory to save image", Toast.LENGTH_SHORT).show();
return;
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = simpleDateFormat.format(new Date());
String photofile = "Cam_Demo" + date + ".jpg";
String file_name = file_image.getPath() + File.separator + photofile;
File picfile = new File(file_name);
try {
outputStream = new FileOutputStream(picfile);
outputStream.write(data);
outputStream.close();
} catch (FileNotFoundException e) {
} catch (IOException ex) {
} finally {
}
Toast.makeText(getApplicationContext(), "Picture saved", Toast.LENGTH_SHORT).show();
refreshCamera();
refreshGallery(picfile);
}
};
}
//refresh gallery
public void refreshGallery(File file) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);
}
public void refreshCamera() {
if (surfaceHolder.getSurface() == null) {
//preview surface does not exist
return;
}
//stop preview before making changes
try {
camera.stopPreview();
} catch (Exception e) {
}
//set preview size and make any resize, rotate or
//reformatting changes here
//start preview with new settings
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
}
}
public File getDirc() {
File dics = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
return new File(dics, "Camera_Demo");
}
public void captureImage() {
//take the picture
camera.takePicture(null, null, jpegCallback);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//open the camera
try {
camera = Camera.open();
} catch (RuntimeException ex) {
}
Camera.Parameters parameters;
parameters = camera.getParameters();
//modify parameter
parameters.setPreviewFrameRate(20);
parameters.setPreviewSize(352, 288);
camera.setParameters(parameters);
camera.setDisplayOrientation(90);
try {
//The surface thas been created, now tell the camera where to draw
//the preview
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
refreshCamera();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//stop preview and release camera
camera.stopPreview();
camera.release();
camera = null;
}
}
In these lines, we find our SurfaceView from our main layout and we get a holder, an abstract interface to someone holding a display surface. This, allows us to control the surface size and format, edit the pixels in the surface, and monitor changes to the surface. We also install a SurfaceHolder.Callback so we get notified when the underlying surface is created and destroyed. We have also written the surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); deprecated setting, but required on Android versions prior to 3.0.
4. Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tb_laota.camerademo">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".CameraActivity"></activity>
</application>
</manifest>
5. Build, compile and run